@antelopejs/dms-frontend 0.7.0 → 0.8.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 +4 -4
- package/dist/commands/build-action.d.ts +8 -5
- package/dist/commands/build-action.js +13 -41
- package/dist/commands/build.js +9 -15
- package/dist/commands/dev-action.js +5 -1
- package/dist/commands/start-action.d.ts +2 -0
- package/dist/commands/start-action.js +36 -49
- package/dist/commands/start.js +8 -6
- package/dist/config.d.ts +2 -0
- package/dist/config.js +6 -0
- package/dist/derived-outputs.js +2 -2
- package/dist/fs-sync.d.ts +1 -0
- package/dist/fs-sync.js +6 -0
- package/dist/help.js +8 -4
- package/dist/index.js +4 -6
- package/dist/layer-watch.js +4 -0
- package/dist/layers.d.ts +1 -3
- package/dist/layers.js +1 -95
- package/dist/manifest.d.ts +8 -8
- package/dist/manifest.js +15 -39
- package/dist/materialize.js +6 -0
- package/dist/module-set.d.ts +14 -12
- package/dist/module-set.js +39 -31
- package/dist/private-values.d.ts +2 -2
- package/dist/private-values.js +1 -6
- package/dist/project-modules.d.ts +46 -0
- package/dist/project-modules.js +233 -0
- package/dist/workspace-setup.d.ts +3 -7
- package/dist/workspace-setup.js +41 -62
- package/dist/workspace.d.ts +2 -4
- package/dist/workspace.js +1 -1
- package/package.json +5 -7
- package/skills/dms-frontend/SKILL.md +2 -2
- package/templates/vue/client-chunking.mjs +61 -0
- package/templates/vue/email-renderer.ts +6 -1
- package/templates/vue/frontend-build-loader.ts +1 -1
- package/templates/vue/frontend-module.ts +24 -0
- package/templates/vue/main.ts +11 -2
- package/templates/vue/package.json +2 -2
- package/templates/vue/prepare-types.mjs +2 -7
- package/templates/vue/public-options.ts +19 -0
- package/templates/vue/server/auth/backend.mjs +20 -3
- package/templates/vue/server/auth/client-ip.mjs +64 -22
- package/templates/vue/server/auth/session.mjs +4 -11
- package/templates/vue/server/backend-proxies.mjs +13 -2
- package/templates/vue/server/backend-response.mjs +2 -13
- package/templates/vue/server/cli-report.mjs +42 -18
- package/templates/vue/server/client-manifest.mjs +22 -58
- package/templates/vue/server/dev-private-files.mjs +1 -1
- package/templates/vue/server/dev-styles.mjs +16 -5
- package/templates/vue/server/homepage.mjs +4 -1
- package/templates/vue/server/module-event.mjs +23 -8
- package/templates/vue/server/module-server.mjs +4 -4
- package/templates/vue/server/module-testing.mjs +5 -3
- package/templates/vue/server/proxy-compression.mjs +15 -8
- package/templates/vue/server/proxy-headers.mjs +12 -1
- package/templates/vue/server/proxy-redirects.mjs +66 -0
- package/templates/vue/server/proxy-transfers.mjs +84 -0
- package/templates/vue/server/public-endpoints.mjs +2 -2
- package/templates/vue/server/public-options.mjs +49 -0
- package/templates/vue/server/request-routing.mjs +20 -0
- package/templates/vue/server/web-body.mjs +24 -0
- package/templates/vue/server-module.ts +19 -7
- package/templates/vue/server.mjs +59 -49
- package/templates/vue/ssr-renderer.ts +19 -1
- package/templates/vue/vite.config.ts +72 -46
- package/templates/vue/vite.email.config.ts +6 -3
- package/templates/vue/vite.server.config.ts +5 -2
- package/dist/commands/snapshot-action.d.ts +0 -6
- package/dist/commands/snapshot-action.js +0 -53
- package/dist/commands/snapshot.d.ts +0 -2
- package/dist/commands/snapshot.js +0 -55
- package/dist/snapshot.d.ts +0 -25
- package/dist/snapshot.js +0 -90
- package/templates/vue/server/backend-wake.mjs +0 -129
package/README.md
CHANGED
|
@@ -44,11 +44,11 @@ In a DMS project started with `ajs project run -w`, serve the dashboard with hot
|
|
|
44
44
|
pnpm exec ajs dms dev
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
For production, build
|
|
47
|
+
For production, build from the project root, without the backend, then start the frontend server with `DMS_SESSION_SECRET` and the backend's secrets set:
|
|
48
48
|
|
|
49
49
|
```bash
|
|
50
|
-
pnpm exec ajs dms build
|
|
51
|
-
pnpm exec ajs dms start -b https://
|
|
50
|
+
pnpm exec ajs dms build
|
|
51
|
+
pnpm exec ajs dms start -b https://api.example.com -p 3001
|
|
52
52
|
```
|
|
53
53
|
|
|
54
54
|
`ajs dms --help` lists every command, and `ajs dms help environment` every environment variable.
|
|
@@ -61,7 +61,7 @@ pnpm exec ajs dms start -b https://dms.example.com -p 3001
|
|
|
61
61
|
| 0.9.0 | `>=0.6.0 <0.7.0` |
|
|
62
62
|
| 0.6.0 – 0.8.3 | 0.5 (exact floor per release in the full table) |
|
|
63
63
|
|
|
64
|
-
The 0.6 line needs Node.js 20.
|
|
64
|
+
The 0.6 line needs Node.js 20.19 or later and `@antelopejs/core` `>=1.13.2 <2`. The [compatibility table](https://dms.antelopejs.com/docs/frontend/introduction#compatibility) lists every release.
|
|
65
65
|
|
|
66
66
|
## Documentation
|
|
67
67
|
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { CliError } from "@antelopejs/core/cli";
|
|
2
2
|
import { type FramedCommandResult } from "../common";
|
|
3
3
|
export interface BuildOptions {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
offline?: boolean;
|
|
7
|
-
bootstrapSecret?: string;
|
|
8
|
-
from?: string;
|
|
4
|
+
project: string;
|
|
5
|
+
env: string;
|
|
9
6
|
workspace?: string;
|
|
7
|
+
force?: boolean;
|
|
10
8
|
}
|
|
9
|
+
export declare const DEFAULT_WORKSPACE_DIR = ".dms-frontend";
|
|
10
|
+
export declare function productionWorkspace(options: {
|
|
11
|
+
project: string;
|
|
12
|
+
workspace?: string;
|
|
13
|
+
}): string;
|
|
11
14
|
interface BuildStep {
|
|
12
15
|
script: string;
|
|
13
16
|
name: string;
|
|
@@ -1,34 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.BUILD_STEPS = void 0;
|
|
3
|
+
exports.BUILD_STEPS = exports.DEFAULT_WORKSPACE_DIR = void 0;
|
|
4
|
+
exports.productionWorkspace = productionWorkspace;
|
|
4
5
|
exports.buildStepFailure = buildStepFailure;
|
|
5
6
|
exports.runBuild = runBuild;
|
|
6
7
|
const node_path_1 = require("node:path");
|
|
7
8
|
const cli_1 = require("@antelopejs/core/cli");
|
|
8
9
|
const child_output_1 = require("../child-output");
|
|
9
10
|
const common_1 = require("../common");
|
|
10
|
-
const snapshot_1 = require("../snapshot");
|
|
11
11
|
const output_1 = require("../output");
|
|
12
12
|
const vite_output_1 = require("../vite-output");
|
|
13
13
|
const workspace_task_1 = require("./workspace-task");
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
if (options.offline) {
|
|
19
|
-
throw new cli_1.CliError({
|
|
20
|
-
title: "--from and --offline cannot be combined",
|
|
21
|
-
reason: "A snapshot build never asks the backend already.",
|
|
22
|
-
fixes: ["Drop --offline"],
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
const snapshot = (0, snapshot_1.readSnapshot)(options.from);
|
|
26
|
-
return {
|
|
27
|
-
backendUrl: options.backendUrl
|
|
28
|
-
? (0, common_1.parseBackendUrl)(options.backendUrl)
|
|
29
|
-
: snapshot.backendUrl,
|
|
30
|
-
snapshot: { dir: options.from, snapshot },
|
|
31
|
-
};
|
|
14
|
+
exports.DEFAULT_WORKSPACE_DIR = ".dms-frontend";
|
|
15
|
+
function productionWorkspace(options) {
|
|
16
|
+
return options.workspace ?? (0, node_path_1.join)(options.project, exports.DEFAULT_WORKSPACE_DIR);
|
|
32
17
|
}
|
|
33
18
|
exports.BUILD_STEPS = [
|
|
34
19
|
{
|
|
@@ -122,27 +107,15 @@ async function runBuild(options) {
|
|
|
122
107
|
}
|
|
123
108
|
}
|
|
124
109
|
async function buildProduction(options, startedAt) {
|
|
125
|
-
const { backendUrl, snapshot } = buildSource(options);
|
|
126
|
-
const bootstrapSecret = snapshot
|
|
127
|
-
? undefined
|
|
128
|
-
: (0, common_1.normalizeBootstrapSecret)(options.bootstrapSecret);
|
|
129
110
|
const ui = (0, cli_1.getProcessUi)();
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
111
|
+
const workspace = productionWorkspace(options);
|
|
112
|
+
(0, output_1.writeHeader)("build", [options.project, options.env]);
|
|
113
|
+
const { workspaceDir, layers } = await (0, workspace_task_1.setUpWorkspace)({
|
|
133
114
|
force: !!options.force,
|
|
134
115
|
mode: "build",
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
workspaceDir: options.workspace,
|
|
138
|
-
snapshot,
|
|
116
|
+
workspaceDir: workspace,
|
|
117
|
+
project: { projectDir: options.project, environment: options.env },
|
|
139
118
|
});
|
|
140
|
-
if (snapshot) {
|
|
141
|
-
ui.message("info", `Building from the snapshot of ${snapshot.snapshot.backendUrl}${(0, output_1.cachedAge)(snapshot.snapshot.takenAt)}`, { detail: `Modules digest ${snapshot.snapshot.digest}` });
|
|
142
|
-
}
|
|
143
|
-
else if (manifestFromCache) {
|
|
144
|
-
ui.message("warn", `Building from the manifest and layers archive${(0, output_1.cachedAge)(manifestFetchedAt)}`, { detail: "The output may not match the current backend." });
|
|
145
|
-
}
|
|
146
119
|
ui.message("info", "Building for production", {
|
|
147
120
|
detail: `Workspace ${(0, output_1.showWorkspace)(workspaceDir)}`,
|
|
148
121
|
});
|
|
@@ -162,7 +135,6 @@ async function buildProduction(options, startedAt) {
|
|
|
162
135
|
};
|
|
163
136
|
for (const step of exports.BUILD_STEPS)
|
|
164
137
|
await runBuildStep(step, context);
|
|
165
|
-
(0, snapshot_1.writeBuildOrigin)(workspaceDir, buildOrigin);
|
|
166
138
|
(0, vite_output_1.reportViteWarnings)(context.warnings, isVerbose, ui);
|
|
167
139
|
(0, output_1.writeBlankLine)();
|
|
168
140
|
ui.summary({
|
|
@@ -172,9 +144,9 @@ async function buildProduction(options, startedAt) {
|
|
|
172
144
|
nextSteps: [
|
|
173
145
|
{
|
|
174
146
|
command: options.workspace
|
|
175
|
-
? `ajs dms start -b
|
|
176
|
-
:
|
|
177
|
-
description: "with DMS_SESSION_SECRET
|
|
147
|
+
? `ajs dms start -b <backend> --workspace ${options.workspace}`
|
|
148
|
+
: "ajs dms start -b <backend>",
|
|
149
|
+
description: "from the project, with DMS_SESSION_SECRET, the server's secrets and the deployment's variables in its environment",
|
|
178
150
|
},
|
|
179
151
|
],
|
|
180
152
|
});
|
package/dist/commands/build.js
CHANGED
|
@@ -39,28 +39,22 @@ const config_1 = require("../config");
|
|
|
39
39
|
const cli_1 = require("@antelopejs/core/cli");
|
|
40
40
|
const BUILD_EXAMPLES = [
|
|
41
41
|
{
|
|
42
|
-
description: "
|
|
43
|
-
command: "ajs dms build
|
|
42
|
+
description: "From the project root, into .dms-frontend: no backend, no secret, no network",
|
|
43
|
+
command: "ajs dms build",
|
|
44
44
|
},
|
|
45
45
|
{
|
|
46
|
-
description: "
|
|
47
|
-
command: "ajs dms build
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
description: "Rebuild from the cache while the backend is down",
|
|
51
|
-
command: "ajs dms build -b https://dms.example.com --offline",
|
|
46
|
+
description: "With another environment's configuration, into a directory",
|
|
47
|
+
command: "ajs dms build -e staging --workspace /srv/dms-frontend",
|
|
52
48
|
},
|
|
53
49
|
];
|
|
54
50
|
function cmdBuild() {
|
|
55
51
|
const command = new commander_1.Command("build")
|
|
56
52
|
.summary("Build the production frontend")
|
|
57
|
-
.description("Build the production frontend from the
|
|
58
|
-
.addOption(config_1.Options.
|
|
59
|
-
.addOption(
|
|
60
|
-
.addOption(config_1.Options.workspace("Build into this directory instead of
|
|
61
|
-
.addOption(config_1.Options.force("
|
|
62
|
-
.addOption(config_1.Options.offline("Build from the last cached manifest and layers archive, without the backend"))
|
|
63
|
-
.addOption(config_1.Options.bootstrapSecret())
|
|
53
|
+
.description("Build the production frontend from the AntelopeJS project itself: its antelope.config.ts, evaluated for the environment, and the frontend of each installed module that declares one (dmsFrontend in its package.json). No backend is asked. The build holds no secret, and start computes the modules' options again from the deployment's variables.")
|
|
54
|
+
.addOption(config_1.Options.project)
|
|
55
|
+
.addOption(config_1.Options.env)
|
|
56
|
+
.addOption(config_1.Options.workspace("Build into this directory instead of <project>/.dms-frontend"))
|
|
57
|
+
.addOption(config_1.Options.force("Reinstall the workspace dependencies"))
|
|
64
58
|
.action(async (options) => (await Promise.resolve().then(() => __importStar(require("./build-action")))).runBuild(options));
|
|
65
59
|
return (0, cli_1.withExamples)(command, BUILD_EXAMPLES);
|
|
66
60
|
}
|
|
@@ -12,6 +12,7 @@ const server_process_1 = require("../server-process");
|
|
|
12
12
|
const update_check_1 = require("../update-check");
|
|
13
13
|
const manifest_1 = require("../manifest");
|
|
14
14
|
const module_set_1 = require("../module-set");
|
|
15
|
+
const project_modules_1 = require("../project-modules");
|
|
15
16
|
const workspace_task_1 = require("./workspace-task");
|
|
16
17
|
function clientHost() {
|
|
17
18
|
const host = process.env.HOST?.trim();
|
|
@@ -109,7 +110,10 @@ function servedModules(setup) {
|
|
|
109
110
|
return (0, manifest_1.readCachedManifest)(setup.workspaceDir)?.manifest.modules ?? [];
|
|
110
111
|
}
|
|
111
112
|
function reportServed(session, setup) {
|
|
112
|
-
return (0, module_set_1.reportFrontendReady)(session.backendUrl, servedModules(setup).map((module) =>
|
|
113
|
+
return (0, module_set_1.reportFrontendReady)(session.backendUrl, servedModules(setup).map((module) => ({
|
|
114
|
+
name: module.name,
|
|
115
|
+
version: module.path ? (0, project_modules_1.readShippingVersion)(module.path) : undefined,
|
|
116
|
+
})), session.bootstrapSecret);
|
|
113
117
|
}
|
|
114
118
|
async function serveWorkspace(session, setup) {
|
|
115
119
|
const restart = new AbortController();
|
|
@@ -10,11 +10,12 @@ const ports_1 = require("../ports");
|
|
|
10
10
|
const server_process_1 = require("../server-process");
|
|
11
11
|
const update_check_1 = require("../update-check");
|
|
12
12
|
const module_set_1 = require("../module-set");
|
|
13
|
-
const
|
|
13
|
+
const project_modules_1 = require("../project-modules");
|
|
14
14
|
const config_1 = require("../config");
|
|
15
15
|
const manifest_secrets_1 = require("../manifest-secrets");
|
|
16
16
|
const private_values_1 = require("../private-values");
|
|
17
|
-
const
|
|
17
|
+
const build_action_1 = require("./build-action");
|
|
18
|
+
const PUBLIC_OPTIONS_VARIABLE = "DMS_PUBLIC_OPTIONS";
|
|
18
19
|
function builtPrivateOptions(workspaceDir) {
|
|
19
20
|
try {
|
|
20
21
|
const { modules } = JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(workspaceDir, config_1.SERVER_OPTIONS_FILE), "utf8"));
|
|
@@ -51,72 +52,54 @@ function serverNodeEnv() {
|
|
|
51
52
|
}
|
|
52
53
|
return nodeEnv;
|
|
53
54
|
}
|
|
54
|
-
|
|
55
|
+
function publicOptionsById(modules) {
|
|
56
|
+
return Object.fromEntries(modules.map(({ layer }) => {
|
|
57
|
+
const options = layer.options ?? {};
|
|
58
|
+
return [
|
|
59
|
+
(0, common_1.getLayerSafeName)(layer),
|
|
60
|
+
layer.configKey ? { [layer.configKey]: options } : options,
|
|
61
|
+
];
|
|
62
|
+
}));
|
|
63
|
+
}
|
|
64
|
+
async function reportServedModules(backendUrl, modules) {
|
|
65
|
+
const isTaken = await (0, module_set_1.reportFrontendReadyOnceAnswered)(backendUrl, modules.map(({ layer, version }) => ({
|
|
66
|
+
name: layer.name ?? layer.path,
|
|
67
|
+
version,
|
|
68
|
+
})), process.env.DMS_BOOTSTRAP_SECRET);
|
|
55
69
|
const ui = (0, cli_1.getProcessUi)();
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return;
|
|
59
|
-
if (origin.authenticated === false) {
|
|
60
|
-
ui.message("info", `Built from modules ${origin.digest}; not compared with the backend`, {
|
|
61
|
-
detail: "The build read the manifest without DMS_BOOTSTRAP_SECRET, which leaves out the backend proxies.",
|
|
62
|
-
});
|
|
70
|
+
if (isTaken) {
|
|
71
|
+
ui.message("info", `[DMS] Reported ${modules.length} modules to the backend (dms-frontend ${module_set_1.OWN_RELEASE.version})`);
|
|
63
72
|
return;
|
|
64
73
|
}
|
|
65
|
-
|
|
66
|
-
ui.message("info", `Built from modules ${origin.digest}; not compared with the backend`, { detail: "Set DMS_BOOTSTRAP_SECRET to have start compare them." });
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
const drift = await (0, module_set_1.compareWithBackend)(backendUrl, origin.digest, snapshot_1.manifestDigest, bootstrapSecret);
|
|
70
|
-
if (drift.status === "matches") {
|
|
71
|
-
ui.message("info", `The backend serves the modules ${origin.digest} this build was made from`);
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
if (drift.status === "unknown") {
|
|
75
|
-
ui.message("info", `Built from modules ${origin.digest}; not compared with the backend: ${drift.reason}`);
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
const refresh = origin.source === "snapshot"
|
|
79
|
-
? `Refresh the snapshot and rebuild: ajs dms snapshot -b ${backendUrl} -o <dir>, then ajs dms build --from <dir>`
|
|
80
|
-
: `Rebuild: ajs dms build -b ${backendUrl}`;
|
|
81
|
-
ui.message("warn", `The backend serves modules ${drift.served}; this build was made from ${origin.digest} (${origin.source}${(0, output_1.cachedAge)(origin.takenAt)})`, {
|
|
74
|
+
ui.message("warn", "[DMS] The backend refused the ready report: it cannot check this build's module versions", {
|
|
82
75
|
details: [
|
|
83
|
-
|
|
84
|
-
`${ui.symbols.levels.hint} ${refresh}`,
|
|
76
|
+
`${ui.symbols.levels.hint} Set DMS_BOOTSTRAP_SECRET to the backend's frontend.bootstrapSecret`,
|
|
85
77
|
],
|
|
86
78
|
});
|
|
87
79
|
}
|
|
88
80
|
async function runStart(options) {
|
|
89
81
|
const startedAt = Date.now();
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
: undefined;
|
|
93
|
-
const origin = explicitWorkspace
|
|
94
|
-
? (0, snapshot_1.readBuildOrigin)(explicitWorkspace)
|
|
95
|
-
: undefined;
|
|
96
|
-
const backendUrl = (0, common_1.requireBackendUrl)(options.backendUrl ?? origin?.backendUrl);
|
|
82
|
+
const workspaceDir = (0, node_path_1.resolve)((0, build_action_1.productionWorkspace)(options));
|
|
83
|
+
const backendUrl = (0, common_1.requireBackendUrl)(options.backendUrl);
|
|
97
84
|
const requestedPort = (0, common_1.parsePort)(options.port);
|
|
98
85
|
const sessionSecret = (0, common_1.resolveSessionSecret)("start");
|
|
99
|
-
const workspaceDir = explicitWorkspace ?? (0, common_1.getWorkspaceDir)(backendUrl);
|
|
100
86
|
const serverPath = (0, node_path_1.join)(workspaceDir, "server.mjs");
|
|
101
87
|
const clientPath = (0, node_path_1.join)(workspaceDir, "dist", "client", "index.html");
|
|
102
88
|
if (!(0, node_fs_1.existsSync)(serverPath) || !(0, node_fs_1.existsSync)(clientPath)) {
|
|
103
89
|
throw new cli_1.CliError({
|
|
104
|
-
title:
|
|
90
|
+
title: "No production build to serve",
|
|
105
91
|
reason: `${(0, output_1.showWorkspace)(workspaceDir)} has no built server or client.`,
|
|
106
92
|
fixes: [
|
|
107
|
-
|
|
108
|
-
? `Build it first: ajs dms build --
|
|
109
|
-
:
|
|
93
|
+
options.workspace
|
|
94
|
+
? `Build it first: ajs dms build --workspace ${options.workspace}`
|
|
95
|
+
: "Build it first: ajs dms build",
|
|
110
96
|
],
|
|
111
97
|
});
|
|
112
98
|
}
|
|
113
|
-
if (!explicitWorkspace) {
|
|
114
|
-
(0, common_1.writeWorkspaceMeta)(workspaceDir, backendUrl, (0, common_1.canonicalizeBackendUrl)(backendUrl));
|
|
115
|
-
}
|
|
116
99
|
const builtAt = (0, node_fs_1.statSync)(clientPath).mtime.toISOString();
|
|
117
100
|
(0, output_1.writeHeader)("start", [
|
|
118
101
|
backendUrl,
|
|
119
|
-
|
|
102
|
+
options.env,
|
|
120
103
|
`built ${(0, output_1.formatAge)(builtAt)}`,
|
|
121
104
|
]);
|
|
122
105
|
const reserved = await (0, ports_1.reservePort)(requestedPort);
|
|
@@ -129,10 +112,14 @@ async function runStart(options) {
|
|
|
129
112
|
});
|
|
130
113
|
}
|
|
131
114
|
const port = reserved.port;
|
|
132
|
-
const
|
|
115
|
+
const modules = await (0, project_modules_1.readProjectFrontendModules)({
|
|
116
|
+
projectDir: options.project,
|
|
117
|
+
environment: options.env,
|
|
118
|
+
});
|
|
119
|
+
const secrets = (0, common_1.resolveManifestSecrets)({ published: {}, conflicts: [] });
|
|
133
120
|
(0, common_1.reportManifestSecrets)(secrets, (count) => `Set ${count === 1 ? "it" : "them"} in the server's environment, with the value${count === 1 ? "" : "s"} the backend uses`);
|
|
134
121
|
reportUnfilledPrivateValues(workspaceDir);
|
|
135
|
-
const secretSources = (0, common_1.describeSecretSources)(secrets.sources
|
|
122
|
+
const secretSources = (0, common_1.describeSecretSources)(secrets.sources);
|
|
136
123
|
const nodeEnv = serverNodeEnv();
|
|
137
124
|
await reserved.release();
|
|
138
125
|
const code = await (0, server_process_1.runServer)({
|
|
@@ -145,6 +132,7 @@ async function runStart(options) {
|
|
|
145
132
|
PORT: String(port),
|
|
146
133
|
DMS_API_BASE_URL: backendUrl,
|
|
147
134
|
DMS_SESSION_SECRET: sessionSecret,
|
|
135
|
+
[PUBLIC_OPTIONS_VARIABLE]: JSON.stringify(publicOptionsById(modules)),
|
|
148
136
|
...secrets.env,
|
|
149
137
|
DMS_COOKIE_SECURE: process.env.DMS_COOKIE_SECURE ?? "true",
|
|
150
138
|
},
|
|
@@ -160,9 +148,8 @@ async function runStart(options) {
|
|
|
160
148
|
]),
|
|
161
149
|
footer: "Ctrl+C to stop",
|
|
162
150
|
});
|
|
163
|
-
void (
|
|
151
|
+
void reportServedModules(backendUrl, modules);
|
|
164
152
|
void (0, update_check_1.reportAvailableUpdate)({ isFollowed: true });
|
|
165
|
-
void reportDrift(backendUrl, origin ?? (0, snapshot_1.readBuildOrigin)(workspaceDir));
|
|
166
153
|
},
|
|
167
154
|
});
|
|
168
155
|
process.exitCode = code;
|
package/dist/commands/start.js
CHANGED
|
@@ -39,21 +39,23 @@ const config_1 = require("../config");
|
|
|
39
39
|
const cli_1 = require("@antelopejs/core/cli");
|
|
40
40
|
const START_EXAMPLES = [
|
|
41
41
|
{
|
|
42
|
-
description: "
|
|
43
|
-
command: "ajs dms start -b https://
|
|
42
|
+
description: "From the project root, after ajs dms build",
|
|
43
|
+
command: "ajs dms start -b https://api.example.com -p 3001",
|
|
44
44
|
},
|
|
45
45
|
{
|
|
46
|
-
description: "
|
|
46
|
+
description: "In a read-only container holding the project and its build",
|
|
47
47
|
command: "ajs dms start --workspace .dms-frontend -p 3000",
|
|
48
48
|
},
|
|
49
49
|
];
|
|
50
50
|
function cmdStart() {
|
|
51
51
|
const command = new commander_1.Command("start")
|
|
52
52
|
.summary("Serve the production build")
|
|
53
|
-
.description("Serve the production frontend ajs dms build made
|
|
54
|
-
.addOption(config_1.Options.backendUrl("Backend URL to serve; required
|
|
53
|
+
.description("Serve the production frontend ajs dms build made from the project. The modules' public options are computed again from the project's configuration and the current environment variables, so a deployment's variables need no rebuild. Reads DMS_SESSION_SECRET and the server's secrets (DMS_HTML_RENDER_SECRET, DMS_OAUTH_RELAY_SECRET) from its environment, and tells the backend once ready which module versions it serves.")
|
|
54
|
+
.addOption(config_1.Options.backendUrl("Backend URL to serve; required"))
|
|
55
55
|
.addOption(config_1.Options.port)
|
|
56
|
-
.addOption(config_1.Options.
|
|
56
|
+
.addOption(config_1.Options.project)
|
|
57
|
+
.addOption(config_1.Options.env)
|
|
58
|
+
.addOption(config_1.Options.workspace("Serve the build in this directory instead of <project>/.dms-frontend; start writes nothing into it"))
|
|
57
59
|
.action(async (options) => (await Promise.resolve().then(() => __importStar(require("./start-action")))).runStart(options));
|
|
58
60
|
return (0, cli_1.withExamples)(command, START_EXAMPLES);
|
|
59
61
|
}
|
package/dist/config.d.ts
CHANGED
|
@@ -33,6 +33,8 @@ export declare const Options: {
|
|
|
33
33
|
offline(description: string): Option;
|
|
34
34
|
strict: Option;
|
|
35
35
|
workspace(description: string): Option;
|
|
36
|
+
project: Option;
|
|
37
|
+
env: Option;
|
|
36
38
|
bootstrapSecret(discovery?: string): Option;
|
|
37
39
|
};
|
|
38
40
|
export interface BootstrapDiscoveryOptions extends DiscoveryOptions {
|
package/dist/config.js
CHANGED
|
@@ -62,6 +62,7 @@ exports.TEMPLATE_FILES = [
|
|
|
62
62
|
["globals.d.ts", "globals.d.ts"],
|
|
63
63
|
["compress-assets.mjs", "compress-assets.mjs"],
|
|
64
64
|
["head-order.mjs", "head-order.mjs"],
|
|
65
|
+
["client-chunking.mjs", "client-chunking.mjs"],
|
|
65
66
|
["client-server-guard.mjs", "client-server-guard.mjs"],
|
|
66
67
|
["ui-inertia-page.mjs", "ui-inertia-page.mjs"],
|
|
67
68
|
["ui-request-state.mjs", "ui-request-state.mjs"],
|
|
@@ -71,6 +72,7 @@ exports.TEMPLATE_FILES = [
|
|
|
71
72
|
["email-runtime.ts", "email-runtime.ts"],
|
|
72
73
|
["email-locales.ts", "email-locales.ts"],
|
|
73
74
|
["email-markup.ts", "email-markup.ts"],
|
|
75
|
+
["public-options.ts", "public-options.ts"],
|
|
74
76
|
["tsconfig.json", "tsconfig.json"],
|
|
75
77
|
["typecheck-loader.mjs", "typecheck-loader.mjs"],
|
|
76
78
|
["prepare-types.mjs", "prepare-types.mjs"],
|
|
@@ -185,6 +187,10 @@ exports.Options = {
|
|
|
185
187
|
workspace(description) {
|
|
186
188
|
return new commander_1.Option("--workspace <dir>", description).env("DMS_WORKSPACE_DIR");
|
|
187
189
|
},
|
|
190
|
+
project: new commander_1.Option("--project <dir>", "The AntelopeJS project whose antelope.config.ts and installed modules make the frontend").default("."),
|
|
191
|
+
env: new commander_1.Option("-e, --env <environment>", "The AntelopeJS environment whose configuration applies, as ajs project start -e")
|
|
192
|
+
.default("production")
|
|
193
|
+
.env("ANTELOPEJS_LAUNCH_ENV"),
|
|
188
194
|
bootstrapSecret(discovery) {
|
|
189
195
|
return new commander_1.Option("--bootstrap-secret <secret>", discovery
|
|
190
196
|
? `${BOOTSTRAP_SECRET_DESCRIPTION}. ${discovery}`
|
package/dist/derived-outputs.js
CHANGED
|
@@ -72,7 +72,7 @@ function writeFrontendModuleLoader(workspaceDir, registry) {
|
|
|
72
72
|
.map((module, index) => `import module${index} from "@frontend/${module.id}/${module.entry}";`)
|
|
73
73
|
.join("\n");
|
|
74
74
|
const registrations = modules
|
|
75
|
-
.map((module, index) => `{ name: ${JSON.stringify(module.name)}, module: module${index}, options: { public: ${JSON.stringify(module.options)} } }`)
|
|
75
|
+
.map((module, index) => `{ id: ${JSON.stringify(module.id)}, name: ${JSON.stringify(module.name)}, module: module${index}, options: { public: ${JSON.stringify(module.options)} } }`)
|
|
76
76
|
.join(", ");
|
|
77
77
|
const content = `${imports}\n\nimport type { DmsFrontendModuleRegistration } from "./frontend-module";\n\nexport const frontendModules: DmsFrontendModuleRegistration[] = [${registrations}];\n`;
|
|
78
78
|
return (0, fs_sync_1.applyContent)(content, (0, node_path_1.join)(workspaceDir, "frontend-modules.generated.ts"));
|
|
@@ -85,7 +85,7 @@ function writeFrontendBuildLoader(workspaceDir, registry) {
|
|
|
85
85
|
const declarations = modules
|
|
86
86
|
.map((module, index) => `{ id: ${JSON.stringify(module.id)}, setup: build${index} }`)
|
|
87
87
|
.join(", ");
|
|
88
|
-
const content = `${imports}\n\nimport type { FrontendBuildDeclaration } from "./frontend-build-loader";\n\nexport const frontendBuilds: FrontendBuildDeclaration[] = [${declarations}];\n`;
|
|
88
|
+
const content = `${imports}\n\nimport type { FrontendBuildDeclaration } from "./frontend-build-loader.ts";\n\nexport const frontendBuilds: FrontendBuildDeclaration[] = [${declarations}];\n`;
|
|
89
89
|
return (0, fs_sync_1.applyContent)(content, (0, node_path_1.join)(workspaceDir, "frontend-builds.generated.ts"));
|
|
90
90
|
}
|
|
91
91
|
function writeServerModuleLoader(workspaceDir, registry) {
|
package/dist/fs-sync.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export declare function stripExtendedLengthPrefix(p: string): string;
|
|
|
2
2
|
export declare function toPosixPath(path: string, separator?: string): string;
|
|
3
3
|
export declare function isBlocklistedCopyPath(src: string, srcPath: string): boolean;
|
|
4
4
|
export declare function sanitizedPackageContent(raw: string): string;
|
|
5
|
+
export declare function sanitizedBuildDeclaration(raw: string): string;
|
|
5
6
|
export declare function filesIdentical(srcPath: string, destPath: string): boolean;
|
|
6
7
|
export declare function applyContent(content: string, destPath: string): boolean;
|
|
7
8
|
export declare function applyFile(srcPath: string, destPath: string): boolean;
|
package/dist/fs-sync.js
CHANGED
|
@@ -7,6 +7,7 @@ exports.stripExtendedLengthPrefix = stripExtendedLengthPrefix;
|
|
|
7
7
|
exports.toPosixPath = toPosixPath;
|
|
8
8
|
exports.isBlocklistedCopyPath = isBlocklistedCopyPath;
|
|
9
9
|
exports.sanitizedPackageContent = sanitizedPackageContent;
|
|
10
|
+
exports.sanitizedBuildDeclaration = sanitizedBuildDeclaration;
|
|
10
11
|
exports.filesIdentical = filesIdentical;
|
|
11
12
|
exports.applyContent = applyContent;
|
|
12
13
|
exports.applyFile = applyFile;
|
|
@@ -39,6 +40,11 @@ function sanitizedPackageContent(raw) {
|
|
|
39
40
|
}
|
|
40
41
|
return `${JSON.stringify(pkg, null, 2)}\n`;
|
|
41
42
|
}
|
|
43
|
+
const BUILD_HELPER_IMPORT = /(["'])#dms\/frontend-build\1/g;
|
|
44
|
+
const BUILD_HELPER_FROM_MODULE_ROOT = "../../frontend-build.ts";
|
|
45
|
+
function sanitizedBuildDeclaration(raw) {
|
|
46
|
+
return raw.replace(BUILD_HELPER_IMPORT, (_, quote) => `${quote}${BUILD_HELPER_FROM_MODULE_ROOT}${quote}`);
|
|
47
|
+
}
|
|
42
48
|
function filesIdentical(srcPath, destPath) {
|
|
43
49
|
if (!(0, node_fs_1.existsSync)(destPath))
|
|
44
50
|
return false;
|
package/dist/help.js
CHANGED
|
@@ -15,6 +15,10 @@ exports.ENVIRONMENT_VARIABLES = [
|
|
|
15
15
|
],
|
|
16
16
|
["DMS_OFFLINE", "Same as --offline, unless 0, false, no or off"],
|
|
17
17
|
["DMS_WORKSPACE_DIR", "Same as build and start --workspace"],
|
|
18
|
+
[
|
|
19
|
+
"ANTELOPEJS_LAUNCH_ENV",
|
|
20
|
+
"AntelopeJS environment build and start evaluate the project in, same as -e",
|
|
21
|
+
],
|
|
18
22
|
["DMS_PREPARE_STRICT", "Same as prepare --strict, read like DMS_OFFLINE"],
|
|
19
23
|
["PORT", "Same as -p"],
|
|
20
24
|
[
|
|
@@ -29,6 +33,10 @@ exports.ENVIRONMENT_VARIABLES = [
|
|
|
29
33
|
"NODE_ENV",
|
|
30
34
|
"Build of Vue and its libraries the server loads (default: development in dev, production in start)",
|
|
31
35
|
],
|
|
36
|
+
[
|
|
37
|
+
"DMS_CLIENT_IP_HEADER",
|
|
38
|
+
"Header the hosting platform overwrites with the client's address, e.g. X-Client-IP (default: none)",
|
|
39
|
+
],
|
|
32
40
|
[
|
|
33
41
|
"DMS_TRUSTED_PROXY_HOPS",
|
|
34
42
|
"Trusted reverse-proxy hops, counted from the right (default: 0)",
|
|
@@ -61,10 +69,6 @@ exports.ENVIRONMENT_VARIABLES = [
|
|
|
61
69
|
"DMS_BACKEND_PROXIES",
|
|
62
70
|
"More backend prefixes the server proxies, as a JSON array of { path, auth? }",
|
|
63
71
|
],
|
|
64
|
-
[
|
|
65
|
-
"DMS_BACKEND_WAKE_BUDGET_MS",
|
|
66
|
-
"How long a GET or HEAD waits out a backend's cold-start 503, in ms (default: 30000; 0: never)",
|
|
67
|
-
],
|
|
68
72
|
["DMS_CLIENT_BASE_URL", "Public frontend URL used in links and e-mails"],
|
|
69
73
|
["NO_COLOR", "Same as --no-color"],
|
|
70
74
|
["ANTELOPEJS_VERBOSE", "Same as --verbose"],
|
package/dist/index.js
CHANGED
|
@@ -8,7 +8,6 @@ const build_1 = require("./commands/build");
|
|
|
8
8
|
const clean_1 = require("./commands/clean");
|
|
9
9
|
const dev_1 = require("./commands/dev");
|
|
10
10
|
const prepare_1 = require("./commands/prepare");
|
|
11
|
-
const snapshot_1 = require("./commands/snapshot");
|
|
12
11
|
const start_1 = require("./commands/start");
|
|
13
12
|
const verify_source_1 = require("./commands/verify-source");
|
|
14
13
|
const workspaces_1 = require("./commands/workspaces");
|
|
@@ -29,12 +28,12 @@ const ROOT_EXAMPLES = [
|
|
|
29
28
|
command: "ajs dms dev",
|
|
30
29
|
},
|
|
31
30
|
{
|
|
32
|
-
description: "Build for production,
|
|
33
|
-
command: "ajs dms build
|
|
31
|
+
description: "Build for production from the project root, without a backend",
|
|
32
|
+
command: "ajs dms build",
|
|
34
33
|
},
|
|
35
34
|
{
|
|
36
|
-
description: "Serve
|
|
37
|
-
command: "ajs dms start -b https://
|
|
35
|
+
description: "Serve the build against its backend, on another port",
|
|
36
|
+
command: "ajs dms start -b https://api.example.com -p 3001",
|
|
38
37
|
},
|
|
39
38
|
];
|
|
40
39
|
function describeVersion(version, width) {
|
|
@@ -117,7 +116,6 @@ const runCLI = async () => {
|
|
|
117
116
|
program.addCommand((0, dev_1.cmdDev)());
|
|
118
117
|
program.addCommand((0, build_1.cmdBuild)());
|
|
119
118
|
program.addCommand((0, start_1.cmdStart)());
|
|
120
|
-
program.addCommand((0, snapshot_1.cmdSnapshot)());
|
|
121
119
|
program.addCommand((0, prepare_1.cmdPrepare)());
|
|
122
120
|
program.addCommand((0, workspaces_1.cmdWorkspaces)());
|
|
123
121
|
program.addCommand((0, clean_1.cmdClean)());
|
package/dist/layer-watch.js
CHANGED
|
@@ -9,6 +9,7 @@ const node_path_1 = require("node:path");
|
|
|
9
9
|
const cli_1 = require("@antelopejs/core/cli");
|
|
10
10
|
const chokidar_1 = __importDefault(require("chokidar"));
|
|
11
11
|
const child_output_1 = require("./child-output");
|
|
12
|
+
const config_1 = require("./config");
|
|
12
13
|
const layers_1 = require("./layers");
|
|
13
14
|
const derived_outputs_1 = require("./derived-outputs");
|
|
14
15
|
const output_1 = require("./output");
|
|
@@ -62,6 +63,9 @@ function createLayerSync(src, dest, reporter, onStaged) {
|
|
|
62
63
|
if (rel === "package.json") {
|
|
63
64
|
(0, fs_sync_1.applyContent)((0, fs_sync_1.sanitizedPackageContent)((0, node_fs_1.readFileSync)(srcPath, "utf-8")), destPath);
|
|
64
65
|
}
|
|
66
|
+
else if (rel === config_1.FRONTEND_BUILD_ENTRY) {
|
|
67
|
+
(0, fs_sync_1.applyContent)((0, fs_sync_1.sanitizedBuildDeclaration)((0, node_fs_1.readFileSync)(srcPath, "utf-8")), destPath);
|
|
68
|
+
}
|
|
65
69
|
else {
|
|
66
70
|
(0, fs_sync_1.applyFile)(srcPath, destPath);
|
|
67
71
|
}
|
package/dist/layers.d.ts
CHANGED
|
@@ -7,15 +7,13 @@ interface PathlessManifestSource {
|
|
|
7
7
|
};
|
|
8
8
|
}
|
|
9
9
|
export declare function assertLayerPathsServed(modules: ManifestModule[], backendUrl: string, { bootstrapSecret, cache }?: PathlessManifestSource): asserts modules is ServedWithPath[];
|
|
10
|
-
export declare function assertCachedArchivesExist(modules: ManifestModule[], cacheDir: string, fetchedAt?: string): void;
|
|
11
10
|
export interface LayerPackage {
|
|
12
11
|
name?: unknown;
|
|
13
12
|
engines?: Record<string, unknown>;
|
|
13
|
+
dmsFrontend?: unknown;
|
|
14
14
|
}
|
|
15
15
|
export declare function readLayerPackage(layerPath: string): LayerPackage | undefined;
|
|
16
16
|
export declare function buildLayersFromPaths(modules: ServedWithPath[]): ResolvedLayer[];
|
|
17
|
-
export declare function downloadAndExtractLayers(backendUrl: string, packUrl: string, cacheDir: string, force: boolean, bootstrapSecret?: string): Promise<void>;
|
|
18
|
-
export declare function buildLayersFromCache(modules: ManifestModule[], cacheDir: string): Promise<ResolvedLayer[]>;
|
|
19
17
|
export declare function getLayerSafeName(layer: ResolvedLayer): string;
|
|
20
18
|
export declare function getLayerWorkspacePath(workspaceDir: string, layer: ResolvedLayer): string;
|
|
21
19
|
export {};
|