@antelopejs/dms-frontend 0.3.5 → 0.3.6

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/dist/fs-sync.js CHANGED
@@ -151,8 +151,7 @@ function collectFiles(dir, baseDir = dir) {
151
151
  const entries = (0, node_fs_1.readdirSync)(dir, { withFileTypes: true });
152
152
  for (const entry of entries) {
153
153
  const fullPath = (0, node_path_1.join)(dir, entry.name);
154
- const { relative } = require("node:path");
155
- const relPath = relative(baseDir, fullPath);
154
+ const relPath = (0, node_path_1.relative)(baseDir, fullPath);
156
155
  if (entry.isDirectory()) {
157
156
  files.push(...collectFiles(fullPath, baseDir));
158
157
  }
@@ -179,12 +178,11 @@ function syncDirectories(src, dest) {
179
178
  cleanEmptyDirs(dest);
180
179
  }
181
180
  function cleanEmptyDirs(dir) {
182
- const { statSync } = require("node:fs");
183
- if (!(0, node_fs_1.existsSync)(dir) || !statSync(dir).isDirectory())
181
+ if (!(0, node_fs_1.existsSync)(dir) || !(0, node_fs_1.statSync)(dir).isDirectory())
184
182
  return;
185
183
  for (const entry of (0, node_fs_1.readdirSync)(dir)) {
186
184
  const full = (0, node_path_1.join)(dir, entry);
187
- if (statSync(full).isDirectory())
185
+ if ((0, node_fs_1.statSync)(full).isDirectory())
188
186
  cleanEmptyDirs(full);
189
187
  }
190
188
  if ((0, node_fs_1.readdirSync)(dir).length === 0) {
@@ -4,6 +4,9 @@ export declare class ManifestUnauthorizedError extends Error {
4
4
  readonly status: number;
5
5
  constructor(url: string, status: number);
6
6
  }
7
+ export declare class ManifestRefusedError extends Error {
8
+ constructor(reason: string);
9
+ }
7
10
  export declare function fetchManifest(backendUrl: string, clientUrl?: string, bootstrapSecret?: string): Promise<Manifest>;
8
11
  export interface ManifestCacheEntry {
9
12
  manifest: Manifest;
package/dist/manifest.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ManifestUnauthorizedError = void 0;
3
+ exports.ManifestRefusedError = exports.ManifestUnauthorizedError = void 0;
4
4
  exports.fetchManifest = fetchManifest;
5
5
  exports.readCachedManifest = readCachedManifest;
6
6
  exports.resolveManifest = resolveManifest;
@@ -22,6 +22,13 @@ class ManifestUnauthorizedError extends Error {
22
22
  }
23
23
  }
24
24
  exports.ManifestUnauthorizedError = ManifestUnauthorizedError;
25
+ class ManifestRefusedError extends Error {
26
+ constructor(reason) {
27
+ super(reason);
28
+ this.name = "ManifestRefusedError";
29
+ }
30
+ }
31
+ exports.ManifestRefusedError = ManifestRefusedError;
25
32
  async function fetchManifest(backendUrl, clientUrl, bootstrapSecret) {
26
33
  const frontendUrl = new URL(`${backendUrl}/dms/frontend`);
27
34
  frontendUrl.searchParams.set("renderer", "vue");
@@ -40,11 +47,11 @@ async function fetchManifest(backendUrl, clientUrl, bootstrapSecret) {
40
47
  }
41
48
  const manifest = (await response.json());
42
49
  if (manifest.version !== workspace_1.FRONTEND_MANIFEST_VERSION) {
43
- throw new Error(`Unsupported frontend manifest version: ${String(manifest.version)}`);
50
+ throw new ManifestRefusedError(`Unsupported frontend manifest version: ${String(manifest.version)}`);
44
51
  }
45
52
  const incompatible = manifest.modules.filter((module) => module.renderer?.name !== "vue" || module.renderer?.version !== "3");
46
53
  if (incompatible.length) {
47
- throw new Error(`Frontend manifest contains incompatible renderer modules: ${incompatible.map((module) => module.name).join(", ")}`);
54
+ throw new ManifestRefusedError(`Frontend manifest contains incompatible renderer modules: ${incompatible.map((module) => module.name).join(", ")}`);
48
55
  }
49
56
  return { pack: manifest.archive, modules: manifest.modules };
50
57
  }
@@ -80,6 +87,8 @@ async function resolveManifest(workspaceDir, backendUrl, offline, clientUrl, boo
80
87
  catch (err) {
81
88
  if (err instanceof ManifestUnauthorizedError)
82
89
  throw err;
90
+ if (err instanceof ManifestRefusedError)
91
+ throw err;
83
92
  const cached = readCachedManifest(workspaceDir);
84
93
  if (!cached)
85
94
  throw err;
package/dist/ports.js CHANGED
@@ -19,7 +19,7 @@ async function reserveFreePort(preferred, range = exports.PORT_FALLBACK_RANGE) {
19
19
  const server = await tryListen(port);
20
20
  if (server) {
21
21
  return {
22
- port,
22
+ port: server.address().port,
23
23
  release: () => new Promise((resolve) => {
24
24
  server.close(() => resolve());
25
25
  }),
@@ -8,9 +8,14 @@ const semver_1 = __importDefault(require("semver"));
8
8
  const layers_1 = require("./layers");
9
9
  const OWN_RELEASE = require("../package.json");
10
10
  const noticedModules = new Set();
11
+ function moduleLabel(layer) {
12
+ if (!layer.packageName)
13
+ return layer.path;
14
+ return `${layer.packageName} (${layer.path})`;
15
+ }
11
16
  function declaredRange(layer, rendererName) {
12
17
  return {
13
- module: layer.packageName ?? layer.path,
18
+ module: moduleLabel(layer),
14
19
  range: (0, layers_1.readLayerPackage)(layer.path)?.engines?.[rendererName],
15
20
  };
16
21
  }
@@ -74,7 +74,13 @@ const layers = roots.map((root) => ({
74
74
  packageName: JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(root, "package.json"), "utf8"))
75
75
  .name,
76
76
  }));
77
- (0, common_1.assertLayersSupportRenderer)(layers);
77
+ try {
78
+ (0, common_1.assertLayersSupportRenderer)(layers);
79
+ }
80
+ catch (error) {
81
+ console.error(`Error: ${error.message}`);
82
+ process.exit(1);
83
+ }
78
84
  (0, common_1.materializeLayers)(workspace, layers);
79
85
  const registry = (0, common_1.createFrontendModuleRegistry)(workspace, layers);
80
86
  registry.modules.forEach((module) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antelopejs/dms-frontend",
3
- "version": "0.3.5",
3
+ "version": "0.3.6",
4
4
  "description": "Frontend-agnostic loader for AntelopeJS DMS, shipping the Vue 3 renderer (Vite, Inertia, SSR)",
5
5
  "keywords": [
6
6
  "antelope",
@@ -906,9 +906,6 @@ export function useDmsRuntimeConfig(): DmsRuntimeConfig {
906
906
  export function useDmsAppConfig(): DmsAppConfig {
907
907
  return appConfig.value as DmsAppConfig;
908
908
  }
909
- export function configureDmsRuntime(config: DmsRuntimeConfig): void {
910
- runtimeConfig.value = config;
911
- }
912
909
  export function defineAppConfig<T extends Record<string, unknown>>(
913
910
  config: T,
914
911
  ): T {
@@ -934,14 +931,6 @@ export function defineDmsPageMeta(meta: Record<string, unknown>): void {
934
931
  export function abortNavigation(): false {
935
932
  return false;
936
933
  }
937
- export function addDmsMiddleware(
938
- handler: DmsMiddleware,
939
- name?: string,
940
- isGlobal = false,
941
- ): void {
942
- if (isGlobal) registry.middleware.push(handler);
943
- else if (name) registry.namedMiddleware.set(name, handler);
944
- }
945
934
  export const useHead = useUnhead;
946
935
  export const useSeoMeta = useUnheadSeoMeta;
947
936
  export function useI18n(): DmsI18n {
@@ -0,0 +1,50 @@
1
+ const INTERNAL_ERROR_STATUS = 500;
2
+ const ERROR_CONTENT_TYPE = "text/plain; charset=utf-8";
3
+ const VITE_ERROR = Symbol("dms.viteError");
4
+
5
+ /**
6
+ * In middleware mode, Vite's own error middleware logs an error, sends it to
7
+ * the client overlay, then passes the request on with no error: a module that
8
+ * fails to transform would fall through to page handling and answer 404. This
9
+ * plugin runs just before it, keeps the error on the request and hands it on,
10
+ * so Vite still logs it and shows the overlay.
11
+ */
12
+ export function captureViteErrors() {
13
+ return {
14
+ name: "dms-capture-vite-errors",
15
+ apply: "serve",
16
+ configureServer(server) {
17
+ return () =>
18
+ server.middlewares.use((error, request, _response, next) => {
19
+ request[VITE_ERROR] = error;
20
+ next(error);
21
+ });
22
+ },
23
+ };
24
+ }
25
+
26
+ /**
27
+ * Hands a request to Vite's middlewares. Resolves `handled` once Vite answered
28
+ * it, `unhandled` when Vite passed it on, and `failed` with the error when a
29
+ * Vite middleware failed on it.
30
+ */
31
+ export function runViteMiddlewares(devServer, request, response) {
32
+ return new Promise((resolve) => {
33
+ devServer.middlewares(request, response, (error) => {
34
+ const failure = error ?? request[VITE_ERROR];
35
+ resolve(
36
+ failure
37
+ ? { status: "failed", error: failure }
38
+ : { status: "unhandled" },
39
+ );
40
+ });
41
+ response.once("finish", () => resolve({ status: "handled" }));
42
+ });
43
+ }
44
+
45
+ /** Answers 500 with Vite's error message instead of rendering a page. */
46
+ export function writeViteError(response, error) {
47
+ response.statusCode = INTERNAL_ERROR_STATUS;
48
+ response.setHeader("content-type", ERROR_CONTENT_TYPE);
49
+ response.end(error?.message ?? String(error));
50
+ }
@@ -21,6 +21,11 @@ import {
21
21
  } from "./server/backend-response.mjs";
22
22
  import { productionHtmlTemplate } from "./server/client-manifest.mjs";
23
23
  import { writeContent } from "./server/content.mjs";
24
+ import {
25
+ captureViteErrors,
26
+ runViteMiddlewares,
27
+ writeViteError,
28
+ } from "./server/vite-errors.mjs";
24
29
  import { documentStyleTags } from "./server/dev-styles.mjs";
25
30
  import { handleEmailRender, watchEmailBundle } from "./server/email.mjs";
26
31
  import { HOMEPAGE } from "./server/homepage.mjs";
@@ -88,7 +93,11 @@ async function developmentServer() {
88
93
  const serverOptions = { middlewareMode: true };
89
94
  if (frontendHttpServer)
90
95
  serverOptions.hmr = { server: frontendHttpServer };
91
- return createViteServer({ server: serverOptions, appType: "custom" });
96
+ return createViteServer({
97
+ server: serverOptions,
98
+ appType: "custom",
99
+ plugins: [captureViteErrors()],
100
+ });
92
101
  })
93
102
  .then((server) => {
94
103
  vite = server;
@@ -385,6 +394,12 @@ async function writeBackendError(error, request, response) {
385
394
  response.end(JSON.stringify(payload));
386
395
  }
387
396
 
397
+ async function answeredByVite(devServer, request, response) {
398
+ const result = await runViteMiddlewares(devServer, request, response);
399
+ if (result.status === "failed") writeViteError(response, result.error);
400
+ return result.status !== "unhandled";
401
+ }
402
+
388
403
  export async function handleRequest(request, response) {
389
404
  const url = new URL(request.url, "http://frontend.local");
390
405
  const pathname = url.pathname;
@@ -409,11 +424,7 @@ export async function handleRequest(request, response) {
409
424
  return;
410
425
  const devServer = await developmentServer();
411
426
  if (devServer && pathname !== "/") {
412
- const handled = await new Promise((resolve) => {
413
- devServer.middlewares(request, response, () => resolve(false));
414
- response.once("finish", () => resolve(true));
415
- });
416
- if (handled) return;
427
+ if (await answeredByVite(devServer, request, response)) return;
417
428
  }
418
429
  if (!devServer && serveAsset(pathname, request, response)) return;
419
430
  if (handleAssetVersionMismatch(request, response)) return;