@fluixi/compiler 1.0.0-alpha.100
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/LICENSE +21 -0
- package/README.md +131 -0
- package/dist/analyze/expr-shape.cjs +62 -0
- package/dist/analyze/expr-shape.d.cts +14 -0
- package/dist/analyze/expr-shape.d.ts +15 -0
- package/dist/analyze/expr-shape.d.ts.map +1 -0
- package/dist/analyze/expr-shape.js +37 -0
- package/dist/analyze/expr-shape.mjs +41 -0
- package/dist/analyze/intrinsics.cjs +112 -0
- package/dist/analyze/intrinsics.d.cts +80 -0
- package/dist/analyze/intrinsics.d.ts +81 -0
- package/dist/analyze/intrinsics.d.ts.map +1 -0
- package/dist/analyze/intrinsics.js +126 -0
- package/dist/analyze/intrinsics.mjs +91 -0
- package/dist/analyze/paren.cjs +134 -0
- package/dist/analyze/paren.d.cts +23 -0
- package/dist/analyze/paren.d.ts +24 -0
- package/dist/analyze/paren.d.ts.map +1 -0
- package/dist/analyze/paren.js +168 -0
- package/dist/analyze/paren.mjs +113 -0
- package/dist/analyze/props-destructure.cjs +226 -0
- package/dist/analyze/props-destructure.d.cts +83 -0
- package/dist/analyze/props-destructure.d.ts +84 -0
- package/dist/analyze/props-destructure.d.ts.map +1 -0
- package/dist/analyze/props-destructure.js +272 -0
- package/dist/analyze/props-destructure.mjs +205 -0
- package/dist/analyze/reactive-bindings.cjs +210 -0
- package/dist/analyze/reactive-bindings.d.cts +42 -0
- package/dist/analyze/reactive-bindings.d.ts +43 -0
- package/dist/analyze/reactive-bindings.d.ts.map +1 -0
- package/dist/analyze/reactive-bindings.js +191 -0
- package/dist/analyze/reactive-bindings.mjs +187 -0
- package/dist/analyze/reactive-expr.cjs +38 -0
- package/dist/analyze/reactive-expr.d.cts +38 -0
- package/dist/analyze/reactive-expr.d.ts +39 -0
- package/dist/analyze/reactive-expr.d.ts.map +1 -0
- package/dist/analyze/reactive-expr.js +31 -0
- package/dist/analyze/reactive-expr.mjs +17 -0
- package/dist/analyze/static-graph.cjs +831 -0
- package/dist/analyze/static-graph.d.cts +102 -0
- package/dist/analyze/static-graph.d.ts +103 -0
- package/dist/analyze/static-graph.d.ts.map +1 -0
- package/dist/analyze/static-graph.js +871 -0
- package/dist/analyze/static-graph.mjs +813 -0
- package/dist/babel-I6BUWUCU.mjs +636 -0
- package/dist/chunk-3AICWNF7.mjs +92 -0
- package/dist/chunk-6CWJWGE2.mjs +2170 -0
- package/dist/chunk-C3XPDB4Y.mjs +16 -0
- package/dist/chunk-GX5XV6Z7.mjs +190 -0
- package/dist/chunk-HXEXPWJ2.mjs +999 -0
- package/dist/chunk-NU3W67UZ.mjs +584 -0
- package/dist/chunk-SKAVY75W.mjs +11 -0
- package/dist/codegen/backend.cjs +18 -0
- package/dist/codegen/backend.d.cts +35 -0
- package/dist/codegen/backend.d.ts +36 -0
- package/dist/codegen/backend.d.ts.map +1 -0
- package/dist/codegen/backend.js +1 -0
- package/dist/codegen/backend.mjs +0 -0
- package/dist/codegen/backends/imperative.cjs +577 -0
- package/dist/codegen/backends/imperative.d.cts +11 -0
- package/dist/codegen/backends/imperative.d.ts +12 -0
- package/dist/codegen/backends/imperative.d.ts.map +1 -0
- package/dist/codegen/backends/imperative.js +362 -0
- package/dist/codegen/backends/imperative.mjs +554 -0
- package/dist/codegen/contract.cjs +52 -0
- package/dist/codegen/contract.d.cts +24 -0
- package/dist/codegen/contract.d.ts +25 -0
- package/dist/codegen/contract.d.ts.map +1 -0
- package/dist/codegen/contract.js +30 -0
- package/dist/codegen/contract.mjs +31 -0
- package/dist/codegen/partial-template.cjs +176 -0
- package/dist/codegen/partial-template.d.cts +61 -0
- package/dist/codegen/partial-template.d.ts +62 -0
- package/dist/codegen/partial-template.d.ts.map +1 -0
- package/dist/codegen/partial-template.js +0 -0
- package/dist/codegen/partial-template.mjs +153 -0
- package/dist/codegen/serialize-static.cjs +125 -0
- package/dist/codegen/serialize-static.d.cts +38 -0
- package/dist/codegen/serialize-static.d.ts +39 -0
- package/dist/codegen/serialize-static.d.ts.map +1 -0
- package/dist/codegen/serialize-static.js +165 -0
- package/dist/codegen/serialize-static.mjs +104 -0
- package/dist/frontend/babel/build-ir-lit.cjs +1933 -0
- package/dist/frontend/babel/build-ir-lit.d.cts +26 -0
- package/dist/frontend/babel/build-ir-lit.d.ts +27 -0
- package/dist/frontend/babel/build-ir-lit.d.ts.map +1 -0
- package/dist/frontend/babel/build-ir-lit.js +13 -0
- package/dist/frontend/babel/build-ir-lit.mjs +1902 -0
- package/dist/frontend/babel/build-ir.cjs +1948 -0
- package/dist/frontend/babel/build-ir.d.cts +35 -0
- package/dist/frontend/babel/build-ir.d.ts +36 -0
- package/dist/frontend/babel/build-ir.d.ts.map +1 -0
- package/dist/frontend/babel/build-ir.js +124 -0
- package/dist/frontend/babel/build-ir.mjs +1919 -0
- package/dist/frontend/babel/index.cjs +2610 -0
- package/dist/frontend/babel/index.d.cts +33 -0
- package/dist/frontend/babel/index.d.ts +34 -0
- package/dist/frontend/babel/index.d.ts.map +1 -0
- package/dist/frontend/babel/index.js +65 -0
- package/dist/frontend/babel/index.mjs +2580 -0
- package/dist/frontend/babel/lower-template.cjs +1931 -0
- package/dist/frontend/babel/lower-template.d.cts +23 -0
- package/dist/frontend/babel/lower-template.d.ts +24 -0
- package/dist/frontend/babel/lower-template.d.ts.map +1 -0
- package/dist/frontend/babel/lower-template.js +64 -0
- package/dist/frontend/babel/lower-template.mjs +1902 -0
- package/dist/frontend/babel/plugin.cjs +2556 -0
- package/dist/frontend/babel/plugin.d.cts +95 -0
- package/dist/frontend/babel/plugin.d.ts +96 -0
- package/dist/frontend/babel/plugin.d.ts.map +1 -0
- package/dist/frontend/babel/plugin.js +523 -0
- package/dist/frontend/babel/plugin.mjs +2527 -0
- package/dist/frontend/babel/server-functions.cjs +110 -0
- package/dist/frontend/babel/server-functions.d.cts +10 -0
- package/dist/frontend/babel/server-functions.d.ts +11 -0
- package/dist/frontend/babel/server-functions.d.ts.map +1 -0
- package/dist/frontend/babel/server-functions.js +81 -0
- package/dist/frontend/babel/server-functions.mjs +89 -0
- package/dist/frontend/babel/types.cjs +18 -0
- package/dist/frontend/babel/types.d.cts +33 -0
- package/dist/frontend/babel/types.d.ts +34 -0
- package/dist/frontend/babel/types.d.ts.map +1 -0
- package/dist/frontend/babel/types.js +1 -0
- package/dist/frontend/babel/types.mjs +0 -0
- package/dist/frontend/types.cjs +18 -0
- package/dist/frontend/types.d.cts +25 -0
- package/dist/frontend/types.d.ts +26 -0
- package/dist/frontend/types.d.ts.map +1 -0
- package/dist/frontend/types.js +1 -0
- package/dist/frontend/types.mjs +0 -0
- package/dist/frontend/vocabulary.cjs +98 -0
- package/dist/frontend/vocabulary.d.cts +79 -0
- package/dist/frontend/vocabulary.d.ts +80 -0
- package/dist/frontend/vocabulary.d.ts.map +1 -0
- package/dist/frontend/vocabulary.js +124 -0
- package/dist/frontend/vocabulary.mjs +77 -0
- package/dist/index.cjs +1957 -0
- package/dist/index.d.cts +27 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.mjs +1949 -0
- package/dist/integrations.cjs +5705 -0
- package/dist/integrations.d.cts +215 -0
- package/dist/integrations.d.ts +216 -0
- package/dist/integrations.d.ts.map +1 -0
- package/dist/integrations.js +566 -0
- package/dist/integrations.mjs +810 -0
- package/dist/ir/nodes.cjs +18 -0
- package/dist/ir/nodes.d.cts +168 -0
- package/dist/ir/nodes.d.ts +169 -0
- package/dist/ir/nodes.d.ts.map +1 -0
- package/dist/ir/nodes.js +1 -0
- package/dist/ir/nodes.mjs +0 -0
- package/dist/lower/compile-template.cjs +1670 -0
- package/dist/lower/compile-template.d.cts +82 -0
- package/dist/lower/compile-template.d.ts +83 -0
- package/dist/lower/compile-template.d.ts.map +1 -0
- package/dist/lower/compile-template.js +79 -0
- package/dist/lower/compile-template.mjs +1662 -0
- package/dist/lower/entities.cjs +288 -0
- package/dist/lower/entities.d.cts +1 -0
- package/dist/lower/entities.d.ts +2 -0
- package/dist/lower/entities.d.ts.map +1 -0
- package/dist/lower/entities.js +54 -0
- package/dist/lower/entities.mjs +267 -0
- package/dist/lower/jsx.cjs +1101 -0
- package/dist/lower/jsx.d.cts +33 -0
- package/dist/lower/jsx.d.ts +34 -0
- package/dist/lower/jsx.d.ts.map +1 -0
- package/dist/lower/jsx.js +414 -0
- package/dist/lower/jsx.mjs +1078 -0
- package/dist/lower/template.cjs +1354 -0
- package/dist/lower/template.d.cts +53 -0
- package/dist/lower/template.d.ts +54 -0
- package/dist/lower/template.d.ts.map +1 -0
- package/dist/lower/template.js +542 -0
- package/dist/lower/template.mjs +1335 -0
- package/dist/lower/text.cjs +42 -0
- package/dist/lower/text.d.cts +10 -0
- package/dist/lower/text.d.ts +11 -0
- package/dist/lower/text.d.ts.map +1 -0
- package/dist/lower/text.js +31 -0
- package/dist/lower/text.mjs +21 -0
- package/dist/optimize/analyze-static.cjs +112 -0
- package/dist/optimize/analyze-static.d.cts +39 -0
- package/dist/optimize/analyze-static.d.ts +40 -0
- package/dist/optimize/analyze-static.d.ts.map +1 -0
- package/dist/optimize/analyze-static.js +131 -0
- package/dist/optimize/analyze-static.mjs +91 -0
- package/dist/optimize/collapse-strategies.cjs +90 -0
- package/dist/optimize/collapse-strategies.d.cts +30 -0
- package/dist/optimize/collapse-strategies.d.ts +31 -0
- package/dist/optimize/collapse-strategies.d.ts.map +1 -0
- package/dist/optimize/collapse-strategies.js +33 -0
- package/dist/optimize/collapse-strategies.mjs +67 -0
- package/dist/options.cjs +33 -0
- package/dist/options.d.cts +39 -0
- package/dist/options.d.ts +40 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +8 -0
- package/dist/options.mjs +12 -0
- package/dist/resolve/builtins.cjs +73 -0
- package/dist/resolve/builtins.d.cts +68 -0
- package/dist/resolve/builtins.d.ts +69 -0
- package/dist/resolve/builtins.d.ts.map +1 -0
- package/dist/resolve/builtins.js +64 -0
- package/dist/resolve/builtins.mjs +53 -0
- package/dist/resolve/component-globals.cjs +272 -0
- package/dist/resolve/component-globals.d.cts +88 -0
- package/dist/resolve/component-globals.d.ts +89 -0
- package/dist/resolve/component-globals.d.ts.map +1 -0
- package/dist/resolve/component-globals.js +160 -0
- package/dist/resolve/component-globals.mjs +249 -0
- package/dist/resolve/component-resolver.cjs +80 -0
- package/dist/resolve/component-resolver.d.cts +68 -0
- package/dist/resolve/component-resolver.d.ts +69 -0
- package/dist/resolve/component-resolver.d.ts.map +1 -0
- package/dist/resolve/component-resolver.js +95 -0
- package/dist/resolve/component-resolver.mjs +59 -0
- package/dist/resolve/load-directive.cjs +93 -0
- package/dist/resolve/load-directive.d.cts +53 -0
- package/dist/resolve/load-directive.d.ts +54 -0
- package/dist/resolve/load-directive.d.ts.map +1 -0
- package/dist/resolve/load-directive.js +93 -0
- package/dist/resolve/load-directive.mjs +72 -0
- package/dist/resolve/resolve-ir.cjs +108 -0
- package/dist/resolve/resolve-ir.d.cts +53 -0
- package/dist/resolve/resolve-ir.d.ts +54 -0
- package/dist/resolve/resolve-ir.d.ts.map +1 -0
- package/dist/resolve/resolve-ir.js +58 -0
- package/dist/resolve/resolve-ir.mjs +85 -0
- package/dist/resolve/write-globals.cjs +383 -0
- package/dist/resolve/write-globals.d.cts +36 -0
- package/dist/resolve/write-globals.d.ts +37 -0
- package/dist/resolve/write-globals.d.ts.map +1 -0
- package/dist/resolve/write-globals.js +169 -0
- package/dist/resolve/write-globals.mjs +362 -0
- package/dist/server-fns-VZLHMQTC.mjs +79 -0
- package/dist/server-functions-UAZKOLZW.mjs +82 -0
- package/dist/transform/bindings.cjs +71 -0
- package/dist/transform/bindings.d.cts +16 -0
- package/dist/transform/bindings.d.ts +17 -0
- package/dist/transform/bindings.d.ts.map +1 -0
- package/dist/transform/bindings.js +69 -0
- package/dist/transform/bindings.mjs +50 -0
- package/dist/transform/index.cjs +3837 -0
- package/dist/transform/index.d.cts +15 -0
- package/dist/transform/index.d.ts +16 -0
- package/dist/transform/index.d.ts.map +1 -0
- package/dist/transform/index.js +12 -0
- package/dist/transform/index.mjs +4882 -0
- package/dist/transform/intrinsics.cjs +261 -0
- package/dist/transform/intrinsics.d.cts +33 -0
- package/dist/transform/intrinsics.d.ts +34 -0
- package/dist/transform/intrinsics.d.ts.map +1 -0
- package/dist/transform/intrinsics.js +120 -0
- package/dist/transform/intrinsics.mjs +238 -0
- package/dist/transform/props.cjs +441 -0
- package/dist/transform/props.d.cts +45 -0
- package/dist/transform/props.d.ts +46 -0
- package/dist/transform/props.d.ts.map +1 -0
- package/dist/transform/props.js +221 -0
- package/dist/transform/props.mjs +1487 -0
- package/dist/transform/server-fn-id.cjs +35 -0
- package/dist/transform/server-fn-id.d.cts +9 -0
- package/dist/transform/server-fn-id.d.ts +10 -0
- package/dist/transform/server-fn-id.d.ts.map +1 -0
- package/dist/transform/server-fn-id.js +18 -0
- package/dist/transform/server-fn-id.mjs +14 -0
- package/dist/transform/server-fns.cjs +114 -0
- package/dist/transform/server-fns.d.cts +12 -0
- package/dist/transform/server-fns.d.ts +13 -0
- package/dist/transform/server-fns.d.ts.map +1 -0
- package/dist/transform/server-fns.js +94 -0
- package/dist/transform/server-fns.mjs +1160 -0
- package/dist/transform/source-locations.cjs +393 -0
- package/dist/transform/source-locations.d.cts +48 -0
- package/dist/transform/source-locations.d.ts +49 -0
- package/dist/transform/source-locations.d.ts.map +1 -0
- package/dist/transform/source-locations.js +303 -0
- package/dist/transform/source-locations.mjs +370 -0
- package/dist/transform/styles.cjs +606 -0
- package/dist/transform/styles.d.cts +237 -0
- package/dist/transform/styles.d.ts +238 -0
- package/dist/transform/styles.d.ts.map +1 -0
- package/dist/transform/styles.js +743 -0
- package/dist/transform/styles.mjs +671 -0
- package/dist/transform/templates.cjs +3806 -0
- package/dist/transform/templates.d.cts +82 -0
- package/dist/transform/templates.d.ts +83 -0
- package/dist/transform/templates.d.ts.map +1 -0
- package/dist/transform/templates.js +613 -0
- package/dist/transform/templates.mjs +4852 -0
- package/dist/transform-3W45L3EA.mjs +951 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -0
- package/dist/vite-styles.cjs +223 -0
- package/dist/vite-styles.d.cts +68 -0
- package/dist/vite-styles.d.ts +69 -0
- package/dist/vite-styles.d.ts.map +1 -0
- package/dist/vite-styles.js +241 -0
- package/dist/vite-styles.mjs +214 -0
- package/package.json +141 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/resolve/component-globals.ts
|
|
21
|
+
var component_globals_exports = {};
|
|
22
|
+
__export(component_globals_exports, {
|
|
23
|
+
componentGlobals: () => componentGlobals
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(component_globals_exports);
|
|
26
|
+
|
|
27
|
+
// src/resolve/component-resolver.ts
|
|
28
|
+
var isMapRule = (rule) => "components" in rule;
|
|
29
|
+
function substitute(template, match) {
|
|
30
|
+
return template.replace(/\$(\d+)/g, (whole, index) => {
|
|
31
|
+
const group = match[Number(index)];
|
|
32
|
+
return group ?? whole;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
function normalise(name, entry) {
|
|
36
|
+
return typeof entry === "string" ? { module: entry, export: name } : entry;
|
|
37
|
+
}
|
|
38
|
+
function createComponentResolver(rules = []) {
|
|
39
|
+
const exact = /* @__PURE__ */ new Map();
|
|
40
|
+
const conflicts = [];
|
|
41
|
+
const patterns = [];
|
|
42
|
+
for (const rule of rules) {
|
|
43
|
+
if (!isMapRule(rule)) {
|
|
44
|
+
patterns.push(rule);
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
for (const [name, entry] of Object.entries(rule.components)) {
|
|
48
|
+
const resolved = normalise(name, entry);
|
|
49
|
+
const existing = exact.get(name);
|
|
50
|
+
if (existing && existing.module !== resolved.module) {
|
|
51
|
+
const conflict = conflicts.find((c) => c.name === name);
|
|
52
|
+
if (conflict) conflict.modules.push(resolved.module);
|
|
53
|
+
else conflicts.push({ name, modules: [existing.module, resolved.module] });
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
exact.set(name, resolved);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const cache = /* @__PURE__ */ new Map();
|
|
60
|
+
const resolve = (name) => {
|
|
61
|
+
if (cache.has(name)) return cache.get(name);
|
|
62
|
+
let result = exact.get(name);
|
|
63
|
+
if (!result) {
|
|
64
|
+
for (const rule of patterns) {
|
|
65
|
+
const match = name.match(new RegExp(rule.match.source, rule.match.flags.replace("g", "")));
|
|
66
|
+
if (!match) continue;
|
|
67
|
+
result = {
|
|
68
|
+
module: substitute(rule.module, match),
|
|
69
|
+
export: rule.export ? substitute(rule.export, match) : name
|
|
70
|
+
};
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
cache.set(name, result);
|
|
75
|
+
return result;
|
|
76
|
+
};
|
|
77
|
+
return {
|
|
78
|
+
resolve,
|
|
79
|
+
names: () => [...exact.keys()],
|
|
80
|
+
conflicts: () => conflicts
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// src/resolve/builtins.ts
|
|
85
|
+
var DOM_CONTROL_FLOW = [
|
|
86
|
+
"Show",
|
|
87
|
+
"For",
|
|
88
|
+
"Index",
|
|
89
|
+
"Switch",
|
|
90
|
+
"Match",
|
|
91
|
+
"Portal",
|
|
92
|
+
"Dynamic",
|
|
93
|
+
"ErrorBoundary"
|
|
94
|
+
];
|
|
95
|
+
var CORE_CONTROL_FLOW = ["Suspense", "SuspenseList", "Await"];
|
|
96
|
+
var ROUTER_COMPONENTS = ["Router", "Outlet", "Redirect", "Link"];
|
|
97
|
+
var BUILTIN_COMPONENTS = [
|
|
98
|
+
...DOM_CONTROL_FLOW,
|
|
99
|
+
...CORE_CONTROL_FLOW,
|
|
100
|
+
...ROUTER_COMPONENTS
|
|
101
|
+
];
|
|
102
|
+
var RESERVED_COMPONENTS = /* @__PURE__ */ new Set([
|
|
103
|
+
...DOM_CONTROL_FLOW,
|
|
104
|
+
...CORE_CONTROL_FLOW
|
|
105
|
+
]);
|
|
106
|
+
function builtinComponentMap(modules = {}) {
|
|
107
|
+
const {
|
|
108
|
+
controlFlowModule = "@fluixi/dom",
|
|
109
|
+
coreModule = "@fluixi/core",
|
|
110
|
+
routerModule = "@fluixi/core/router"
|
|
111
|
+
} = modules;
|
|
112
|
+
const map = {};
|
|
113
|
+
for (const name of DOM_CONTROL_FLOW) map[name] = controlFlowModule;
|
|
114
|
+
for (const name of CORE_CONTROL_FLOW) map[name] = coreModule;
|
|
115
|
+
for (const name of ROUTER_COMPONENTS) map[name] = routerModule;
|
|
116
|
+
return map;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// src/analyze/intrinsics.ts
|
|
120
|
+
var REACTIVE_MODULE = "@fluixi/reactive/signal";
|
|
121
|
+
var INTRINSICS = {
|
|
122
|
+
$signal: { export: "signal", module: REACTIVE_MODULE, returns: "signal-handle" },
|
|
123
|
+
$memo: { export: "memo", module: REACTIVE_MODULE, returns: "memo-handle" },
|
|
124
|
+
$effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
|
|
125
|
+
$store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
|
|
126
|
+
$resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
|
|
127
|
+
$cachedResource: { export: "cachedResource", module: "@fluixi/reactive/cached-resource", returns: "resource-handle" },
|
|
128
|
+
// No short runtime form for these yet, so the intrinsic stands for the `create*`
|
|
129
|
+
// name. Still worth having: no import to write, and when a shorter form is
|
|
130
|
+
// designed, the change is this line rather than a compiler pass.
|
|
131
|
+
$selector: { export: "createSelector", module: REACTIVE_MODULE, returns: "memo-accessor" },
|
|
132
|
+
$deferred: { export: "createDeferred", module: REACTIVE_MODULE, returns: "memo-accessor" },
|
|
133
|
+
// Not value constructors, but the compiler has to know them: they change what a read
|
|
134
|
+
// does. `untrack` suppresses dependency collection, which is exactly the kind of thing
|
|
135
|
+
// dependency analysis must not guess at.
|
|
136
|
+
$untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
|
|
137
|
+
$untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
|
|
138
|
+
// Scopes, scheduling and lifecycle: no value to classify, but the same authoring promise,
|
|
139
|
+
// no import to write. `$cleanup` registers a callback on the current owner (`onCleanup`).
|
|
140
|
+
$batch: { export: "batch", module: REACTIVE_MODULE, returns: "plain" },
|
|
141
|
+
$cleanup: { export: "onCleanup", module: REACTIVE_MODULE, returns: "plain" },
|
|
142
|
+
$root: { export: "root", module: REACTIVE_MODULE, returns: "plain" },
|
|
143
|
+
$context: { export: "context", module: REACTIVE_MODULE, returns: "plain" },
|
|
144
|
+
$renderEffect: { export: "renderEffect", module: REACTIVE_MODULE, returns: "effect" },
|
|
145
|
+
$computed: { export: "computed", module: REACTIVE_MODULE, returns: "effect" },
|
|
146
|
+
// Storage for where the code runs, and a signal kept in it. `$persisted` is a signal
|
|
147
|
+
// handle as far as reads go: the same accessor with `set` on it.
|
|
148
|
+
$storage: { export: "useStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
149
|
+
$asyncStorage: { export: "useAsyncStorage", module: "@fluixi/core/storage", returns: "plain" },
|
|
150
|
+
$persisted: { export: "persisted", module: "@fluixi/core/storage", returns: "signal-handle" },
|
|
151
|
+
// An environment variable, public or server-only; the browser build refuses a secret.
|
|
152
|
+
$env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
|
|
153
|
+
};
|
|
154
|
+
var TAG_INTRINSICS = {
|
|
155
|
+
$html: { export: "html", module: "@fluixi/core" },
|
|
156
|
+
$svg: { export: "svg", module: "@fluixi/core" },
|
|
157
|
+
$css: { export: "css", module: "@fluixi/core" }
|
|
158
|
+
};
|
|
159
|
+
var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
|
|
160
|
+
|
|
161
|
+
// src/resolve/component-globals.ts
|
|
162
|
+
var DOM_GLOBALS = /* @__PURE__ */ new Set([
|
|
163
|
+
"Text",
|
|
164
|
+
"Image",
|
|
165
|
+
"Option",
|
|
166
|
+
"Audio",
|
|
167
|
+
"Comment",
|
|
168
|
+
"Range",
|
|
169
|
+
"Selection",
|
|
170
|
+
"Notification",
|
|
171
|
+
"Event",
|
|
172
|
+
"Document",
|
|
173
|
+
"Element",
|
|
174
|
+
"Node",
|
|
175
|
+
"Screen",
|
|
176
|
+
"Window",
|
|
177
|
+
"Location",
|
|
178
|
+
"History",
|
|
179
|
+
"Storage",
|
|
180
|
+
"Response",
|
|
181
|
+
"Request",
|
|
182
|
+
"Headers"
|
|
183
|
+
]);
|
|
184
|
+
function packageOf(specifier) {
|
|
185
|
+
if (specifier.startsWith(".") || specifier.startsWith("/")) return void 0;
|
|
186
|
+
if (/^[~@]\//.test(specifier)) return void 0;
|
|
187
|
+
const parts = specifier.split("/");
|
|
188
|
+
return specifier.startsWith("@") ? parts.slice(0, 2).join("/") : parts[0];
|
|
189
|
+
}
|
|
190
|
+
function namespaceAlias(module2) {
|
|
191
|
+
return `_${module2.replace(/[^A-Za-z0-9]/g, "_")}`;
|
|
192
|
+
}
|
|
193
|
+
function componentGlobals(rules, options = {}) {
|
|
194
|
+
const {
|
|
195
|
+
available: availableList,
|
|
196
|
+
builtins = true,
|
|
197
|
+
intrinsics = true,
|
|
198
|
+
generator = "@fluixi/compiler",
|
|
199
|
+
specifier = (module2) => module2,
|
|
200
|
+
candidates = []
|
|
201
|
+
} = options;
|
|
202
|
+
const all = [...rules];
|
|
203
|
+
if (builtins) {
|
|
204
|
+
all.push({ components: builtinComponentMap() });
|
|
205
|
+
}
|
|
206
|
+
const resolver = createComponentResolver(all);
|
|
207
|
+
const available = availableList ? new Set(availableList) : void 0;
|
|
208
|
+
const declared = [];
|
|
209
|
+
const shadowedByDom = [];
|
|
210
|
+
const unavailable = [];
|
|
211
|
+
const resolved = /* @__PURE__ */ new Map();
|
|
212
|
+
const names = /* @__PURE__ */ new Set([...resolver.names(), ...[...candidates].filter((n) => /^[A-Za-z_$][\w$]*$/.test(n))]);
|
|
213
|
+
for (const name of [...names].sort()) {
|
|
214
|
+
const target = resolver.resolve(name);
|
|
215
|
+
if (!target) continue;
|
|
216
|
+
const pkg = packageOf(target.module);
|
|
217
|
+
if (DOM_GLOBALS.has(name)) shadowedByDom.push(name);
|
|
218
|
+
else if (available && pkg && !available.has(pkg)) unavailable.push(name);
|
|
219
|
+
else {
|
|
220
|
+
declared.push(name);
|
|
221
|
+
resolved.set(name, target);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
const usableIntrinsics = intrinsics ? Object.entries({ ...INTRINSICS, ...TAG_INTRINSICS }).filter(([, i]) => {
|
|
225
|
+
const pkg = packageOf(i.module);
|
|
226
|
+
return !available || !pkg || available.has(pkg);
|
|
227
|
+
}) : [];
|
|
228
|
+
const intrinsicModules = [...new Set(usableIntrinsics.map(([, i]) => i.module))];
|
|
229
|
+
const modules = [
|
|
230
|
+
.../* @__PURE__ */ new Set([...declared.map((name) => resolved.get(name).module), ...intrinsicModules])
|
|
231
|
+
].sort();
|
|
232
|
+
const imports = modules.map(
|
|
233
|
+
(m) => `import * as ${namespaceAlias(m)} from '${specifier(m)}';`
|
|
234
|
+
);
|
|
235
|
+
const lines = declared.map((name) => {
|
|
236
|
+
const target = resolved.get(name);
|
|
237
|
+
const ns = namespaceAlias(target.module);
|
|
238
|
+
return target.export === "default" ? ` const ${name}: typeof ${ns}.default;` : ` export import ${name} = ${ns}.${target.export};`;
|
|
239
|
+
});
|
|
240
|
+
const note = shadowedByDom.length > 0 ? `//
|
|
241
|
+
// Import these explicitly: lib.dom already declares the name, so an ambient
|
|
242
|
+
// declaration cannot win:
|
|
243
|
+
` + shadowedByDom.map((n) => {
|
|
244
|
+
const module2 = resolver.resolve(n)?.module;
|
|
245
|
+
return `// import { ${n} } from '${module2 ? specifier(module2) : ""}';
|
|
246
|
+
`;
|
|
247
|
+
}).join("") : "";
|
|
248
|
+
const intrinsicLines = usableIntrinsics.map(
|
|
249
|
+
([name, intrinsic]) => ` const ${name}: typeof ${namespaceAlias(intrinsic.module)}.${intrinsic.export};`
|
|
250
|
+
);
|
|
251
|
+
const patternRules = rules.filter((rule) => "match" in rule).length;
|
|
252
|
+
const patternNote = patternRules === 0 ? "" : options.candidates ? `//
|
|
253
|
+
// ${patternRules} pattern rule${patternRules === 1 ? "" : "s"}: declared for the files the module path
|
|
254
|
+
// points at. A name with no such file still resolves at build time; declare it by hand.
|
|
255
|
+
` : `//
|
|
256
|
+
// ${patternRules} pattern rule${patternRules === 1 ? "" : "s"} cannot be declared:
|
|
257
|
+
// a pattern matches unboundedly many names, so there is no list to emit. Those
|
|
258
|
+
// tags still resolve at build time; declare them by hand if the editor needs them.
|
|
259
|
+
`;
|
|
260
|
+
const source = `// GENERATED by ${generator}, do not edit.
|
|
261
|
+
//
|
|
262
|
+
// The components \`resolve\` supplies without an import. This describes what the
|
|
263
|
+
// compiler already does; it does not enable it.
|
|
264
|
+
` + note + patternNote + (imports.length > 0 ? `
|
|
265
|
+
${imports.join("\n")}
|
|
266
|
+
` : "\n") + `
|
|
267
|
+
declare global {
|
|
268
|
+
${[...lines, ...intrinsicLines].join("\n")}
|
|
269
|
+
}
|
|
270
|
+
`;
|
|
271
|
+
return { source, declared, shadowedByDom, unavailable, patternRules };
|
|
272
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ambient declarations for the components `resolve` supplies without an import.
|
|
3
|
+
*
|
|
4
|
+
* The compiler injects the import, so nothing in the source imports these, which leaves
|
|
5
|
+
* TypeScript reporting `TS2304: Cannot find name`. The code compiles and runs; the editor
|
|
6
|
+
* is unusable and `tsc` fails. These declarations describe what the compiler already
|
|
7
|
+
* does. They do not enable it.
|
|
8
|
+
*
|
|
9
|
+
* This lives next to the resolver, and takes rules rather than a flat map, because the
|
|
10
|
+
* resolver is the only thing that knows the whole picture: a UI library's components, the
|
|
11
|
+
* project's own, and the framework builtins all arrive through the same config. A
|
|
12
|
+
* component library cannot generate this on its own, it does not know what else the
|
|
13
|
+
* project resolves: which is why the generator belongs here and the library-specific CLI
|
|
14
|
+
* that predates it does not.
|
|
15
|
+
*
|
|
16
|
+
* Pure, like the resolver: rules in, source out, no filesystem. Writing the file is the
|
|
17
|
+
* caller's job (the Vite plugin does it on config resolve; a CLI can do it in CI).
|
|
18
|
+
*/
|
|
19
|
+
import { type ComponentResolverRule } from './component-resolver.cjs';
|
|
20
|
+
export interface ComponentGlobalsOptions {
|
|
21
|
+
/**
|
|
22
|
+
* Packages the project can actually resolve: normally its declared dependencies.
|
|
23
|
+
*
|
|
24
|
+
* Declaring a component from a package the project does not depend on produces an
|
|
25
|
+
* unresolvable `import(...)`, and under the usual `skipLibCheck: true` that failure is
|
|
26
|
+
* silent: the component degrades to `any` and every prop typo type-checks, which is
|
|
27
|
+
* worse than the error it replaced. Omit to declare everything, which is only correct
|
|
28
|
+
* when every package is present.
|
|
29
|
+
*
|
|
30
|
+
* Relative and alias specifiers are never filtered, there is no package to check.
|
|
31
|
+
*/
|
|
32
|
+
available?: Iterable<string>;
|
|
33
|
+
/**
|
|
34
|
+
* Declare the framework builtins (`Show`, `For`, `Portal`, `Router`, …) too.
|
|
35
|
+
*
|
|
36
|
+
* On by default because the compiler resolves them whether or not a rule mentions
|
|
37
|
+
* them, so declaring them is what matches reality. A real import shadows the ambient
|
|
38
|
+
* declaration, so this stays safe for code that imports them explicitly.
|
|
39
|
+
*/
|
|
40
|
+
builtins?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Declare the `$` reactive intrinsics (`$signal`, `$memo`, …).
|
|
43
|
+
*
|
|
44
|
+
* On by default, matching the compiler: it rewrites those calls whether or not
|
|
45
|
+
* anything declares them, and without the declaration the editor reports
|
|
46
|
+
* "Cannot find name '$signal'" for code that builds correctly.
|
|
47
|
+
*/
|
|
48
|
+
intrinsics?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Names to try against the pattern rules.
|
|
51
|
+
*
|
|
52
|
+
* A pattern has no name list of its own, but the files it points at do: the caller lists
|
|
53
|
+
* them (the generator stays off the filesystem) and each name the resolver answers is
|
|
54
|
+
* declared like any other.
|
|
55
|
+
*/
|
|
56
|
+
candidates?: Iterable<string>;
|
|
57
|
+
/** Attribution written into the header. */
|
|
58
|
+
generator?: string;
|
|
59
|
+
/**
|
|
60
|
+
* Rewrite a module specifier for the file being generated.
|
|
61
|
+
*
|
|
62
|
+
* A bundler and TypeScript do not agree on every specifier: Vite resolves a
|
|
63
|
+
* root-absolute `/src/x.tsx` that TypeScript cannot see at all. The caller knows where
|
|
64
|
+
* the file will land and so is the only one able to fix that up; the generator stays
|
|
65
|
+
* pure and just asks.
|
|
66
|
+
*/
|
|
67
|
+
specifier?: (module: string) => string;
|
|
68
|
+
}
|
|
69
|
+
export interface ComponentGlobalsResult {
|
|
70
|
+
/** The `.d.ts` source to write. */
|
|
71
|
+
source: string;
|
|
72
|
+
/** Components declared. */
|
|
73
|
+
declared: string[];
|
|
74
|
+
/** Left out because `lib.dom` already claims the name. */
|
|
75
|
+
shadowedByDom: string[];
|
|
76
|
+
/** Left out because the project does not depend on their package. */
|
|
77
|
+
unavailable: string[];
|
|
78
|
+
/**
|
|
79
|
+
* Pattern rules, which have no finite name list and so cannot be declared.
|
|
80
|
+
*
|
|
81
|
+
* `Icon(.+) -> @/icons/$1` matches unboundedly many names; the resolver answers them on
|
|
82
|
+
* demand but cannot enumerate them. Those tags stay manual, and the caller is told how
|
|
83
|
+
* many rules are in that position rather than left to wonder why nothing appeared.
|
|
84
|
+
*/
|
|
85
|
+
patternRules: number;
|
|
86
|
+
}
|
|
87
|
+
/** Build the ambient `.d.ts` for the components a project's `resolve` config supplies. */
|
|
88
|
+
export declare function componentGlobals(rules: readonly ComponentResolverRule[], options?: ComponentGlobalsOptions): ComponentGlobalsResult;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ambient declarations for the components `resolve` supplies without an import.
|
|
3
|
+
*
|
|
4
|
+
* The compiler injects the import, so nothing in the source imports these, which leaves
|
|
5
|
+
* TypeScript reporting `TS2304: Cannot find name`. The code compiles and runs; the editor
|
|
6
|
+
* is unusable and `tsc` fails. These declarations describe what the compiler already
|
|
7
|
+
* does. They do not enable it.
|
|
8
|
+
*
|
|
9
|
+
* This lives next to the resolver, and takes rules rather than a flat map, because the
|
|
10
|
+
* resolver is the only thing that knows the whole picture: a UI library's components, the
|
|
11
|
+
* project's own, and the framework builtins all arrive through the same config. A
|
|
12
|
+
* component library cannot generate this on its own, it does not know what else the
|
|
13
|
+
* project resolves: which is why the generator belongs here and the library-specific CLI
|
|
14
|
+
* that predates it does not.
|
|
15
|
+
*
|
|
16
|
+
* Pure, like the resolver: rules in, source out, no filesystem. Writing the file is the
|
|
17
|
+
* caller's job (the Vite plugin does it on config resolve; a CLI can do it in CI).
|
|
18
|
+
*/
|
|
19
|
+
import { type ComponentResolverRule } from './component-resolver.js';
|
|
20
|
+
export interface ComponentGlobalsOptions {
|
|
21
|
+
/**
|
|
22
|
+
* Packages the project can actually resolve: normally its declared dependencies.
|
|
23
|
+
*
|
|
24
|
+
* Declaring a component from a package the project does not depend on produces an
|
|
25
|
+
* unresolvable `import(...)`, and under the usual `skipLibCheck: true` that failure is
|
|
26
|
+
* silent: the component degrades to `any` and every prop typo type-checks, which is
|
|
27
|
+
* worse than the error it replaced. Omit to declare everything, which is only correct
|
|
28
|
+
* when every package is present.
|
|
29
|
+
*
|
|
30
|
+
* Relative and alias specifiers are never filtered, there is no package to check.
|
|
31
|
+
*/
|
|
32
|
+
available?: Iterable<string>;
|
|
33
|
+
/**
|
|
34
|
+
* Declare the framework builtins (`Show`, `For`, `Portal`, `Router`, …) too.
|
|
35
|
+
*
|
|
36
|
+
* On by default because the compiler resolves them whether or not a rule mentions
|
|
37
|
+
* them, so declaring them is what matches reality. A real import shadows the ambient
|
|
38
|
+
* declaration, so this stays safe for code that imports them explicitly.
|
|
39
|
+
*/
|
|
40
|
+
builtins?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Declare the `$` reactive intrinsics (`$signal`, `$memo`, …).
|
|
43
|
+
*
|
|
44
|
+
* On by default, matching the compiler: it rewrites those calls whether or not
|
|
45
|
+
* anything declares them, and without the declaration the editor reports
|
|
46
|
+
* "Cannot find name '$signal'" for code that builds correctly.
|
|
47
|
+
*/
|
|
48
|
+
intrinsics?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Names to try against the pattern rules.
|
|
51
|
+
*
|
|
52
|
+
* A pattern has no name list of its own, but the files it points at do: the caller lists
|
|
53
|
+
* them (the generator stays off the filesystem) and each name the resolver answers is
|
|
54
|
+
* declared like any other.
|
|
55
|
+
*/
|
|
56
|
+
candidates?: Iterable<string>;
|
|
57
|
+
/** Attribution written into the header. */
|
|
58
|
+
generator?: string;
|
|
59
|
+
/**
|
|
60
|
+
* Rewrite a module specifier for the file being generated.
|
|
61
|
+
*
|
|
62
|
+
* A bundler and TypeScript do not agree on every specifier: Vite resolves a
|
|
63
|
+
* root-absolute `/src/x.tsx` that TypeScript cannot see at all. The caller knows where
|
|
64
|
+
* the file will land and so is the only one able to fix that up; the generator stays
|
|
65
|
+
* pure and just asks.
|
|
66
|
+
*/
|
|
67
|
+
specifier?: (module: string) => string;
|
|
68
|
+
}
|
|
69
|
+
export interface ComponentGlobalsResult {
|
|
70
|
+
/** The `.d.ts` source to write. */
|
|
71
|
+
source: string;
|
|
72
|
+
/** Components declared. */
|
|
73
|
+
declared: string[];
|
|
74
|
+
/** Left out because `lib.dom` already claims the name. */
|
|
75
|
+
shadowedByDom: string[];
|
|
76
|
+
/** Left out because the project does not depend on their package. */
|
|
77
|
+
unavailable: string[];
|
|
78
|
+
/**
|
|
79
|
+
* Pattern rules, which have no finite name list and so cannot be declared.
|
|
80
|
+
*
|
|
81
|
+
* `Icon(.+) -> @/icons/$1` matches unboundedly many names; the resolver answers them on
|
|
82
|
+
* demand but cannot enumerate them. Those tags stay manual, and the caller is told how
|
|
83
|
+
* many rules are in that position rather than left to wonder why nothing appeared.
|
|
84
|
+
*/
|
|
85
|
+
patternRules: number;
|
|
86
|
+
}
|
|
87
|
+
/** Build the ambient `.d.ts` for the components a project's `resolve` config supplies. */
|
|
88
|
+
export declare function componentGlobals(rules: readonly ComponentResolverRule[], options?: ComponentGlobalsOptions): ComponentGlobalsResult;
|
|
89
|
+
//# sourceMappingURL=component-globals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component-globals.d.ts","sourceRoot":"","sources":["../../src/resolve/component-globals.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAEL,KAAK,qBAAqB,EAE3B,MAAM,yBAAyB,CAAC;AAmCjC,MAAM,WAAW,uBAAuB;IACtC;;;;;;;;;;OAUG;IACH,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC7B;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC9B,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;CACxC;AAED,MAAM,WAAW,sBAAsB;IACrC,mCAAmC;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,2BAA2B;IAC3B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,0DAA0D;IAC1D,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,qEAAqE;IACrE,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB;;;;;;OAMG;IACH,YAAY,EAAE,MAAM,CAAC;CACtB;AAgBD,0FAA0F;AAC1F,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,SAAS,qBAAqB,EAAE,EACvC,OAAO,GAAE,uBAA4B,GACpC,sBAAsB,CAoHxB"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ambient declarations for the components `resolve` supplies without an import.
|
|
3
|
+
*
|
|
4
|
+
* The compiler injects the import, so nothing in the source imports these, which leaves
|
|
5
|
+
* TypeScript reporting `TS2304: Cannot find name`. The code compiles and runs; the editor
|
|
6
|
+
* is unusable and `tsc` fails. These declarations describe what the compiler already
|
|
7
|
+
* does. They do not enable it.
|
|
8
|
+
*
|
|
9
|
+
* This lives next to the resolver, and takes rules rather than a flat map, because the
|
|
10
|
+
* resolver is the only thing that knows the whole picture: a UI library's components, the
|
|
11
|
+
* project's own, and the framework builtins all arrive through the same config. A
|
|
12
|
+
* component library cannot generate this on its own, it does not know what else the
|
|
13
|
+
* project resolves: which is why the generator belongs here and the library-specific CLI
|
|
14
|
+
* that predates it does not.
|
|
15
|
+
*
|
|
16
|
+
* Pure, like the resolver: rules in, source out, no filesystem. Writing the file is the
|
|
17
|
+
* caller's job (the Vite plugin does it on config resolve; a CLI can do it in CI).
|
|
18
|
+
*/
|
|
19
|
+
import { createComponentResolver, } from './component-resolver.js';
|
|
20
|
+
import { builtinComponentMap } from './builtins.js';
|
|
21
|
+
import { INTRINSICS, TAG_INTRINSICS } from '../analyze/intrinsics.js';
|
|
22
|
+
/**
|
|
23
|
+
* Names `lib.dom` already declares as globals.
|
|
24
|
+
*
|
|
25
|
+
* An ambient `const Text` cannot beat `lib.dom`'s `var Text`, so for these the editor
|
|
26
|
+
* would disagree with the compiler: resolution still works at runtime, but the type
|
|
27
|
+
* shown would be the DOM node's. They are left out and reported instead, since importing
|
|
28
|
+
* them explicitly makes both agree.
|
|
29
|
+
*/
|
|
30
|
+
const DOM_GLOBALS = new Set([
|
|
31
|
+
'Text',
|
|
32
|
+
'Image',
|
|
33
|
+
'Option',
|
|
34
|
+
'Audio',
|
|
35
|
+
'Comment',
|
|
36
|
+
'Range',
|
|
37
|
+
'Selection',
|
|
38
|
+
'Notification',
|
|
39
|
+
'Event',
|
|
40
|
+
'Document',
|
|
41
|
+
'Element',
|
|
42
|
+
'Node',
|
|
43
|
+
'Screen',
|
|
44
|
+
'Window',
|
|
45
|
+
'Location',
|
|
46
|
+
'History',
|
|
47
|
+
'Storage',
|
|
48
|
+
'Response',
|
|
49
|
+
'Request',
|
|
50
|
+
'Headers',
|
|
51
|
+
]);
|
|
52
|
+
/** The package a specifier belongs to, or undefined when it is not a package import. */
|
|
53
|
+
function packageOf(specifier) {
|
|
54
|
+
if (specifier.startsWith('.') || specifier.startsWith('/'))
|
|
55
|
+
return undefined;
|
|
56
|
+
// Alias specifiers (`@/x`, `~/x`) are project-local and resolve through tsconfig paths.
|
|
57
|
+
if (/^[~@]\//.test(specifier))
|
|
58
|
+
return undefined;
|
|
59
|
+
const parts = specifier.split('/');
|
|
60
|
+
return specifier.startsWith('@') ? parts.slice(0, 2).join('/') : parts[0];
|
|
61
|
+
}
|
|
62
|
+
/** A valid identifier for the namespace import of `module`. */
|
|
63
|
+
function namespaceAlias(module) {
|
|
64
|
+
return `_${module.replace(/[^A-Za-z0-9]/g, '_')}`;
|
|
65
|
+
}
|
|
66
|
+
/** Build the ambient `.d.ts` for the components a project's `resolve` config supplies. */
|
|
67
|
+
export function componentGlobals(rules, options = {}) {
|
|
68
|
+
const { available: availableList, builtins = true, intrinsics = true, generator = '@fluixi/compiler', specifier = (module) => module, candidates = [], } = options;
|
|
69
|
+
const all = [...rules];
|
|
70
|
+
if (builtins) {
|
|
71
|
+
// Appended, so an explicit rule for the same name still wins, the resolver is
|
|
72
|
+
// first-match, and a project retargeting `Router` should keep its own answer.
|
|
73
|
+
all.push({ components: builtinComponentMap() });
|
|
74
|
+
}
|
|
75
|
+
const resolver = createComponentResolver(all);
|
|
76
|
+
const available = availableList ? new Set(availableList) : undefined;
|
|
77
|
+
const declared = [];
|
|
78
|
+
const shadowedByDom = [];
|
|
79
|
+
const unavailable = [];
|
|
80
|
+
const resolved = new Map();
|
|
81
|
+
const names = new Set([...resolver.names(), ...[...candidates].filter((n) => /^[A-Za-z_$][\w$]*$/.test(n))]);
|
|
82
|
+
for (const name of [...names].sort()) {
|
|
83
|
+
const target = resolver.resolve(name);
|
|
84
|
+
if (!target)
|
|
85
|
+
continue;
|
|
86
|
+
const pkg = packageOf(target.module);
|
|
87
|
+
if (DOM_GLOBALS.has(name))
|
|
88
|
+
shadowedByDom.push(name);
|
|
89
|
+
else if (available && pkg && !available.has(pkg))
|
|
90
|
+
unavailable.push(name);
|
|
91
|
+
else {
|
|
92
|
+
declared.push(name);
|
|
93
|
+
resolved.set(name, target);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// The `$` intrinsics need declaring too, or the editor says "Cannot find name
|
|
97
|
+
// '$signal'" for code that compiles. tsc doesn't load language-service plugins, so an
|
|
98
|
+
// ambient declaration is the only thing that answers for both the editor and the
|
|
99
|
+
// command line.
|
|
100
|
+
// Only the intrinsics whose package the project has: `$env` comes from `@fluixi/start`, and
|
|
101
|
+
// an app without it would otherwise get a declaration that fails to resolve.
|
|
102
|
+
const usableIntrinsics = intrinsics
|
|
103
|
+
? Object.entries({ ...INTRINSICS, ...TAG_INTRINSICS }).filter(([, i]) => {
|
|
104
|
+
const pkg = packageOf(i.module);
|
|
105
|
+
return !available || !pkg || available.has(pkg);
|
|
106
|
+
})
|
|
107
|
+
: [];
|
|
108
|
+
const intrinsicModules = [...new Set(usableIntrinsics.map(([, i]) => i.module))];
|
|
109
|
+
const modules = [
|
|
110
|
+
...new Set([...declared.map((name) => resolved.get(name).module), ...intrinsicModules]),
|
|
111
|
+
].sort();
|
|
112
|
+
const imports = modules.map((m) => `import * as ${namespaceAlias(m)} from '${specifier(m)}';`);
|
|
113
|
+
// `export import X = ns.X` rather than `const X: typeof import('…').X`: an alias
|
|
114
|
+
// resolves to the original symbol, so hover shows the real declaration
|
|
115
|
+
// (`Button(props: ButtonProps): ComponentChild`) and go-to-definition lands on the
|
|
116
|
+
// source. Both forms keep the JSDoc; the alias also keeps the shape.
|
|
117
|
+
//
|
|
118
|
+
// A default export cannot use it: `import X = ns.default` is a syntax error, since
|
|
119
|
+
// `default` is a reserved word in that position, so those fall back to the `const`
|
|
120
|
+
// form, which types and documents correctly but renders as an anonymous arrow.
|
|
121
|
+
const lines = declared.map((name) => {
|
|
122
|
+
const target = resolved.get(name);
|
|
123
|
+
const ns = namespaceAlias(target.module);
|
|
124
|
+
return target.export === 'default'
|
|
125
|
+
? ` const ${name}: typeof ${ns}.default;`
|
|
126
|
+
: ` export import ${name} = ${ns}.${target.export};`;
|
|
127
|
+
});
|
|
128
|
+
const note = shadowedByDom.length > 0
|
|
129
|
+
? `//\n// Import these explicitly: lib.dom already declares the name, so an ambient\n` +
|
|
130
|
+
`// declaration cannot win:\n` +
|
|
131
|
+
shadowedByDom
|
|
132
|
+
.map((n) => {
|
|
133
|
+
const module = resolver.resolve(n)?.module;
|
|
134
|
+
return `// import { ${n} } from '${module ? specifier(module) : ''}';\n`;
|
|
135
|
+
})
|
|
136
|
+
.join('')
|
|
137
|
+
: '';
|
|
138
|
+
// `typeof ns.signal` rather than an alias: the intrinsic is a global that stands for
|
|
139
|
+
// the runtime call, so it takes the runtime's signature without claiming to be that
|
|
140
|
+
// symbol: go-to-definition on `$signal` should land on what it compiles to.
|
|
141
|
+
const intrinsicLines = usableIntrinsics.map(([name, intrinsic]) => ` const ${name}: typeof ${namespaceAlias(intrinsic.module)}.${intrinsic.export};`);
|
|
142
|
+
const patternRules = rules.filter((rule) => 'match' in rule).length;
|
|
143
|
+
const patternNote = patternRules === 0
|
|
144
|
+
? ''
|
|
145
|
+
: options.candidates
|
|
146
|
+
? `//\n// ${patternRules} pattern rule${patternRules === 1 ? '' : 's'}: declared for the files the module path\n` +
|
|
147
|
+
`// points at. A name with no such file still resolves at build time; declare it by hand.\n`
|
|
148
|
+
: `//\n// ${patternRules} pattern rule${patternRules === 1 ? '' : 's'} cannot be declared:\n` +
|
|
149
|
+
`// a pattern matches unboundedly many names, so there is no list to emit. Those\n` +
|
|
150
|
+
`// tags still resolve at build time; declare them by hand if the editor needs them.\n`;
|
|
151
|
+
const source = `// GENERATED by ${generator}, do not edit.\n` +
|
|
152
|
+
`//\n` +
|
|
153
|
+
`// The components \`resolve\` supplies without an import. This describes what the\n` +
|
|
154
|
+
`// compiler already does; it does not enable it.\n` +
|
|
155
|
+
note +
|
|
156
|
+
patternNote +
|
|
157
|
+
(imports.length > 0 ? `\n${imports.join('\n')}\n` : '\n') +
|
|
158
|
+
`\ndeclare global {\n${[...lines, ...intrinsicLines].join('\n')}\n}\n`;
|
|
159
|
+
return { source, declared, shadowedByDom, unavailable, patternRules };
|
|
160
|
+
}
|