@gtkx/cli 1.4.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. package/README.md +1 -1
  2. package/dist/builder.d.ts +1 -0
  3. package/dist/builder.d.ts.map +1 -1
  4. package/dist/builder.js +2 -2
  5. package/dist/builder.js.map +1 -1
  6. package/dist/cli.js +4 -0
  7. package/dist/cli.js.map +1 -1
  8. package/dist/codegen/freshness.d.ts.map +1 -1
  9. package/dist/codegen/freshness.js +2 -1
  10. package/dist/codegen/freshness.js.map +1 -1
  11. package/dist/codegen/reference.d.ts +17 -0
  12. package/dist/codegen/reference.d.ts.map +1 -0
  13. package/dist/codegen/reference.js +37 -0
  14. package/dist/codegen/reference.js.map +1 -0
  15. package/dist/codegen/report.d.ts.map +1 -1
  16. package/dist/codegen/report.js +17 -3
  17. package/dist/codegen/report.js.map +1 -1
  18. package/dist/codegen/run-codegen.d.ts +4 -0
  19. package/dist/codegen/run-codegen.d.ts.map +1 -1
  20. package/dist/codegen/run-codegen.js +93 -27
  21. package/dist/codegen/run-codegen.js.map +1 -1
  22. package/dist/commands/codegen.js +1 -1
  23. package/dist/commands/codegen.js.map +1 -1
  24. package/dist/commands/docs.d.ts.map +1 -1
  25. package/dist/commands/docs.js +10 -16
  26. package/dist/commands/docs.js.map +1 -1
  27. package/dist/commands/mcp.d.ts +13 -0
  28. package/dist/commands/mcp.d.ts.map +1 -0
  29. package/dist/commands/mcp.js +68 -0
  30. package/dist/commands/mcp.js.map +1 -0
  31. package/dist/deploy/freedesktop/localize.d.ts +6 -0
  32. package/dist/deploy/freedesktop/localize.d.ts.map +1 -0
  33. package/dist/deploy/freedesktop/localize.js +107 -0
  34. package/dist/deploy/freedesktop/localize.js.map +1 -0
  35. package/dist/deploy/install-hints.d.ts.map +1 -1
  36. package/dist/deploy/install-hints.js +5 -0
  37. package/dist/deploy/install-hints.js.map +1 -1
  38. package/dist/deploy/notices/gtkx.js +1 -1
  39. package/dist/deploy/notices/gtkx.js.map +1 -1
  40. package/dist/deploy/notices/libraries.d.ts.map +1 -1
  41. package/dist/deploy/notices/libraries.js +2 -1
  42. package/dist/deploy/notices/libraries.js.map +1 -1
  43. package/dist/deploy/payload/launcher.d.ts.map +1 -1
  44. package/dist/deploy/payload/launcher.js +2 -0
  45. package/dist/deploy/payload/launcher.js.map +1 -1
  46. package/dist/deploy/payload/stage.d.ts +1 -1
  47. package/dist/deploy/payload/stage.d.ts.map +1 -1
  48. package/dist/deploy/payload/stage.js +20 -11
  49. package/dist/deploy/payload/stage.js.map +1 -1
  50. package/dist/deploy/run-deploy.d.ts.map +1 -1
  51. package/dist/deploy/run-deploy.js +87 -15
  52. package/dist/deploy/run-deploy.js.map +1 -1
  53. package/dist/deploy/settings/libraries.d.ts.map +1 -1
  54. package/dist/deploy/settings/libraries.js +7 -9
  55. package/dist/deploy/settings/libraries.js.map +1 -1
  56. package/dist/deploy/targets/flatpak-source.d.ts.map +1 -1
  57. package/dist/deploy/targets/flatpak-source.js +21 -10
  58. package/dist/deploy/targets/flatpak-source.js.map +1 -1
  59. package/dist/deploy/tools.d.ts +6 -1
  60. package/dist/deploy/tools.d.ts.map +1 -1
  61. package/dist/deploy/tools.js +27 -4
  62. package/dist/deploy/tools.js.map +1 -1
  63. package/dist/dev/locale-dir.d.ts +3 -0
  64. package/dist/dev/locale-dir.d.ts.map +1 -0
  65. package/dist/dev/locale-dir.js +17 -0
  66. package/dist/dev/locale-dir.js.map +1 -0
  67. package/dist/dev/runner-main.d.ts.map +1 -1
  68. package/dist/dev/runner-main.js +4 -1
  69. package/dist/dev/runner-main.js.map +1 -1
  70. package/dist/dev/runner.d.ts.map +1 -1
  71. package/dist/dev/runner.js +6 -0
  72. package/dist/dev/runner.js.map +1 -1
  73. package/dist/dev/vite-dev-server.d.ts +1 -0
  74. package/dist/dev/vite-dev-server.d.ts.map +1 -1
  75. package/dist/dev/vite-dev-server.js.map +1 -1
  76. package/dist/i18n/binding-extractor.d.ts +30 -0
  77. package/dist/i18n/binding-extractor.d.ts.map +1 -0
  78. package/dist/i18n/binding-extractor.js +1324 -0
  79. package/dist/i18n/binding-extractor.js.map +1 -0
  80. package/dist/i18n/catalog-template.d.ts +3 -0
  81. package/dist/i18n/catalog-template.d.ts.map +1 -0
  82. package/dist/i18n/catalog-template.js +18 -0
  83. package/dist/i18n/catalog-template.js.map +1 -0
  84. package/dist/i18n/catalogs.d.ts +21 -0
  85. package/dist/i18n/catalogs.d.ts.map +1 -0
  86. package/dist/i18n/catalogs.js +139 -0
  87. package/dist/i18n/catalogs.js.map +1 -0
  88. package/dist/i18n/extractor-plugin.d.ts +8 -0
  89. package/dist/i18n/extractor-plugin.d.ts.map +1 -0
  90. package/dist/i18n/extractor-plugin.js +247 -0
  91. package/dist/i18n/extractor-plugin.js.map +1 -0
  92. package/dist/i18n/metadata-templates.d.ts +11 -0
  93. package/dist/i18n/metadata-templates.d.ts.map +1 -0
  94. package/dist/i18n/metadata-templates.js +11 -0
  95. package/dist/i18n/metadata-templates.js.map +1 -0
  96. package/dist/i18n/source-messages.d.ts +23 -0
  97. package/dist/i18n/source-messages.d.ts.map +1 -0
  98. package/dist/i18n/source-messages.js +403 -0
  99. package/dist/i18n/source-messages.js.map +1 -0
  100. package/dist/i18n/types.d.ts +10 -0
  101. package/dist/i18n/types.d.ts.map +1 -0
  102. package/dist/i18n/types.js +108 -0
  103. package/dist/i18n/types.js.map +1 -0
  104. package/dist/internal/agent-rules.d.ts +7 -0
  105. package/dist/internal/agent-rules.d.ts.map +1 -0
  106. package/dist/internal/agent-rules.js +106 -0
  107. package/dist/internal/agent-rules.js.map +1 -0
  108. package/dist/internal/docs-elements.d.ts +8 -0
  109. package/dist/internal/docs-elements.d.ts.map +1 -0
  110. package/dist/internal/docs-elements.js +12 -0
  111. package/dist/internal/docs-elements.js.map +1 -0
  112. package/dist/internal/source-imports.d.ts +5 -1
  113. package/dist/internal/source-imports.d.ts.map +1 -1
  114. package/dist/internal/source-imports.js +25 -47
  115. package/dist/internal/source-imports.js.map +1 -1
  116. package/dist/mcp/client-config.d.ts +22 -0
  117. package/dist/mcp/client-config.d.ts.map +1 -0
  118. package/dist/mcp/client-config.js +94 -0
  119. package/dist/mcp/client-config.js.map +1 -0
  120. package/dist/mcp/client.d.ts +0 -1
  121. package/dist/mcp/client.d.ts.map +1 -1
  122. package/dist/mcp/client.js +11 -39
  123. package/dist/mcp/client.js.map +1 -1
  124. package/dist/mcp/handlers.d.ts +2 -1
  125. package/dist/mcp/handlers.d.ts.map +1 -1
  126. package/dist/mcp/handlers.js.map +1 -1
  127. package/dist/settings/render.d.ts +4 -1
  128. package/dist/settings/render.d.ts.map +1 -1
  129. package/dist/settings/render.js +11 -2
  130. package/dist/settings/render.js.map +1 -1
  131. package/dist/settings/schema.d.ts.map +1 -1
  132. package/dist/settings/schema.js +3 -1
  133. package/dist/settings/schema.js.map +1 -1
  134. package/dist/vite-plugins/animated.d.ts +5 -0
  135. package/dist/vite-plugins/animated.d.ts.map +1 -0
  136. package/dist/vite-plugins/animated.js +325 -0
  137. package/dist/vite-plugins/animated.js.map +1 -0
  138. package/dist/vite-plugins/asset-imports.d.ts.map +1 -1
  139. package/dist/vite-plugins/asset-imports.js +4 -14
  140. package/dist/vite-plugins/asset-imports.js.map +1 -1
  141. package/dist/vite-plugins/i18n.d.ts +5 -0
  142. package/dist/vite-plugins/i18n.d.ts.map +1 -0
  143. package/dist/vite-plugins/i18n.js +88 -0
  144. package/dist/vite-plugins/i18n.js.map +1 -0
  145. package/dist/vite-plugins/index.d.ts +1 -1
  146. package/dist/vite-plugins/index.d.ts.map +1 -1
  147. package/dist/vite-plugins/index.js +5 -1
  148. package/dist/vite-plugins/index.js.map +1 -1
  149. package/dist/vite-plugins/resources.d.ts.map +1 -1
  150. package/dist/vite-plugins/resources.js +12 -57
  151. package/dist/vite-plugins/resources.js.map +1 -1
  152. package/dist/vite-plugins/self-contained.d.ts.map +1 -1
  153. package/dist/vite-plugins/self-contained.js +128 -135
  154. package/dist/vite-plugins/self-contained.js.map +1 -1
  155. package/dist/vite-plugins/settings-worker-env.js +2 -2
  156. package/dist/vite-plugins/settings-worker-env.js.map +1 -1
  157. package/dist/vite-plugins/settings.d.ts.map +1 -1
  158. package/dist/vite-plugins/settings.js +2 -1
  159. package/dist/vite-plugins/settings.js.map +1 -1
  160. package/package.json +11 -9
  161. package/src/builder.ts +3 -2
  162. package/src/cli.ts +5 -0
  163. package/src/codegen/freshness.ts +2 -1
  164. package/src/codegen/reference.ts +59 -0
  165. package/src/codegen/report.ts +18 -3
  166. package/src/codegen/run-codegen.ts +134 -31
  167. package/src/commands/codegen.ts +1 -1
  168. package/src/commands/docs.ts +10 -28
  169. package/src/commands/mcp.ts +81 -0
  170. package/src/deploy/freedesktop/localize.ts +144 -0
  171. package/src/deploy/install-hints.ts +5 -0
  172. package/src/deploy/notices/gtkx.ts +1 -1
  173. package/src/deploy/notices/libraries.ts +2 -1
  174. package/src/deploy/payload/launcher.ts +2 -0
  175. package/src/deploy/payload/stage.ts +35 -10
  176. package/src/deploy/run-deploy.ts +128 -13
  177. package/src/deploy/settings/libraries.ts +7 -10
  178. package/src/deploy/targets/flatpak-source.ts +33 -10
  179. package/src/deploy/tools.ts +36 -3
  180. package/src/dev/locale-dir.ts +22 -0
  181. package/src/dev/runner-main.ts +4 -1
  182. package/src/dev/runner.ts +8 -0
  183. package/src/dev/vite-dev-server.ts +1 -0
  184. package/src/i18n/binding-extractor.ts +1969 -0
  185. package/src/i18n/catalog-template.ts +24 -0
  186. package/src/i18n/catalogs.ts +216 -0
  187. package/src/i18n/extractor-plugin.ts +413 -0
  188. package/src/i18n/metadata-templates.ts +29 -0
  189. package/src/i18n/source-messages.ts +608 -0
  190. package/src/i18n/types.ts +154 -0
  191. package/src/internal/agent-rules.ts +135 -0
  192. package/src/internal/docs-elements.ts +21 -0
  193. package/src/internal/source-imports.ts +31 -60
  194. package/src/mcp/client-config.ts +130 -0
  195. package/src/mcp/client.ts +17 -44
  196. package/src/mcp/handlers.ts +7 -6
  197. package/src/settings/render.ts +16 -2
  198. package/src/settings/schema.ts +3 -1
  199. package/src/vite-plugins/animated.ts +486 -0
  200. package/src/vite-plugins/asset-imports.ts +5 -17
  201. package/src/vite-plugins/i18n.ts +146 -0
  202. package/src/vite-plugins/index.ts +5 -0
  203. package/src/vite-plugins/resources.ts +12 -74
  204. package/src/vite-plugins/self-contained.ts +150 -169
  205. package/src/vite-plugins/settings-worker-env.ts +2 -2
  206. package/src/vite-plugins/settings.ts +2 -1
@@ -1,10 +1,7 @@
1
- import type { Plugin } from "vite";
2
- import { isRecord } from "@gtkx/utils";
1
+ import type { ESTree, Plugin, VisitorObject } from "vite";
3
2
  import { isBuiltin } from "node:module";
4
3
  import { posix } from "node:path";
5
- import { parseSync } from "vite";
6
-
7
- type AstNode = Record<string, unknown>;
4
+ import { parseSync, Visitor } from "vite";
8
5
 
9
6
  type Bindings = {
10
7
  declarations: Map<string, number>;
@@ -15,7 +12,7 @@ type Bindings = {
15
12
 
16
13
  type Scan = {
17
14
  bindings: Bindings;
18
- calls: AstNode[];
15
+ calls: ESTree.CallExpression[];
19
16
  sources: string[];
20
17
  };
21
18
 
@@ -24,133 +21,144 @@ type Chunk = {
24
21
  code: string;
25
22
  };
26
23
 
24
+ type PatternItem =
25
+ | ESTree.BindingPattern |
26
+ ESTree.BindingProperty |
27
+ ESTree.BindingRestElement |
28
+ ESTree.FormalParameterRest |
29
+ ESTree.TSParameterProperty |
30
+ null;
31
+
27
32
  const REQUIRE_FACTORY = "createRequire";
28
33
  const REQUIRE_BINDING = "require";
29
34
  const RESOLVE_PROPERTY = "resolve";
30
35
  const MODULE_BUILTIN = "node:module";
31
36
  const OUTPUT_DIRECTORY = ".";
32
37
  const RELATIVE_SPECIFIER = /^\.\.?(?:\/|$)/;
33
- const DECLARATION_KEYS = ["id", "local", "param", "params"];
34
-
35
- const SOURCE_STATEMENTS = new Set([
36
- "ExportAllDeclaration",
37
- "ExportNamedDeclaration",
38
- "ImportDeclaration",
39
- "ImportExpression",
40
- ]);
41
-
42
- const isAstNode = (value: unknown): value is AstNode => isRecord(value) && typeof value.type === "string";
43
- const nodeType = (node: AstNode): string => (typeof node.type === "string" ? node.type : "");
44
-
45
- const nodeName = (node: AstNode | null): string | null =>
46
- node !== null && typeof node.name === "string" ? node.name : null;
47
38
 
48
- const childNode = (node: AstNode, key: string): AstNode | null => {
49
- const value = node[key];
39
+ const exportName = (name: ESTree.ModuleExportName): string | null => (name.type === "Identifier" ? name.name : null);
40
+ const referenceName = (node: ESTree.Argument): string | null => (node.type === "Identifier" ? node.name : null);
50
41
 
51
- return isAstNode(value) ? value : null;
52
- };
53
-
54
- const childNodes = (node: AstNode, key: string): AstNode[] => {
55
- const value = node[key];
56
-
57
- if (!Array.isArray(value)) {
58
- return [];
42
+ const countName = (declarations: Map<string, number>, name: string | null): void => {
43
+ if (name !== null) {
44
+ declarations.set(name, (declarations.get(name) ?? 0) + 1);
59
45
  }
60
-
61
- const entries: unknown[] = value;
62
-
63
- return entries.filter(isAstNode);
64
46
  };
65
47
 
66
- const childValues = (value: unknown): unknown[] => {
67
- if (Array.isArray(value)) {
68
- const entries: unknown[] = value;
48
+ const boundPattern = (item: PatternItem): ESTree.BindingPattern | null => {
49
+ if (item === null) {
50
+ return null;
51
+ }
69
52
 
70
- return entries;
53
+ if (item.type === "Property") {
54
+ return item.value;
71
55
  }
72
56
 
73
- if (!isAstNode(value)) {
74
- return [];
57
+ if (item.type === "RestElement") {
58
+ return item.argument;
75
59
  }
76
60
 
77
- return Object.values(value).filter((child) => typeof child === "object" && child !== null);
61
+ return item.type === "TSParameterProperty" ? item.parameter : item;
78
62
  };
79
63
 
80
- const visitNode = (value: unknown, visit: (node: AstNode) => void): void => {
81
- if (isAstNode(value)) {
82
- visit(value);
64
+ const countPatterns = (declarations: Map<string, number>, items: PatternItem[]): void => {
65
+ for (const item of items) {
66
+ countPattern(declarations, boundPattern(item));
83
67
  }
84
68
  };
85
69
 
86
- const walk = (root: unknown, visit: (node: AstNode) => void): void => {
87
- const stack: unknown[] = [root];
70
+ const countPattern = (declarations: Map<string, number>, pattern: ESTree.BindingPattern | null): void => {
71
+ if (pattern === null) {
72
+ return;
73
+ }
88
74
 
89
- while (stack.length > 0) {
90
- const current = stack.pop();
91
- visitNode(current, visit);
75
+ if (pattern.type === "Identifier") {
76
+ countName(declarations, pattern.name);
92
77
 
93
- for (const value of childValues(current)) {
94
- stack.push(value);
95
- }
78
+ return;
96
79
  }
97
- };
98
80
 
99
- const countName = (declarations: Map<string, number>, node: AstNode): void => {
100
- const name = nodeName(node);
81
+ if (pattern.type === "AssignmentPattern") {
82
+ countPattern(declarations, pattern.left);
101
83
 
102
- if (name !== null) {
103
- declarations.set(name, (declarations.get(name) ?? 0) + 1);
84
+ return;
104
85
  }
86
+
87
+ countPatterns(declarations, pattern.type === "ObjectPattern" ? pattern.properties : pattern.elements);
105
88
  };
106
89
 
107
- const countDeclarations = (node: AstNode, declarations: Map<string, number>): void => {
108
- for (const key of DECLARATION_KEYS) {
109
- walk(node[key], (declared) => {
110
- countName(declarations, declared);
111
- });
112
- }
90
+ const countFunction = (
91
+ declarations: Map<string, number>,
92
+ node: ESTree.ArrowFunctionExpression | ESTree.Function,
93
+ ): void => {
94
+ countPattern(declarations, node.id);
95
+ countPatterns(declarations, node.params);
113
96
  };
114
97
 
115
- const isUnshadowed = (name: string, bindings: Bindings): boolean => (bindings.declarations.get(name) ?? 0) <= 1;
98
+ const declarationVisitor = (declarations: Map<string, number>): VisitorObject => ({
99
+ ArrowFunctionExpression: (node) => {
100
+ countFunction(declarations, node);
101
+ },
102
+ CatchClause: (node) => {
103
+ countPattern(declarations, node.param);
104
+ },
105
+ ClassDeclaration: (node) => {
106
+ countPattern(declarations, node.id);
107
+ },
108
+ ClassExpression: (node) => {
109
+ countPattern(declarations, node.id);
110
+ },
111
+ ExportSpecifier: (node) => {
112
+ countName(declarations, exportName(node.local));
113
+ },
114
+ FunctionDeclaration: (node) => {
115
+ countFunction(declarations, node);
116
+ },
117
+ FunctionExpression: (node) => {
118
+ countFunction(declarations, node);
119
+ },
120
+ ImportDefaultSpecifier: (node) => {
121
+ countPattern(declarations, node.local);
122
+ },
123
+ ImportNamespaceSpecifier: (node) => {
124
+ countPattern(declarations, node.local);
125
+ },
126
+ ImportSpecifier: (node) => {
127
+ countPattern(declarations, node.local);
128
+ },
129
+ VariableDeclarator: (node) => {
130
+ countPattern(declarations, node.id);
131
+ },
132
+ });
116
133
 
117
- const templateString = (node: AstNode): string | null => {
118
- if (childNodes(node, "expressions").length > 0) {
119
- return null;
120
- }
134
+ const isUnshadowed = (name: string, bindings: Bindings): boolean => (bindings.declarations.get(name) ?? 0) <= 1;
121
135
 
122
- const [quasi] = childNodes(node, "quasis");
123
- const value = quasi === undefined ? null : quasi.value;
136
+ const templateString = (node: ESTree.TemplateLiteral): string | null => {
137
+ const [quasi] = node.quasis;
124
138
 
125
- return isRecord(value) && typeof value.cooked === "string" ? value.cooked : null;
139
+ return quasi === undefined || node.expressions.length > 0 ? null : quasi.value.cooked;
126
140
  };
127
141
 
128
- const literalString = (node: AstNode | null): string | null => {
129
- if (node === null) {
130
- return null;
131
- }
132
-
133
- if (nodeType(node) === "Literal") {
134
- return typeof node.value === "string" ? node.value : null;
142
+ const literalString = (node: ESTree.Argument | null): string | null => {
143
+ if (node?.type === "TemplateLiteral") {
144
+ return templateString(node);
135
145
  }
136
146
 
137
- return nodeType(node) === "TemplateLiteral" ? templateString(node) : null;
147
+ return node?.type === "Literal" && typeof node.value === "string" ? node.value : null;
138
148
  };
139
149
 
140
- const isMetaUrl = (node: AstNode, bindings: Bindings): boolean => {
141
- if (nodeType(node) === "MemberExpression") {
142
- const object = childNode(node, "object");
143
-
144
- return object !== null && nodeType(object) === "MetaProperty";
150
+ const isMetaUrl = (node: ESTree.Argument, bindings: Bindings): boolean => {
151
+ if (node.type === "MemberExpression") {
152
+ return node.object.type === "MetaProperty";
145
153
  }
146
154
 
147
- const name = nodeName(node);
155
+ const name = referenceName(node);
148
156
 
149
157
  return name !== null && bindings.urls.has(name) && isUnshadowed(name, bindings);
150
158
  };
151
159
 
152
- const hasMetaUrl = (node: AstNode, bindings: Bindings): boolean =>
153
- childNodes(node, "arguments").some((argument) => isMetaUrl(argument, bindings));
160
+ const hasMetaUrl = (node: ESTree.CallExpression, bindings: Bindings): boolean =>
161
+ node.arguments.some((argument) => isMetaUrl(argument, bindings));
154
162
 
155
163
  const isRequireName = (name: string | null, bindings: Bindings): boolean =>
156
164
  name !== null && (name === REQUIRE_BINDING || bindings.requires.has(name)) && isUnshadowed(name, bindings);
@@ -158,116 +166,89 @@ const isRequireName = (name: string | null, bindings: Bindings): boolean =>
158
166
  const isFactoryName = (name: string | null, bindings: Bindings): boolean =>
159
167
  name !== null && (name === REQUIRE_FACTORY || bindings.factories.has(name)) && isUnshadowed(name, bindings);
160
168
 
161
- const isRequireFactory = (node: AstNode, bindings: Bindings): boolean => {
162
- if (nodeType(node) !== "CallExpression") {
163
- return false;
164
- }
165
-
166
- return isFactoryName(nodeName(childNode(node, "callee")), bindings) || hasMetaUrl(node, bindings);
167
- };
169
+ const isRequireFactory = (node: ESTree.Argument, bindings: Bindings): boolean =>
170
+ node.type === "CallExpression" &&
171
+ (isFactoryName(referenceName(node.callee), bindings) || hasMetaUrl(node, bindings));
168
172
 
169
- const isResolveTarget = (object: AstNode, bindings: Bindings): boolean =>
170
- nodeType(object) === "MetaProperty" ||
171
- isRequireName(nodeName(object), bindings) ||
173
+ const isResolveTarget = (object: ESTree.Expression, bindings: Bindings): boolean =>
174
+ object.type === "MetaProperty" ||
175
+ isRequireName(referenceName(object), bindings) ||
172
176
  isRequireFactory(object, bindings);
173
177
 
174
- const isResolveMember = (callee: AstNode, bindings: Bindings): boolean => {
175
- if (nodeType(callee) !== "MemberExpression" || callee.computed === true) {
176
- return false;
177
- }
178
-
179
- if (nodeName(childNode(callee, "property")) !== RESOLVE_PROPERTY) {
180
- return false;
181
- }
182
-
183
- const object = childNode(callee, "object");
184
-
185
- return object !== null && isResolveTarget(object, bindings);
186
- };
187
-
188
- const isResolvingCall = (call: AstNode, bindings: Bindings): boolean => {
189
- if (hasMetaUrl(call, bindings)) {
190
- return true;
191
- }
192
-
193
- const callee = childNode(call, "callee");
194
-
195
- if (callee === null) {
196
- return false;
197
- }
198
-
199
- return (
200
- isRequireName(nodeName(callee), bindings) ||
201
- isRequireFactory(callee, bindings) ||
202
- isResolveMember(callee, bindings)
203
- );
204
- };
205
-
206
- const collectFactories = (node: AstNode, bindings: Bindings): void => {
207
- if (literalString(childNode(node, "source")) !== MODULE_BUILTIN) {
178
+ const isResolveMember = (callee: ESTree.Expression, bindings: Bindings): boolean =>
179
+ callee.type === "MemberExpression" &&
180
+ !callee.computed &&
181
+ callee.property.type === "Identifier" &&
182
+ callee.property.name === RESOLVE_PROPERTY &&
183
+ isResolveTarget(callee.object, bindings);
184
+
185
+ const isResolvingCall = (call: ESTree.CallExpression, bindings: Bindings): boolean =>
186
+ hasMetaUrl(call, bindings) ||
187
+ isRequireName(referenceName(call.callee), bindings) ||
188
+ isRequireFactory(call.callee, bindings) ||
189
+ isResolveMember(call.callee, bindings);
190
+
191
+ const collectFactories = (node: ESTree.ImportDeclaration, bindings: Bindings): void => {
192
+ if (node.source.value !== MODULE_BUILTIN) {
208
193
  return;
209
194
  }
210
195
 
211
- for (const specifier of childNodes(node, "specifiers")) {
212
- const local = nodeName(childNode(specifier, "local"));
213
-
214
- if (local !== null && nodeName(childNode(specifier, "imported")) === REQUIRE_FACTORY) {
215
- bindings.factories.add(local);
196
+ for (const specifier of node.specifiers) {
197
+ if (specifier.type === "ImportSpecifier" && exportName(specifier.imported) === REQUIRE_FACTORY) {
198
+ bindings.factories.add(specifier.local.name);
216
199
  }
217
200
  }
218
201
  };
219
202
 
220
- const collectBinding = (node: AstNode, bindings: Bindings): void => {
221
- const name = nodeName(childNode(node, "id"));
222
- const init = childNode(node, "init");
203
+ const collectBinding = (node: ESTree.VariableDeclarator, bindings: Bindings): void => {
204
+ const { id, init } = node;
223
205
 
224
- if (name === null || init === null) {
206
+ if (init === null || id.type !== "Identifier") {
225
207
  return;
226
208
  }
227
209
 
228
210
  if (isMetaUrl(init, bindings)) {
229
- bindings.urls.add(name);
211
+ bindings.urls.add(id.name);
230
212
  }
231
213
 
232
214
  if (isRequireFactory(init, bindings)) {
233
- bindings.requires.add(name);
215
+ bindings.requires.add(id.name);
234
216
  }
235
217
  };
236
218
 
237
- const hasStringArgument = (call: AstNode): boolean =>
238
- childNodes(call, "arguments").some((argument) => literalString(argument) !== null);
239
-
240
- const collectSource = (scan: Scan, node: AstNode, type: string): void => {
241
- if (!SOURCE_STATEMENTS.has(type)) {
242
- return;
243
- }
244
-
245
- const source = literalString(childNode(node, "source"));
246
-
219
+ const collectSource = (scan: Scan, source: string | null): void => {
247
220
  if (source !== null) {
248
221
  scan.sources.push(source);
249
222
  }
250
223
  };
251
224
 
252
- const collectCall = (scan: Scan, node: AstNode, type: string): void => {
253
- if (type === "CallExpression" && hasStringArgument(node)) {
225
+ const collectCall = (scan: Scan, node: ESTree.CallExpression): void => {
226
+ if (node.arguments.some((argument) => literalString(argument) !== null)) {
254
227
  scan.calls.push(node);
255
228
  }
256
229
  };
257
230
 
258
- const scanNode = (scan: Scan, node: AstNode): void => {
259
- const type = nodeType(node);
260
- countDeclarations(node, scan.bindings.declarations);
261
-
262
- if (type === "ImportDeclaration") {
231
+ const scanVisitor = (scan: Scan): VisitorObject => ({
232
+ CallExpression: (node) => {
233
+ collectCall(scan, node);
234
+ },
235
+ ExportAllDeclaration: (node) => {
236
+ collectSource(scan, node.source.value);
237
+ },
238
+ ExportNamedDeclaration: (node) => {
239
+ collectSource(scan, node.source?.value ?? null);
240
+ },
241
+ ImportDeclaration: (node) => {
263
242
  collectFactories(node, scan.bindings);
264
- } else if (type === "VariableDeclarator") {
243
+ collectSource(scan, node.source.value);
244
+ },
245
+ ImportExpression: (node) => {
246
+ collectSource(scan, literalString(node.source));
247
+ },
248
+ VariableDeclarator: (node) => {
265
249
  collectBinding(node, scan.bindings);
266
- }
267
-
268
- collectSource(scan, node, type);
269
- collectCall(scan, node, type);
270
- };
250
+ },
251
+ });
271
252
 
272
253
  const scanChunk = (chunk: Chunk): Scan => {
273
254
  const scan: Scan = {
@@ -276,9 +257,9 @@ const scanChunk = (chunk: Chunk): Scan => {
276
257
  sources: [],
277
258
  };
278
259
 
279
- walk(parseSync(chunk.fileName, chunk.code).program, (node) => {
280
- scanNode(scan, node);
281
- });
260
+ const { program } = parseSync(chunk.fileName, chunk.code);
261
+ new Visitor(declarationVisitor(scan.bindings.declarations)).visit(program);
262
+ new Visitor(scanVisitor(scan)).visit(program);
282
263
 
283
264
  return scan;
284
265
  };
@@ -286,7 +267,7 @@ const scanChunk = (chunk: Chunk): Scan => {
286
267
  const callSpecifiers = (scan: Scan): string[] =>
287
268
  scan.calls
288
269
  .filter((call) => isResolvingCall(call, scan.bindings))
289
- .flatMap((call) => childNodes(call, "arguments"))
270
+ .flatMap((call) => call.arguments)
290
271
  .map((argument) => literalString(argument))
291
272
  .filter((specifier) => specifier !== null);
292
273
 
@@ -1,6 +1,6 @@
1
1
  import type { UserConfig } from "vite";
2
2
  import type { Plugin } from "vitest/config";
3
- import { createConfigLoader } from "@gtkx/config/internal";
3
+ import { createConfigLoader, resolveFuture } from "@gtkx/config/internal";
4
4
  import { resolveDataDir } from "../internal/data-dir.js";
5
5
  import { prependSchemaDir, stageAndCompileProjectSchemas } from "../settings/schema.js";
6
6
 
@@ -13,7 +13,7 @@ function gtkxSettingsWorkerEnv(): Plugin {
13
13
 
14
14
  async config(config: UserConfig) {
15
15
  const loaded = await loadConfig.load(config.root ?? process.cwd());
16
- const dataDir = loaded.config.future?.v2ResourceImports === true ? null : resolveDataDir(loaded.root);
16
+ const dataDir = resolveFuture(loaded.config.future).isResourceImported ? null : resolveDataDir(loaded.root);
17
17
  const dir = stageAndCompileProjectSchemas(loaded.root, dataDir);
18
18
 
19
19
  if (dir === null) {
@@ -1,5 +1,6 @@
1
1
  import type { ConfigLoader } from "@gtkx/config";
2
2
  import type { ModuleNode, Plugin, ResolvedConfig, UserConfig, ViteDevServer } from "vite";
3
+ import { resolveFuture } from "@gtkx/config/internal";
3
4
  import { error, errorMessage, info, sortStrings } from "@gtkx/utils";
4
5
  import { readFileSync } from "node:fs";
5
6
  import { basename, join } from "node:path";
@@ -106,7 +107,7 @@ const scheduleSchemaEnvSync = (state: PluginState): void => {
106
107
 
107
108
  const applyUserConfig = async (state: PluginState, config: UserConfig, loadConfig: ConfigLoader): Promise<void> => {
108
109
  const loaded = await loadConfig.load(config.root ?? process.cwd());
109
- state.isV2ResourceImports = loaded.config.future?.v2ResourceImports === true;
110
+ state.isV2ResourceImports = resolveFuture(loaded.config.future).isResourceImported;
110
111
  state.dataDir = state.isV2ResourceImports ? null : resolveDataDir(loaded.root);
111
112
  };
112
113