@antelopejs/dms-frontend 0.3.7 → 0.3.9
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 +82 -23
- package/dist/cancellation.d.ts +8 -0
- package/dist/cancellation.js +23 -0
- package/dist/child-output.d.ts +45 -0
- package/dist/child-output.js +183 -0
- package/dist/commands/build-action.d.ts +21 -0
- package/dist/commands/build-action.js +144 -0
- package/dist/commands/build.js +54 -62
- package/dist/commands/clean-action.d.ts +8 -0
- package/dist/commands/clean-action.js +97 -0
- package/dist/commands/clean.js +52 -39
- package/dist/commands/dev-action.d.ts +8 -0
- package/dist/commands/dev-action.js +120 -0
- package/dist/commands/dev.js +55 -115
- package/dist/commands/prepare-action.d.ts +8 -0
- package/dist/commands/prepare-action.js +73 -0
- package/dist/commands/prepare.js +55 -54
- package/dist/commands/start-action.d.ts +5 -0
- package/dist/commands/start-action.js +77 -0
- package/dist/commands/start.js +48 -48
- package/dist/commands/verify-source-action.d.ts +10 -0
- package/dist/commands/verify-source-action.js +104 -0
- package/dist/commands/verify-source.d.ts +0 -1
- package/dist/commands/verify-source.js +53 -31
- package/dist/commands/workspace-task.d.ts +2 -0
- package/dist/commands/workspace-task.js +26 -0
- package/dist/commands/workspaces-action.d.ts +25 -0
- package/dist/commands/workspaces-action.js +71 -0
- package/dist/commands/workspaces.d.ts +2 -0
- package/dist/commands/workspaces.js +60 -0
- package/dist/common.d.ts +1 -0
- package/dist/common.js +1 -0
- package/dist/config.d.ts +13 -4
- package/dist/config.js +115 -18
- package/dist/derived-outputs.d.ts +6 -1
- package/dist/derived-outputs.js +12 -3
- package/dist/discovery.d.ts +2 -1
- package/dist/discovery.js +28 -11
- package/dist/env-file.js +5 -2
- package/dist/help.d.ts +5 -0
- package/dist/help.js +70 -0
- package/dist/index.js +98 -38
- package/dist/layer-watch.d.ts +2 -1
- package/dist/layer-watch.js +129 -26
- package/dist/layers.d.ts +2 -2
- package/dist/layers.js +71 -23
- package/dist/manifest-secrets.d.ts +3 -2
- package/dist/manifest-secrets.js +25 -21
- package/dist/manifest.d.ts +22 -5
- package/dist/manifest.js +184 -28
- package/dist/materialize.js +2 -1
- package/dist/output.d.ts +41 -0
- package/dist/output.js +197 -0
- package/dist/ports.d.ts +2 -0
- package/dist/ports.js +23 -13
- package/dist/renderer-range.d.ts +3 -1
- package/dist/renderer-range.js +49 -17
- package/dist/server-process.d.ts +39 -0
- package/dist/server-process.js +221 -0
- package/dist/typecheck-output.d.ts +13 -0
- package/dist/typecheck-output.js +87 -0
- package/dist/update-check.d.ts +14 -2
- package/dist/update-check.js +95 -29
- package/dist/verify-source-result.d.ts +11 -0
- package/dist/verify-source-result.js +17 -0
- package/dist/verify-source-runner.js +266 -131
- package/dist/vite-output.d.ts +14 -0
- package/dist/vite-output.js +99 -0
- package/dist/workspace-setup.d.ts +17 -3
- package/dist/workspace-setup.js +119 -35
- package/dist/workspace.d.ts +8 -2
- package/dist/workspace.js +47 -12
- package/package.json +4 -12
- package/templates/vue/frontend-module.ts +32 -10
- package/templates/vue/package.json +4 -0
- package/templates/vue/server/cli-report.mjs +91 -0
- package/templates/vue/server.mjs +45 -21
- package/templates/vue/vite.config.ts +8 -1
- package/templates/vue/vite.email.config.ts +5 -1
- package/dist/utils/cli-ui.d.ts +0 -27
- package/dist/utils/cli-ui.js +0 -178
package/dist/update-check.js
CHANGED
|
@@ -1,27 +1,62 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
5
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
36
|
exports.NO_UPDATE_CHECK_FLAG = exports.UPDATE_CHECK_TIMEOUT_MS = exports.UPDATE_CHECK_RETRY_INTERVAL_MS = exports.UPDATE_CHECK_INTERVAL_MS = exports.UPDATE_CHECK_PACKAGE = void 0;
|
|
7
37
|
exports.stripUpdateCheckFlag = stripUpdateCheckFlag;
|
|
8
38
|
exports.isUpdateCheckEnabled = isUpdateCheckEnabled;
|
|
9
39
|
exports.updateCheckCacheFile = updateCheckCacheFile;
|
|
10
40
|
exports.fetchLatestVersionFromRegistry = fetchLatestVersionFromRegistry;
|
|
11
|
-
exports.
|
|
41
|
+
exports.startUpdateCheck = startUpdateCheck;
|
|
42
|
+
exports.startProcessUpdateCheck = startProcessUpdateCheck;
|
|
43
|
+
exports.reportAvailableUpdate = reportAvailableUpdate;
|
|
12
44
|
const node_fs_1 = require("node:fs");
|
|
13
45
|
const node_http_1 = require("node:http");
|
|
14
46
|
const node_https_1 = require("node:https");
|
|
15
47
|
const node_path_1 = require("node:path");
|
|
16
|
-
const
|
|
48
|
+
const cli_1 = require("@antelopejs/core/cli");
|
|
17
49
|
const config_1 = require("./config");
|
|
50
|
+
const output_1 = require("./output");
|
|
18
51
|
exports.UPDATE_CHECK_PACKAGE = "@antelopejs/dms-frontend";
|
|
19
52
|
const DEFAULT_REGISTRY_URL = "https://registry.npmjs.org/";
|
|
53
|
+
const UPDATE_COMMAND = "ajs update dms";
|
|
54
|
+
const DUMB_TERMINAL = "dumb";
|
|
20
55
|
exports.UPDATE_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
21
56
|
exports.UPDATE_CHECK_RETRY_INTERVAL_MS = 60 * 60 * 1000;
|
|
22
57
|
exports.UPDATE_CHECK_TIMEOUT_MS = 3000;
|
|
23
58
|
exports.NO_UPDATE_CHECK_FLAG = "--no-update-check";
|
|
24
|
-
const
|
|
59
|
+
const SILENT_FLAGS = ["--help", "-h", "--version", "-v", "--json"];
|
|
25
60
|
const VALUE_TAKING_OPTIONS = [
|
|
26
61
|
"-b",
|
|
27
62
|
"--backend-url",
|
|
@@ -56,11 +91,13 @@ function isUpdateCheckEnabled(argv, env) {
|
|
|
56
91
|
return false;
|
|
57
92
|
if (env.NO_UPDATE_NOTIFIER)
|
|
58
93
|
return false;
|
|
94
|
+
if (env.TERM === DUMB_TERMINAL)
|
|
95
|
+
return false;
|
|
59
96
|
if (argv[0] === "help")
|
|
60
97
|
return false;
|
|
61
98
|
if (flagIndexes(argv, [exports.NO_UPDATE_CHECK_FLAG]).length)
|
|
62
99
|
return false;
|
|
63
|
-
return flagIndexes(argv,
|
|
100
|
+
return flagIndexes(argv, SILENT_FLAGS).length === 0;
|
|
64
101
|
}
|
|
65
102
|
function updateCheckCacheFile() {
|
|
66
103
|
return (0, node_path_1.join)(config_1.DMS_FRONTEND_HOME, "update-check.json");
|
|
@@ -143,22 +180,27 @@ function fetchLatestVersionFromRegistry(packageName, registryUrl = DEFAULT_REGIS
|
|
|
143
180
|
}
|
|
144
181
|
});
|
|
145
182
|
}
|
|
146
|
-
function formatNotice(currentVersion, latestVersion) {
|
|
147
|
-
|
|
148
|
-
|
|
183
|
+
function formatNotice(currentVersion, latestVersion, ui) {
|
|
184
|
+
const palette = ui.palette("feedback");
|
|
185
|
+
const { info, hint } = ui.symbols.levels;
|
|
186
|
+
return (`${palette.blue(info)} ajs dms ${latestVersion} is available ` +
|
|
187
|
+
`(you have ${currentVersion}) ${palette.cyan(`${hint} ${UPDATE_COMMAND}`)}`);
|
|
149
188
|
}
|
|
150
|
-
function isNewer(currentVersion, latestVersion) {
|
|
151
|
-
|
|
152
|
-
|
|
189
|
+
async function isNewer(currentVersion, latestVersion) {
|
|
190
|
+
if (currentVersion === latestVersion)
|
|
191
|
+
return false;
|
|
192
|
+
const { lt, valid } = await Promise.resolve().then(() => __importStar(require("semver")));
|
|
193
|
+
const current = valid(currentVersion);
|
|
194
|
+
const latest = valid(latestVersion);
|
|
153
195
|
if (!current || !latest)
|
|
154
196
|
return false;
|
|
155
|
-
return
|
|
197
|
+
return lt(current, latest);
|
|
156
198
|
}
|
|
157
|
-
|
|
199
|
+
function startUpdateCheck(options) {
|
|
158
200
|
try {
|
|
159
|
-
const { currentVersion, argv = process.argv.slice(2), env = process.env, now = Date.now, cacheFile = updateCheckCacheFile(), fetchLatestVersion = fetchLatestVersionFromRegistry,
|
|
160
|
-
if (!isUpdateCheckEnabled(argv, env))
|
|
161
|
-
return;
|
|
201
|
+
const { currentVersion, argv = process.argv.slice(2), env = process.env, isTerminal = (0, output_1.isTerminalFeedback)(), now = Date.now, cacheFile = updateCheckCacheFile(), fetchLatestVersion = fetchLatestVersionFromRegistry, ui = (0, cli_1.getProcessUi)(), write = output_1.writeFeedback, } = options;
|
|
202
|
+
if (!isTerminal || !isUpdateCheckEnabled(argv, env))
|
|
203
|
+
return undefined;
|
|
162
204
|
const cached = readCache(cacheFile);
|
|
163
205
|
const checkedAt = now();
|
|
164
206
|
const lastAttemptAnswered = cached?.succeeded ?? cached?.latestVersion !== undefined;
|
|
@@ -167,19 +209,43 @@ async function checkForUpdate(options) {
|
|
|
167
209
|
: exports.UPDATE_CHECK_RETRY_INTERVAL_MS;
|
|
168
210
|
const withinInterval = cached !== undefined && checkedAt - cached.checkedAt < interval;
|
|
169
211
|
let latestVersion = cached?.latestVersion;
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
212
|
+
const completion = withinInterval
|
|
213
|
+
? Promise.resolve()
|
|
214
|
+
: fetchLatestVersion(exports.UPDATE_CHECK_PACKAGE).then((published) => {
|
|
215
|
+
latestVersion = published ?? latestVersion;
|
|
216
|
+
writeCache(cacheFile, {
|
|
217
|
+
checkedAt,
|
|
218
|
+
latestVersion,
|
|
219
|
+
succeeded: published !== undefined,
|
|
220
|
+
});
|
|
221
|
+
}, () => {
|
|
177
222
|
});
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
223
|
+
let isReported = false;
|
|
224
|
+
const report = async (placement = {}) => {
|
|
225
|
+
if (isReported)
|
|
226
|
+
return;
|
|
227
|
+
isReported = true;
|
|
228
|
+
const known = latestVersion;
|
|
229
|
+
if (!known || !(await isNewer(currentVersion, known)))
|
|
230
|
+
return;
|
|
231
|
+
const line = formatNotice(currentVersion, known, ui);
|
|
232
|
+
for (const text of placement.isFollowed ? [line, ""] : ["", line]) {
|
|
233
|
+
write(text);
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
return {
|
|
237
|
+
completion,
|
|
238
|
+
report: (placement) => report(placement).catch(() => undefined),
|
|
239
|
+
};
|
|
182
240
|
}
|
|
183
241
|
catch {
|
|
242
|
+
return undefined;
|
|
184
243
|
}
|
|
185
244
|
}
|
|
245
|
+
let processUpdateCheck;
|
|
246
|
+
function startProcessUpdateCheck(options) {
|
|
247
|
+
processUpdateCheck = startUpdateCheck(options);
|
|
248
|
+
}
|
|
249
|
+
async function reportAvailableUpdate(options) {
|
|
250
|
+
await processUpdateCheck?.report(options);
|
|
251
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type CliProblem, type Ui } from "@antelopejs/core/cli";
|
|
2
|
+
export type VerificationResult = {
|
|
3
|
+
ok: true;
|
|
4
|
+
modules: number;
|
|
5
|
+
} | {
|
|
6
|
+
ok: false;
|
|
7
|
+
problem: CliProblem;
|
|
8
|
+
};
|
|
9
|
+
export declare const VERIFY_SOURCE_COMMAND = "ajs dms verify-source";
|
|
10
|
+
export declare const LAYER_PATH_FIX = "Pass the root of a DMS frontend package (it contains dms.frontend.ts)";
|
|
11
|
+
export declare function reportVerification(result: VerificationResult, durationMs: number, ui?: Ui): void;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LAYER_PATH_FIX = exports.VERIFY_SOURCE_COMMAND = void 0;
|
|
4
|
+
exports.reportVerification = reportVerification;
|
|
5
|
+
const cli_1 = require("@antelopejs/core/cli");
|
|
6
|
+
const output_1 = require("./output");
|
|
7
|
+
exports.VERIFY_SOURCE_COMMAND = "ajs dms verify-source";
|
|
8
|
+
exports.LAYER_PATH_FIX = "Pass the root of a DMS frontend package (it contains dms.frontend.ts)";
|
|
9
|
+
function reportVerification(result, durationMs, ui = (0, cli_1.getProcessUi)()) {
|
|
10
|
+
if (!result.ok)
|
|
11
|
+
throw new cli_1.CliError(result.problem);
|
|
12
|
+
(0, output_1.writeBlankLine)();
|
|
13
|
+
ui.summary({
|
|
14
|
+
headline: `Verified ${(0, cli_1.pluralize)(result.modules, "module")}`,
|
|
15
|
+
durationMs,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
@@ -32,137 +32,180 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
32
32
|
return result;
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
const strict_1 = __importDefault(require("node:assert/strict"));
|
|
40
|
-
const node_child_process_1 = require("node:child_process");
|
|
41
36
|
const node_fs_1 = require("node:fs");
|
|
42
37
|
const node_path_1 = require("node:path");
|
|
38
|
+
const cli_1 = require("@antelopejs/core/cli");
|
|
39
|
+
const child_output_1 = require("./child-output");
|
|
40
|
+
const build_action_1 = require("./commands/build-action");
|
|
43
41
|
const common_1 = require("./common");
|
|
42
|
+
const output_1 = require("./output");
|
|
44
43
|
const temporary_workspace_1 = require("./temporary-workspace");
|
|
44
|
+
const typecheck_output_1 = require("./typecheck-output");
|
|
45
|
+
const verify_source_result_1 = require("./verify-source-result");
|
|
46
|
+
const vite_output_1 = require("./vite-output");
|
|
47
|
+
const EMAIL_BUILD_SIZE_CEILING_BYTES = 256 * 1024;
|
|
48
|
+
const NON_EMAIL_RUNTIME_PATTERN = /DisplayRichText|ApexCharts|Tiptap|FlowCanvas|app\/.*table|components\/table/i;
|
|
49
|
+
const LAZY_LIBRARIES = [
|
|
50
|
+
{ name: "ApexCharts", pattern: /ApexCharts/ },
|
|
51
|
+
{ name: "Tiptap", pattern: /tiptap/i },
|
|
52
|
+
];
|
|
53
|
+
const RUNTIME_MARKERS = ["auth/login", "DefaultLayout", "error.500.title"];
|
|
54
|
+
function readJson(path) {
|
|
55
|
+
return JSON.parse((0, node_fs_1.readFileSync)(path, "utf8"));
|
|
56
|
+
}
|
|
57
|
+
function ensure(condition, title, reason) {
|
|
58
|
+
if (!condition)
|
|
59
|
+
throw new cli_1.CliError({ title, reason });
|
|
60
|
+
}
|
|
61
|
+
function readLayer(root) {
|
|
62
|
+
const packagePath = (0, node_path_1.join)(root, "package.json");
|
|
63
|
+
if (!(0, node_fs_1.existsSync)(packagePath))
|
|
64
|
+
throw new common_1.UsageError({
|
|
65
|
+
title: `No package.json in ${(0, output_1.showPath)(root)}`,
|
|
66
|
+
fixes: [verify_source_result_1.LAYER_PATH_FIX],
|
|
67
|
+
});
|
|
68
|
+
const { name } = readJson(packagePath);
|
|
69
|
+
return { path: root, sourcePath: root, packageName: name };
|
|
70
|
+
}
|
|
71
|
+
function readSources() {
|
|
72
|
+
const layerSource = process.env.DMS_LAYER_SOURCE;
|
|
73
|
+
if (!layerSource)
|
|
74
|
+
throw new common_1.UsageError({
|
|
75
|
+
title: "DMS_LAYER_SOURCE is not set",
|
|
76
|
+
fixes: [
|
|
77
|
+
`Set it to the root of a DMS frontend package, or run ${verify_source_result_1.VERIFY_SOURCE_COMMAND} -l <path>`,
|
|
78
|
+
],
|
|
79
|
+
});
|
|
80
|
+
const sourceRoot = (0, node_path_1.resolve)(layerSource);
|
|
81
|
+
if (!(0, node_fs_1.statSync)(sourceRoot, { throwIfNoEntry: false })?.isDirectory())
|
|
82
|
+
throw new common_1.UsageError({
|
|
83
|
+
title: `Layer path not found: ${(0, output_1.showPath)(sourceRoot)}`,
|
|
84
|
+
fixes: [verify_source_result_1.LAYER_PATH_FIX],
|
|
85
|
+
});
|
|
86
|
+
const extraSources = JSON.parse(process.env.DMS_MODULE_SOURCES ?? "[]");
|
|
87
|
+
const layerRoots = (0, node_fs_1.existsSync)((0, node_path_1.join)(sourceRoot, "dms.frontend.ts"))
|
|
88
|
+
? [sourceRoot]
|
|
89
|
+
: (0, node_fs_1.readdirSync)(sourceRoot, { withFileTypes: true })
|
|
90
|
+
.filter((entry) => entry.isDirectory())
|
|
91
|
+
.map((entry) => (0, node_path_1.join)(sourceRoot, entry.name));
|
|
92
|
+
if (layerRoots.length === 0)
|
|
93
|
+
throw new common_1.UsageError({
|
|
94
|
+
title: `No frontend package in ${(0, output_1.showPath)(sourceRoot)}`,
|
|
95
|
+
fixes: [verify_source_result_1.LAYER_PATH_FIX],
|
|
96
|
+
});
|
|
97
|
+
return [...layerRoots, ...extraSources.map((root) => (0, node_path_1.resolve)(root))].map(readLayer);
|
|
98
|
+
}
|
|
45
99
|
function removeDevelopmentDependencies(root) {
|
|
46
100
|
const packagePath = (0, node_path_1.join)(root, "package.json");
|
|
47
101
|
if (!(0, node_fs_1.existsSync)(packagePath))
|
|
48
102
|
return;
|
|
49
|
-
const packageData =
|
|
103
|
+
const packageData = readJson(packagePath);
|
|
50
104
|
delete packageData.devDependencies;
|
|
51
105
|
(0, node_fs_1.writeFileSync)(packagePath, `${JSON.stringify(packageData, null, 2)}\n`);
|
|
52
106
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
107
|
+
function materializeWorkspace(workspace, layers) {
|
|
108
|
+
const templateRoot = (0, node_path_1.join)((0, common_1.getPackageRoot)(), "templates", "vue");
|
|
109
|
+
const templateFiles = (0, node_fs_1.readdirSync)(templateRoot).filter((file) => !file.startsWith("npmrc"));
|
|
110
|
+
for (const file of templateFiles)
|
|
111
|
+
(0, node_fs_1.cpSync)((0, node_path_1.join)(templateRoot, file), (0, node_path_1.join)(workspace, file), {
|
|
112
|
+
recursive: true,
|
|
113
|
+
});
|
|
114
|
+
(0, common_1.materializeLayers)(workspace, layers);
|
|
115
|
+
const registry = (0, common_1.createFrontendModuleRegistry)(workspace, layers);
|
|
116
|
+
registry.modules.forEach((module) => {
|
|
117
|
+
removeDevelopmentDependencies(module.root);
|
|
118
|
+
});
|
|
119
|
+
(0, common_1.writeFrontendModuleRegistry)(workspace, layers);
|
|
120
|
+
(0, node_fs_1.writeFileSync)((0, node_path_1.join)(workspace, "dms-main.css"), '@import "tailwindcss";\n@import "@nuxt/ui";\n');
|
|
121
|
+
(0, common_1.writeWorkspacePackageJson)(workspace, layers);
|
|
122
|
+
const packagePath = (0, node_path_1.join)(workspace, "package.json");
|
|
123
|
+
const workspacePackage = readJson(packagePath);
|
|
124
|
+
const localPackages = JSON.parse(process.env.DMS_LOCAL_PACKAGES ?? "{}");
|
|
125
|
+
workspacePackage.pnpm = {
|
|
126
|
+
overrides: {
|
|
127
|
+
...Object.fromEntries(layers.map((layer) => [layer.packageName, "workspace:*"])),
|
|
128
|
+
...Object.fromEntries(Object.entries(localPackages).map(([name, path]) => [
|
|
129
|
+
name,
|
|
130
|
+
`link:${(0, node_path_1.resolve)(path)}`,
|
|
131
|
+
])),
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
(0, node_fs_1.writeFileSync)(packagePath, `${JSON.stringify(workspacePackage, null, 2)}\n`);
|
|
79
135
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
136
|
+
async function buildBundles(context) {
|
|
137
|
+
const [firstStep] = build_action_1.BUILD_STEPS;
|
|
138
|
+
await (0, cli_1.getProcessTasks)().run(firstStep.running, async (task) => {
|
|
139
|
+
for (const step of build_action_1.BUILD_STEPS) {
|
|
140
|
+
task.update(step.running);
|
|
141
|
+
const result = await (0, common_1.runFramedCommand)("pnpm", ["--silent", "run", step.script], {
|
|
142
|
+
name: step.name,
|
|
143
|
+
cwd: context.workspace,
|
|
144
|
+
env: context.env,
|
|
145
|
+
mapLine: context.mapLine,
|
|
146
|
+
onLine: (line) => context.warnings.read(line),
|
|
147
|
+
});
|
|
148
|
+
if (result.code !== 0) {
|
|
149
|
+
task.fail(step.failed);
|
|
150
|
+
throw (0, build_action_1.buildStepFailure)(step, result, context.isVerbose, verify_source_result_1.VERIFY_SOURCE_COMMAND);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}, { done: "Built client, SSR and e-mail bundles" });
|
|
154
|
+
(0, vite_output_1.reportViteWarnings)(context.warnings, context.isVerbose, (0, cli_1.getProcessUi)());
|
|
83
155
|
}
|
|
84
|
-
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
(0,
|
|
90
|
-
(0, node_fs_1.
|
|
91
|
-
(
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
(0,
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const
|
|
137
|
-
.filter((file) => file.endsWith(".js"))
|
|
138
|
-
.map((file) => (0, node_fs_1.readFileSync)((0, node_path_1.join)(clientRoot, "assets", file), "utf8"))
|
|
139
|
-
.join("\n");
|
|
140
|
-
strict_1.default.ok(Object.keys(manifest).length > 0, "Vite manifest must contain reachable entries");
|
|
141
|
-
strict_1.default.doesNotMatch(mainJavascript, /ApexCharts|tiptap/i);
|
|
142
|
-
strict_1.default.match(javascript, /ApexCharts/);
|
|
143
|
-
strict_1.default.match(javascript, /tiptap/i);
|
|
144
|
-
strict_1.default.ok(Object.keys(manifest).some((source) => source.endsWith("/kpi/KpiCard.vue")), "DmsKpiCard must be reachable at runtime");
|
|
145
|
-
const emailRoot = (0, node_path_1.join)(workspace, "dist", "server");
|
|
146
|
-
const emailManifestContent = (0, node_fs_1.readFileSync)((0, node_path_1.join)(emailRoot, ".vite", "manifest.json"), "utf8");
|
|
147
|
-
strict_1.default.doesNotMatch(emailManifestContent, NON_EMAIL_RUNTIME_PATTERN);
|
|
148
|
-
const emailManifest = JSON.parse(emailManifestContent);
|
|
149
|
-
const emailJavascriptFiles = [
|
|
150
|
-
...new Set([
|
|
151
|
-
"email-renderer.js",
|
|
152
|
-
...Object.values(emailManifest)
|
|
153
|
-
.map((entry) => entry.file)
|
|
154
|
-
.filter((file) => file.endsWith(".js")),
|
|
155
|
-
]),
|
|
156
|
-
];
|
|
157
|
-
const emailJavascript = emailJavascriptFiles
|
|
158
|
-
.map((file) => (0, node_fs_1.readFileSync)((0, node_path_1.join)(emailRoot, file), "utf8"))
|
|
159
|
-
.join("\n");
|
|
160
|
-
strict_1.default.doesNotMatch(emailJavascript, NON_EMAIL_RUNTIME_PATTERN);
|
|
161
|
-
const emailBuildSize = Buffer.byteLength(emailJavascript);
|
|
162
|
-
const emailLocaleBytes = (0, node_fs_1.readdirSync)((0, node_path_1.join)(emailRoot, "locales")).reduce((total, file) => total + (0, node_fs_1.readFileSync)((0, node_path_1.join)(emailRoot, "locales", file)).byteLength, 0);
|
|
163
|
-
process.stdout.write(`Email JavaScript: ${emailBuildSize} bytes; locale data: ${emailLocaleBytes} bytes\n`);
|
|
164
|
-
strict_1.default.ok(emailBuildSize <= EMAIL_BUILD_SIZE_CEILING_BYTES, `Email build is ${emailBuildSize} bytes; ceiling is ${EMAIL_BUILD_SIZE_CEILING_BYTES}`);
|
|
165
|
-
const emailCases = [
|
|
156
|
+
function checkClientBundle(workspace) {
|
|
157
|
+
const clientRoot = (0, node_path_1.join)(workspace, "dist", "client");
|
|
158
|
+
const manifest = readJson((0, node_path_1.join)(clientRoot, ".vite", "manifest.json"));
|
|
159
|
+
const mainEntry = Object.values(manifest).find((entry) => entry.isEntry);
|
|
160
|
+
ensure(mainEntry, "The Vite manifest names no entry chunk");
|
|
161
|
+
const mainJavascript = (0, node_fs_1.readFileSync)((0, node_path_1.join)(clientRoot, mainEntry.file), "utf8");
|
|
162
|
+
const javascript = (0, node_fs_1.readdirSync)((0, node_path_1.join)(clientRoot, "assets"))
|
|
163
|
+
.filter((file) => file.endsWith(".js"))
|
|
164
|
+
.map((file) => (0, node_fs_1.readFileSync)((0, node_path_1.join)(clientRoot, "assets", file), "utf8"))
|
|
165
|
+
.join("\n");
|
|
166
|
+
for (const { name, pattern } of LAZY_LIBRARIES) {
|
|
167
|
+
ensure(!pattern.test(mainJavascript), `The main chunk bundles ${name}`, "It must stay in a lazily loaded chunk.");
|
|
168
|
+
ensure(pattern.test(javascript), `No client chunk bundles ${name}`);
|
|
169
|
+
}
|
|
170
|
+
ensure(Object.keys(manifest).some((source) => source.endsWith("/kpi/KpiCard.vue")), "DmsKpiCard is not reachable at runtime");
|
|
171
|
+
for (const marker of RUNTIME_MARKERS)
|
|
172
|
+
ensure(javascript.includes(marker), `${marker} is not reachable at runtime`);
|
|
173
|
+
}
|
|
174
|
+
async function typeCheck(context) {
|
|
175
|
+
const typecheckArguments = [
|
|
176
|
+
"--import",
|
|
177
|
+
"./typecheck-loader.mjs",
|
|
178
|
+
"./node_modules/vue-tsc/bin/vue-tsc.js",
|
|
179
|
+
"--noEmit",
|
|
180
|
+
"--pretty",
|
|
181
|
+
];
|
|
182
|
+
const isWindows = process.platform === "win32";
|
|
183
|
+
const command = isWindows ? process.execPath : "env";
|
|
184
|
+
const commandArguments = isWindows
|
|
185
|
+
? typecheckArguments
|
|
186
|
+
: ["-u", "NODE_OPTIONS", process.execPath, ...typecheckArguments];
|
|
187
|
+
await (0, cli_1.getProcessTasks)().run("Type checking", async (task) => {
|
|
188
|
+
const result = await (0, common_1.runFramedCommand)(command, commandArguments, {
|
|
189
|
+
name: "vue-tsc",
|
|
190
|
+
cwd: context.workspace,
|
|
191
|
+
mapLine: context.mapLine,
|
|
192
|
+
});
|
|
193
|
+
if (result.code === 0)
|
|
194
|
+
return;
|
|
195
|
+
const report = (0, typecheck_output_1.parseTypeCheckOutput)(result.lines);
|
|
196
|
+
const count = report.count > 0 ? [(0, cli_1.pluralize)(report.count, "error")] : [];
|
|
197
|
+
task.fail(["Type check failed", ...count].join((0, cli_1.getProcessUi)().symbols.separator));
|
|
198
|
+
throw new cli_1.CliError((0, typecheck_output_1.describeTypeCheckErrors)(report, verify_source_result_1.VERIFY_SOURCE_COMMAND) ??
|
|
199
|
+
(0, child_output_1.describeChildFailure)({
|
|
200
|
+
title: "Type check failed",
|
|
201
|
+
command: "vue-tsc --noEmit",
|
|
202
|
+
code: result.code,
|
|
203
|
+
lines: result.lines,
|
|
204
|
+
isVerbose: context.isVerbose,
|
|
205
|
+
}));
|
|
206
|
+
}, { done: "Type check passed" });
|
|
207
|
+
}
|
|
208
|
+
const EMAIL_CASES = [
|
|
166
209
|
{
|
|
167
210
|
name: "EmailAdminInvite",
|
|
168
211
|
props: {
|
|
@@ -214,22 +257,114 @@ const emailCases = [
|
|
|
214
257
|
marker: "445566",
|
|
215
258
|
},
|
|
216
259
|
];
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
260
|
+
const BROWSER_ONLY_REASON = "It must not load rich text, charts, tables or flows.";
|
|
261
|
+
function checkLayoutEmail(html) {
|
|
262
|
+
ensure(/<meta charset="utf-8"/.test(html), "EmailLayout declares no UTF-8 charset");
|
|
263
|
+
ensure(/images\/antelope-logo\/light\.svg/.test(html), "EmailLayout renders no logo");
|
|
264
|
+
ensure(!/<h1[^>]*\bas=/.test(html), "EmailLayout leaks an `as` attribute onto its heading");
|
|
265
|
+
}
|
|
266
|
+
async function checkEmailContracts(workspace) {
|
|
267
|
+
const emailRoot = (0, node_path_1.join)(workspace, "dist", "server");
|
|
268
|
+
const emailManifestContent = (0, node_fs_1.readFileSync)((0, node_path_1.join)(emailRoot, ".vite", "manifest.json"), "utf8");
|
|
269
|
+
ensure(!NON_EMAIL_RUNTIME_PATTERN.test(emailManifestContent), "The e-mail manifest references browser-only modules", BROWSER_ONLY_REASON);
|
|
270
|
+
const emailManifest = JSON.parse(emailManifestContent);
|
|
271
|
+
const emailJavascriptFiles = [
|
|
272
|
+
...new Set([
|
|
273
|
+
"email-renderer.js",
|
|
274
|
+
...Object.values(emailManifest)
|
|
275
|
+
.map((entry) => entry.file)
|
|
276
|
+
.filter((file) => file.endsWith(".js")),
|
|
277
|
+
]),
|
|
278
|
+
];
|
|
279
|
+
const emailJavascript = emailJavascriptFiles
|
|
280
|
+
.map((file) => (0, node_fs_1.readFileSync)((0, node_path_1.join)(emailRoot, file), "utf8"))
|
|
281
|
+
.join("\n");
|
|
282
|
+
ensure(!NON_EMAIL_RUNTIME_PATTERN.test(emailJavascript), "The e-mail bundle loads browser-only modules", BROWSER_ONLY_REASON);
|
|
283
|
+
const emailBuildSize = Buffer.byteLength(emailJavascript);
|
|
284
|
+
const emailLocaleBytes = (0, node_fs_1.readdirSync)((0, node_path_1.join)(emailRoot, "locales")).reduce((total, file) => total + (0, node_fs_1.readFileSync)((0, node_path_1.join)(emailRoot, "locales", file)).byteLength, 0);
|
|
285
|
+
const limit = (0, output_1.formatSize)(EMAIL_BUILD_SIZE_CEILING_BYTES);
|
|
286
|
+
ensure(emailBuildSize <= EMAIL_BUILD_SIZE_CEILING_BYTES, `The e-mail bundle is ${(0, output_1.formatSize)(emailBuildSize)} of JavaScript`, `The limit is ${limit}.`);
|
|
287
|
+
const { renderEmail } = await Promise.resolve(`${(0, node_path_1.join)(emailRoot, "email-renderer.js")}`).then(s => __importStar(require(s)));
|
|
288
|
+
for (const emailCase of EMAIL_CASES) {
|
|
220
289
|
const html = await renderEmail(emailCase.name, emailCase.props);
|
|
221
|
-
|
|
222
|
-
if (emailCase.name === "EmailLayout")
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
strict_1.default.doesNotMatch(html, /<h1[^>]*\bas=/);
|
|
226
|
-
}
|
|
227
|
-
strict_1.default.match(html, new RegExp(emailCase.marker.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")));
|
|
290
|
+
ensure(html.startsWith("<!doctype html>"), `${emailCase.name} does not render a full HTML document`);
|
|
291
|
+
if (emailCase.name === "EmailLayout")
|
|
292
|
+
checkLayoutEmail(html);
|
|
293
|
+
ensure(html.includes(emailCase.marker), `${emailCase.name} does not render its props`, `Its HTML lacks ${emailCase.marker}.`);
|
|
228
294
|
}
|
|
295
|
+
return [
|
|
296
|
+
"E-mail contracts hold",
|
|
297
|
+
(0, cli_1.pluralize)(EMAIL_CASES.length, "template"),
|
|
298
|
+
`${(0, output_1.formatSize)(emailBuildSize)} JS (limit ${limit})`,
|
|
299
|
+
`${(0, output_1.formatSize)(emailLocaleBytes)} locale data`,
|
|
300
|
+
].join((0, cli_1.getProcessUi)().symbols.separator);
|
|
229
301
|
}
|
|
230
|
-
|
|
231
|
-
|
|
302
|
+
const LINE_BREAK = /\r?\n/;
|
|
303
|
+
const STACK_TRACE_HINT = "Run with --verbose for the full trace.";
|
|
304
|
+
function describeError(error, isVerbose) {
|
|
305
|
+
if (error instanceof cli_1.CliError)
|
|
306
|
+
return error.problem;
|
|
307
|
+
if (!(error instanceof Error))
|
|
308
|
+
return { title: String(error) };
|
|
309
|
+
const [title] = error.message.split(LINE_BREAK);
|
|
310
|
+
const stack = (error.stack ?? "").split(LINE_BREAK);
|
|
311
|
+
return {
|
|
312
|
+
title: title || error.name,
|
|
313
|
+
details: isVerbose ? stack : [STACK_TRACE_HINT],
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
async function verifySources() {
|
|
317
|
+
const layers = readSources();
|
|
318
|
+
(0, output_1.writeHeader)("verify-source", [(0, cli_1.pluralize)(layers.length, "module")]);
|
|
319
|
+
(0, common_1.assertLayersSupportRenderer)(layers);
|
|
320
|
+
const workspace = (0, temporary_workspace_1.createTemporaryWorkspace)("dms-frontend-real-source-");
|
|
321
|
+
const isVerbose = (0, cli_1.isVerboseRun)();
|
|
322
|
+
const context = {
|
|
323
|
+
workspace,
|
|
324
|
+
isVerbose,
|
|
325
|
+
mapLine: (0, child_output_1.createPathMapper)(workspace, layers),
|
|
326
|
+
warnings: new vite_output_1.ViteWarnings(),
|
|
327
|
+
env: { ...process.env, [vite_output_1.VITE_LOG_LEVEL_VARIABLE]: (0, vite_output_1.viteLogLevel)(isVerbose) },
|
|
328
|
+
};
|
|
329
|
+
const tasks = (0, cli_1.getProcessTasks)();
|
|
330
|
+
await tasks.run(`Materializing ${(0, cli_1.pluralize)(layers.length, "module")}`, async () => materializeWorkspace(workspace, layers), { done: `Materialized ${(0, cli_1.pluralize)(layers.length, "module")}` });
|
|
331
|
+
await (0, common_1.installDeps)(workspace, context.mapLine, ["--ignore-scripts"]);
|
|
332
|
+
await buildBundles(context);
|
|
333
|
+
await tasks.run("Checking the client bundle", async () => checkClientBundle(workspace), { done: "Client bundle checked", failed: "Client bundle check failed" });
|
|
334
|
+
await typeCheck(context);
|
|
335
|
+
await tasks.run("Checking the e-mail contracts", async () => checkEmailContracts(workspace), { done: (line) => line, failed: "E-mail contracts failed" });
|
|
336
|
+
return { ok: true, modules: layers.length };
|
|
337
|
+
}
|
|
338
|
+
function sendResult(result) {
|
|
339
|
+
return new Promise((settle) => {
|
|
340
|
+
process.send?.(result, undefined, undefined, () => settle());
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
async function main() {
|
|
344
|
+
(0, output_1.exitOnBrokenPipe)();
|
|
345
|
+
const startedAt = Date.now();
|
|
346
|
+
delete process.env.NODE_OPTIONS;
|
|
347
|
+
let result;
|
|
348
|
+
try {
|
|
349
|
+
result = await verifySources();
|
|
350
|
+
}
|
|
351
|
+
catch (error) {
|
|
352
|
+
if (error instanceof common_1.CancelledError) {
|
|
353
|
+
if (!process.send)
|
|
354
|
+
(0, output_1.reportStopped)(error);
|
|
355
|
+
process.exitCode = error.exitCode;
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
result = { ok: false, problem: describeError(error, (0, cli_1.isVerboseRun)()) };
|
|
359
|
+
}
|
|
360
|
+
if (process.send) {
|
|
361
|
+
process.exitCode = result.ok ? 0 : 1;
|
|
362
|
+
await sendResult(result);
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
(0, verify_source_result_1.reportVerification)(result, Date.now() - startedAt);
|
|
232
366
|
}
|
|
233
|
-
void
|
|
234
|
-
|
|
367
|
+
void (0, cli_1.runWithErrorBoundary)(main, { verbose: (0, cli_1.isVerboseRun)() }).then(() => {
|
|
368
|
+
if (process.connected)
|
|
369
|
+
process.disconnect();
|
|
235
370
|
});
|