@fluixi/compiler 1.0.0-alpha.91 → 1.0.0-alpha.93
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.
- package/dist/analyze/intrinsics.cjs +21 -1
- package/dist/analyze/intrinsics.d.ts.map +1 -1
- package/dist/analyze/intrinsics.js +20 -0
- package/dist/analyze/intrinsics.mjs +21 -1
- package/dist/analyze/reactive-bindings.cjs +21 -1
- package/dist/analyze/reactive-bindings.mjs +21 -1
- package/dist/analyze/static-graph.cjs +25 -5
- package/dist/analyze/static-graph.d.ts.map +1 -1
- package/dist/analyze/static-graph.js +6 -4
- package/dist/analyze/static-graph.mjs +25 -5
- package/dist/{babel-VBLQRHQ2.mjs → babel-RJHJQVEM.mjs} +4 -4
- package/dist/{chunk-D53J7ICY.mjs → chunk-56QSOVVL.mjs} +1 -1
- package/dist/{chunk-S4J4OCWK.mjs → chunk-OD53TMER.mjs} +22 -2
- package/dist/{chunk-TWDJUXWZ.mjs → chunk-R7PPFBCL.mjs} +1 -1
- package/dist/{chunk-QX6Y3OAR.mjs → chunk-TJIH7TLX.mjs} +1 -1
- package/dist/{chunk-3JWMCK4A.mjs → chunk-U7HCFLZ2.mjs} +153 -48
- package/dist/codegen/backends/imperative.cjs +27 -7
- package/dist/codegen/backends/imperative.d.ts.map +1 -1
- package/dist/codegen/backends/imperative.js +19 -4
- package/dist/codegen/backends/imperative.mjs +27 -7
- package/dist/frontend/babel/build-ir-lit.cjs +123 -44
- package/dist/frontend/babel/build-ir-lit.mjs +123 -44
- package/dist/frontend/babel/build-ir.cjs +123 -44
- package/dist/frontend/babel/build-ir.mjs +123 -44
- package/dist/frontend/babel/index.cjs +124 -45
- package/dist/frontend/babel/index.mjs +124 -45
- package/dist/frontend/babel/lower-template.cjs +123 -44
- package/dist/frontend/babel/lower-template.mjs +123 -44
- package/dist/frontend/babel/plugin.cjs +123 -44
- package/dist/frontend/babel/plugin.mjs +123 -44
- package/dist/index.cjs +86 -46
- package/dist/index.mjs +88 -48
- package/dist/integrations.cjs +246 -61
- package/dist/integrations.mjs +53 -19
- package/dist/lower/compile-template.cjs +44 -39
- package/dist/lower/compile-template.mjs +44 -39
- package/dist/lower/jsx.cjs +509 -6
- package/dist/lower/jsx.d.ts.map +1 -1
- package/dist/lower/jsx.js +114 -6
- package/dist/lower/jsx.mjs +509 -6
- package/dist/lower/template.cjs +43 -38
- package/dist/lower/template.d.ts.map +1 -1
- package/dist/lower/template.js +22 -30
- package/dist/lower/template.mjs +43 -38
- package/dist/resolve/builtins.cjs +1 -1
- package/dist/resolve/builtins.mjs +1 -1
- package/dist/resolve/component-globals.cjs +33 -8
- package/dist/resolve/component-globals.d.cts +8 -0
- package/dist/resolve/component-globals.d.ts +8 -0
- package/dist/resolve/component-globals.d.ts.map +1 -1
- package/dist/resolve/component-globals.js +21 -12
- package/dist/resolve/component-globals.mjs +33 -8
- package/dist/resolve/write-globals.cjs +59 -8
- package/dist/resolve/write-globals.d.cts +6 -0
- package/dist/resolve/write-globals.d.ts +6 -0
- package/dist/resolve/write-globals.d.ts.map +1 -1
- package/dist/resolve/write-globals.js +35 -2
- package/dist/resolve/write-globals.mjs +61 -10
- package/dist/{server-fns-J56G3PFP.mjs → server-fns-ZFRDIQ2X.mjs} +4 -4
- package/dist/{server-functions-7PUFLRGF.mjs → server-functions-CTDXX67X.mjs} +3 -3
- package/dist/transform/index.cjs +199 -49
- package/dist/transform/index.mjs +199 -49
- package/dist/transform/intrinsics.cjs +47 -2
- package/dist/transform/intrinsics.d.cts +12 -0
- package/dist/transform/intrinsics.d.ts +12 -0
- package/dist/transform/intrinsics.d.ts.map +1 -1
- package/dist/transform/intrinsics.js +43 -1
- package/dist/transform/intrinsics.mjs +47 -2
- package/dist/transform/source-locations.cjs +67 -4
- package/dist/transform/source-locations.d.cts +7 -2
- package/dist/transform/source-locations.d.ts +7 -2
- package/dist/transform/source-locations.d.ts.map +1 -1
- package/dist/transform/source-locations.js +68 -3
- package/dist/transform/source-locations.mjs +67 -4
- package/dist/transform/templates.cjs +198 -48
- package/dist/transform/templates.d.ts.map +1 -1
- package/dist/transform/templates.js +5 -3
- package/dist/transform/templates.mjs +198 -48
- package/dist/{transform-D536WXGM.mjs → transform-QWWQDCXE.mjs} +33 -8
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +9 -3
|
@@ -98,6 +98,7 @@ var INTRINSICS = {
|
|
|
98
98
|
$effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
|
|
99
99
|
$store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
|
|
100
100
|
$resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
|
|
101
|
+
$cachedResource: { export: "cachedResource", module: "@fluixi/reactive/cached-resource", returns: "resource-handle" },
|
|
101
102
|
// No short runtime form for these yet, so the intrinsic stands for the `create*`
|
|
102
103
|
// name. Still worth having: no import to write, and when a shorter form is
|
|
103
104
|
// designed, the change is this line rather than a compiler pass.
|
|
@@ -107,7 +108,22 @@ var INTRINSICS = {
|
|
|
107
108
|
// does. `untrack` suppresses dependency collection, which is exactly the kind of thing
|
|
108
109
|
// dependency analysis must not guess at.
|
|
109
110
|
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
110
|
-
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" }
|
|
111
|
+
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
|
|
112
|
+
// Scopes, scheduling and lifecycle: no value to classify, but the same authoring promise,
|
|
113
|
+
// no import to write. `$cleanup` registers a callback on the current owner (`onCleanup`).
|
|
114
|
+
$batch: { export: "batch", module: REACTIVE_MODULE, returns: "plain" },
|
|
115
|
+
$cleanup: { export: "onCleanup", module: REACTIVE_MODULE, returns: "plain" },
|
|
116
|
+
$root: { export: "root", module: REACTIVE_MODULE, returns: "plain" },
|
|
117
|
+
$context: { export: "context", module: REACTIVE_MODULE, returns: "plain" },
|
|
118
|
+
$renderEffect: { export: "renderEffect", module: REACTIVE_MODULE, returns: "effect" },
|
|
119
|
+
$computed: { export: "computed", module: REACTIVE_MODULE, returns: "effect" },
|
|
120
|
+
// Storage for where the code runs, and a signal kept in it. `$persisted` is a signal
|
|
121
|
+
// handle as far as reads go: the same accessor with `set` on it.
|
|
122
|
+
$storage: { export: "useStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
123
|
+
$asyncStorage: { export: "useAsyncStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
124
|
+
$persisted: { export: "persisted", module: "@fluixi/core/storage", returns: "signal-handle" },
|
|
125
|
+
// An environment variable, public or server-only; the browser build refuses a secret.
|
|
126
|
+
$env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
|
|
111
127
|
};
|
|
112
128
|
var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
|
|
113
129
|
|
|
@@ -149,7 +165,8 @@ function componentGlobals(rules, options = {}) {
|
|
|
149
165
|
builtins = true,
|
|
150
166
|
intrinsics = true,
|
|
151
167
|
generator = "@fluixi/compiler",
|
|
152
|
-
specifier = (module) => module
|
|
168
|
+
specifier = (module) => module,
|
|
169
|
+
candidates = []
|
|
153
170
|
} = options;
|
|
154
171
|
const all = [...rules];
|
|
155
172
|
if (builtins) {
|
|
@@ -161,7 +178,8 @@ function componentGlobals(rules, options = {}) {
|
|
|
161
178
|
const shadowedByDom = [];
|
|
162
179
|
const unavailable = [];
|
|
163
180
|
const resolved = /* @__PURE__ */ new Map();
|
|
164
|
-
|
|
181
|
+
const names = /* @__PURE__ */ new Set([...resolver.names(), ...[...candidates].filter((n) => /^[A-Za-z_$][\w$]*$/.test(n))]);
|
|
182
|
+
for (const name of [...names].sort()) {
|
|
165
183
|
const target = resolver.resolve(name);
|
|
166
184
|
if (!target) continue;
|
|
167
185
|
const pkg = packageOf(target.module);
|
|
@@ -172,7 +190,11 @@ function componentGlobals(rules, options = {}) {
|
|
|
172
190
|
resolved.set(name, target);
|
|
173
191
|
}
|
|
174
192
|
}
|
|
175
|
-
const
|
|
193
|
+
const usableIntrinsics = intrinsics ? Object.entries(INTRINSICS).filter(([, i]) => {
|
|
194
|
+
const pkg = packageOf(i.module);
|
|
195
|
+
return !available || !pkg || available.has(pkg);
|
|
196
|
+
}) : [];
|
|
197
|
+
const intrinsicModules = [...new Set(usableIntrinsics.map(([, i]) => i.module))];
|
|
176
198
|
const modules = [
|
|
177
199
|
.../* @__PURE__ */ new Set([...declared.map((name) => resolved.get(name).module), ...intrinsicModules])
|
|
178
200
|
].sort();
|
|
@@ -192,15 +214,18 @@ function componentGlobals(rules, options = {}) {
|
|
|
192
214
|
return `// import { ${n} } from '${module ? specifier(module) : ""}';
|
|
193
215
|
`;
|
|
194
216
|
}).join("") : "";
|
|
195
|
-
const intrinsicLines =
|
|
217
|
+
const intrinsicLines = usableIntrinsics.map(
|
|
196
218
|
([name, intrinsic]) => ` const ${name}: typeof ${namespaceAlias(intrinsic.module)}.${intrinsic.export};`
|
|
197
|
-
)
|
|
219
|
+
);
|
|
198
220
|
const patternRules = rules.filter((rule) => "match" in rule).length;
|
|
199
|
-
const patternNote = patternRules
|
|
221
|
+
const patternNote = patternRules === 0 ? "" : options.candidates ? `//
|
|
222
|
+
// ${patternRules} pattern rule${patternRules === 1 ? "" : "s"}: declared for the files the module path
|
|
223
|
+
// points at. A name with no such file still resolves at build time; declare it by hand.
|
|
224
|
+
` : `//
|
|
200
225
|
// ${patternRules} pattern rule${patternRules === 1 ? "" : "s"} cannot be declared:
|
|
201
226
|
// a pattern matches unboundedly many names, so there is no list to emit. Those
|
|
202
227
|
// tags still resolve at build time; declare them by hand if the editor needs them.
|
|
203
|
-
|
|
228
|
+
`;
|
|
204
229
|
const source = `// GENERATED by ${generator}, do not edit.
|
|
205
230
|
//
|
|
206
231
|
// The components \`resolve\` supplies without an import. This describes what the
|
|
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var write_globals_exports = {};
|
|
22
22
|
__export(write_globals_exports, {
|
|
23
23
|
DEFAULT_GLOBALS_PATH: () => DEFAULT_GLOBALS_PATH,
|
|
24
|
+
patternCandidates: () => patternCandidates,
|
|
24
25
|
writeComponentGlobals: () => writeComponentGlobals
|
|
25
26
|
});
|
|
26
27
|
module.exports = __toCommonJS(write_globals_exports);
|
|
@@ -127,6 +128,7 @@ var INTRINSICS = {
|
|
|
127
128
|
$effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
|
|
128
129
|
$store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
|
|
129
130
|
$resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
|
|
131
|
+
$cachedResource: { export: "cachedResource", module: "@fluixi/reactive/cached-resource", returns: "resource-handle" },
|
|
130
132
|
// No short runtime form for these yet, so the intrinsic stands for the `create*`
|
|
131
133
|
// name. Still worth having: no import to write, and when a shorter form is
|
|
132
134
|
// designed, the change is this line rather than a compiler pass.
|
|
@@ -136,7 +138,22 @@ var INTRINSICS = {
|
|
|
136
138
|
// does. `untrack` suppresses dependency collection, which is exactly the kind of thing
|
|
137
139
|
// dependency analysis must not guess at.
|
|
138
140
|
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
139
|
-
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" }
|
|
141
|
+
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
|
|
142
|
+
// Scopes, scheduling and lifecycle: no value to classify, but the same authoring promise,
|
|
143
|
+
// no import to write. `$cleanup` registers a callback on the current owner (`onCleanup`).
|
|
144
|
+
$batch: { export: "batch", module: REACTIVE_MODULE, returns: "plain" },
|
|
145
|
+
$cleanup: { export: "onCleanup", module: REACTIVE_MODULE, returns: "plain" },
|
|
146
|
+
$root: { export: "root", module: REACTIVE_MODULE, returns: "plain" },
|
|
147
|
+
$context: { export: "context", module: REACTIVE_MODULE, returns: "plain" },
|
|
148
|
+
$renderEffect: { export: "renderEffect", module: REACTIVE_MODULE, returns: "effect" },
|
|
149
|
+
$computed: { export: "computed", module: REACTIVE_MODULE, returns: "effect" },
|
|
150
|
+
// Storage for where the code runs, and a signal kept in it. `$persisted` is a signal
|
|
151
|
+
// handle as far as reads go: the same accessor with `set` on it.
|
|
152
|
+
$storage: { export: "useStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
153
|
+
$asyncStorage: { export: "useAsyncStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
154
|
+
$persisted: { export: "persisted", module: "@fluixi/core/storage", returns: "signal-handle" },
|
|
155
|
+
// An environment variable, public or server-only; the browser build refuses a secret.
|
|
156
|
+
$env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
|
|
140
157
|
};
|
|
141
158
|
var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
|
|
142
159
|
|
|
@@ -178,7 +195,8 @@ function componentGlobals(rules, options = {}) {
|
|
|
178
195
|
builtins = true,
|
|
179
196
|
intrinsics = true,
|
|
180
197
|
generator = "@fluixi/compiler",
|
|
181
|
-
specifier = (module2) => module2
|
|
198
|
+
specifier = (module2) => module2,
|
|
199
|
+
candidates = []
|
|
182
200
|
} = options;
|
|
183
201
|
const all = [...rules];
|
|
184
202
|
if (builtins) {
|
|
@@ -190,7 +208,8 @@ function componentGlobals(rules, options = {}) {
|
|
|
190
208
|
const shadowedByDom = [];
|
|
191
209
|
const unavailable = [];
|
|
192
210
|
const resolved = /* @__PURE__ */ new Map();
|
|
193
|
-
|
|
211
|
+
const names = /* @__PURE__ */ new Set([...resolver.names(), ...[...candidates].filter((n) => /^[A-Za-z_$][\w$]*$/.test(n))]);
|
|
212
|
+
for (const name of [...names].sort()) {
|
|
194
213
|
const target = resolver.resolve(name);
|
|
195
214
|
if (!target) continue;
|
|
196
215
|
const pkg = packageOf(target.module);
|
|
@@ -201,7 +220,11 @@ function componentGlobals(rules, options = {}) {
|
|
|
201
220
|
resolved.set(name, target);
|
|
202
221
|
}
|
|
203
222
|
}
|
|
204
|
-
const
|
|
223
|
+
const usableIntrinsics = intrinsics ? Object.entries(INTRINSICS).filter(([, i]) => {
|
|
224
|
+
const pkg = packageOf(i.module);
|
|
225
|
+
return !available || !pkg || available.has(pkg);
|
|
226
|
+
}) : [];
|
|
227
|
+
const intrinsicModules = [...new Set(usableIntrinsics.map(([, i]) => i.module))];
|
|
205
228
|
const modules = [
|
|
206
229
|
.../* @__PURE__ */ new Set([...declared.map((name) => resolved.get(name).module), ...intrinsicModules])
|
|
207
230
|
].sort();
|
|
@@ -221,15 +244,18 @@ function componentGlobals(rules, options = {}) {
|
|
|
221
244
|
return `// import { ${n} } from '${module2 ? specifier(module2) : ""}';
|
|
222
245
|
`;
|
|
223
246
|
}).join("") : "";
|
|
224
|
-
const intrinsicLines =
|
|
247
|
+
const intrinsicLines = usableIntrinsics.map(
|
|
225
248
|
([name, intrinsic]) => ` const ${name}: typeof ${namespaceAlias(intrinsic.module)}.${intrinsic.export};`
|
|
226
|
-
)
|
|
249
|
+
);
|
|
227
250
|
const patternRules = rules.filter((rule) => "match" in rule).length;
|
|
228
|
-
const patternNote = patternRules
|
|
251
|
+
const patternNote = patternRules === 0 ? "" : options.candidates ? `//
|
|
252
|
+
// ${patternRules} pattern rule${patternRules === 1 ? "" : "s"}: declared for the files the module path
|
|
253
|
+
// points at. A name with no such file still resolves at build time; declare it by hand.
|
|
254
|
+
` : `//
|
|
229
255
|
// ${patternRules} pattern rule${patternRules === 1 ? "" : "s"} cannot be declared:
|
|
230
256
|
// a pattern matches unboundedly many names, so there is no list to emit. Those
|
|
231
257
|
// tags still resolve at build time; declare them by hand if the editor needs them.
|
|
232
|
-
|
|
258
|
+
`;
|
|
233
259
|
const source = `// GENERATED by ${generator}, do not edit.
|
|
234
260
|
//
|
|
235
261
|
// The components \`resolve\` supplies without an import. This describes what the
|
|
@@ -286,6 +312,30 @@ function projectDependencies(root) {
|
|
|
286
312
|
return void 0;
|
|
287
313
|
}
|
|
288
314
|
}
|
|
315
|
+
function patternCandidates(rules, root) {
|
|
316
|
+
const out = [];
|
|
317
|
+
for (const rule of rules) {
|
|
318
|
+
if (!("match" in rule) || !rule.module.startsWith("/")) continue;
|
|
319
|
+
const dir = (0, import_node_path.dirname)(rule.module);
|
|
320
|
+
const file = (0, import_node_path.basename)(rule.module);
|
|
321
|
+
const group = file.match(/\$\d+/);
|
|
322
|
+
if (dir.includes("$") || !group || file.indexOf("$", group.index + 1) !== -1) continue;
|
|
323
|
+
const before = file.slice(0, group.index);
|
|
324
|
+
const after = file.slice(group.index + group[0].length);
|
|
325
|
+
let entries;
|
|
326
|
+
try {
|
|
327
|
+
entries = (0, import_node_fs.readdirSync)((0, import_node_path.resolve)(root, dir.slice(1)));
|
|
328
|
+
} catch {
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
for (const entry of entries) {
|
|
332
|
+
if (entry.length > before.length + after.length && entry.startsWith(before) && entry.endsWith(after)) {
|
|
333
|
+
out.push(entry.slice(before.length, entry.length - after.length));
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
return out;
|
|
338
|
+
}
|
|
289
339
|
function writeComponentGlobals(options, root) {
|
|
290
340
|
if (options.globals === false) return { status: "skipped", reason: "disabled" };
|
|
291
341
|
const rules = options.resolve ?? [];
|
|
@@ -301,6 +351,7 @@ function writeComponentGlobals(options, root) {
|
|
|
301
351
|
}
|
|
302
352
|
const { source, declared } = componentGlobals(rules, {
|
|
303
353
|
available: projectDependencies(root),
|
|
354
|
+
candidates: patternCandidates(rules, root),
|
|
304
355
|
specifier: (module2) => forTypeScript(module2, (0, import_node_path.dirname)(target), root)
|
|
305
356
|
});
|
|
306
357
|
if (existing === source) {
|
|
@@ -26,5 +26,11 @@ export type WriteGlobalsOutcome = ({
|
|
|
26
26
|
*/
|
|
27
27
|
warning?: string;
|
|
28
28
|
};
|
|
29
|
+
/**
|
|
30
|
+
* Names from the files a pattern rule points at: `/src/components/$1.tsx` lists
|
|
31
|
+
* `src/components` and offers each `X` for `X.tsx`. Only a project path with the group in
|
|
32
|
+
* the file name; the resolver still decides whether a name matches.
|
|
33
|
+
*/
|
|
34
|
+
export declare function patternCandidates(rules: readonly ComponentResolverRule[], root: string): string[];
|
|
29
35
|
/** Generate and write the declarations for `root`, returning what was done. */
|
|
30
36
|
export declare function writeComponentGlobals(options: WriteGlobalsOptions, root: string): WriteGlobalsOutcome;
|
|
@@ -26,6 +26,12 @@ export type WriteGlobalsOutcome = ({
|
|
|
26
26
|
*/
|
|
27
27
|
warning?: string;
|
|
28
28
|
};
|
|
29
|
+
/**
|
|
30
|
+
* Names from the files a pattern rule points at: `/src/components/$1.tsx` lists
|
|
31
|
+
* `src/components` and offers each `X` for `X.tsx`. Only a project path with the group in
|
|
32
|
+
* the file name; the resolver still decides whether a name matches.
|
|
33
|
+
*/
|
|
34
|
+
export declare function patternCandidates(rules: readonly ComponentResolverRule[], root: string): string[];
|
|
29
35
|
/** Generate and write the declarations for `root`, returning what was done. */
|
|
30
36
|
export declare function writeComponentGlobals(options: WriteGlobalsOptions, root: string): WriteGlobalsOutcome;
|
|
31
37
|
//# sourceMappingURL=write-globals.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write-globals.d.ts","sourceRoot":"","sources":["../../src/resolve/write-globals.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAKrE,eAAO,MAAM,oBAAoB,gBAAgB,CAAC;AAElD,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,SAAS,qBAAqB,EAAE,CAAC;IAC3C,OAAO,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;CAC1B;AAED,MAAM,MAAM,mBAAmB,GAAG,CAC9B;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACrD;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,UAAU,GAAG,cAAc,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAC5E,GAAG;IACF;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AA2EF,+EAA+E;AAC/E,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,mBAAmB,EAC5B,IAAI,EAAE,MAAM,GACX,mBAAmB,
|
|
1
|
+
{"version":3,"file":"write-globals.d.ts","sourceRoot":"","sources":["../../src/resolve/write-globals.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAKrE,eAAO,MAAM,oBAAoB,gBAAgB,CAAC;AAElD,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,SAAS,qBAAqB,EAAE,CAAC;IAC3C,OAAO,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;CAC1B;AAED,MAAM,MAAM,mBAAmB,GAAG,CAC9B;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACrD;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,UAAU,GAAG,cAAc,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAC5E,GAAG;IACF;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AA2EF;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,qBAAqB,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAuBjG;AAED,+EAA+E;AAC/E,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,mBAAmB,EAC5B,IAAI,EAAE,MAAM,GACX,mBAAmB,CAyCrB"}
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
* - **Only declare what the project can resolve.** Dependencies come from its manifest,
|
|
13
13
|
* so a component from an uninstalled package is skipped rather than degraded to `any`.
|
|
14
14
|
*/
|
|
15
|
-
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
16
|
-
import { dirname, relative, sep, resolve as resolvePath } from 'node:path';
|
|
15
|
+
import { mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
16
|
+
import { basename, dirname, relative, sep, resolve as resolvePath } from 'node:path';
|
|
17
17
|
import { componentGlobals } from './component-globals.js';
|
|
18
18
|
/** The marker every generated file carries, used to tell ours from a hand-written one. */
|
|
19
19
|
const GENERATED_MARKER = 'GENERATED by @fluixi/compiler';
|
|
@@ -88,6 +88,38 @@ function projectDependencies(root) {
|
|
|
88
88
|
return undefined;
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Names from the files a pattern rule points at: `/src/components/$1.tsx` lists
|
|
93
|
+
* `src/components` and offers each `X` for `X.tsx`. Only a project path with the group in
|
|
94
|
+
* the file name; the resolver still decides whether a name matches.
|
|
95
|
+
*/
|
|
96
|
+
export function patternCandidates(rules, root) {
|
|
97
|
+
const out = [];
|
|
98
|
+
for (const rule of rules) {
|
|
99
|
+
if (!('match' in rule) || !rule.module.startsWith('/'))
|
|
100
|
+
continue;
|
|
101
|
+
const dir = dirname(rule.module);
|
|
102
|
+
const file = basename(rule.module);
|
|
103
|
+
const group = file.match(/\$\d+/);
|
|
104
|
+
if (dir.includes('$') || !group || file.indexOf('$', group.index + 1) !== -1)
|
|
105
|
+
continue;
|
|
106
|
+
const before = file.slice(0, group.index);
|
|
107
|
+
const after = file.slice(group.index + group[0].length);
|
|
108
|
+
let entries;
|
|
109
|
+
try {
|
|
110
|
+
entries = readdirSync(resolvePath(root, dir.slice(1)));
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
for (const entry of entries) {
|
|
116
|
+
if (entry.length > before.length + after.length && entry.startsWith(before) && entry.endsWith(after)) {
|
|
117
|
+
out.push(entry.slice(before.length, entry.length - after.length));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return out;
|
|
122
|
+
}
|
|
91
123
|
/** Generate and write the declarations for `root`, returning what was done. */
|
|
92
124
|
export function writeComponentGlobals(options, root) {
|
|
93
125
|
if (options.globals === false)
|
|
@@ -106,6 +138,7 @@ export function writeComponentGlobals(options, root) {
|
|
|
106
138
|
}
|
|
107
139
|
const { source, declared } = componentGlobals(rules, {
|
|
108
140
|
available: projectDependencies(root),
|
|
141
|
+
candidates: patternCandidates(rules, root),
|
|
109
142
|
specifier: (module) => forTypeScript(module, dirname(target), root),
|
|
110
143
|
});
|
|
111
144
|
if (existing === source) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/resolve/write-globals.ts
|
|
2
|
-
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
-
import { dirname, relative, sep, resolve as resolvePath } from "node:path";
|
|
2
|
+
import { mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { basename, dirname, relative, sep, resolve as resolvePath } from "node:path";
|
|
4
4
|
|
|
5
5
|
// src/resolve/component-resolver.ts
|
|
6
6
|
var isMapRule = (rule) => "components" in rule;
|
|
@@ -102,6 +102,7 @@ var INTRINSICS = {
|
|
|
102
102
|
$effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
|
|
103
103
|
$store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
|
|
104
104
|
$resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
|
|
105
|
+
$cachedResource: { export: "cachedResource", module: "@fluixi/reactive/cached-resource", returns: "resource-handle" },
|
|
105
106
|
// No short runtime form for these yet, so the intrinsic stands for the `create*`
|
|
106
107
|
// name. Still worth having: no import to write, and when a shorter form is
|
|
107
108
|
// designed, the change is this line rather than a compiler pass.
|
|
@@ -111,7 +112,22 @@ var INTRINSICS = {
|
|
|
111
112
|
// does. `untrack` suppresses dependency collection, which is exactly the kind of thing
|
|
112
113
|
// dependency analysis must not guess at.
|
|
113
114
|
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
114
|
-
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" }
|
|
115
|
+
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
|
|
116
|
+
// Scopes, scheduling and lifecycle: no value to classify, but the same authoring promise,
|
|
117
|
+
// no import to write. `$cleanup` registers a callback on the current owner (`onCleanup`).
|
|
118
|
+
$batch: { export: "batch", module: REACTIVE_MODULE, returns: "plain" },
|
|
119
|
+
$cleanup: { export: "onCleanup", module: REACTIVE_MODULE, returns: "plain" },
|
|
120
|
+
$root: { export: "root", module: REACTIVE_MODULE, returns: "plain" },
|
|
121
|
+
$context: { export: "context", module: REACTIVE_MODULE, returns: "plain" },
|
|
122
|
+
$renderEffect: { export: "renderEffect", module: REACTIVE_MODULE, returns: "effect" },
|
|
123
|
+
$computed: { export: "computed", module: REACTIVE_MODULE, returns: "effect" },
|
|
124
|
+
// Storage for where the code runs, and a signal kept in it. `$persisted` is a signal
|
|
125
|
+
// handle as far as reads go: the same accessor with `set` on it.
|
|
126
|
+
$storage: { export: "useStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
127
|
+
$asyncStorage: { export: "useAsyncStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
128
|
+
$persisted: { export: "persisted", module: "@fluixi/core/storage", returns: "signal-handle" },
|
|
129
|
+
// An environment variable, public or server-only; the browser build refuses a secret.
|
|
130
|
+
$env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
|
|
115
131
|
};
|
|
116
132
|
var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
|
|
117
133
|
|
|
@@ -153,7 +169,8 @@ function componentGlobals(rules, options = {}) {
|
|
|
153
169
|
builtins = true,
|
|
154
170
|
intrinsics = true,
|
|
155
171
|
generator = "@fluixi/compiler",
|
|
156
|
-
specifier = (module) => module
|
|
172
|
+
specifier = (module) => module,
|
|
173
|
+
candidates = []
|
|
157
174
|
} = options;
|
|
158
175
|
const all = [...rules];
|
|
159
176
|
if (builtins) {
|
|
@@ -165,7 +182,8 @@ function componentGlobals(rules, options = {}) {
|
|
|
165
182
|
const shadowedByDom = [];
|
|
166
183
|
const unavailable = [];
|
|
167
184
|
const resolved = /* @__PURE__ */ new Map();
|
|
168
|
-
|
|
185
|
+
const names = /* @__PURE__ */ new Set([...resolver.names(), ...[...candidates].filter((n) => /^[A-Za-z_$][\w$]*$/.test(n))]);
|
|
186
|
+
for (const name of [...names].sort()) {
|
|
169
187
|
const target = resolver.resolve(name);
|
|
170
188
|
if (!target) continue;
|
|
171
189
|
const pkg = packageOf(target.module);
|
|
@@ -176,7 +194,11 @@ function componentGlobals(rules, options = {}) {
|
|
|
176
194
|
resolved.set(name, target);
|
|
177
195
|
}
|
|
178
196
|
}
|
|
179
|
-
const
|
|
197
|
+
const usableIntrinsics = intrinsics ? Object.entries(INTRINSICS).filter(([, i]) => {
|
|
198
|
+
const pkg = packageOf(i.module);
|
|
199
|
+
return !available || !pkg || available.has(pkg);
|
|
200
|
+
}) : [];
|
|
201
|
+
const intrinsicModules = [...new Set(usableIntrinsics.map(([, i]) => i.module))];
|
|
180
202
|
const modules = [
|
|
181
203
|
.../* @__PURE__ */ new Set([...declared.map((name) => resolved.get(name).module), ...intrinsicModules])
|
|
182
204
|
].sort();
|
|
@@ -196,15 +218,18 @@ function componentGlobals(rules, options = {}) {
|
|
|
196
218
|
return `// import { ${n} } from '${module ? specifier(module) : ""}';
|
|
197
219
|
`;
|
|
198
220
|
}).join("") : "";
|
|
199
|
-
const intrinsicLines =
|
|
221
|
+
const intrinsicLines = usableIntrinsics.map(
|
|
200
222
|
([name, intrinsic]) => ` const ${name}: typeof ${namespaceAlias(intrinsic.module)}.${intrinsic.export};`
|
|
201
|
-
)
|
|
223
|
+
);
|
|
202
224
|
const patternRules = rules.filter((rule) => "match" in rule).length;
|
|
203
|
-
const patternNote = patternRules
|
|
225
|
+
const patternNote = patternRules === 0 ? "" : options.candidates ? `//
|
|
226
|
+
// ${patternRules} pattern rule${patternRules === 1 ? "" : "s"}: declared for the files the module path
|
|
227
|
+
// points at. A name with no such file still resolves at build time; declare it by hand.
|
|
228
|
+
` : `//
|
|
204
229
|
// ${patternRules} pattern rule${patternRules === 1 ? "" : "s"} cannot be declared:
|
|
205
230
|
// a pattern matches unboundedly many names, so there is no list to emit. Those
|
|
206
231
|
// tags still resolve at build time; declare them by hand if the editor needs them.
|
|
207
|
-
|
|
232
|
+
`;
|
|
208
233
|
const source = `// GENERATED by ${generator}, do not edit.
|
|
209
234
|
//
|
|
210
235
|
// The components \`resolve\` supplies without an import. This describes what the
|
|
@@ -261,6 +286,30 @@ function projectDependencies(root) {
|
|
|
261
286
|
return void 0;
|
|
262
287
|
}
|
|
263
288
|
}
|
|
289
|
+
function patternCandidates(rules, root) {
|
|
290
|
+
const out = [];
|
|
291
|
+
for (const rule of rules) {
|
|
292
|
+
if (!("match" in rule) || !rule.module.startsWith("/")) continue;
|
|
293
|
+
const dir = dirname(rule.module);
|
|
294
|
+
const file = basename(rule.module);
|
|
295
|
+
const group = file.match(/\$\d+/);
|
|
296
|
+
if (dir.includes("$") || !group || file.indexOf("$", group.index + 1) !== -1) continue;
|
|
297
|
+
const before = file.slice(0, group.index);
|
|
298
|
+
const after = file.slice(group.index + group[0].length);
|
|
299
|
+
let entries;
|
|
300
|
+
try {
|
|
301
|
+
entries = readdirSync(resolvePath(root, dir.slice(1)));
|
|
302
|
+
} catch {
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
for (const entry of entries) {
|
|
306
|
+
if (entry.length > before.length + after.length && entry.startsWith(before) && entry.endsWith(after)) {
|
|
307
|
+
out.push(entry.slice(before.length, entry.length - after.length));
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
return out;
|
|
312
|
+
}
|
|
264
313
|
function writeComponentGlobals(options, root) {
|
|
265
314
|
if (options.globals === false) return { status: "skipped", reason: "disabled" };
|
|
266
315
|
const rules = options.resolve ?? [];
|
|
@@ -276,6 +325,7 @@ function writeComponentGlobals(options, root) {
|
|
|
276
325
|
}
|
|
277
326
|
const { source, declared } = componentGlobals(rules, {
|
|
278
327
|
available: projectDependencies(root),
|
|
328
|
+
candidates: patternCandidates(rules, root),
|
|
279
329
|
specifier: (module) => forTypeScript(module, dirname(target), root)
|
|
280
330
|
});
|
|
281
331
|
if (existing === source) {
|
|
@@ -302,5 +352,6 @@ function warnIfUnreachable(root, target) {
|
|
|
302
352
|
}
|
|
303
353
|
export {
|
|
304
354
|
DEFAULT_GLOBALS_PATH,
|
|
355
|
+
patternCandidates,
|
|
305
356
|
writeComponentGlobals
|
|
306
357
|
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
/*! @fluixi/compiler v1.0.0-alpha.
|
|
1
|
+
/*! @fluixi/compiler v1.0.0-alpha.93 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
|
|
2
2
|
import {
|
|
3
3
|
MagicString
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-R7PPFBCL.mjs";
|
|
5
5
|
import {
|
|
6
6
|
serverFnId
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-56QSOVVL.mjs";
|
|
8
|
+
import "./chunk-TJIH7TLX.mjs";
|
|
9
9
|
|
|
10
10
|
// src/transform/server-fns.ts
|
|
11
11
|
import { parse } from "@babel/parser";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
/*! @fluixi/compiler v1.0.0-alpha.
|
|
1
|
+
/*! @fluixi/compiler v1.0.0-alpha.93 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
|
|
2
2
|
import {
|
|
3
3
|
serverFnId
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-56QSOVVL.mjs";
|
|
5
|
+
import "./chunk-TJIH7TLX.mjs";
|
|
6
6
|
|
|
7
7
|
// src/frontend/babel/server-functions.ts
|
|
8
8
|
import { transformSync } from "@babel/core";
|