@antelopejs/dms-frontend 0.9.3 → 0.10.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.
Files changed (116) hide show
  1. package/README.md +18 -24
  2. package/dist/commands/build-action.js +3 -2
  3. package/dist/commands/dev-action.js +2 -1
  4. package/dist/commands/prepare-action.js +1 -1
  5. package/dist/commands/start-action.js +3 -24
  6. package/dist/commands/workspace-task.js +2 -1
  7. package/dist/derived-outputs.js +3 -3
  8. package/dist/discovery.js +17 -6
  9. package/dist/entry-weight.js +15 -0
  10. package/dist/fs-sync.js +7 -4
  11. package/dist/index.js +2 -1
  12. package/dist/internal/built-workspace.d.ts +4 -0
  13. package/dist/internal/built-workspace.js +43 -0
  14. package/dist/internal/ensure.d.ts +1 -0
  15. package/dist/internal/ensure.js +8 -0
  16. package/dist/internal/locale-catalogs.d.ts +8 -3
  17. package/dist/internal/locale-catalogs.js +16 -6
  18. package/dist/internal/manifest-decoder.d.ts +7 -0
  19. package/dist/internal/manifest-decoder.js +81 -0
  20. package/dist/internal/own-release.d.ts +5 -0
  21. package/dist/internal/own-release.js +20 -0
  22. package/dist/internal/plain-object.d.ts +1 -0
  23. package/dist/internal/plain-object.js +6 -0
  24. package/dist/internal/text-list.d.ts +1 -0
  25. package/dist/internal/text-list.js +10 -0
  26. package/dist/internal/vite-manifest.d.ts +6 -0
  27. package/dist/internal/vite-manifest.js +24 -0
  28. package/dist/layer-watch.js +25 -24
  29. package/dist/layers.d.ts +1 -1
  30. package/dist/layers.js +3 -1
  31. package/dist/locale-files.d.ts +2 -1
  32. package/dist/locale-files.js +4 -0
  33. package/dist/manifest.d.ts +1 -1
  34. package/dist/manifest.js +44 -31
  35. package/dist/materialize.js +6 -2
  36. package/dist/module-set.js +2 -1
  37. package/dist/node-options.d.ts +1 -0
  38. package/dist/node-options.js +8 -0
  39. package/dist/output.d.ts +15 -9
  40. package/dist/output.js +30 -18
  41. package/dist/private-values.d.ts +1 -1
  42. package/dist/private-values.js +5 -3
  43. package/dist/project-modules.js +13 -8
  44. package/dist/renderer-range.js +5 -3
  45. package/dist/server-process.js +1 -1
  46. package/dist/verify-source-build.js +10 -2
  47. package/dist/verify-source-client-bundle.d.ts +1 -0
  48. package/dist/verify-source-client-bundle.js +30 -0
  49. package/dist/verify-source-runner.js +44 -60
  50. package/dist/verify-source-sources.js +49 -11
  51. package/dist/workspace-setup.js +1 -1
  52. package/package.json +6 -4
  53. package/skills/dms-frontend/SKILL.md +1 -1
  54. package/templates/vue/app-runtime.ts +2 -9
  55. package/templates/vue/client-server-guard.mjs +16 -0
  56. package/templates/vue/compress-assets.mjs +9 -1
  57. package/templates/vue/entry-weight.mjs +22 -0
  58. package/templates/vue/frontend-module.ts +1 -0
  59. package/templates/vue/frontend-runtime/module-registration.ts +2 -2
  60. package/templates/vue/frontend-runtime/state.ts +2 -2
  61. package/templates/vue/frontend-runtime/types.ts +8 -2
  62. package/templates/vue/head-order.mjs +7 -0
  63. package/templates/vue/icon-scan.mjs +4 -0
  64. package/templates/vue/server/auth/backend.mjs +41 -4
  65. package/templates/vue/server/auth/client-ip.mjs +52 -4
  66. package/templates/vue/server/auth/establish-endpoints.mjs +10 -6
  67. package/templates/vue/server/auth/session.mjs +81 -2
  68. package/templates/vue/server/auth-hooks.mjs +15 -5
  69. package/templates/vue/server/backend-proxies.mjs +65 -9
  70. package/templates/vue/server/backend-request.mjs +61 -0
  71. package/templates/vue/server/backend-response.mjs +23 -6
  72. package/templates/vue/server/built-files.mjs +7 -0
  73. package/templates/vue/server/cli-report.mjs +53 -11
  74. package/templates/vue/server/client-manifest.mjs +23 -1
  75. package/templates/vue/server/content.mjs +18 -1
  76. package/templates/vue/server/dev-private-files.mjs +17 -1
  77. package/templates/vue/server/dev-styles.mjs +38 -0
  78. package/templates/vue/server/email.mjs +9 -3
  79. package/templates/vue/server/favicon.mjs +3 -0
  80. package/templates/vue/server/generated-files.mjs +211 -0
  81. package/templates/vue/server/homepage.mjs +21 -9
  82. package/templates/vue/server/html-tag.mjs +4 -0
  83. package/templates/vue/server/icons.mjs +80 -7
  84. package/templates/vue/server/in-place-render.mjs +35 -0
  85. package/templates/vue/server/inertia.mjs +61 -2
  86. package/templates/vue/server/module-event.mjs +98 -17
  87. package/templates/vue/server/module-route-types.mjs +78 -0
  88. package/templates/vue/server/module-routes.mjs +138 -31
  89. package/templates/vue/server/module-server.mjs +98 -27
  90. package/templates/vue/server/module-testing.mjs +14 -5
  91. package/templates/vue/server/page-props.mjs +92 -2
  92. package/templates/vue/server/page-redirects.mjs +37 -0
  93. package/templates/vue/server/path-patterns.mjs +13 -1
  94. package/templates/vue/server/proxy-compression.mjs +22 -0
  95. package/templates/vue/server/proxy-headers.mjs +11 -1
  96. package/templates/vue/server/proxy-redirects.mjs +20 -5
  97. package/templates/vue/server/proxy-request.mjs +57 -0
  98. package/templates/vue/server/proxy-transfers.mjs +33 -5
  99. package/templates/vue/server/public-endpoints.mjs +138 -23
  100. package/templates/vue/server/public-options.mjs +20 -6
  101. package/templates/vue/server/request-failure.mjs +23 -0
  102. package/templates/vue/server/request-routing.mjs +26 -9
  103. package/templates/vue/server/request-target.mjs +9 -3
  104. package/templates/vue/server/route-rules.mjs +39 -15
  105. package/templates/vue/server/ssr-module.mjs +32 -0
  106. package/templates/vue/server/static-files.mjs +24 -1
  107. package/templates/vue/server/type-guards.mjs +71 -0
  108. package/templates/vue/server/vite-errors.mjs +32 -5
  109. package/templates/vue/server/web-body.mjs +3 -0
  110. package/templates/vue/server-module.ts +10 -1
  111. package/templates/vue/server.mjs +132 -148
  112. package/templates/vue/sfc-global-types.mjs +112 -13
  113. package/templates/vue/ssr-renderer.ts +2 -2
  114. package/templates/vue/ui-inertia-page.mjs +16 -1
  115. package/templates/vue/ui-kbd.mjs +2 -1
  116. package/templates/vue/ui-request-state.mjs +2 -1
@@ -0,0 +1,6 @@
1
+ export interface ViteChunk {
2
+ file: string;
3
+ src?: string;
4
+ isEntry?: boolean;
5
+ }
6
+ export declare function parseViteManifest(content: string, label: string): ViteChunk[];
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseViteManifest = parseViteManifest;
4
+ const cli_1 = require("@antelopejs/core/cli");
5
+ const guards_1 = require("./guards");
6
+ const plain_object_1 = require("./plain-object");
7
+ function isViteChunk(value) {
8
+ return ((0, plain_object_1.isPlainObject)(value) &&
9
+ (0, guards_1.isText)(value.file) &&
10
+ (value.src === undefined || (0, guards_1.isText)(value.src)) &&
11
+ (value.isEntry === undefined || (0, guards_1.isFlag)(value.isEntry)));
12
+ }
13
+ function parseViteManifest(content, label) {
14
+ const manifest = JSON.parse(content);
15
+ const chunks = (0, plain_object_1.isPlainObject)(manifest)
16
+ ? Object.values(manifest)
17
+ : [];
18
+ if (!(0, plain_object_1.isPlainObject)(manifest) || !chunks.every(isViteChunk))
19
+ throw new cli_1.CliError({
20
+ title: `The ${label} is not a Vite manifest`,
21
+ reason: "Every entry of it must name the chunk's file.",
22
+ });
23
+ return chunks;
24
+ }
@@ -24,11 +24,11 @@ function createSyncFailures(src, reporter) {
24
24
  const failed = new Set();
25
25
  const show = (rel) => reporter.show((0, node_path_1.join)(src, rel));
26
26
  return {
27
- fail(rel, err) {
27
+ fail(rel, errorLines) {
28
28
  failed.add(rel);
29
29
  reporter.warn(`${show(rel)} not copied to the workspace`, {
30
30
  details: [
31
- ...reporter.describe(err),
31
+ ...errorLines,
32
32
  "The dev server keeps its previous version until the next save.",
33
33
  ],
34
34
  });
@@ -73,7 +73,7 @@ function createLayerSync(src, dest, reporter, onStaged) {
73
73
  failures.applied(rel);
74
74
  }
75
75
  catch (err) {
76
- failures.fail(rel, err);
76
+ failures.fail(rel, reporter.describe((0, output_1.classifyFailure)(err)));
77
77
  }
78
78
  };
79
79
  const remove = (rel, recursive) => {
@@ -86,7 +86,7 @@ function createLayerSync(src, dest, reporter, onStaged) {
86
86
  failures.applied(rel);
87
87
  }
88
88
  catch (err) {
89
- failures.fail(rel, err);
89
+ failures.fail(rel, reporter.describe((0, output_1.classifyFailure)(err)));
90
90
  }
91
91
  };
92
92
  const stage = (p, add, cancel) => {
@@ -113,7 +113,7 @@ function createLayerSync(src, dest, reporter, onStaged) {
113
113
  failures.applied(rel);
114
114
  }
115
115
  catch (err) {
116
- failures.fail(rel, err);
116
+ failures.fail(rel, reporter.describe((0, output_1.classifyFailure)(err)));
117
117
  }
118
118
  }
119
119
  },
@@ -127,22 +127,6 @@ function createLayerSync(src, dest, reporter, onStaged) {
127
127
  },
128
128
  };
129
129
  }
130
- function describeOutputFailure(output, err, reporter) {
131
- const kept = `The dev server keeps the previous ${output.name} until the file is fixed.`;
132
- if (err instanceof locale_files_1.InvalidLocaleFileError) {
133
- const file = reporter.show(err.path);
134
- return {
135
- text: `${file} is not a valid locale file`,
136
- options: { details: [...err.reason.split("\n"), kept] },
137
- fixed: [`${file} fixed`, `${output.name} regenerated`].join((0, cli_1.getProcessUi)().symbols.separator),
138
- };
139
- }
140
- return {
141
- text: `${capitalize(output.name)} not regenerated`,
142
- options: { details: [...reporter.describe(err), kept] },
143
- fixed: `${capitalize(output.name)} regenerated`,
144
- };
145
- }
146
130
  function describeLayerDirectories(paths, reporter) {
147
131
  const layers = [...new Set(paths)].filter((path) => !paths.some((other) => other.startsWith(`${path}${node_path_1.sep}`)));
148
132
  const shown = layers.map((path) => reporter.show(path));
@@ -183,7 +167,24 @@ function createDerivedOutputRefresher(workspaceDir, layers, reporter) {
183
167
  return isChanged;
184
168
  }
185
169
  catch (err) {
186
- fail(output, describeOutputFailure(output, err, reporter));
170
+ const kept = `The dev server keeps the previous ${output.name} until the file is fixed.`;
171
+ if (err instanceof locale_files_1.InvalidLocaleFileError) {
172
+ const file = reporter.show(err.path);
173
+ fail(output, {
174
+ text: `${file} is not a valid locale file`,
175
+ options: { details: [...err.reason.split("\n"), kept] },
176
+ fixed: [`${file} fixed`, `${output.name} regenerated`].join((0, cli_1.getProcessUi)().symbols.separator),
177
+ });
178
+ }
179
+ else {
180
+ fail(output, {
181
+ text: `${capitalize(output.name)} not regenerated`,
182
+ options: {
183
+ details: [...reporter.describe((0, output_1.classifyFailure)(err)), kept],
184
+ },
185
+ fixed: `${capitalize(output.name)} regenerated`,
186
+ });
187
+ }
187
188
  return false;
188
189
  }
189
190
  };
@@ -198,7 +199,7 @@ function createDerivedOutputRefresher(workspaceDir, layers, reporter) {
198
199
  text: "Derived files not regenerated",
199
200
  options: {
200
201
  details: [
201
- ...reporter.describe(err),
202
+ ...reporter.describe((0, output_1.classifyFailure)(err)),
202
203
  "The dev server keeps the previous ones until the module is fixed.",
203
204
  ],
204
205
  },
@@ -278,7 +279,7 @@ function startLayerWatchers(workspaceDir, layers, ui = (0, cli_1.getProcessUi)()
278
279
  if (!isQuiet)
279
280
  write((0, output_1.formatTimedMessage)("success", text, {}, ui));
280
281
  },
281
- describe: (error) => (0, output_1.failureDetails)(error, ui).map((line) => mapPath(line)),
282
+ describe: (failure) => (0, output_1.failureDetails)(failure, ui).map((line) => mapPath(line)),
282
283
  show: (path) => {
283
284
  const mapped = mapPath(path);
284
285
  return mapped === path ? (0, output_1.showPath)(path) : mapped;
package/dist/layers.d.ts CHANGED
@@ -9,7 +9,7 @@ interface PathlessManifestSource {
9
9
  export declare function assertLayerPathsServed(modules: ManifestModule[], backendUrl: string, { bootstrapSecret, cache }?: PathlessManifestSource): asserts modules is ServedWithPath[];
10
10
  export interface LayerPackage {
11
11
  name?: unknown;
12
- engines?: Record<string, unknown>;
12
+ engines?: unknown;
13
13
  dmsFrontend?: unknown;
14
14
  antelopeJs?: unknown;
15
15
  }
package/dist/layers.js CHANGED
@@ -12,6 +12,7 @@ const manifest_1 = require("./manifest");
12
12
  const config_1 = require("./config");
13
13
  const output_1 = require("./output");
14
14
  const guards_1 = require("./internal/guards");
15
+ const plain_object_1 = require("./internal/plain-object");
15
16
  const BUILD_FIX = "A remote or production backend never sends them: build the frontend from the project instead, with `ajs dms build`";
16
17
  function assertLayerPathsServed(modules, backendUrl, { bootstrapSecret, cache } = {}) {
17
18
  const pathless = modules.filter((mod) => !mod.path);
@@ -56,7 +57,8 @@ function readLayerPackage(layerPath) {
56
57
  if (!(0, node_fs_1.existsSync)(pkgPath))
57
58
  return undefined;
58
59
  try {
59
- return JSON.parse((0, node_fs_1.readFileSync)(pkgPath, "utf-8"));
60
+ const parsed = JSON.parse((0, node_fs_1.readFileSync)(pkgPath, "utf-8"));
61
+ return (0, plain_object_1.isPlainObject)(parsed) ? parsed : undefined;
60
62
  }
61
63
  catch {
62
64
  return undefined;
@@ -1,6 +1,7 @@
1
+ import { type LocaleMessages } from "./internal/locale-catalogs";
1
2
  export declare class InvalidLocaleFileError extends Error {
2
3
  readonly path: string;
3
4
  readonly reason: string;
4
5
  constructor(path: string, reason: string);
5
6
  }
6
- export declare function readLocaleFile(path: string): Record<string, unknown>;
7
+ export declare function readLocaleFile(path: string): LocaleMessages;
@@ -5,6 +5,7 @@ exports.readLocaleFile = readLocaleFile;
5
5
  const node_fs_1 = require("node:fs");
6
6
  const message_compiler_1 = require("@intlify/message-compiler");
7
7
  const guards_1 = require("./internal/guards");
8
+ const locale_catalogs_1 = require("./internal/locale-catalogs");
8
9
  class InvalidLocaleFileError extends Error {
9
10
  constructor(path, reason) {
10
11
  super(`Invalid locale file ${path}: ${reason}`);
@@ -68,6 +69,9 @@ function readLocaleFile(path) {
68
69
  const reason = error instanceof Error ? error.message : String(error);
69
70
  throw new InvalidLocaleFileError(path, reason);
70
71
  }
72
+ if (!(0, locale_catalogs_1.isLocaleValue)(value) || !(0, locale_catalogs_1.isMessageGroup)(value)) {
73
+ throw new InvalidLocaleFileError(path, "a locale file must hold a JSON object of messages");
74
+ }
71
75
  const problems = messageProblems(value, "");
72
76
  if (problems.length) {
73
77
  const reason = [
@@ -16,7 +16,7 @@ export declare function fetchFromBackend(backendUrl: string, url: URL, bootstrap
16
16
  export declare class ManifestRefusedError extends CliError {
17
17
  constructor(problem: string | CliProblem);
18
18
  }
19
- export declare function describeManifestVersion(version: unknown): CliProblem;
19
+ export declare function describeManifestVersion(version: number | undefined): CliProblem;
20
20
  export declare class BackendResponseError extends CliError {
21
21
  readonly status: number;
22
22
  constructor(subject: string, url: string | URL, response: Pick<Response, "status" | "statusText">);
package/dist/manifest.js CHANGED
@@ -17,6 +17,9 @@ const config_1 = require("./config");
17
17
  const output_1 = require("./output");
18
18
  const workspace_1 = require("./workspace");
19
19
  const guards_1 = require("./internal/guards");
20
+ const plain_object_1 = require("./internal/plain-object");
21
+ const manifest_decoder_1 = require("./internal/manifest-decoder");
22
+ const own_release_1 = require("./internal/own-release");
20
23
  class ManifestUnauthorizedError extends cli_1.CliError {
21
24
  constructor(url, status, credentialSent) {
22
25
  super({
@@ -34,22 +37,23 @@ class ManifestUnauthorizedError extends cli_1.CliError {
34
37
  }
35
38
  }
36
39
  exports.ManifestUnauthorizedError = ManifestUnauthorizedError;
37
- const UNREACHABLE_REASONS = {
38
- ECONNREFUSED: "Connection refused",
39
- ECONNRESET: "Connection reset",
40
- ENOTFOUND: "Unknown host",
41
- EAI_AGAIN: "Host name lookup failed",
42
- ETIMEDOUT: "Connection timed out",
43
- UND_ERR_CONNECT_TIMEOUT: "Connection timed out",
44
- };
40
+ const UNREACHABLE_REASONS = new Map([
41
+ ["ECONNREFUSED", "Connection refused"],
42
+ ["ECONNRESET", "Connection reset"],
43
+ ["ENOTFOUND", "Unknown host"],
44
+ ["EAI_AGAIN", "Host name lookup failed"],
45
+ ["ETIMEDOUT", "Connection timed out"],
46
+ ["UND_ERR_CONNECT_TIMEOUT", "Connection timed out"],
47
+ ]);
45
48
  const UNKNOWN_HOST_CODES = ["ENOTFOUND", "EAI_AGAIN"];
46
49
  class BackendUnreachableError extends cli_1.CliError {
47
50
  constructor(url, failure) {
48
51
  const cause = (hasProperties(failure) ? failure.cause : undefined) ?? failure;
49
- const code = errorCode(cause);
52
+ const code = hasProperties(cause) ? errorCode(cause) : undefined;
53
+ const message = () => cause instanceof Error ? cause.message : String(cause);
50
54
  const detail = code
51
- ? (UNREACHABLE_REASONS[code] ?? errorMessage(cause))
52
- : `The request failed: ${errorMessage(cause)}`;
55
+ ? (UNREACHABLE_REASONS.get(code) ?? message())
56
+ : `The request failed: ${message()}`;
53
57
  const fix = code && UNKNOWN_HOST_CODES.includes(code)
54
58
  ? `Check the host name '${new URL(url).hostname}' in -b <url> or DMS_API_BASE_URL`
55
59
  : "Start the backend (`ajs project dev` for a local one), or pass its URL with -b <url>";
@@ -68,15 +72,13 @@ function hasProperties(value) {
68
72
  return (value !== null && (typeof value === "object" || typeof value === "function"));
69
73
  }
70
74
  function errorCode(err) {
71
- if (!hasProperties(err))
72
- return undefined;
73
75
  const { code, errors } = err;
74
76
  if ((0, guards_1.isText)(code))
75
77
  return code;
76
- return Array.isArray(errors) ? errorCode(errors[0]) : undefined;
77
- }
78
- function errorMessage(err) {
79
- return err instanceof Error ? err.message : String(err);
78
+ if (!Array.isArray(errors))
79
+ return undefined;
80
+ const first = errors[0];
81
+ return hasProperties(first) ? errorCode(first) : undefined;
80
82
  }
81
83
  function displayUrl(url) {
82
84
  const { origin, pathname } = new URL(url);
@@ -112,13 +114,12 @@ class ManifestRefusedError extends cli_1.CliError {
112
114
  }
113
115
  }
114
116
  exports.ManifestRefusedError = ManifestRefusedError;
115
- const OWN_RELEASE = require("../package.json");
116
117
  const BACKEND_PACKAGE = "@antelopejs/dms";
117
118
  const LOADER_UPDATE_COMMAND = "ajs update dms";
118
119
  function describeManifestVersion(version) {
119
- const loader = `${OWN_RELEASE.name} ${OWN_RELEASE.version}`;
120
+ const loader = `${own_release_1.ownRelease.name} ${own_release_1.ownRelease.version}`;
120
121
  const supported = `This loader reads version ${workspace_1.FRONTEND_MANIFEST_VERSION}`;
121
- if (!(0, guards_1.isNumber)(version)) {
122
+ if (version === undefined) {
122
123
  return {
123
124
  title: "The backend served a frontend manifest without a protocol version",
124
125
  reason: `${supported}; the answer does not look like one from ${BACKEND_PACKAGE}.`,
@@ -141,7 +142,7 @@ function describeManifestVersion(version) {
141
142
  title,
142
143
  reason: `${supported}; the backend's ${BACKEND_PACKAGE} is older than this loader.`,
143
144
  fixes: [
144
- `Upgrade ${BACKEND_PACKAGE} on the backend, or use a ${OWN_RELEASE.name} release that reads version ${version}`,
145
+ `Upgrade ${BACKEND_PACKAGE} on the backend, or use a ${own_release_1.ownRelease.name} release that reads version ${version}`,
145
146
  ],
146
147
  };
147
148
  }
@@ -192,19 +193,29 @@ async function fetchManifest(backendUrl, clientUrl, bootstrapSecret) {
192
193
  if (!response.ok) {
193
194
  throw new BackendResponseError("the frontend manifest", frontendUrl, response);
194
195
  }
195
- const manifest = (await response.json());
196
- if (manifest.version !== workspace_1.FRONTEND_MANIFEST_VERSION) {
197
- throw new ManifestRefusedError(describeManifestVersion(manifest.version));
196
+ const body = await response.json();
197
+ const version = (0, manifest_decoder_1.hasManifestVersion)(body) ? body.version : undefined;
198
+ if (version !== workspace_1.FRONTEND_MANIFEST_VERSION) {
199
+ throw new ManifestRefusedError(describeManifestVersion(version));
198
200
  }
199
- const incompatible = manifest.modules.filter((module) => module.renderer?.name !== "vue" || module.renderer?.version !== "3");
201
+ if (!(0, manifest_decoder_1.isManifest)(body)) {
202
+ throw new ManifestRefusedError({
203
+ title: "The backend served a frontend manifest this loader cannot read",
204
+ reason: `It states version ${workspace_1.FRONTEND_MANIFEST_VERSION}, but its modules, settling flag or origin rewrites do not have the shape ${own_release_1.ownRelease.name} ${own_release_1.ownRelease.version} reads.`,
205
+ fixes: [
206
+ `Check that -b <url> points at a DMS backend running ${BACKEND_PACKAGE}`,
207
+ ],
208
+ });
209
+ }
210
+ const incompatible = body.modules.filter((module) => module.renderer?.name !== "vue" || module.renderer?.version !== "3");
200
211
  if (incompatible.length) {
201
212
  throw new ManifestRefusedError(`Frontend manifest contains incompatible renderer modules: ${incompatible.map((module) => module.name).join(", ")}`);
202
213
  }
203
- const resolved = { modules: manifest.modules };
204
- if (manifest.settling)
214
+ const resolved = { modules: body.modules };
215
+ if (body.settling)
205
216
  resolved.settling = true;
206
- if (manifest.originRewrites)
207
- resolved.originRewrites = manifest.originRewrites;
217
+ if (body.originRewrites)
218
+ resolved.originRewrites = body.originRewrites;
208
219
  return resolved;
209
220
  }
210
221
  const MANIFEST_CACHE_FILE = ".manifest-cache.json";
@@ -214,9 +225,11 @@ function readCachedManifest(workspaceDir) {
214
225
  return undefined;
215
226
  try {
216
227
  const parsed = JSON.parse((0, node_fs_1.readFileSync)(file, "utf-8"));
217
- if (!parsed?.manifest)
228
+ if (!(0, plain_object_1.isPlainObject)(parsed) || !(0, guards_1.isText)(parsed.fetchedAt))
229
+ return undefined;
230
+ if (!(0, manifest_decoder_1.isManifest)(parsed.manifest))
218
231
  return undefined;
219
- return parsed;
232
+ return { manifest: parsed.manifest, fetchedAt: parsed.fetchedAt };
220
233
  }
221
234
  catch {
222
235
  return undefined;
@@ -16,6 +16,7 @@ const layers_1 = require("./layers");
16
16
  const manifest_secrets_1 = require("./manifest-secrets");
17
17
  const fs_sync_1 = require("./fs-sync");
18
18
  const guards_1 = require("./internal/guards");
19
+ const plain_object_1 = require("./internal/plain-object");
19
20
  function getPackageRoot() {
20
21
  return (0, node_path_1.resolve)(__dirname, "..");
21
22
  }
@@ -43,11 +44,14 @@ function copyStaticTemplates(workspaceDir) {
43
44
  function writeWorkspacePackageJson(workspaceDir, layers) {
44
45
  const templatePath = (0, node_path_1.join)(getTemplateDir(), "package.json");
45
46
  const pkg = JSON.parse((0, node_fs_1.readFileSync)(templatePath, "utf-8"));
46
- pkg.dependencies ??= {};
47
+ if (!(0, plain_object_1.isPlainObject)(pkg))
48
+ throw new Error(`${templatePath} is not a JSON object`);
49
+ const dependencies = (0, plain_object_1.isPlainObject)(pkg.dependencies) ? pkg.dependencies : {};
50
+ pkg.dependencies = dependencies;
47
51
  for (const layer of layers) {
48
52
  if (!layer.packageName)
49
53
  continue;
50
- pkg.dependencies[layer.packageName] = "workspace:*";
54
+ dependencies[layer.packageName] = "workspace:*";
51
55
  }
52
56
  (0, node_fs_1.writeFileSync)((0, node_path_1.join)(workspaceDir, "package.json"), `${JSON.stringify(pkg, null, 2)}\n`);
53
57
  }
@@ -7,12 +7,13 @@ exports.reportFrontendReady = reportFrontendReady;
7
7
  exports.reportFrontendReadyOnceAnswered = reportFrontendReadyOnceAnswered;
8
8
  const promises_1 = require("node:timers/promises");
9
9
  const manifest_1 = require("./manifest");
10
+ const own_release_1 = require("./internal/own-release");
10
11
  const workspace_1 = require("./workspace");
11
12
  exports.MODULE_SET_POLL_INTERVAL_MS = 3000;
12
13
  const READY_ENDPOINT = "/dms/frontend/ready";
13
14
  const READY_TIMEOUT_MS = 5000;
14
15
  const JSON_CONTENT_TYPE = "application/json";
15
- exports.OWN_RELEASE = require("../package.json");
16
+ exports.OWN_RELEASE = own_release_1.ownRelease;
16
17
  function moduleSetFingerprint(modules) {
17
18
  return JSON.stringify([...modules]
18
19
  .sort((left, right) => left.name.localeCompare(right.name))
@@ -0,0 +1 @@
1
+ export declare function serverNodeOptions(inherited: string | undefined): string;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.serverNodeOptions = serverNodeOptions;
4
+ const HEAP_OPTION = "--max-old-space-size=4096";
5
+ function serverNodeOptions(inherited) {
6
+ const own = inherited?.trim();
7
+ return own ? `${HEAP_OPTION} ${own}` : HEAP_OPTION;
8
+ }
package/dist/output.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type TaskHandle, type Ui } from "@antelopejs/core/cli";
1
+ import { CliError, type TaskHandle, type Ui } from "@antelopejs/core/cli";
2
2
  import { CancelledError } from "./cancellation";
3
3
  export declare function exitOnBrokenPipe(stream?: NodeJS.WriteStream): void;
4
4
  export declare function isTerminalFeedback(): boolean;
@@ -15,8 +15,19 @@ export declare function workspaceId(dir: string, isTerminal: boolean): string;
15
15
  export declare function formatSize(bytes: number): string;
16
16
  export declare function formatAge(iso: string, now?: number): string;
17
17
  export declare function cachedAge(fetchedAt: string | undefined): string;
18
- export declare function failureDetails(error: unknown, ui?: Ui): string[];
19
- export declare function endInterruptedTask(task: TaskHandle, error: unknown, stopped: string): void;
18
+ export type Failure = {
19
+ kind: "cli";
20
+ error: CliError;
21
+ } | {
22
+ kind: "error";
23
+ error: Error;
24
+ } | {
25
+ kind: "thrown";
26
+ text: string;
27
+ };
28
+ export declare function classifyFailure(thrown: unknown): Failure;
29
+ export declare function failureDetails(failure: Failure, ui?: Ui): string[];
30
+ export declare function endInterruptedTask(task: TaskHandle, error: CancelledError | undefined, stopped: string): void;
20
31
  export declare function reportStopped(stop: CancelledError, ui?: Ui): void;
21
32
  export interface ReadyLine {
22
33
  label: string;
@@ -31,12 +42,7 @@ export interface ReadyBlock {
31
42
  }
32
43
  export declare function formatReadyBlock(block: ReadyBlock, ui?: Ui, isQuiet?: boolean, columns?: number | undefined): string[];
33
44
  export declare function writeReadyBlock(block: ReadyBlock, ui?: Ui): void;
34
- declare const TIMED_LEVEL_COLORS: {
35
- readonly success: "green";
36
- readonly info: "blue";
37
- readonly warn: "yellow";
38
- };
39
- type TimedLevel = keyof typeof TIMED_LEVEL_COLORS;
45
+ type TimedLevel = "success" | "info" | "warn";
40
46
  export interface TimedMessageOptions {
41
47
  details?: readonly string[];
42
48
  fixes?: readonly string[];
package/dist/output.js CHANGED
@@ -15,6 +15,7 @@ exports.workspaceId = workspaceId;
15
15
  exports.formatSize = formatSize;
16
16
  exports.formatAge = formatAge;
17
17
  exports.cachedAge = cachedAge;
18
+ exports.classifyFailure = classifyFailure;
18
19
  exports.failureDetails = failureDetails;
19
20
  exports.endInterruptedTask = endInterruptedTask;
20
21
  exports.reportStopped = reportStopped;
@@ -25,7 +26,6 @@ const node_os_1 = require("node:os");
25
26
  const node_path_1 = require("node:path");
26
27
  const node_util_1 = require("node:util");
27
28
  const cli_1 = require("@antelopejs/core/cli");
28
- const cancellation_1 = require("./cancellation");
29
29
  const HOME_PREFIX = "~";
30
30
  const CURRENT_DIRECTORY = ".";
31
31
  const WORKSPACE_ID_LENGTH = 8;
@@ -140,17 +140,24 @@ function formatAge(iso, now = Date.now()) {
140
140
  function cachedAge(fetchedAt) {
141
141
  return fetchedAt ? ` cached ${formatAge(fetchedAt)}` : "";
142
142
  }
143
- function describeProblem(error) {
144
- if (error instanceof cli_1.CliError)
145
- return error.problem;
146
- const message = error instanceof Error ? error.message : String(error);
147
- return { title: message.split(LINE_BREAK)[0] };
148
- }
149
- function failureDetails(error, ui = (0, cli_1.getProcessUi)()) {
150
- const { title, reason, fixes = [], details = [] } = describeProblem(error);
143
+ function classifyFailure(thrown) {
144
+ if (thrown instanceof cli_1.CliError)
145
+ return { kind: "cli", error: thrown };
146
+ if (thrown instanceof Error)
147
+ return { kind: "error", error: thrown };
148
+ return { kind: "thrown", text: String(thrown) };
149
+ }
150
+ function failureDetails(failure, ui = (0, cli_1.getProcessUi)()) {
151
+ const { title, reason, fixes = [], details = [], } = failure.kind === "cli"
152
+ ? failure.error.problem
153
+ : {
154
+ title: (failure.kind === "error"
155
+ ? failure.error.message
156
+ : failure.text).split(LINE_BREAK)[0],
157
+ };
151
158
  const hint = ui.symbols.levels.hint;
152
- const stack = (0, cli_1.isVerboseRun)() && error instanceof Error && !(error instanceof cli_1.CliError)
153
- ? (error.stack ?? "").split(LINE_BREAK).slice(1)
159
+ const stack = (0, cli_1.isVerboseRun)() && failure.kind === "error"
160
+ ? (failure.error.stack ?? "").split(LINE_BREAK).slice(1)
154
161
  : [];
155
162
  return [
156
163
  title,
@@ -164,7 +171,7 @@ function lineStartAfter(signal) {
164
171
  return signal === "SIGINT" && process.stderr.isTTY ? CARRIAGE_RETURN : "";
165
172
  }
166
173
  function endInterruptedTask(task, error, stopped) {
167
- if (!(error instanceof cancellation_1.CancelledError))
174
+ if (!error)
168
175
  return task.dismiss();
169
176
  const lineStart = lineStartAfter(error.signal);
170
177
  if (lineStart)
@@ -212,18 +219,23 @@ function writeReadyBlock(block, ui = (0, cli_1.getProcessUi)()) {
212
219
  writeFeedback(line);
213
220
  writeInfo("");
214
221
  }
215
- const TIMED_LEVEL_COLORS = {
216
- success: "green",
217
- info: "blue",
218
- warn: "yellow",
219
- };
222
+ function timedLevelColor(level) {
223
+ switch (level) {
224
+ case "success":
225
+ return "green";
226
+ case "info":
227
+ return "blue";
228
+ case "warn":
229
+ return "yellow";
230
+ }
231
+ }
220
232
  function clockTime(date) {
221
233
  return date.toTimeString().slice(0, TIME_LENGTH);
222
234
  }
223
235
  function formatTimedMessage(level, text, options = {}, ui = (0, cli_1.getProcessUi)(), now = new Date()) {
224
236
  const { details = [], fixes = [], columns = feedbackColumns() } = options;
225
237
  const palette = ui.palette();
226
- const paint = palette[TIMED_LEVEL_COLORS[level]];
238
+ const paint = palette[timedLevelColor(level)];
227
239
  const hint = palette.cyan(ui.symbols.levels.hint);
228
240
  const indent = " ".repeat(TIME_LENGTH + 1) + BLOCK_INDENT;
229
241
  return [
@@ -1,6 +1,6 @@
1
1
  import type { FrontendModuleOptions } from "./workspace";
2
2
  export declare function emptiedOptions(options: FrontendModuleOptions): FrontendModuleOptions;
3
- export declare function filledOptions(shape: FrontendModuleOptions, values: FrontendModuleOptions | undefined): FrontendModuleOptions;
3
+ export declare function filledOptions(declared: FrontendModuleOptions, values: FrontendModuleOptions | undefined): FrontendModuleOptions;
4
4
  export declare const PRIVATE_OPTIONS_VARIABLE = "DMS_PRIVATE_OPTIONS";
5
5
  export interface UnfilledPrivateValue {
6
6
  module: string;
@@ -34,8 +34,8 @@ function filled(declared, value) {
34
34
  return filledOptions(declared, isOptions(value) ? value : undefined);
35
35
  return declared;
36
36
  }
37
- function filledOptions(shape, values) {
38
- return Object.fromEntries(Object.entries(shape).map(([key, value]) => [
37
+ function filledOptions(declared, values) {
38
+ return Object.fromEntries(Object.entries(declared).map(([key, value]) => [
39
39
  key,
40
40
  filled(value, values?.[key]),
41
41
  ]));
@@ -90,7 +90,9 @@ function unfilledPrivateValues(modules, given, covered) {
90
90
  return Object.entries(modules).flatMap(([module, options]) => [...emptyStrings(options)]
91
91
  .filter((path) => path.length > 0 && !isCovered(path))
92
92
  .filter((path) => {
93
- const value = readPath(given[module], path);
93
+ const value = readPath(Object.prototype.hasOwnProperty.call(given, module)
94
+ ? given[module]
95
+ : undefined, path);
94
96
  return !(0, guards_1.isText)(value) || value === "";
95
97
  })
96
98
  .map((path) => ({ module, path })));
@@ -107,26 +107,31 @@ function computeConfigVars(id, provider, config) {
107
107
  reason: error instanceof Error ? error.message : String(error),
108
108
  }, { cause: error });
109
109
  }
110
- return Object.fromEntries(provider.declared
111
- .filter((name) => name in computed)
112
- .map((name) => [name, computed[name]]));
110
+ return Object.fromEntries(provider.declared.flatMap((name) => Object.prototype.hasOwnProperty.call(computed, name)
111
+ ? [[name, computed[name]]]
112
+ : []));
113
113
  }
114
114
  function configVarLookup(modules) {
115
115
  const published = new Map();
116
116
  const lookup = (id, name) => {
117
117
  if (!published.has(id)) {
118
118
  published.set(id, undefined);
119
- const module = modules[id];
119
+ const module = Object.prototype.hasOwnProperty.call(modules, id)
120
+ ? modules[id]
121
+ : undefined;
120
122
  const provider = module?.folder && configVarsProvider(id, module.folder);
121
- if (provider)
123
+ if (module && provider)
122
124
  published.set(id, computeConfigVars(id, provider, substituteConfigVars(module.config, lookup)));
123
125
  }
124
- return published.get(id)?.[name];
126
+ const variables = published.get(id);
127
+ return variables && Object.prototype.hasOwnProperty.call(variables, name)
128
+ ? variables[name]
129
+ : undefined;
125
130
  };
126
131
  return lookup;
127
132
  }
128
133
  function substituteConfigVars(value, lookup) {
129
- if (typeof value === "string") {
134
+ if ((0, guards_1.isText)(value)) {
130
135
  const pure = value.match(PURE_CONFIG_VAR);
131
136
  if (pure)
132
137
  return lookup(pure[1], pure[2]);
@@ -137,7 +142,7 @@ function substituteConfigVars(value, lookup) {
137
142
  }
138
143
  if (Array.isArray(value))
139
144
  return value.map((item) => substituteConfigVars(item, lookup));
140
- if (value && typeof value === "object") {
145
+ if ((0, guards_1.isObjectLike)(value)) {
141
146
  return Object.fromEntries(Object.entries(value).map(([key, item]) => [
142
147
  key,
143
148
  substituteConfigVars(item, lookup),
@@ -11,7 +11,8 @@ const semver_1 = __importDefault(require("semver"));
11
11
  const layers_1 = require("./layers");
12
12
  const output_1 = require("./output");
13
13
  const guards_1 = require("./internal/guards");
14
- const OWN_RELEASE = require("../package.json");
14
+ const plain_object_1 = require("./internal/plain-object");
15
+ const own_release_1 = require("./internal/own-release");
15
16
  const noticedModules = new Set();
16
17
  const NOTICED_MODULES_FILE = ".renderer-range-noticed";
17
18
  function readNoticedModules(workspaceDir) {
@@ -35,10 +36,11 @@ function shownModule(layer) {
35
36
  return layer.packageName ? `${layer.packageName} (${where})` : where;
36
37
  }
37
38
  function declaredRange(layer, rendererName) {
39
+ const engines = (0, layers_1.readLayerPackage)(layer.path)?.engines;
38
40
  return {
39
41
  module: moduleLabel(layer),
40
42
  shown: shownModule(layer),
41
- range: (0, layers_1.readLayerPackage)(layer.path)?.engines?.[rendererName],
43
+ range: (0, plain_object_1.isPlainObject)(engines) ? engines[rendererName] : undefined,
42
44
  };
43
45
  }
44
46
  function releaseLine(version) {
@@ -73,7 +75,7 @@ function noticeUndeclared(declarations, renderer, warn, workspaceDir) {
73
75
  });
74
76
  }
75
77
  function assertLayersSupportRenderer(layers, options = {}) {
76
- const renderer = options.renderer ?? OWN_RELEASE;
78
+ const renderer = options.renderer ?? own_release_1.ownRelease;
77
79
  const declarations = layers.map((layer) => declaredRange(layer, renderer.name));
78
80
  noticeUndeclared(declarations, renderer, options.warn ??
79
81
  ((text, messageOptions) => (0, cli_1.getProcessUi)().message("warn", text, messageOptions)), options.workspaceDir);