@antelopejs/dms-frontend 0.7.1 → 0.9.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 +16 -41
- package/dist/commands/build.js +9 -15
- package/dist/commands/dev-action.d.ts +2 -0
- package/dist/commands/dev-action.js +14 -3
- package/dist/commands/dev.js +3 -1
- package/dist/commands/start-action.d.ts +2 -0
- package/dist/commands/start-action.js +65 -47
- package/dist/commands/start.js +8 -6
- 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 -0
- package/dist/derived-outputs.d.ts +1 -5
- package/dist/derived-outputs.js +48 -35
- package/dist/dev-modules.d.ts +5 -0
- package/dist/dev-modules.js +88 -0
- package/dist/entry-weight.d.ts +24 -0
- package/dist/entry-weight.js +86 -0
- package/dist/fs-sync.d.ts +1 -0
- package/dist/fs-sync.js +6 -0
- package/dist/help.js +12 -4
- package/dist/index.js +4 -6
- package/dist/layer-watch.js +7 -2
- package/dist/layers.d.ts +2 -3
- package/dist/layers.js +1 -95
- package/dist/locale-files.d.ts +6 -0
- package/dist/locale-files.js +75 -0
- package/dist/manifest.d.ts +8 -8
- package/dist/manifest.js +17 -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 +3 -2
- package/dist/private-values.js +16 -5
- package/dist/project-modules-child.d.ts +13 -0
- package/dist/project-modules-child.js +26 -0
- package/dist/project-modules.d.ts +47 -0
- package/dist/project-modules.js +268 -0
- package/dist/workspace-setup.d.ts +3 -7
- package/dist/workspace-setup.js +79 -62
- package/dist/workspace.d.ts +8 -4
- package/dist/workspace.js +1 -1
- package/package.json +13 -8
- package/skills/dms-frontend/SKILL.md +2 -2
- package/templates/vue/app-runtime.ts +8 -1
- package/templates/vue/client-chunking.mjs +61 -0
- package/templates/vue/email-renderer.ts +6 -1
- package/templates/vue/entry-weight.mjs +132 -0
- package/templates/vue/frontend-build-loader.ts +1 -1
- package/templates/vue/frontend-module.ts +168 -1
- package/templates/vue/gitignore +1 -0
- package/templates/vue/main.ts +32 -2
- package/templates/vue/network-error.ts +3 -1
- package/templates/vue/package.json +3 -3
- package/templates/vue/patches/@vueuse__core@14.4.0.patch +24 -0
- package/templates/vue/pnpm-workspace.yaml +5 -0
- 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 +34 -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/in-place-render.mjs +110 -0
- 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/page-props.mjs +10 -0
- 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 +110 -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 +98 -78
- package/templates/vue/sfc-global-types.mjs +119 -0
- package/templates/vue/ssr-renderer.ts +27 -1
- package/templates/vue/ui-kbd.mjs +45 -0
- package/templates/vue/vite.config.ts +104 -47
- 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,20 @@
|
|
|
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
|
+
const entry_weight_1 = require("../entry-weight");
|
|
13
14
|
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
|
-
};
|
|
15
|
+
exports.DEFAULT_WORKSPACE_DIR = ".dms-frontend";
|
|
16
|
+
function productionWorkspace(options) {
|
|
17
|
+
return options.workspace ?? (0, node_path_1.join)(options.project, exports.DEFAULT_WORKSPACE_DIR);
|
|
32
18
|
}
|
|
33
19
|
exports.BUILD_STEPS = [
|
|
34
20
|
{
|
|
@@ -122,27 +108,16 @@ async function runBuild(options) {
|
|
|
122
108
|
}
|
|
123
109
|
}
|
|
124
110
|
async function buildProduction(options, startedAt) {
|
|
125
|
-
|
|
126
|
-
const bootstrapSecret = snapshot
|
|
127
|
-
? undefined
|
|
128
|
-
: (0, common_1.normalizeBootstrapSecret)(options.bootstrapSecret);
|
|
111
|
+
(0, entry_weight_1.entryWeightThreshold)(process.env);
|
|
129
112
|
const ui = (0, cli_1.getProcessUi)();
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
113
|
+
const workspace = productionWorkspace(options);
|
|
114
|
+
(0, output_1.writeHeader)("build", [options.project, options.env]);
|
|
115
|
+
const { workspaceDir, layers } = await (0, workspace_task_1.setUpWorkspace)({
|
|
133
116
|
force: !!options.force,
|
|
134
117
|
mode: "build",
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
workspaceDir: options.workspace,
|
|
138
|
-
snapshot,
|
|
118
|
+
workspaceDir: workspace,
|
|
119
|
+
project: { projectDir: options.project, environment: options.env },
|
|
139
120
|
});
|
|
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
121
|
ui.message("info", "Building for production", {
|
|
147
122
|
detail: `Workspace ${(0, output_1.showWorkspace)(workspaceDir)}`,
|
|
148
123
|
});
|
|
@@ -162,8 +137,8 @@ async function buildProduction(options, startedAt) {
|
|
|
162
137
|
};
|
|
163
138
|
for (const step of exports.BUILD_STEPS)
|
|
164
139
|
await runBuildStep(step, context);
|
|
165
|
-
(0, snapshot_1.writeBuildOrigin)(workspaceDir, buildOrigin);
|
|
166
140
|
(0, vite_output_1.reportViteWarnings)(context.warnings, isVerbose, ui);
|
|
141
|
+
(0, entry_weight_1.reportEntryWeight)(ui, workspaceDir, process.env);
|
|
167
142
|
(0, output_1.writeBlankLine)();
|
|
168
143
|
ui.summary({
|
|
169
144
|
headline: "Built the production frontend",
|
|
@@ -172,9 +147,9 @@ async function buildProduction(options, startedAt) {
|
|
|
172
147
|
nextSteps: [
|
|
173
148
|
{
|
|
174
149
|
command: options.workspace
|
|
175
|
-
? `ajs dms start -b
|
|
176
|
-
:
|
|
177
|
-
description: "with DMS_SESSION_SECRET
|
|
150
|
+
? `ajs dms start -b <backend> --workspace ${options.workspace}`
|
|
151
|
+
: "ajs dms start -b <backend>",
|
|
152
|
+
description: "from the project, with DMS_SESSION_SECRET, the server's secrets and the deployment's variables in its environment",
|
|
178
153
|
},
|
|
179
154
|
],
|
|
180
155
|
});
|
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,7 +12,9 @@ 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");
|
|
17
|
+
const BASE_ENVIRONMENT = "default";
|
|
16
18
|
function clientHost() {
|
|
17
19
|
const host = process.env.HOST?.trim();
|
|
18
20
|
if (!host || host === "0.0.0.0" || host === "::" || host === "[::]") {
|
|
@@ -40,6 +42,10 @@ async function runDev(options) {
|
|
|
40
42
|
const offline = (0, common_1.flagOrEnv)(options.offline, "DMS_OFFLINE");
|
|
41
43
|
const sessionSecret = (0, common_1.resolveSessionSecret)("dev");
|
|
42
44
|
const { backendUrl, workspaceKey, projectDir } = resolveBackend(options);
|
|
45
|
+
const project = {
|
|
46
|
+
projectDir: options.project ?? projectDir ?? process.cwd(),
|
|
47
|
+
environment: options.env ?? BASE_ENVIRONMENT,
|
|
48
|
+
};
|
|
43
49
|
const bootstrapSecret = (0, common_1.resolveBootstrapSecret)(options.bootstrapSecret, backendUrl);
|
|
44
50
|
const ui = (0, cli_1.getProcessUi)();
|
|
45
51
|
(0, output_1.writeHeader)("dev", [backendUrl, "development"]);
|
|
@@ -57,6 +63,7 @@ async function runDev(options) {
|
|
|
57
63
|
clientUrl,
|
|
58
64
|
workspaceKey,
|
|
59
65
|
bootstrapSecret,
|
|
66
|
+
project,
|
|
60
67
|
});
|
|
61
68
|
if (port !== requestedPort) {
|
|
62
69
|
ui.message("warn", `Port ${requestedPort} is busy, using ${port}`);
|
|
@@ -102,14 +109,18 @@ async function runDev(options) {
|
|
|
102
109
|
clientUrl,
|
|
103
110
|
workspaceKey,
|
|
104
111
|
bootstrapSecret: session.bootstrapSecret,
|
|
112
|
+
project,
|
|
105
113
|
});
|
|
106
114
|
}
|
|
107
115
|
}
|
|
108
|
-
function
|
|
116
|
+
function backendModuleSet(setup) {
|
|
109
117
|
return (0, manifest_1.readCachedManifest)(setup.workspaceDir)?.manifest.modules ?? [];
|
|
110
118
|
}
|
|
111
119
|
function reportServed(session, setup) {
|
|
112
|
-
return (0, module_set_1.reportFrontendReady)(session.backendUrl,
|
|
120
|
+
return (0, module_set_1.reportFrontendReady)(session.backendUrl, setup.layers.map((layer) => ({
|
|
121
|
+
name: layer.name ?? layer.path,
|
|
122
|
+
version: (0, project_modules_1.readShippingVersion)(layer.path),
|
|
123
|
+
})), session.bootstrapSecret);
|
|
113
124
|
}
|
|
114
125
|
async function serveWorkspace(session, setup) {
|
|
115
126
|
const restart = new AbortController();
|
|
@@ -122,7 +133,7 @@ async function serveWorkspace(session, setup) {
|
|
|
122
133
|
session.bootstrapSecret = session.refreshBootstrapSecret();
|
|
123
134
|
return session.bootstrapSecret;
|
|
124
135
|
},
|
|
125
|
-
fingerprint: (0, module_set_1.moduleSetFingerprint)(
|
|
136
|
+
fingerprint: (0, module_set_1.moduleSetFingerprint)(backendModuleSet(setup)),
|
|
126
137
|
onChange: () => restart.abort(),
|
|
127
138
|
onUnchanged: () => void reportServed(session, setup),
|
|
128
139
|
});
|
package/dist/commands/dev.js
CHANGED
|
@@ -50,8 +50,10 @@ const DEV_EXAMPLES = [
|
|
|
50
50
|
function cmdDev() {
|
|
51
51
|
const command = new commander_1.Command("dev")
|
|
52
52
|
.summary("Run the dev server against a local backend, with hot reload")
|
|
53
|
-
.description("Run the dev server with hot reload. It reads the frontend modules in place
|
|
53
|
+
.description("Run the dev server with hot reload. It reads the frontend modules from the AntelopeJS project as build does, each module's frontendModule called with dev: true, and serves them in place from their sources. The backend, on this machine, gives the secrets it holds and says when the module store changes its modules.")
|
|
54
54
|
.addOption(config_1.Options.backendUrl("Backend URL; when omitted, discovered from the enclosing antelope project's .antelope/dev.json"))
|
|
55
|
+
.addOption(new commander_1.Option("--project <dir>", "The AntelopeJS project the modules are read from (default: the discovered backend's, else the current directory)"))
|
|
56
|
+
.addOption(new commander_1.Option("-e, --env <environment>", "The AntelopeJS environment the backend runs, as ajs project dev -e (default: the base configuration)").env("ANTELOPEJS_LAUNCH_ENV"))
|
|
55
57
|
.addOption(config_1.Options.port)
|
|
56
58
|
.addOption(config_1.Options.force("Reinstall the workspace dependencies"))
|
|
57
59
|
.addOption(config_1.Options.offline("Reuse the last cached manifest instead of fetching it"))
|
|
@@ -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,83 @@ function serverNodeEnv() {
|
|
|
51
52
|
}
|
|
52
53
|
return nodeEnv;
|
|
53
54
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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
|
+
function builtModules(workspaceDir) {
|
|
65
|
+
try {
|
|
66
|
+
const { modules } = JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(workspaceDir, "generated-frontend-modules.json"), "utf8"));
|
|
67
|
+
return (modules ?? []).map((module) => ({
|
|
68
|
+
name: module.name ?? module.id,
|
|
69
|
+
version: module.version,
|
|
70
|
+
}));
|
|
64
71
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
return;
|
|
72
|
+
catch {
|
|
73
|
+
return [];
|
|
68
74
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
75
|
+
}
|
|
76
|
+
function reportModuleSetDrift(built, modules) {
|
|
77
|
+
const builtNames = new Set(built.map(({ name }) => name));
|
|
78
|
+
const currentNames = new Set(modules.map(({ layer }) => layer.name ?? layer.path));
|
|
79
|
+
const added = [...currentNames].filter((name) => !builtNames.has(name));
|
|
80
|
+
const removed = [...builtNames].filter((name) => !currentNames.has(name));
|
|
81
|
+
if (added.length === 0 && removed.length === 0)
|
|
72
82
|
return;
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
83
|
+
const ui = (0, cli_1.getProcessUi)();
|
|
84
|
+
ui.message("warn", "The project's modules differ from the ones the build serves: rebuild to apply them", {
|
|
85
|
+
details: [
|
|
86
|
+
...(added.length > 0
|
|
87
|
+
? [`Not in the build: ${added.sort().join(", ")}`]
|
|
88
|
+
: []),
|
|
89
|
+
...(removed.length > 0
|
|
90
|
+
? [`Built, no longer in the project: ${removed.sort().join(", ")}`]
|
|
91
|
+
: []),
|
|
92
|
+
`${ui.symbols.levels.hint} Build again with the deployment's variables: ajs dms build`,
|
|
93
|
+
],
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
async function reportServedModules(backendUrl, modules) {
|
|
97
|
+
const isTaken = await (0, module_set_1.reportFrontendReadyOnceAnswered)(backendUrl, modules, process.env.DMS_BOOTSTRAP_SECRET);
|
|
98
|
+
const ui = (0, cli_1.getProcessUi)();
|
|
99
|
+
if (isTaken) {
|
|
100
|
+
ui.message("info", `[DMS] Reported ${modules.length} modules to the backend (dms-frontend ${module_set_1.OWN_RELEASE.version})`);
|
|
76
101
|
return;
|
|
77
102
|
}
|
|
78
|
-
|
|
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)})`, {
|
|
103
|
+
ui.message("warn", "[DMS] The backend refused the ready report: it cannot check this build's module versions", {
|
|
82
104
|
details: [
|
|
83
|
-
|
|
84
|
-
`${ui.symbols.levels.hint} ${refresh}`,
|
|
105
|
+
`${ui.symbols.levels.hint} Set DMS_BOOTSTRAP_SECRET to the backend's frontend.bootstrapSecret`,
|
|
85
106
|
],
|
|
86
107
|
});
|
|
87
108
|
}
|
|
88
109
|
async function runStart(options) {
|
|
89
110
|
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);
|
|
111
|
+
const workspaceDir = (0, node_path_1.resolve)((0, build_action_1.productionWorkspace)(options));
|
|
112
|
+
const backendUrl = (0, common_1.requireBackendUrl)(options.backendUrl);
|
|
97
113
|
const requestedPort = (0, common_1.parsePort)(options.port);
|
|
98
114
|
const sessionSecret = (0, common_1.resolveSessionSecret)("start");
|
|
99
|
-
const workspaceDir = explicitWorkspace ?? (0, common_1.getWorkspaceDir)(backendUrl);
|
|
100
115
|
const serverPath = (0, node_path_1.join)(workspaceDir, "server.mjs");
|
|
101
116
|
const clientPath = (0, node_path_1.join)(workspaceDir, "dist", "client", "index.html");
|
|
102
117
|
if (!(0, node_fs_1.existsSync)(serverPath) || !(0, node_fs_1.existsSync)(clientPath)) {
|
|
103
118
|
throw new cli_1.CliError({
|
|
104
|
-
title:
|
|
119
|
+
title: "No production build to serve",
|
|
105
120
|
reason: `${(0, output_1.showWorkspace)(workspaceDir)} has no built server or client.`,
|
|
106
121
|
fixes: [
|
|
107
|
-
|
|
108
|
-
? `Build it first: ajs dms build --
|
|
109
|
-
:
|
|
122
|
+
options.workspace
|
|
123
|
+
? `Build it first: ajs dms build --workspace ${options.workspace}`
|
|
124
|
+
: "Build it first: ajs dms build",
|
|
110
125
|
],
|
|
111
126
|
});
|
|
112
127
|
}
|
|
113
|
-
if (!explicitWorkspace) {
|
|
114
|
-
(0, common_1.writeWorkspaceMeta)(workspaceDir, backendUrl, (0, common_1.canonicalizeBackendUrl)(backendUrl));
|
|
115
|
-
}
|
|
116
128
|
const builtAt = (0, node_fs_1.statSync)(clientPath).mtime.toISOString();
|
|
117
129
|
(0, output_1.writeHeader)("start", [
|
|
118
130
|
backendUrl,
|
|
119
|
-
|
|
131
|
+
options.env,
|
|
120
132
|
`built ${(0, output_1.formatAge)(builtAt)}`,
|
|
121
133
|
]);
|
|
122
134
|
const reserved = await (0, ports_1.reservePort)(requestedPort);
|
|
@@ -129,10 +141,16 @@ async function runStart(options) {
|
|
|
129
141
|
});
|
|
130
142
|
}
|
|
131
143
|
const port = reserved.port;
|
|
132
|
-
const
|
|
144
|
+
const modules = await (0, project_modules_1.readProjectFrontendModules)({
|
|
145
|
+
projectDir: options.project,
|
|
146
|
+
environment: options.env,
|
|
147
|
+
});
|
|
148
|
+
const built = builtModules(workspaceDir);
|
|
149
|
+
reportModuleSetDrift(built, modules);
|
|
150
|
+
const secrets = (0, common_1.resolveManifestSecrets)({ published: {}, conflicts: [] });
|
|
133
151
|
(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
152
|
reportUnfilledPrivateValues(workspaceDir);
|
|
135
|
-
const secretSources = (0, common_1.describeSecretSources)(secrets.sources
|
|
153
|
+
const secretSources = (0, common_1.describeSecretSources)(secrets.sources);
|
|
136
154
|
const nodeEnv = serverNodeEnv();
|
|
137
155
|
await reserved.release();
|
|
138
156
|
const code = await (0, server_process_1.runServer)({
|
|
@@ -145,6 +163,7 @@ async function runStart(options) {
|
|
|
145
163
|
PORT: String(port),
|
|
146
164
|
DMS_API_BASE_URL: backendUrl,
|
|
147
165
|
DMS_SESSION_SECRET: sessionSecret,
|
|
166
|
+
[PUBLIC_OPTIONS_VARIABLE]: JSON.stringify(publicOptionsById(modules)),
|
|
148
167
|
...secrets.env,
|
|
149
168
|
DMS_COOKIE_SECURE: process.env.DMS_COOKIE_SECURE ?? "true",
|
|
150
169
|
},
|
|
@@ -160,9 +179,8 @@ async function runStart(options) {
|
|
|
160
179
|
]),
|
|
161
180
|
footer: "Ctrl+C to stop",
|
|
162
181
|
});
|
|
163
|
-
void (
|
|
182
|
+
void reportServedModules(backendUrl, built);
|
|
164
183
|
void (0, update_check_1.reportAvailableUpdate)({ isFollowed: true });
|
|
165
|
-
void reportDrift(backendUrl, origin ?? (0, snapshot_1.readBuildOrigin)(workspaceDir));
|
|
166
184
|
},
|
|
167
185
|
});
|
|
168
186
|
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/common.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export * from "./manifest-secrets";
|
|
|
8
8
|
export * from "./layer-watch";
|
|
9
9
|
export * from "./materialize";
|
|
10
10
|
export * from "./derived-outputs";
|
|
11
|
+
export * from "./locale-files";
|
|
11
12
|
export * from "./app-configs";
|
|
12
13
|
export * from "./renderer-range";
|
|
13
14
|
export * from "./workspace";
|
package/dist/common.js
CHANGED
|
@@ -24,6 +24,7 @@ __exportStar(require("./manifest-secrets"), exports);
|
|
|
24
24
|
__exportStar(require("./layer-watch"), exports);
|
|
25
25
|
__exportStar(require("./materialize"), exports);
|
|
26
26
|
__exportStar(require("./derived-outputs"), exports);
|
|
27
|
+
__exportStar(require("./locale-files"), exports);
|
|
27
28
|
__exportStar(require("./app-configs"), exports);
|
|
28
29
|
__exportStar(require("./renderer-range"), exports);
|
|
29
30
|
__exportStar(require("./workspace"), exports);
|
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,15 +62,20 @@ 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"],
|
|
66
|
+
["entry-weight.mjs", "entry-weight.mjs"],
|
|
65
67
|
["client-server-guard.mjs", "client-server-guard.mjs"],
|
|
66
68
|
["ui-inertia-page.mjs", "ui-inertia-page.mjs"],
|
|
67
69
|
["ui-request-state.mjs", "ui-request-state.mjs"],
|
|
70
|
+
["sfc-global-types.mjs", "sfc-global-types.mjs"],
|
|
68
71
|
["icon-api.mjs", "icon-api.mjs"],
|
|
69
72
|
["icon-scan.mjs", "icon-scan.mjs"],
|
|
73
|
+
["ui-kbd.mjs", "ui-kbd.mjs"],
|
|
70
74
|
["email-renderer.ts", "email-renderer.ts"],
|
|
71
75
|
["email-runtime.ts", "email-runtime.ts"],
|
|
72
76
|
["email-locales.ts", "email-locales.ts"],
|
|
73
77
|
["email-markup.ts", "email-markup.ts"],
|
|
78
|
+
["public-options.ts", "public-options.ts"],
|
|
74
79
|
["tsconfig.json", "tsconfig.json"],
|
|
75
80
|
["typecheck-loader.mjs", "typecheck-loader.mjs"],
|
|
76
81
|
["prepare-types.mjs", "prepare-types.mjs"],
|
|
@@ -185,6 +190,10 @@ exports.Options = {
|
|
|
185
190
|
workspace(description) {
|
|
186
191
|
return new commander_1.Option("--workspace <dir>", description).env("DMS_WORKSPACE_DIR");
|
|
187
192
|
},
|
|
193
|
+
project: new commander_1.Option("--project <dir>", "The AntelopeJS project whose antelope.config.ts and installed modules make the frontend").default("."),
|
|
194
|
+
env: new commander_1.Option("-e, --env <environment>", "The AntelopeJS environment whose configuration applies, as ajs project start -e")
|
|
195
|
+
.default("production")
|
|
196
|
+
.env("ANTELOPEJS_LAUNCH_ENV"),
|
|
188
197
|
bootstrapSecret(discovery) {
|
|
189
198
|
return new commander_1.Option("--bootstrap-secret <secret>", discovery
|
|
190
199
|
? `${BOOTSTRAP_SECRET_DESCRIPTION}. ${discovery}`
|
|
@@ -3,6 +3,7 @@ export interface FrontendModuleRegistryEntry {
|
|
|
3
3
|
id: string;
|
|
4
4
|
name?: string;
|
|
5
5
|
packageName?: string;
|
|
6
|
+
version?: string;
|
|
6
7
|
root: string;
|
|
7
8
|
priority: number;
|
|
8
9
|
entry?: string;
|
|
@@ -14,11 +15,6 @@ export interface FrontendModuleRegistry {
|
|
|
14
15
|
modules: FrontendModuleRegistryEntry[];
|
|
15
16
|
}
|
|
16
17
|
export declare function createFrontendModuleRegistry(workspaceDir: string, layers: ResolvedLayer[]): FrontendModuleRegistry;
|
|
17
|
-
export declare class InvalidLocaleFileError extends Error {
|
|
18
|
-
readonly path: string;
|
|
19
|
-
readonly reason: string;
|
|
20
|
-
constructor(path: string, reason: string);
|
|
21
|
-
}
|
|
22
18
|
export declare function affectsLocaleMessages(relativePath: string): boolean;
|
|
23
19
|
export declare function writeLocaleMessages(workspaceDir: string, registry: FrontendModuleRegistry): boolean;
|
|
24
20
|
export interface DerivedOutput {
|