@impetik/xeer-mcp 0.2.18 → 0.2.20
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/README.md +2 -2
- package/dist/server.js +4 -1
- package/package.json +2 -2
- package/vendor/spec/actions.d.ts +10 -5
- package/vendor/spec/actions.js +23 -8
- package/vendor/spec/diagnostics.js +95 -11
- package/vendor/spec/editor-settings.d.ts +26 -0
- package/vendor/spec/editor-settings.js +33 -0
- package/vendor/spec/import-policy.d.ts +168 -18
- package/vendor/spec/import-policy.js +284 -56
- package/vendor/spec/index.d.ts +2 -0
- package/vendor/spec/index.js +2 -0
- package/vendor/spec/schema.d.ts +5 -1
- package/vendor/spec/schema.js +57 -6
- package/vendor/spec/template-distribution.d.ts +101 -0
- package/vendor/spec/template-distribution.js +158 -0
- package/vendor/spec/template.d.ts +54 -6
- package/vendor/spec/template.js +34 -14
- package/vendor/spec/tunnel.d.ts +3 -0
- package/vendor/spec/tunnel.js +18 -0
- package/vendor/spec/type-check-profile.d.ts +65 -4
- package/vendor/spec/type-check-profile.js +144 -12
- package/vendor/spec/types.d.ts +49 -11
- package/vendor/spec/types.js +24 -0
|
@@ -15,15 +15,33 @@
|
|
|
15
15
|
* source, and vendoring folds it into the published tarball with everything else.
|
|
16
16
|
*/
|
|
17
17
|
/**
|
|
18
|
-
* The
|
|
19
|
-
*
|
|
20
|
-
*
|
|
18
|
+
* The UI providers the platform implements, in the spelling `client.runtime.provider` uses.
|
|
19
|
+
*
|
|
20
|
+
* A provider is a whole renderer family — packages, entrypoint classification, JSX runtimes, and
|
|
21
|
+
* the compat aliases the family does or does not offer — and the client zone's policy is a pure
|
|
22
|
+
* function of which one the manifest declares ({@link clientImportPolicy}). Adding a provider is
|
|
23
|
+
* adding a family and a case, never a flag threaded through the consumers: what a specifier means
|
|
24
|
+
* on the client has exactly one answer per provider, stated here.
|
|
25
|
+
*/
|
|
26
|
+
export const CLIENT_RUNTIME_PROVIDERS = Object.freeze(['preact', 'react']);
|
|
27
|
+
/**
|
|
28
|
+
* The default client runtime. `client.runtime` in the manifest is optional and omission normalizes
|
|
29
|
+
* to exactly this value, so an application that says nothing gets the Preact provider it always
|
|
30
|
+
* had — byte-for-byte, down to the artifact identity.
|
|
31
|
+
*
|
|
32
|
+
* The *normalized* runtime of a given application is whatever its manifest declares; this is only
|
|
33
|
+
* the value omission means. Provenance and compiler facts must derive from the manifest's own
|
|
34
|
+
* runtime through {@link clientRuntimeId}, never from this constant.
|
|
21
35
|
*/
|
|
22
36
|
export const NORMALIZED_CLIENT_RUNTIME = Object.freeze({
|
|
23
37
|
provider: 'preact',
|
|
24
38
|
source: 'platform',
|
|
25
39
|
});
|
|
26
|
-
/**
|
|
40
|
+
/** How a client runtime is spelled in compiler facts and artifact provenance. */
|
|
41
|
+
export function clientRuntimeId(runtime) {
|
|
42
|
+
return `${runtime.provider}/${runtime.source}`;
|
|
43
|
+
}
|
|
44
|
+
/** The default client runtime as compiler facts and artifact provenance spell it. */
|
|
27
45
|
export const CLIENT_RUNTIME_ID = `${NORMALIZED_CLIENT_RUNTIME.provider}/${NORMALIZED_CLIENT_RUNTIME.source}`;
|
|
28
46
|
/**
|
|
29
47
|
* Default and advisory budgets for the open client bundle, minified pre-gzip bytes of the single
|
|
@@ -33,38 +51,57 @@ export const CLIENT_RUNTIME_ID = `${NORMALIZED_CLIENT_RUNTIME.provider}/${NORMAL
|
|
|
33
51
|
*/
|
|
34
52
|
export const CLIENT_BUNDLE_ERROR_BUDGET_BYTES = 1024 * 1024;
|
|
35
53
|
export const CLIENT_BUNDLE_ADVISORY_BUDGET_BYTES = 400 * 1024;
|
|
54
|
+
/** An entrypoint the anchor package ships declarations for, through its own `types` condition. */
|
|
55
|
+
function selfTyped(classification) {
|
|
56
|
+
return { classification, types: { kind: 'anchor' } };
|
|
57
|
+
}
|
|
58
|
+
/** An entrypoint whose declarations a `@types/*` package publishes, at `specifier`. */
|
|
59
|
+
function typedBy(classification, specifier) {
|
|
60
|
+
return { classification, types: { kind: 'types-package', specifier } };
|
|
61
|
+
}
|
|
62
|
+
/** An entrypoint no package publishes declarations for. */
|
|
63
|
+
function untyped(classification) {
|
|
64
|
+
return { classification, types: { kind: 'none' } };
|
|
65
|
+
}
|
|
36
66
|
/**
|
|
37
|
-
* Every public entrypoint of the platform Preact package,
|
|
38
|
-
* test compares this map against the installed package's `exports`
|
|
39
|
-
* Preact upgrade that adds, removes, or renames an entrypoint fails
|
|
40
|
-
* classified here
|
|
67
|
+
* Every public entrypoint of the platform Preact package: what it is for, and where its declarations
|
|
68
|
+
* live. The compiler's conformance test compares this map against the installed package's `exports`
|
|
69
|
+
* map in both directions, so a Preact upgrade that adds, removes, or renames an entrypoint fails
|
|
70
|
+
* until it is deliberately classified here — and a second test resolves every declared types source,
|
|
71
|
+
* so an upgrade that *moves* the declarations fails here rather than silently in an editor.
|
|
72
|
+
*
|
|
73
|
+
* Preact ships its own declarations, so almost every entrypoint is `anchor`. The exceptions are
|
|
74
|
+
* facts about the published package rather than judgements: `compat/server` and `compat/scheduler`
|
|
75
|
+
* publish no `types` condition at all, and `compat/server.browser` publishes one naming
|
|
76
|
+
* `./compat/server.d.ts`, a file the package does not contain. All three are `none`, which is why
|
|
77
|
+
* neither `xeer check` nor an editor answers them — the same refusal, from the same declaration.
|
|
41
78
|
*/
|
|
42
79
|
const PREACT_ENTRYPOINTS = new Map([
|
|
43
|
-
['preact', 'runtime'],
|
|
44
|
-
['preact/hooks', 'runtime'],
|
|
45
|
-
['preact/jsx-runtime', 'runtime'],
|
|
46
|
-
['preact/jsx-dev-runtime', 'runtime'],
|
|
47
|
-
['preact/compat', 'runtime'],
|
|
48
|
-
['preact/compat/client', 'runtime'],
|
|
80
|
+
['preact', selfTyped('runtime')],
|
|
81
|
+
['preact/hooks', selfTyped('runtime')],
|
|
82
|
+
['preact/jsx-runtime', selfTyped('runtime')],
|
|
83
|
+
['preact/jsx-dev-runtime', selfTyped('runtime')],
|
|
84
|
+
['preact/compat', selfTyped('runtime')],
|
|
85
|
+
['preact/compat/client', selfTyped('runtime')],
|
|
49
86
|
// Browser-safe server rendering: both resolve to the browser build under the client conditions.
|
|
50
|
-
['preact/compat/server', 'runtime'],
|
|
51
|
-
['preact/compat/server.browser', 'runtime'],
|
|
52
|
-
['preact/compat/jsx-runtime', 'runtime'],
|
|
53
|
-
['preact/compat/jsx-dev-runtime', 'runtime'],
|
|
54
|
-
['preact/compat/scheduler', 'runtime'],
|
|
87
|
+
['preact/compat/server', untyped('runtime')],
|
|
88
|
+
['preact/compat/server.browser', untyped('runtime')],
|
|
89
|
+
['preact/compat/jsx-runtime', selfTyped('runtime')],
|
|
90
|
+
['preact/compat/jsx-dev-runtime', selfTyped('runtime')],
|
|
91
|
+
['preact/compat/scheduler', untyped('runtime')],
|
|
55
92
|
// Side-effectful development surfaces: they mutate the shared renderer options, which is exactly
|
|
56
93
|
// why they must be pinned to the same singleton as everything else.
|
|
57
|
-
['preact/debug', 'development'],
|
|
58
|
-
['preact/devtools', 'development'],
|
|
59
|
-
['preact/test-utils', 'test'],
|
|
60
|
-
['preact/compat/test-utils', 'test'],
|
|
61
|
-
['preact/package.json', 'metadata'],
|
|
62
|
-
['preact/compat/package.json', 'metadata'],
|
|
63
|
-
['preact/debug/package.json', 'metadata'],
|
|
64
|
-
['preact/devtools/package.json', 'metadata'],
|
|
65
|
-
['preact/hooks/package.json', 'metadata'],
|
|
66
|
-
['preact/test-utils/package.json', 'metadata'],
|
|
67
|
-
['preact/jsx-runtime/package.json', 'metadata'],
|
|
94
|
+
['preact/debug', selfTyped('development')],
|
|
95
|
+
['preact/devtools', selfTyped('development')],
|
|
96
|
+
['preact/test-utils', selfTyped('test')],
|
|
97
|
+
['preact/compat/test-utils', selfTyped('test')],
|
|
98
|
+
['preact/package.json', untyped('metadata')],
|
|
99
|
+
['preact/compat/package.json', untyped('metadata')],
|
|
100
|
+
['preact/debug/package.json', untyped('metadata')],
|
|
101
|
+
['preact/devtools/package.json', untyped('metadata')],
|
|
102
|
+
['preact/hooks/package.json', untyped('metadata')],
|
|
103
|
+
['preact/test-utils/package.json', untyped('metadata')],
|
|
104
|
+
['preact/jsx-runtime/package.json', untyped('metadata')],
|
|
68
105
|
]);
|
|
69
106
|
/**
|
|
70
107
|
* The complete per-subpath React-family alias table. Every key is pinned to its target for every
|
|
@@ -85,7 +122,8 @@ const REACT_COMPAT_ALIASES = new Map([
|
|
|
85
122
|
]);
|
|
86
123
|
/** The client renderer family under the Preact provider. */
|
|
87
124
|
export const PREACT_RENDERER_FAMILY = Object.freeze({
|
|
88
|
-
|
|
125
|
+
provider: 'preact',
|
|
126
|
+
anchorPackages: Object.freeze(['preact']),
|
|
89
127
|
packages: Object.freeze(['preact', 'react', 'react-dom', 'scheduler']),
|
|
90
128
|
entrypoints: PREACT_ENTRYPOINTS,
|
|
91
129
|
compatAliases: REACT_COMPAT_ALIASES,
|
|
@@ -95,8 +133,98 @@ export const PREACT_RENDERER_FAMILY = Object.freeze({
|
|
|
95
133
|
devRuntime: 'preact/jsx-dev-runtime',
|
|
96
134
|
}),
|
|
97
135
|
});
|
|
136
|
+
/**
|
|
137
|
+
* Every public entrypoint of the platform React packages, classified — the same hand-maintained
|
|
138
|
+
* statement `PREACT_ENTRYPOINTS` makes, across the three packages React ships its client surface in,
|
|
139
|
+
* and gated by the same bidirectional conformance test per package.
|
|
140
|
+
*
|
|
141
|
+
* Two things are decided here that Preact never had to decide. The first is the `react-server`
|
|
142
|
+
* condition: every subpath publishes one, and the client zone is not a React Server Components
|
|
143
|
+
* environment, so resolution under `browser`/`import`/`module` deliberately never selects it. The
|
|
144
|
+
* second is that React publishes one subpath per *host runtime* — `server.node`, `server.bun`,
|
|
145
|
+
* `server.edge` and their `static` counterparts. Those are real, supported entrypoints holding bytes
|
|
146
|
+
* for a runtime the browser is not, so they are classified `other-runtime` rather than left
|
|
147
|
+
* unclassified: the difference is a diagnostic that explains itself against one that misinforms.
|
|
148
|
+
* The condition-switched `react-dom/server` and `react-dom/static` resolve to the browser build here
|
|
149
|
+
* and are admitted, exactly as `preact/compat/server` is.
|
|
150
|
+
*
|
|
151
|
+
* `scheduler` publishes no `exports` map at all, so nothing gates its classification the way the
|
|
152
|
+
* other two are gated; its conformance test pins the absence instead.
|
|
153
|
+
*
|
|
154
|
+
* React ships no declarations of its own, so every types source here is a `@types/*` subpath — and
|
|
155
|
+
* the two entrypoints DefinitelyTyped does not cover are stated as such rather than left out.
|
|
156
|
+
* `react-dom/profiling` has no `@types/react-dom` subpath and `scheduler` has no types package
|
|
157
|
+
* installed at all, which is why both tools refuse them and both are right.
|
|
158
|
+
*/
|
|
159
|
+
const REACT_ENTRYPOINTS = new Map([
|
|
160
|
+
['react', typedBy('runtime', '@types/react')],
|
|
161
|
+
['react/jsx-runtime', typedBy('runtime', '@types/react/jsx-runtime')],
|
|
162
|
+
['react/jsx-dev-runtime', typedBy('runtime', '@types/react/jsx-dev-runtime')],
|
|
163
|
+
// Emitted by the React Compiler in place of the hooks it rewrites; part of the runtime surface
|
|
164
|
+
// whether or not this application runs the compiler, because a dependency's build may have.
|
|
165
|
+
['react/compiler-runtime', typedBy('runtime', '@types/react/compiler-runtime')],
|
|
166
|
+
['react-dom', typedBy('runtime', '@types/react-dom')],
|
|
167
|
+
['react-dom/client', typedBy('runtime', '@types/react-dom/client')],
|
|
168
|
+
// Browser-safe server rendering: both resolve to the browser build under the client conditions.
|
|
169
|
+
['react-dom/server', typedBy('runtime', '@types/react-dom/server')],
|
|
170
|
+
['react-dom/server.browser', typedBy('runtime', '@types/react-dom/server.browser')],
|
|
171
|
+
['react-dom/static', typedBy('runtime', '@types/react-dom/static')],
|
|
172
|
+
['react-dom/static.browser', typedBy('runtime', '@types/react-dom/static.browser')],
|
|
173
|
+
['react-dom/server.bun', typedBy('other-runtime', '@types/react-dom/server.bun')],
|
|
174
|
+
['react-dom/server.edge', typedBy('other-runtime', '@types/react-dom/server.edge')],
|
|
175
|
+
['react-dom/server.node', typedBy('other-runtime', '@types/react-dom/server.node')],
|
|
176
|
+
['react-dom/static.edge', typedBy('other-runtime', '@types/react-dom/static.edge')],
|
|
177
|
+
['react-dom/static.node', typedBy('other-runtime', '@types/react-dom/static.node')],
|
|
178
|
+
// The profiling build swaps in an instrumented reconciler, which is exactly the kind of
|
|
179
|
+
// whole-renderer substitution that must stay pinned to the one instance.
|
|
180
|
+
['react-dom/profiling', untyped('development')],
|
|
181
|
+
['react-dom/test-utils', typedBy('test', '@types/react-dom/test-utils')],
|
|
182
|
+
['scheduler', untyped('runtime')],
|
|
183
|
+
['react/package.json', untyped('metadata')],
|
|
184
|
+
['react-dom/package.json', untyped('metadata')],
|
|
185
|
+
['scheduler/package.json', untyped('metadata')],
|
|
186
|
+
]);
|
|
187
|
+
/**
|
|
188
|
+
* The client renderer family under the React provider: React itself, not a compatibility layer.
|
|
189
|
+
*
|
|
190
|
+
* No `compatAliases`, and the omission is the point. Under Preact the React-ecosystem specifiers are
|
|
191
|
+
* aliases onto `preact/compat` so a React library and the renderer stay one instance; under React
|
|
192
|
+
* they *are* the renderer, and an alias table would be a second name for the same file.
|
|
193
|
+
*/
|
|
194
|
+
export const REACT_RENDERER_FAMILY = Object.freeze({
|
|
195
|
+
provider: 'react',
|
|
196
|
+
anchorPackages: Object.freeze(['react', 'react-dom', 'scheduler']),
|
|
197
|
+
packages: Object.freeze(['react', 'react-dom', 'scheduler']),
|
|
198
|
+
entrypoints: REACT_ENTRYPOINTS,
|
|
199
|
+
compatAliases: new Map(),
|
|
200
|
+
jsx: Object.freeze({
|
|
201
|
+
importSource: '@impetik/xeer',
|
|
202
|
+
runtime: 'react/jsx-runtime',
|
|
203
|
+
devRuntime: 'react/jsx-dev-runtime',
|
|
204
|
+
}),
|
|
205
|
+
});
|
|
206
|
+
/**
|
|
207
|
+
* The client facade, and the provider-specific subpaths it resolves to.
|
|
208
|
+
*
|
|
209
|
+
* The platform publishes one adapter subpath per provider beside `@impetik/xeer/client`, so that
|
|
210
|
+
* the facade has a physical module to resolve to and a packed install can be verified against the
|
|
211
|
+
* adapter directly. `./client/preact` is an alias of `./client` rather than a module of its own —
|
|
212
|
+
* the Preact adapter has always been what the facade resolves to by default, and giving it a name
|
|
213
|
+
* moves nothing about how it resolves or what a build produces. Every provider being addressable is
|
|
214
|
+
* what makes this set derivable from {@link CLIENT_RUNTIME_PROVIDERS} instead of hand-listed, and
|
|
215
|
+
* what keeps the refusal below able to say the adapter exists.
|
|
216
|
+
*
|
|
217
|
+
* Naming an adapter is not an application's business under either provider: it would pin one
|
|
218
|
+
* renderer into sources whose entire contract is that `client.runtime.provider` picks the renderer
|
|
219
|
+
* and the sources do not change. So the targets are published and inadmissible everywhere — but the
|
|
220
|
+
* *reason* they are refused is per zone, because the repair is. Where the facade is admitted, the
|
|
221
|
+
* repair is to write the facade; where it is not, the module is in the wrong zone and is told so,
|
|
222
|
+
* which is the same thing `@impetik/xeer/client` itself is told there.
|
|
223
|
+
*/
|
|
224
|
+
const CLIENT_FACADE_MODULE = '@impetik/xeer/client';
|
|
225
|
+
const CLIENT_FACADE_TARGETS = Object.freeze(new Set(CLIENT_RUNTIME_PROVIDERS.map((provider) => `${CLIENT_FACADE_MODULE}/${provider}`)));
|
|
98
226
|
const CLIENT_PLATFORM_MODULES = Object.freeze([
|
|
99
|
-
|
|
227
|
+
CLIENT_FACADE_MODULE,
|
|
100
228
|
'@impetik/xeer/client/core',
|
|
101
229
|
'@impetik/xeer/shared',
|
|
102
230
|
'@impetik/xeer/jsx-runtime',
|
|
@@ -106,21 +234,58 @@ const SERVER_PLATFORM_MODULES = Object.freeze([
|
|
|
106
234
|
'@impetik/xeer/server',
|
|
107
235
|
'@impetik/xeer/shared',
|
|
108
236
|
]);
|
|
237
|
+
/**
|
|
238
|
+
* What the client zone admits *besides* the renderer, which is the same under every provider: the
|
|
239
|
+
* open application-dependency set, its resolution conditions, its compile-time defines, and its byte
|
|
240
|
+
* budgets. Shared by identity across the provider policies so that choosing a renderer cannot
|
|
241
|
+
* silently change the byte budget an application is held to.
|
|
242
|
+
*/
|
|
243
|
+
const CLIENT_APPLICATION_DEPENDENCIES = Object.freeze({
|
|
244
|
+
mode: 'open',
|
|
245
|
+
conditions: Object.freeze(['browser', 'import']),
|
|
246
|
+
defines: Object.freeze({ 'process.env.NODE_ENV': '"production"' }),
|
|
247
|
+
bundleBudget: Object.freeze({
|
|
248
|
+
errorBytes: CLIENT_BUNDLE_ERROR_BUDGET_BYTES,
|
|
249
|
+
advisoryBytes: CLIENT_BUNDLE_ADVISORY_BUDGET_BYTES,
|
|
250
|
+
}),
|
|
251
|
+
});
|
|
109
252
|
export const CLIENT_IMPORT_POLICY = Object.freeze({
|
|
110
253
|
zone: 'client',
|
|
254
|
+
provider: 'preact',
|
|
111
255
|
platformModules: CLIENT_PLATFORM_MODULES,
|
|
112
256
|
managedFamilies: Object.freeze([PREACT_RENDERER_FAMILY]),
|
|
113
257
|
foreignFamilies: Object.freeze([]),
|
|
114
|
-
applicationDependencies:
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
258
|
+
applicationDependencies: CLIENT_APPLICATION_DEPENDENCIES,
|
|
259
|
+
});
|
|
260
|
+
/**
|
|
261
|
+
* The client zone under the React provider.
|
|
262
|
+
*
|
|
263
|
+
* The Preact family is *foreign* here for the same reason the renderer is foreign on the server: it
|
|
264
|
+
* is declared and installed by the platform whatever the application chose, so nothing but an
|
|
265
|
+
* explicit rule keeps it out of a React bundle — and a bundle holding both renderers has two
|
|
266
|
+
* reconcilers rendering into one tree. The two families name overlapping packages (`react` and
|
|
267
|
+
* friends are Preact's alias keys and React's own entrypoints), which is resolved by precedence
|
|
268
|
+
* rather than by trimming either list: {@link admitBareImport} asks the managed families first, so
|
|
269
|
+
* under this policy `react` is the renderer and only `preact*` is left for the foreign rule to
|
|
270
|
+
* refuse. {@link foreignPackageFamily} is that precedence, shared with every other consumer.
|
|
271
|
+
*/
|
|
272
|
+
const REACT_CLIENT_IMPORT_POLICY = Object.freeze({
|
|
273
|
+
zone: 'client',
|
|
274
|
+
provider: 'react',
|
|
275
|
+
platformModules: CLIENT_PLATFORM_MODULES,
|
|
276
|
+
managedFamilies: Object.freeze([REACT_RENDERER_FAMILY]),
|
|
277
|
+
foreignFamilies: Object.freeze([PREACT_RENDERER_FAMILY]),
|
|
278
|
+
applicationDependencies: CLIENT_APPLICATION_DEPENDENCIES,
|
|
123
279
|
});
|
|
280
|
+
/**
|
|
281
|
+
* The client zone's policy under one UI provider — a pure function of the normalized manifest's
|
|
282
|
+
* `client.runtime.provider`, with no state and no first-caller latching. The Preact instance is
|
|
283
|
+
* returned by identity so consumers that still read {@link CLIENT_IMPORT_POLICY} and consumers that
|
|
284
|
+
* ask for the default share one object, and so the resolver caches keyed on it stay shared.
|
|
285
|
+
*/
|
|
286
|
+
export function clientImportPolicy(provider) {
|
|
287
|
+
return provider === 'react' ? REACT_CLIENT_IMPORT_POLICY : CLIENT_IMPORT_POLICY;
|
|
288
|
+
}
|
|
124
289
|
/**
|
|
125
290
|
* The server zone, open to application dependencies since ADR 0005 was accepted (#244).
|
|
126
291
|
*
|
|
@@ -141,6 +306,7 @@ export const CLIENT_IMPORT_POLICY = Object.freeze({
|
|
|
141
306
|
*/
|
|
142
307
|
export const SERVER_IMPORT_POLICY = Object.freeze({
|
|
143
308
|
zone: 'server',
|
|
309
|
+
provider: null,
|
|
144
310
|
platformModules: SERVER_PLATFORM_MODULES,
|
|
145
311
|
managedFamilies: Object.freeze([]),
|
|
146
312
|
foreignFamilies: Object.freeze([PREACT_RENDERER_FAMILY]),
|
|
@@ -151,14 +317,38 @@ export const SERVER_IMPORT_POLICY = Object.freeze({
|
|
|
151
317
|
bundleBudget: null,
|
|
152
318
|
}),
|
|
153
319
|
});
|
|
154
|
-
|
|
155
|
-
|
|
320
|
+
/**
|
|
321
|
+
* One zone's policy. The provider only reaches the client zone — the server has no renderer to
|
|
322
|
+
* choose — and defaults to the manifest default so a caller with no manifest in hand (documentation,
|
|
323
|
+
* the server zone) reads exactly what it read before.
|
|
324
|
+
*/
|
|
325
|
+
export function zoneImportPolicy(zone, provider = NORMALIZED_CLIENT_RUNTIME.provider) {
|
|
326
|
+
return zone === 'client' ? clientImportPolicy(provider) : SERVER_IMPORT_POLICY;
|
|
156
327
|
}
|
|
157
328
|
/** The bare package name of a specifier: the first segment, or the first two for a scope. */
|
|
158
329
|
export function packageNameOfSpecifier(specifier) {
|
|
159
330
|
const segments = specifier.split('/');
|
|
160
331
|
return specifier.startsWith('@') ? segments.slice(0, 2).join('/') : segments[0];
|
|
161
332
|
}
|
|
333
|
+
/**
|
|
334
|
+
* DefinitelyTyped's name for a package's declarations.
|
|
335
|
+
*
|
|
336
|
+
* A naming rule rather than a lookup, and one nobody guesses correctly for a scoped package: the
|
|
337
|
+
* scope is *flattened into* the name rather than kept, so `@acme/widget` publishes as
|
|
338
|
+
* `@types/acme__widget`. Computed here, beside the specifier-naming rule it is a sibling of, so the
|
|
339
|
+
* two places that need it — the repair for a package with no declarations, and the check for whether
|
|
340
|
+
* an acknowledgment is still true — cannot disagree.
|
|
341
|
+
*
|
|
342
|
+
* Computed rather than read out of TypeScript's own TS7016 message, which carries the same name in
|
|
343
|
+
* English prose. That prose is not contract and has been reworded across releases; a rule this short
|
|
344
|
+
* is cheaper to state than to parse.
|
|
345
|
+
*
|
|
346
|
+
* Whether the package actually exists on the registry is unknowable offline, and nothing in the
|
|
347
|
+
* compiler contacts one at check time — so a caller quoting this must say it as the convention it is.
|
|
348
|
+
*/
|
|
349
|
+
export function definitelyTypedPackage(packageName) {
|
|
350
|
+
return `@types/${packageName.replace(/^@/, '').replace('/', '__')}`;
|
|
351
|
+
}
|
|
162
352
|
/**
|
|
163
353
|
* Classifies one bare specifier under a zone's policy. Node builtins and native addons are the
|
|
164
354
|
* caller's concern (the analyzer already owns those, and they are refused in every zone); everything
|
|
@@ -168,33 +358,67 @@ export function packageNameOfSpecifier(specifier) {
|
|
|
168
358
|
export function admitBareImport(policy, specifier) {
|
|
169
359
|
if (policy.platformModules.includes(specifier))
|
|
170
360
|
return { kind: 'platform' };
|
|
361
|
+
// Only where the facade is admitted is "import the facade instead" the repair; a server module
|
|
362
|
+
// naming a client adapter is in the wrong zone, and gets told that instead.
|
|
363
|
+
if (CLIENT_FACADE_TARGETS.has(specifier) && policy.platformModules.includes(CLIENT_FACADE_MODULE)) {
|
|
364
|
+
return { kind: 'rejected', reason: 'provider-facade' };
|
|
365
|
+
}
|
|
171
366
|
if (specifier === '@impetik/xeer' || specifier.startsWith('@impetik/xeer/')) {
|
|
172
367
|
return { kind: 'rejected', reason: 'platform-subpath' };
|
|
173
368
|
}
|
|
174
369
|
const packageName = packageNameOfSpecifier(specifier);
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
const
|
|
179
|
-
const classification = family.entrypoints.get(target);
|
|
370
|
+
const managed = managedPackageFamily(policy, packageName);
|
|
371
|
+
if (managed) {
|
|
372
|
+
const target = managed.compatAliases.get(specifier) ?? specifier;
|
|
373
|
+
const classification = managed.entrypoints.get(target)?.classification;
|
|
180
374
|
if (!classification)
|
|
181
375
|
return { kind: 'managed-rejected', reason: 'unknown-entrypoint' };
|
|
182
376
|
if (classification === 'test')
|
|
183
377
|
return { kind: 'managed-rejected', reason: 'test-only' };
|
|
184
378
|
if (classification === 'metadata')
|
|
185
379
|
return { kind: 'managed-rejected', reason: 'metadata' };
|
|
380
|
+
if (classification === 'other-runtime')
|
|
381
|
+
return { kind: 'managed-rejected', reason: 'other-runtime' };
|
|
186
382
|
return { kind: 'managed', classification, target };
|
|
187
383
|
}
|
|
188
384
|
// Before the open set, or an installed renderer would be admitted by the declaration invariant it
|
|
189
385
|
// satisfies in every application that has a client.
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
return { kind: 'rejected', reason: 'foreign-family' };
|
|
193
|
-
}
|
|
386
|
+
if (foreignPackageFamily(policy, packageName))
|
|
387
|
+
return { kind: 'rejected', reason: 'foreign-family' };
|
|
194
388
|
if (policy.applicationDependencies.mode === 'open')
|
|
195
389
|
return { kind: 'open' };
|
|
196
390
|
return { kind: 'rejected', reason: 'closed' };
|
|
197
391
|
}
|
|
392
|
+
/** The managed family that owns a bare package name in a zone, or null. */
|
|
393
|
+
export function managedPackageFamily(policy, packageName) {
|
|
394
|
+
return policy.managedFamilies.find((family) => family.packages.includes(packageName)) ?? null;
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* The foreign family that refuses a bare package name in a zone, or null.
|
|
398
|
+
*
|
|
399
|
+
* Managed ownership wins, and that precedence is the whole reason this is a function rather than a
|
|
400
|
+
* lookup each caller writes: under the React provider the foreign Preact family names `react`,
|
|
401
|
+
* `react-dom`, and `scheduler` among its own compat-alias territory, and those are precisely the
|
|
402
|
+
* packages the managed React family *is*. Asking managed-first is what lets the two descriptors stay
|
|
403
|
+
* complete statements about themselves instead of being trimmed to avoid each other.
|
|
404
|
+
*/
|
|
405
|
+
export function foreignPackageFamily(policy, packageName) {
|
|
406
|
+
if (managedPackageFamily(policy, packageName))
|
|
407
|
+
return null;
|
|
408
|
+
return policy.foreignFamilies.find((family) => family.packages.includes(packageName)) ?? null;
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* The package whose installed root one classified entrypoint resolves from. Derived from the
|
|
412
|
+
* specifier rather than declared a second time, so a family cannot claim an entrypoint it does not
|
|
413
|
+
* anchor — which is what keeps `entrypoints` and `anchorPackages` from drifting apart.
|
|
414
|
+
*/
|
|
415
|
+
export function entrypointAnchorPackage(family, specifier) {
|
|
416
|
+
const packageName = packageNameOfSpecifier(specifier);
|
|
417
|
+
if (!family.anchorPackages.includes(packageName)) {
|
|
418
|
+
throw new Error(`${specifier} names no package this renderer family anchors.`);
|
|
419
|
+
}
|
|
420
|
+
return packageName;
|
|
421
|
+
}
|
|
198
422
|
/**
|
|
199
423
|
* The admitted managed-family surface of a zone, alias keys included — what bundling and the dev
|
|
200
424
|
* server must pin to the anchor, and what documentation lists as the renderer surface.
|
|
@@ -202,15 +426,19 @@ export function admitBareImport(policy, specifier) {
|
|
|
202
426
|
export function managedImportSpecifiers(policy) {
|
|
203
427
|
const result = new Map();
|
|
204
428
|
for (const family of policy.managedFamilies) {
|
|
205
|
-
for (const [specifier,
|
|
206
|
-
if (classification
|
|
429
|
+
for (const [specifier, entrypoint] of family.entrypoints) {
|
|
430
|
+
if (isImportableClassification(entrypoint.classification))
|
|
207
431
|
result.set(specifier, specifier);
|
|
208
432
|
}
|
|
209
433
|
for (const [alias, target] of family.compatAliases) {
|
|
210
|
-
const
|
|
211
|
-
if (
|
|
434
|
+
const entrypoint = family.entrypoints.get(target);
|
|
435
|
+
if (entrypoint && isImportableClassification(entrypoint.classification))
|
|
212
436
|
result.set(alias, target);
|
|
213
437
|
}
|
|
214
438
|
}
|
|
215
439
|
return result;
|
|
216
440
|
}
|
|
441
|
+
/** Whether client application code may import an entrypoint with this classification. */
|
|
442
|
+
export function isImportableClassification(classification) {
|
|
443
|
+
return classification === 'runtime' || classification === 'development';
|
|
444
|
+
}
|
package/vendor/spec/index.d.ts
CHANGED
|
@@ -20,5 +20,7 @@ export * from './admin-sql.js';
|
|
|
20
20
|
export * from './network-policy.js';
|
|
21
21
|
export * from './review.js';
|
|
22
22
|
export * from './template.js';
|
|
23
|
+
export * from './template-distribution.js';
|
|
23
24
|
export * from './tunnel.js';
|
|
24
25
|
export * from './type-check-profile.js';
|
|
26
|
+
export * from './editor-settings.js';
|
package/vendor/spec/index.js
CHANGED
|
@@ -20,5 +20,7 @@ export * from './admin-sql.js';
|
|
|
20
20
|
export * from './network-policy.js';
|
|
21
21
|
export * from './review.js';
|
|
22
22
|
export * from './template.js';
|
|
23
|
+
export * from './template-distribution.js';
|
|
23
24
|
export * from './tunnel.js';
|
|
24
25
|
export * from './type-check-profile.js';
|
|
26
|
+
export * from './editor-settings.js';
|
package/vendor/spec/schema.d.ts
CHANGED
|
@@ -159,9 +159,13 @@ export declare const applicationManifestSchema: z.ZodObject<{
|
|
|
159
159
|
database: "database";
|
|
160
160
|
storage: "storage";
|
|
161
161
|
}>>>;
|
|
162
|
+
untypedDependencies: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
162
163
|
client: z.ZodOptional<z.ZodObject<{
|
|
163
164
|
runtime: z.ZodOptional<z.ZodObject<{
|
|
164
|
-
provider: z.
|
|
165
|
+
provider: z.ZodEnum<{
|
|
166
|
+
preact: "preact";
|
|
167
|
+
react: "react";
|
|
168
|
+
}>;
|
|
165
169
|
source: z.ZodOptional<z.ZodLiteral<"platform">>;
|
|
166
170
|
}, z.core.$strict>>;
|
|
167
171
|
}, z.core.$strict>>;
|
package/vendor/spec/schema.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { CAPABILITIES, SOURCE_FORMAT, } from './types.js';
|
|
3
|
+
import { CLIENT_RUNTIME_PROVIDERS, NORMALIZED_CLIENT_RUNTIME } from './import-policy.js';
|
|
3
4
|
import { STORAGE_DEFAULT_READ_BYTES, STORAGE_DEFAULT_WRITE_BYTES, STORAGE_MAX_OBJECT_BYTES, STORAGE_MAX_READ_BYTES, STORAGE_MAX_WRITE_BYTES, } from './storage.js';
|
|
4
5
|
import { SQL_EXPRESSION_MAX_LENGTH } from './sql-expression.js';
|
|
5
6
|
import { databaseDdl, indexColumns, referenceCycle, RESERVED_TABLE_PREFIXES, reservedTableName } from './table-ddl.js';
|
|
@@ -23,6 +24,13 @@ const favicon = z.string().min(2).max(256)
|
|
|
23
24
|
* table and manifest refinements below run the real check by generating the DDL.
|
|
24
25
|
*/
|
|
25
26
|
const expression = z.string().min(1).max(SQL_EXPRESSION_MAX_LENGTH);
|
|
27
|
+
/**
|
|
28
|
+
* An npm package name, as the registry defines one: optionally scoped, lowercase, and with no
|
|
29
|
+
* subpath. Bounded at npm's own 214 characters.
|
|
30
|
+
*/
|
|
31
|
+
const packageName = z.string()
|
|
32
|
+
.regex(/^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/, 'must be an npm package name')
|
|
33
|
+
.max(214);
|
|
26
34
|
const collation = z.enum(['binary', 'nocase', 'rtrim']);
|
|
27
35
|
const referentialAction = z.enum(['noAction', 'restrict', 'cascade', 'setNull', 'setDefault']);
|
|
28
36
|
const LOWERCASE_HEX = /^(?:[0-9a-f]{2})*$/;
|
|
@@ -275,13 +283,34 @@ export const applicationManifestSchema = z.strictObject({
|
|
|
275
283
|
}).optional(),
|
|
276
284
|
capabilities: z.array(z.enum(CAPABILITIES)).optional(),
|
|
277
285
|
/**
|
|
278
|
-
*
|
|
279
|
-
*
|
|
280
|
-
*
|
|
286
|
+
* Dependencies the application accepts having no TypeScript declarations for.
|
|
287
|
+
*
|
|
288
|
+
* The one legal thing the open client zone could not express. A package that is declared,
|
|
289
|
+
* installed, and simply ships no declarations is not a mistake — plenty of working JavaScript never
|
|
290
|
+
* grew types — but it stops `xeer check` with a type error the application did not cause, and the
|
|
291
|
+
* repair used to be a hand-written declaration file plus a triple-slash reference, per package and
|
|
292
|
+
* per subpath. Naming the package here is that whole ritual: the compiler derives the ambient
|
|
293
|
+
* declarations, subpaths included, into the generated contract both tools read.
|
|
294
|
+
*
|
|
295
|
+
* Explicit and checked in, deliberately. What it buys is that the named package's exports are
|
|
296
|
+
* `any`, which is a hole in the guarantee every other rule here exists to make — so it belongs in a
|
|
297
|
+
* diff someone reviews, not in an inference. The compiler warns about an entry whose package does
|
|
298
|
+
* ship declarations, because an acknowledgment nobody removes is how this list would rot into a
|
|
299
|
+
* standing exemption.
|
|
300
|
+
*
|
|
301
|
+
* Package names rather than specifiers: one entry covers the package and everything under it, so
|
|
302
|
+
* there is nothing to add when an import reaches a new subpath.
|
|
303
|
+
*/
|
|
304
|
+
untypedDependencies: z.array(packageName).optional(),
|
|
305
|
+
/**
|
|
306
|
+
* The client runtime selection (#212, #214). Closed: only implemented provider/source
|
|
307
|
+
* combinations are accepted, and omitting any level of it normalizes to the platform-managed
|
|
308
|
+
* Preact runtime with identical semantics and build output. A provider the platform has no
|
|
309
|
+
* renderer family for is refused here rather than surfacing later as an unresolvable JSX runtime.
|
|
281
310
|
*/
|
|
282
311
|
client: z.strictObject({
|
|
283
312
|
runtime: z.strictObject({
|
|
284
|
-
provider: z.
|
|
313
|
+
provider: z.enum(CLIENT_RUNTIME_PROVIDERS),
|
|
285
314
|
source: z.literal('platform').optional(),
|
|
286
315
|
}).optional(),
|
|
287
316
|
}).optional(),
|
|
@@ -363,6 +392,12 @@ export const applicationManifestJsonSchema = Object.freeze({
|
|
|
363
392
|
...describeProperty('capabilities', 'Powers granted to the application. Duplicate names are invalid.'),
|
|
364
393
|
uniqueItems: true,
|
|
365
394
|
},
|
|
395
|
+
untypedDependencies: {
|
|
396
|
+
...describeProperty('untypedDependencies', 'Installed dependencies that ship no TypeScript declarations, acknowledged by name. Xeer '
|
|
397
|
+
+ 'generates ambient declarations for each one and its subpaths, typed as any. Duplicate '
|
|
398
|
+
+ 'names are invalid.'),
|
|
399
|
+
uniqueItems: true,
|
|
400
|
+
},
|
|
366
401
|
budgets: describeProperty('budgets', 'Per-operation resource ceilings, each lowerable from platform defaults.'),
|
|
367
402
|
},
|
|
368
403
|
allOf: [
|
|
@@ -418,9 +453,25 @@ export function normalizeApplicationManifest(manifest) {
|
|
|
418
453
|
}
|
|
419
454
|
: null,
|
|
420
455
|
capabilities: [...(manifest.capabilities ?? [])].sort(),
|
|
456
|
+
// Total, like `capabilities` and unlike `storage`: sorted, deduplicated, and `[]` when the
|
|
457
|
+
// manifest declares nothing, so every reader gets an array rather than a `?? []` of its own.
|
|
458
|
+
//
|
|
459
|
+
// The present-only-when-declared shape next door exists to protect `artifactId`, and that
|
|
460
|
+
// concern does not reach here: the artifact payload enumerates the manifest fields it carries
|
|
461
|
+
// rather than spreading the manifest, and this one is deliberately not among them. An
|
|
462
|
+
// acknowledgment is type-space only — it changes no byte of the bundle — so moving the artifact
|
|
463
|
+
// id of a bundle-identical application would be a plain lie about what shipped.
|
|
464
|
+
untypedDependencies: [...new Set(manifest.untypedDependencies ?? [])].sort(),
|
|
421
465
|
// Always normalized: omission and the explicit default are the same statement, and everything
|
|
422
|
-
// downstream (
|
|
423
|
-
|
|
466
|
+
// downstream (import policy, type resolution, artifact provenance) reads one canonical value.
|
|
467
|
+
// The declared provider is *carried*, not defaulted away — returning the default unconditionally
|
|
468
|
+
// is what let a declared React application build as Preact with no diagnostic anywhere (#214).
|
|
469
|
+
client: {
|
|
470
|
+
runtime: {
|
|
471
|
+
provider: manifest.client?.runtime?.provider ?? NORMALIZED_CLIENT_RUNTIME.provider,
|
|
472
|
+
source: manifest.client?.runtime?.source ?? NORMALIZED_CLIENT_RUNTIME.source,
|
|
473
|
+
},
|
|
474
|
+
},
|
|
424
475
|
budgets: {
|
|
425
476
|
queryRows: manifest.budgets?.queryRows ?? 1_000,
|
|
426
477
|
mutationWrites: manifest.budgets?.mutationWrites ?? 100,
|