22
33const bannedPackageName = "@effect-template/lib"
44
5- /** @type {ReadonlyArray<string> } */
6- export const appLegacyLibImportAllowlist = [
7- "src/app/program.ts" ,
8- "src/docker-git/cli/input.ts" ,
9- "src/docker-git/cli/parser-apply.ts" ,
10- "src/docker-git/cli/parser-attach.ts" ,
11- "src/docker-git/cli/parser-auth.ts" ,
12- "src/docker-git/cli/parser-clone.ts" ,
13- "src/docker-git/cli/parser-create.ts" ,
14- "src/docker-git/cli/parser-mcp-playwright.ts" ,
15- "src/docker-git/cli/parser-options.ts" ,
16- "src/docker-git/cli/parser-panes.ts" ,
17- "src/docker-git/cli/parser-scrap.ts" ,
18- "src/docker-git/cli/parser-session-gists.ts" ,
19- "src/docker-git/cli/parser-sessions.ts" ,
20- "src/docker-git/cli/parser-shared.ts" ,
21- "src/docker-git/cli/parser-state.ts" ,
22- "src/docker-git/cli/parser.ts" ,
23- "src/docker-git/cli/read-command.ts" ,
24- "src/docker-git/cli/usage.ts" ,
25- "src/docker-git/menu-actions.ts" ,
26- "src/docker-git/menu-auth-data.ts" ,
27- "src/docker-git/menu-auth-effects.ts" ,
28- "src/docker-git/menu-auth-helpers.ts" ,
29- "src/docker-git/menu-auth-snapshot-builder.ts" ,
30- "src/docker-git/menu-auth.ts" ,
31- "src/docker-git/menu-create.ts" ,
32- "src/docker-git/menu-labeled-env.ts" ,
33- "src/docker-git/menu-menu.ts" ,
34- "src/docker-git/menu-project-auth-data.ts" ,
35- "src/docker-git/menu-project-auth-flows.ts" ,
36- "src/docker-git/menu-project-auth.ts" ,
37- "src/docker-git/menu-render-select.ts" ,
38- "src/docker-git/menu-render.ts" ,
39- "src/docker-git/menu-select-actions.ts" ,
40- "src/docker-git/menu-select-connect.ts" ,
41- "src/docker-git/menu-select-load.ts" ,
42- "src/docker-git/menu-select-order.ts" ,
43- "src/docker-git/menu-select-runtime.ts" ,
44- "src/docker-git/menu-select-view.ts" ,
45- "src/docker-git/menu-startup.ts" ,
46- "src/docker-git/menu-types.ts" ,
47- "src/docker-git/menu.ts" ,
48- "src/docker-git/program.ts" ,
49- "src/docker-git/tmux.ts" ,
50- "tests/docker-git/entrypoint-auth.test.ts" ,
51- "tests/docker-git/fixtures/project-item.ts" ,
52- "tests/docker-git/menu-select-connect.test.ts" ,
53- "tests/docker-git/parser-helpers.ts" ,
54- "tests/docker-git/parser.test.ts"
55- ]
56-
57- /** @param {string } value */
58- const normalizePath = ( value ) => value . replaceAll ( "\\" , "/" )
59-
605/** @param {string } value */
616const isDirectLibImport = ( value ) =>
627 value === bannedPackageName || value . startsWith ( `${ bannedPackageName } /` )
638
64- /**
65- * @param {string } filename
66- * @param {ReadonlyArray<string> } allowInFiles
67- */
68- const isAllowlistedFile = ( filename , allowInFiles ) => {
69- const normalized = normalizePath ( filename )
70- return allowInFiles . some ( ( entry ) => normalized === entry || normalized . endsWith ( `/${ entry } ` ) )
71- }
72-
739/** @param {(import("eslint").JSSyntaxElement & { readonly value?: unknown }) | null | undefined } source */
74- const readSourceText = ( source ) =>
75- source && source . type === "Literal" && typeof source . value === "string"
76- ? source . value
77- : null
10+ const readSourceText = ( source ) => {
11+ if ( source == null ) {
12+ return null
13+ }
14+
15+ if ( source . type === "Literal" && typeof source . value === "string" ) {
16+ return source . value
17+ }
18+
19+ if (
20+ source . type === "TemplateLiteral" &&
21+ source . expressions . length === 0 &&
22+ source . quasis . length === 1
23+ ) {
24+ const [ quasi ] = source . quasis
25+ return typeof quasi ?. value . cooked === "string" ? quasi . value . cooked : null
26+ }
27+
28+ return null
29+ }
7830
7931/**
8032 * @param {import("eslint").Rule.RuleContext } context
8133 * @returns {import("eslint").Rule.RuleListener }
8234 */
8335const createRuleListener = ( context ) => {
84- const [ options = { } ] = context . options
85- const allowInFiles = Array . isArray ( options . allowInFiles )
86- ? options . allowInFiles . map (
87- /** @param {unknown } value */ ( value ) => normalizePath ( String ( value ) )
88- )
89- : [ ]
90- const filename = typeof context . filename === "string" ? context . filename : ""
91-
92- if ( isAllowlistedFile ( filename , allowInFiles ) ) {
93- return { }
94- }
95-
9636 /** @param {(import("eslint").JSSyntaxElement & { readonly value?: unknown }) | null | undefined } source */
9737 const checkSource = ( source ) => {
9838 if ( source == null ) {
@@ -112,6 +52,23 @@ const createRuleListener = (context) => {
11252 }
11353
11454 return {
55+ /** @param {{ readonly callee?: import("eslint").JSSyntaxElement | null | undefined, readonly arguments?: ReadonlyArray<import("eslint").JSSyntaxElement | import("eslint").SpreadElement> | null | undefined } } node */
56+ CallExpression ( node ) {
57+ if (
58+ node . callee ?. type !== "Identifier" ||
59+ node . callee . name !== "require" ||
60+ ! Array . isArray ( node . arguments )
61+ ) {
62+ return
63+ }
64+
65+ const [ firstArgument ] = node . arguments
66+ if ( firstArgument ?. type === "SpreadElement" ) {
67+ return
68+ }
69+
70+ checkSource ( firstArgument )
71+ } ,
11572 /** @param {{ readonly source?: (import("eslint").JSSyntaxElement & { readonly value?: unknown }) | null | undefined } } node */
11673 ExportAllDeclaration ( node ) {
11774 checkSource ( node . source )
@@ -131,6 +88,10 @@ const createRuleListener = (context) => {
13188 /** @param {{ readonly source?: (import("eslint").JSSyntaxElement & { readonly value?: unknown }) | null | undefined, readonly argument?: (import("eslint").JSSyntaxElement & { readonly value?: unknown }) | null | undefined } } node */
13289 TSImportType ( node ) {
13390 checkSource ( "source" in node ? node . source : node . argument )
91+ } ,
92+ /** @param {{ readonly expression?: (import("eslint").JSSyntaxElement & { readonly value?: unknown }) | null | undefined } } node */
93+ TSExternalModuleReference ( node ) {
94+ checkSource ( node . expression )
13495 }
13596 }
13697}
@@ -140,23 +101,13 @@ export const noLibImportsRule = {
140101 meta : {
141102 type : "problem" ,
142103 docs : {
143- description : "forbid direct imports from @effect-template/lib inside package/app"
104+ description :
105+ "forbid direct imports, re-exports, and require calls from @effect-template/lib inside package/app"
144106 } ,
145- schema : [
146- {
147- type : "object" ,
148- properties : {
149- allowInFiles : {
150- type : "array" ,
151- items : { type : "string" }
152- }
153- } ,
154- additionalProperties : false
155- }
156- ] ,
107+ schema : [ ] ,
157108 messages : {
158109 noLibImport :
159- "Direct import '{{source}}' from @effect-template/lib is forbidden in package/app. Use the API client or a local app adapter instead."
110+ "Direct import or require '{{source}}' from @effect-template/lib is forbidden in package/app. Use the API client or a local app adapter instead."
160111 }
161112 } ,
162113 create : createRuleListener
0 commit comments