@antelopejs/dms-frontend 0.5.5 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +377 -19
- package/dist/app-configs.d.ts +9 -0
- package/dist/app-configs.js +52 -0
- package/dist/asset-roots.d.ts +7 -0
- package/dist/asset-roots.js +34 -0
- package/dist/commands/build-action.js +9 -0
- package/dist/commands/dev-action.js +88 -19
- package/dist/commands/start-action.js +2 -0
- package/dist/common.d.ts +1 -0
- package/dist/common.js +1 -0
- package/dist/config.d.ts +2 -0
- package/dist/config.js +9 -3
- package/dist/derived-outputs.d.ts +2 -0
- package/dist/derived-outputs.js +38 -31
- package/dist/help.js +10 -3
- package/dist/layer-watch.js +123 -131
- package/dist/layers.js +2 -0
- package/dist/manifest-secrets.js +5 -5
- package/dist/manifest.js +7 -1
- package/dist/materialize.js +21 -1
- package/dist/module-set.d.ts +16 -0
- package/dist/module-set.js +80 -0
- package/dist/server-process.d.ts +1 -0
- package/dist/server-process.js +28 -2
- package/dist/verify-source-build.d.ts +11 -0
- package/dist/verify-source-build.js +113 -0
- package/dist/verify-source-runner.js +14 -57
- package/dist/workspace.d.ts +9 -0
- package/package.json +2 -1
- package/templates/vue/app-runtime.ts +58 -16
- package/templates/vue/client-server-guard.mjs +73 -0
- package/templates/vue/email-renderer.ts +17 -4
- package/templates/vue/email-runtime.ts +1 -1
- package/templates/vue/frontend-module.ts +1817 -259
- package/templates/vue/globals.d.ts +1 -1
- package/templates/vue/icon-hydration.ts +106 -1
- package/templates/vue/index.html +0 -1
- package/templates/vue/layer-app-config.ts +92 -0
- package/templates/vue/main.ts +10 -2
- package/templates/vue/package.json +5 -1
- package/templates/vue/prepare-types.mjs +34 -0
- package/templates/vue/server/auth/backend.mjs +13 -19
- package/templates/vue/server/auth/client-ip.mjs +27 -0
- package/templates/vue/server/auth/establish-endpoints.mjs +70 -0
- package/templates/vue/server/auth/session.mjs +6 -97
- package/templates/vue/server/auth-hooks.mjs +84 -0
- package/templates/vue/server/backend-proxies.mjs +110 -0
- package/templates/vue/server/dev-private-files.mjs +99 -0
- package/templates/vue/server/email.mjs +11 -33
- package/templates/vue/server/favicon.mjs +20 -0
- package/templates/vue/server/inertia.mjs +48 -3
- package/templates/vue/server/listen-host.mjs +19 -0
- package/templates/vue/server/module-event.mjs +265 -0
- package/templates/vue/server/module-routes.mjs +513 -0
- package/templates/vue/server/module-server.mjs +225 -0
- package/templates/vue/server/module-testing.mjs +65 -0
- package/templates/vue/server/page-props.mjs +151 -0
- package/templates/vue/server/path-patterns.mjs +38 -0
- package/templates/vue/server/proxy-headers.mjs +25 -0
- package/templates/vue/server/public-endpoints.mjs +69 -11
- package/templates/vue/server/request-routing.mjs +47 -0
- package/templates/vue/server/route-rules.mjs +129 -0
- package/templates/vue/server-module.ts +294 -0
- package/templates/vue/server.mjs +178 -169
- package/templates/vue/ssr-renderer.ts +60 -19
- package/templates/vue/tsconfig.json +2 -1
- package/templates/vue/ui-app-config.ts +18 -6
- package/templates/vue/ui-inertia-page.mjs +37 -0
- package/templates/vue/vite.config.ts +31 -10
- package/templates/vue/vite.email.config.ts +1 -1
- package/templates/vue/vite.server.config.ts +57 -0
- package/templates/vue/server/auth/oauth.mjs +0 -233
- package/templates/vue/server/auth/routes.mjs +0 -444
- package/templates/vue/server/render-token.mjs +0 -81
- package/templates/vue/server/tester.mjs +0 -227
package/dist/layer-watch.js
CHANGED
|
@@ -14,7 +14,7 @@ const derived_outputs_1 = require("./derived-outputs");
|
|
|
14
14
|
const output_1 = require("./output");
|
|
15
15
|
const fs_sync_1 = require("./fs-sync");
|
|
16
16
|
const WATCH_DEBOUNCE_MS = 80;
|
|
17
|
-
const
|
|
17
|
+
const DERIVED_REFRESH_GAP_MS = 100;
|
|
18
18
|
function capitalize(text) {
|
|
19
19
|
return `${text.charAt(0).toUpperCase()}${text.slice(1)}`;
|
|
20
20
|
}
|
|
@@ -37,126 +37,88 @@ function createSyncFailures(src, reporter) {
|
|
|
37
37
|
},
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
|
-
function createLayerSync(src, dest,
|
|
40
|
+
function createLayerSync(src, dest, reporter, onStaged) {
|
|
41
41
|
const fileUpserts = new Set();
|
|
42
42
|
const fileDeletes = new Set();
|
|
43
43
|
const dirCreates = new Set();
|
|
44
44
|
const dirDeletes = new Set();
|
|
45
45
|
const failures = createSyncFailures(src, reporter);
|
|
46
|
-
let timer = null;
|
|
47
46
|
const toRel = (p) => {
|
|
48
47
|
const r = (0, node_path_1.relative)(src, p);
|
|
49
48
|
return r ? r : null;
|
|
50
49
|
};
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
50
|
+
const take = (staged, select) => {
|
|
51
|
+
const taken = [...staged].filter(select);
|
|
52
|
+
for (const rel of taken)
|
|
53
|
+
staged.delete(rel);
|
|
54
|
+
return taken;
|
|
55
|
+
};
|
|
56
|
+
const upsert = (rel) => {
|
|
57
|
+
try {
|
|
58
|
+
const srcPath = (0, node_path_1.join)(src, rel);
|
|
59
|
+
if (!(0, node_fs_1.existsSync)(srcPath))
|
|
60
|
+
return;
|
|
61
|
+
const destPath = (0, node_path_1.join)(dest, rel);
|
|
62
|
+
if (rel === "package.json") {
|
|
63
|
+
(0, fs_sync_1.applyContent)((0, fs_sync_1.sanitizedPackageContent)((0, node_fs_1.readFileSync)(srcPath, "utf-8")), destPath);
|
|
63
64
|
}
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
else {
|
|
66
|
+
(0, fs_sync_1.applyFile)(srcPath, destPath);
|
|
66
67
|
}
|
|
68
|
+
failures.applied(rel);
|
|
67
69
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
try {
|
|
71
|
-
const srcPath = (0, node_path_1.join)(src, rel);
|
|
72
|
-
if (!(0, node_fs_1.existsSync)(srcPath))
|
|
73
|
-
continue;
|
|
74
|
-
const destPath = (0, node_path_1.join)(dest, rel);
|
|
75
|
-
if (rel === "package.json") {
|
|
76
|
-
(0, fs_sync_1.applyContent)((0, fs_sync_1.sanitizedPackageContent)((0, node_fs_1.readFileSync)(srcPath, "utf-8")), destPath);
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
79
|
-
(0, fs_sync_1.applyFile)(srcPath, destPath);
|
|
80
|
-
}
|
|
81
|
-
failures.applied(rel);
|
|
82
|
-
}
|
|
83
|
-
catch (err) {
|
|
84
|
-
failures.fail(rel, err);
|
|
85
|
-
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
failures.fail(rel, err);
|
|
86
72
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
catch (err) {
|
|
98
|
-
failures.fail(rel, err);
|
|
99
|
-
}
|
|
73
|
+
};
|
|
74
|
+
const remove = (rel, recursive) => {
|
|
75
|
+
try {
|
|
76
|
+
if ((0, node_fs_1.existsSync)((0, node_path_1.join)(src, rel)))
|
|
77
|
+
return;
|
|
78
|
+
const destPath = (0, node_path_1.join)(dest, rel);
|
|
79
|
+
if ((0, node_fs_1.existsSync)(destPath))
|
|
80
|
+
(0, node_fs_1.rmSync)(destPath, { recursive, force: true });
|
|
81
|
+
failures.applied(rel);
|
|
100
82
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
try {
|
|
104
|
-
if ((0, node_fs_1.existsSync)((0, node_path_1.join)(src, rel)))
|
|
105
|
-
continue;
|
|
106
|
-
const destPath = (0, node_path_1.join)(dest, rel);
|
|
107
|
-
if ((0, node_fs_1.existsSync)(destPath))
|
|
108
|
-
(0, node_fs_1.rmSync)(destPath, { recursive: true, force: true });
|
|
109
|
-
failures.applied(rel);
|
|
110
|
-
}
|
|
111
|
-
catch (err) {
|
|
112
|
-
failures.fail(rel, err);
|
|
113
|
-
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
failures.fail(rel, err);
|
|
114
85
|
}
|
|
115
|
-
dirDeletes.clear();
|
|
116
|
-
onFlushed(touched);
|
|
117
86
|
};
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
87
|
+
const stage = (p, add, cancel) => {
|
|
88
|
+
const r = toRel(p);
|
|
89
|
+
if (!r)
|
|
90
|
+
return;
|
|
91
|
+
cancel.delete(r);
|
|
92
|
+
add.add(r);
|
|
93
|
+
onStaged();
|
|
122
94
|
};
|
|
123
95
|
return {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
96
|
+
src,
|
|
97
|
+
upsertFile: (p) => stage(p, fileUpserts, fileDeletes),
|
|
98
|
+
deleteFile: (p) => stage(p, fileDeletes, fileUpserts),
|
|
99
|
+
createDir: (p) => stage(p, dirCreates, dirDeletes),
|
|
100
|
+
deleteDir: (p) => stage(p, dirDeletes, dirCreates),
|
|
101
|
+
pending() {
|
|
102
|
+
return [...dirCreates, ...fileUpserts, ...fileDeletes, ...dirDeletes];
|
|
131
103
|
},
|
|
132
|
-
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
if (!r)
|
|
143
|
-
return;
|
|
144
|
-
dirDeletes.delete(r);
|
|
145
|
-
dirCreates.add(r);
|
|
146
|
-
arm();
|
|
147
|
-
},
|
|
148
|
-
deleteDir(p) {
|
|
149
|
-
const r = toRel(p);
|
|
150
|
-
if (!r)
|
|
151
|
-
return;
|
|
152
|
-
dirCreates.delete(r);
|
|
153
|
-
dirDeletes.add(r);
|
|
154
|
-
arm();
|
|
104
|
+
createDirs() {
|
|
105
|
+
for (const rel of take(dirCreates, () => true).sort((a, b) => a.length - b.length)) {
|
|
106
|
+
try {
|
|
107
|
+
(0, node_fs_1.mkdirSync)((0, node_path_1.join)(dest, rel), { recursive: true });
|
|
108
|
+
failures.applied(rel);
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
failures.fail(rel, err);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
155
114
|
},
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
115
|
+
apply(select) {
|
|
116
|
+
for (const rel of take(fileUpserts, select))
|
|
117
|
+
upsert(rel);
|
|
118
|
+
for (const rel of take(fileDeletes, select))
|
|
119
|
+
remove(rel, false);
|
|
120
|
+
for (const rel of take(dirDeletes, select).sort((a, b) => b.length - a.length))
|
|
121
|
+
remove(rel, true);
|
|
160
122
|
},
|
|
161
123
|
};
|
|
162
124
|
}
|
|
@@ -186,10 +148,8 @@ function describeLayerDirectories(paths, reporter) {
|
|
|
186
148
|
: `Layer directory ${shown[0]} removed`;
|
|
187
149
|
}
|
|
188
150
|
function createDerivedOutputRefresher(workspaceDir, layers, reporter) {
|
|
189
|
-
const pending = new Map();
|
|
190
151
|
const failures = new Map();
|
|
191
152
|
let hasRestartNotice = false;
|
|
192
|
-
let timer = null;
|
|
193
153
|
const fail = (key, failure) => {
|
|
194
154
|
failures.set(key, failure);
|
|
195
155
|
reporter.warn(failure.text, failure.options);
|
|
@@ -215,19 +175,18 @@ function createDerivedOutputRefresher(workspaceDir, layers, reporter) {
|
|
|
215
175
|
recover(output);
|
|
216
176
|
if (isChanged)
|
|
217
177
|
noticeRestart(output, paths);
|
|
178
|
+
return isChanged;
|
|
218
179
|
}
|
|
219
180
|
catch (err) {
|
|
220
181
|
fail(output, describeOutputFailure(output, err, reporter));
|
|
182
|
+
return false;
|
|
221
183
|
}
|
|
222
184
|
};
|
|
223
|
-
const
|
|
224
|
-
timer = null;
|
|
225
|
-
const outputs = derived_outputs_1.DERIVED_OUTPUTS.filter((output) => pending.has(output)).map((output) => [output, pending.get(output) ?? []]);
|
|
226
|
-
pending.clear();
|
|
227
|
-
let registry;
|
|
185
|
+
const buildRegistry = () => {
|
|
228
186
|
try {
|
|
229
|
-
registry = (0, derived_outputs_1.createFrontendModuleRegistry)(workspaceDir, layers);
|
|
187
|
+
const registry = (0, derived_outputs_1.createFrontendModuleRegistry)(workspaceDir, layers);
|
|
230
188
|
recover("registry");
|
|
189
|
+
return registry;
|
|
231
190
|
}
|
|
232
191
|
catch (err) {
|
|
233
192
|
fail("registry", {
|
|
@@ -240,35 +199,69 @@ function createDerivedOutputRefresher(workspaceDir, layers, reporter) {
|
|
|
240
199
|
},
|
|
241
200
|
fixed: "Derived files regenerated",
|
|
242
201
|
});
|
|
243
|
-
return;
|
|
202
|
+
return undefined;
|
|
244
203
|
}
|
|
245
|
-
for (const [output, paths] of outputs)
|
|
246
|
-
regenerate(output, paths, registry);
|
|
247
204
|
};
|
|
248
205
|
return {
|
|
249
|
-
|
|
250
|
-
|
|
206
|
+
plan(touched) {
|
|
207
|
+
const pending = new Map();
|
|
251
208
|
for (const output of derived_outputs_1.DERIVED_OUTPUTS) {
|
|
252
|
-
const affected =
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
...(pending.get(output) ?? []),
|
|
258
|
-
...affected.map((path) => (0, node_path_1.join)(src, path)),
|
|
259
|
-
]);
|
|
209
|
+
const affected = touched.flatMap(({ src, paths }) => paths
|
|
210
|
+
.filter((path) => output.affects(path))
|
|
211
|
+
.map((path) => (0, node_path_1.join)(src, path)));
|
|
212
|
+
if (affected.length > 0)
|
|
213
|
+
pending.set(output, affected);
|
|
260
214
|
}
|
|
261
|
-
|
|
262
|
-
|
|
215
|
+
const registry = pending.size > 0 ? buildRegistry() : undefined;
|
|
216
|
+
return (select) => {
|
|
217
|
+
let isChanged = false;
|
|
218
|
+
if (!registry)
|
|
219
|
+
return isChanged;
|
|
220
|
+
for (const [output, paths] of pending) {
|
|
221
|
+
if (select(output))
|
|
222
|
+
isChanged = regenerate(output, paths, registry) || isChanged;
|
|
223
|
+
}
|
|
224
|
+
return isChanged;
|
|
225
|
+
};
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
function isReadAsData(relativePath) {
|
|
230
|
+
return derived_outputs_1.DERIVED_OUTPUTS.some((output) => output.readsSourcesAsData && output.affects(relativePath));
|
|
231
|
+
}
|
|
232
|
+
function runPass(syncs, refresher) {
|
|
233
|
+
const writeOutputs = refresher.plan(syncs.map((sync) => ({ src: sync.src, paths: sync.pending() })));
|
|
234
|
+
const isDataOutput = (output) => output.readsSourcesAsData === true;
|
|
235
|
+
for (const sync of syncs)
|
|
236
|
+
sync.createDirs();
|
|
237
|
+
for (const sync of syncs)
|
|
238
|
+
sync.apply(isReadAsData);
|
|
239
|
+
const isDataChanged = writeOutputs(isDataOutput);
|
|
240
|
+
for (const sync of syncs)
|
|
241
|
+
sync.apply((path) => !isReadAsData(path));
|
|
242
|
+
const isChanged = writeOutputs((output) => !isDataOutput(output));
|
|
243
|
+
return isDataChanged || isChanged;
|
|
244
|
+
}
|
|
245
|
+
function createPassScheduler(pass) {
|
|
246
|
+
let timer = null;
|
|
247
|
+
let lastRegeneration = Number.NEGATIVE_INFINITY;
|
|
248
|
+
const flush = () => {
|
|
249
|
+
timer = null;
|
|
250
|
+
if (pass())
|
|
251
|
+
lastRegeneration = Date.now();
|
|
252
|
+
};
|
|
253
|
+
return {
|
|
254
|
+
arm: () => {
|
|
263
255
|
if (timer)
|
|
264
256
|
clearTimeout(timer);
|
|
265
|
-
|
|
257
|
+
const gap = lastRegeneration + DERIVED_REFRESH_GAP_MS - Date.now();
|
|
258
|
+
timer = setTimeout(flush, Math.max(WATCH_DEBOUNCE_MS, gap));
|
|
266
259
|
},
|
|
267
|
-
flushNow() {
|
|
260
|
+
flushNow: () => {
|
|
268
261
|
if (!timer)
|
|
269
262
|
return;
|
|
270
263
|
clearTimeout(timer);
|
|
271
|
-
|
|
264
|
+
flush();
|
|
272
265
|
},
|
|
273
266
|
};
|
|
274
267
|
}
|
|
@@ -289,12 +282,13 @@ function startLayerWatchers(workspaceDir, layers, ui = (0, cli_1.getProcessUi)()
|
|
|
289
282
|
const watchers = [];
|
|
290
283
|
const syncs = [];
|
|
291
284
|
const refresher = createDerivedOutputRefresher(workspaceDir, layers, reporter);
|
|
285
|
+
const passes = createPassScheduler(() => runPass(syncs, refresher));
|
|
292
286
|
for (const layer of layers) {
|
|
293
287
|
if (!layer.packageName)
|
|
294
288
|
continue;
|
|
295
289
|
const dest = (0, layers_1.getLayerWorkspacePath)(workspaceDir, layer);
|
|
296
290
|
const src = layer.path;
|
|
297
|
-
const sync = createLayerSync(src, dest,
|
|
291
|
+
const sync = createLayerSync(src, dest, reporter, passes.arm);
|
|
298
292
|
syncs.push(sync);
|
|
299
293
|
const watcher = chokidar_1.default.watch(src, {
|
|
300
294
|
ignoreInitial: true,
|
|
@@ -310,8 +304,6 @@ function startLayerWatchers(workspaceDir, layers, ui = (0, cli_1.getProcessUi)()
|
|
|
310
304
|
}
|
|
311
305
|
return async () => {
|
|
312
306
|
await Promise.all(watchers.map((w) => w.close().catch(() => { })));
|
|
313
|
-
|
|
314
|
-
sync.flushNow();
|
|
315
|
-
refresher.flushNow();
|
|
307
|
+
passes.flushNow();
|
|
316
308
|
};
|
|
317
309
|
}
|
package/dist/layers.js
CHANGED
|
@@ -125,8 +125,10 @@ function resolveLayer(layerPath, mod) {
|
|
|
125
125
|
priority: mod.priority,
|
|
126
126
|
configKey: mod.configKey,
|
|
127
127
|
options: mod.options,
|
|
128
|
+
privateOptions: mod.privateOptions,
|
|
128
129
|
authEstablishEndpoints: mod.authEstablishEndpoints,
|
|
129
130
|
publicEndpoints: mod.publicEndpoints,
|
|
131
|
+
backendProxies: mod.backendProxies,
|
|
130
132
|
};
|
|
131
133
|
}
|
|
132
134
|
function buildLayersFromPaths(modules) {
|
package/dist/manifest-secrets.js
CHANGED
|
@@ -59,14 +59,14 @@ function resolveManifestSecrets(secrets, env = process.env) {
|
|
|
59
59
|
for (const name of SECRET_NAMES) {
|
|
60
60
|
const explicit = env[name];
|
|
61
61
|
const published = secrets.published[name];
|
|
62
|
-
if (
|
|
63
|
-
resolved.env[name] = explicit;
|
|
64
|
-
resolved.sources[name] = "env";
|
|
65
|
-
}
|
|
66
|
-
else if (published) {
|
|
62
|
+
if (published) {
|
|
67
63
|
resolved.env[name] = published.value;
|
|
68
64
|
resolved.sources[name] = "manifest";
|
|
69
65
|
}
|
|
66
|
+
else if (explicit) {
|
|
67
|
+
resolved.env[name] = explicit;
|
|
68
|
+
resolved.sources[name] = "env";
|
|
69
|
+
}
|
|
70
70
|
else {
|
|
71
71
|
resolved.sources[name] = "not set";
|
|
72
72
|
}
|
package/dist/manifest.js
CHANGED
|
@@ -192,7 +192,13 @@ async function fetchManifest(backendUrl, clientUrl, bootstrapSecret) {
|
|
|
192
192
|
if (incompatible.length) {
|
|
193
193
|
throw new ManifestRefusedError(`Frontend manifest contains incompatible renderer modules: ${incompatible.map((module) => module.name).join(", ")}`);
|
|
194
194
|
}
|
|
195
|
-
|
|
195
|
+
const resolved = {
|
|
196
|
+
pack: manifest.archive,
|
|
197
|
+
modules: manifest.modules,
|
|
198
|
+
};
|
|
199
|
+
if (manifest.settling)
|
|
200
|
+
resolved.settling = true;
|
|
201
|
+
return resolved;
|
|
196
202
|
}
|
|
197
203
|
const MANIFEST_CACHE_FILE = ".manifest-cache.json";
|
|
198
204
|
function readCachedManifest(workspaceDir) {
|
package/dist/materialize.js
CHANGED
|
@@ -13,6 +13,7 @@ const cli_1 = require("@antelopejs/core/cli");
|
|
|
13
13
|
const config_1 = require("./config");
|
|
14
14
|
const derived_outputs_1 = require("./derived-outputs");
|
|
15
15
|
const layers_1 = require("./layers");
|
|
16
|
+
const manifest_secrets_1 = require("./manifest-secrets");
|
|
16
17
|
const fs_sync_1 = require("./fs-sync");
|
|
17
18
|
function getPackageRoot() {
|
|
18
19
|
return (0, node_path_1.resolve)(__dirname, "..");
|
|
@@ -98,13 +99,32 @@ function writeAuthEstablishEndpoints(workspaceDir, layers) {
|
|
|
98
99
|
function collectPublicEndpoints(layers) {
|
|
99
100
|
return layers.flatMap((layer) => (Array.isArray(layer.publicEndpoints) ? layer.publicEndpoints : []).filter((endpoint) => typeof endpoint === "object" && endpoint !== null));
|
|
100
101
|
}
|
|
102
|
+
function collectBackendProxies(layers) {
|
|
103
|
+
return layers.flatMap((layer) => (Array.isArray(layer.backendProxies) ? layer.backendProxies : [])
|
|
104
|
+
.filter((proxy) => typeof proxy === "object" && proxy !== null)
|
|
105
|
+
.map((proxy) => ({
|
|
106
|
+
...proxy,
|
|
107
|
+
module: layer.name ?? layer.packageName ?? "unknown",
|
|
108
|
+
})));
|
|
109
|
+
}
|
|
101
110
|
function writePublicEndpoints(workspaceDir, layers) {
|
|
102
|
-
|
|
111
|
+
const declared = {
|
|
112
|
+
endpoints: collectPublicEndpoints(layers),
|
|
113
|
+
proxies: collectBackendProxies(layers),
|
|
114
|
+
};
|
|
115
|
+
(0, node_fs_1.writeFileSync)((0, node_path_1.join)(workspaceDir, config_1.PUBLIC_ENDPOINTS_FILE), `${JSON.stringify(declared, null, 2)}\n`);
|
|
116
|
+
}
|
|
117
|
+
function writeServerOptions(workspaceDir, layers) {
|
|
118
|
+
const modules = Object.fromEntries(layers.flatMap((layer) => layer.privateOptions
|
|
119
|
+
? [[(0, layers_1.getLayerSafeName)(layer), layer.privateOptions]]
|
|
120
|
+
: []));
|
|
121
|
+
(0, config_1.writeSecretBearingFile)((0, node_path_1.join)(workspaceDir, config_1.SERVER_OPTIONS_FILE), `${JSON.stringify({ modules, environment: manifest_secrets_1.MANIFEST_SECRET_ENV }, null, 2)}\n`);
|
|
103
122
|
}
|
|
104
123
|
function writeFrontendModuleRegistry(workspaceDir, layers) {
|
|
105
124
|
const registry = (0, derived_outputs_1.createFrontendModuleRegistry)(workspaceDir, layers);
|
|
106
125
|
writeAuthEstablishEndpoints(workspaceDir, layers);
|
|
107
126
|
writePublicEndpoints(workspaceDir, layers);
|
|
127
|
+
writeServerOptions(workspaceDir, layers);
|
|
108
128
|
for (const output of derived_outputs_1.DERIVED_OUTPUTS)
|
|
109
129
|
output.write(workspaceDir, registry);
|
|
110
130
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type ManifestModule } from "./workspace";
|
|
2
|
+
export declare const MODULE_SET_POLL_INTERVAL_MS = 3000;
|
|
3
|
+
export type ModuleSetMember = Pick<ManifestModule, "name" | "path" | "priority" | "publicEndpoints" | "backendProxies">;
|
|
4
|
+
export type BootstrapSecretSource = () => string | undefined;
|
|
5
|
+
export interface ModuleSetFollowOptions {
|
|
6
|
+
backendUrl: string;
|
|
7
|
+
clientUrl?: string;
|
|
8
|
+
bootstrapSecret?: BootstrapSecretSource;
|
|
9
|
+
fingerprint: string;
|
|
10
|
+
onChange: () => void;
|
|
11
|
+
onUnchanged?: () => void;
|
|
12
|
+
intervalMs?: number;
|
|
13
|
+
}
|
|
14
|
+
export declare function moduleSetFingerprint(modules: readonly ModuleSetMember[]): string;
|
|
15
|
+
export declare function followModuleSet(options: ModuleSetFollowOptions): () => void;
|
|
16
|
+
export declare function reportFrontendReady(backendUrl: string, moduleNames: readonly string[], bootstrapSecret?: string): Promise<boolean>;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MODULE_SET_POLL_INTERVAL_MS = void 0;
|
|
4
|
+
exports.moduleSetFingerprint = moduleSetFingerprint;
|
|
5
|
+
exports.followModuleSet = followModuleSet;
|
|
6
|
+
exports.reportFrontendReady = reportFrontendReady;
|
|
7
|
+
const manifest_1 = require("./manifest");
|
|
8
|
+
const workspace_1 = require("./workspace");
|
|
9
|
+
exports.MODULE_SET_POLL_INTERVAL_MS = 3000;
|
|
10
|
+
const READY_ENDPOINT = "/dms/frontend/ready";
|
|
11
|
+
const READY_TIMEOUT_MS = 5000;
|
|
12
|
+
const JSON_CONTENT_TYPE = "application/json";
|
|
13
|
+
function moduleSetFingerprint(modules) {
|
|
14
|
+
return JSON.stringify([...modules]
|
|
15
|
+
.sort((left, right) => left.name.localeCompare(right.name))
|
|
16
|
+
.map((module) => [
|
|
17
|
+
module.name,
|
|
18
|
+
module.path ?? "",
|
|
19
|
+
module.priority,
|
|
20
|
+
module.publicEndpoints ?? [],
|
|
21
|
+
module.backendProxies ?? [],
|
|
22
|
+
]));
|
|
23
|
+
}
|
|
24
|
+
function followModuleSet(options) {
|
|
25
|
+
let isStopped = false;
|
|
26
|
+
let timer;
|
|
27
|
+
let candidate;
|
|
28
|
+
const inspect = (fingerprint) => {
|
|
29
|
+
if (fingerprint === options.fingerprint) {
|
|
30
|
+
candidate = undefined;
|
|
31
|
+
options.onUnchanged?.();
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (fingerprint !== candidate) {
|
|
35
|
+
candidate = fingerprint;
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
isStopped = true;
|
|
39
|
+
options.onChange();
|
|
40
|
+
};
|
|
41
|
+
const poll = async () => {
|
|
42
|
+
try {
|
|
43
|
+
const manifest = await (0, manifest_1.fetchManifest)(options.backendUrl, options.clientUrl, options.bootstrapSecret?.());
|
|
44
|
+
if (!isStopped && !manifest.settling) {
|
|
45
|
+
inspect(moduleSetFingerprint(manifest.modules));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
}
|
|
50
|
+
if (!isStopped)
|
|
51
|
+
schedule();
|
|
52
|
+
};
|
|
53
|
+
const schedule = () => {
|
|
54
|
+
timer = setTimeout(() => void poll(), options.intervalMs ?? exports.MODULE_SET_POLL_INTERVAL_MS);
|
|
55
|
+
timer.unref();
|
|
56
|
+
};
|
|
57
|
+
schedule();
|
|
58
|
+
return () => {
|
|
59
|
+
isStopped = true;
|
|
60
|
+
if (timer)
|
|
61
|
+
clearTimeout(timer);
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
async function reportFrontendReady(backendUrl, moduleNames, bootstrapSecret) {
|
|
65
|
+
try {
|
|
66
|
+
const response = await fetch((0, manifest_1.backendEndpoint)(backendUrl, READY_ENDPOINT), {
|
|
67
|
+
method: "POST",
|
|
68
|
+
headers: {
|
|
69
|
+
...(0, workspace_1.bootstrapHeaders)(bootstrapSecret),
|
|
70
|
+
"content-type": JSON_CONTENT_TYPE,
|
|
71
|
+
},
|
|
72
|
+
body: JSON.stringify({ modules: moduleNames }),
|
|
73
|
+
signal: AbortSignal.timeout(READY_TIMEOUT_MS),
|
|
74
|
+
});
|
|
75
|
+
return response.ok;
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
}
|
package/dist/server-process.d.ts
CHANGED
|
@@ -30,6 +30,7 @@ export interface RunServerOptions {
|
|
|
30
30
|
env: NodeJS.ProcessEnv;
|
|
31
31
|
mapPath?: PathMapper;
|
|
32
32
|
onReady: (address: ServerAddress) => void;
|
|
33
|
+
stopSignal?: AbortSignal;
|
|
33
34
|
}
|
|
34
35
|
export declare function describeStartError(error: StartError, mapPath?: PathMapper): CliProblem;
|
|
35
36
|
export declare function describeListenError(error: ListenError): CliProblem;
|
package/dist/server-process.js
CHANGED
|
@@ -22,6 +22,30 @@ const VIRTUAL_INTERFACE_NAME = /^(docker\d|br-|veth|virbr|cni|flannel|cali|ciliu
|
|
|
22
22
|
const LINK_LOCAL_IPV4 = /^169\.254\./;
|
|
23
23
|
const MAX_NETWORK_URLS = 3;
|
|
24
24
|
const LINUX_NET_DIR = "/sys/class/net";
|
|
25
|
+
function stopOnAbort(child, signal) {
|
|
26
|
+
if (!signal)
|
|
27
|
+
return;
|
|
28
|
+
const stop = () => {
|
|
29
|
+
if (child.pid === undefined || child.exitCode !== null)
|
|
30
|
+
return;
|
|
31
|
+
try {
|
|
32
|
+
if (process.platform === "win32") {
|
|
33
|
+
child.kill();
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
process.kill(-child.pid, "SIGTERM");
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
if (signal.aborted) {
|
|
43
|
+
stop();
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
signal.addEventListener("abort", stop, { once: true });
|
|
47
|
+
child.once("exit", () => signal.removeEventListener("abort", stop));
|
|
48
|
+
}
|
|
25
49
|
function isRecord(value) {
|
|
26
50
|
return typeof value === "object" && value !== null;
|
|
27
51
|
}
|
|
@@ -128,8 +152,9 @@ function describeListenError(error) {
|
|
|
128
152
|
reason: error.message,
|
|
129
153
|
};
|
|
130
154
|
}
|
|
155
|
+
const LOOPBACK_ADDRESSES = new Set(["127.0.0.1", "::1"]);
|
|
131
156
|
function urlHost(address) {
|
|
132
|
-
if (WILDCARD_ADDRESSES.has(address))
|
|
157
|
+
if (WILDCARD_ADDRESSES.has(address) || LOOPBACK_ADDRESSES.has(address))
|
|
133
158
|
return LOCAL_HOST;
|
|
134
159
|
return address.includes(":") ? `[${address}]` : address;
|
|
135
160
|
}
|
|
@@ -188,7 +213,7 @@ function readyLines(address, settings, interfaces, isGuestInterface) {
|
|
|
188
213
|
];
|
|
189
214
|
}
|
|
190
215
|
async function runServer(options) {
|
|
191
|
-
const { name, script, cwd, env, mapPath, onReady } = options;
|
|
216
|
+
const { name, script, cwd, env, mapPath, onReady, stopSignal } = options;
|
|
192
217
|
let readyAt;
|
|
193
218
|
let listenError;
|
|
194
219
|
let startError;
|
|
@@ -199,6 +224,7 @@ async function runServer(options) {
|
|
|
199
224
|
shell: false,
|
|
200
225
|
stdio: ["inherit", "inherit", "inherit", "ipc"],
|
|
201
226
|
}, (child) => {
|
|
227
|
+
stopOnAbort(child, stopSignal);
|
|
202
228
|
child.on("message", (message) => {
|
|
203
229
|
const ready = readReady(message);
|
|
204
230
|
if (ready && readyAt === undefined) {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type PathMapper } from "./child-output";
|
|
2
|
+
import { ViteWarnings } from "./vite-output";
|
|
3
|
+
export interface VerificationContext {
|
|
4
|
+
workspace: string;
|
|
5
|
+
env: NodeJS.ProcessEnv;
|
|
6
|
+
mapLine: PathMapper;
|
|
7
|
+
warnings: ViteWarnings;
|
|
8
|
+
isVerbose: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function prepareTypes(context: VerificationContext): Promise<void>;
|
|
11
|
+
export declare function buildAndTypeCheck(context: VerificationContext): Promise<void>;
|