@antelopejs/dms-frontend 0.10.3 → 0.10.4

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/config.js CHANGED
@@ -74,6 +74,7 @@ exports.TEMPLATE_FILES = [
74
74
  ["sfc-global-types.mjs", "sfc-global-types.mjs"],
75
75
  ["icon-api.mjs", "icon-api.mjs"],
76
76
  ["icon-scan.mjs", "icon-scan.mjs"],
77
+ ["auto-imports.mjs", "auto-imports.mjs"],
77
78
  ["ui-kbd.mjs", "ui-kbd.mjs"],
78
79
  ["ui-lazy-icons.mjs", "ui-lazy-icons.mjs"],
79
80
  ["email-renderer.ts", "email-renderer.ts"],
@@ -8,7 +8,7 @@ export declare class ManifestUnauthorizedError extends CliError {
8
8
  export declare class BackendUnreachableError extends CliError {
9
9
  readonly url: string;
10
10
  readonly code?: string;
11
- constructor(url: string, failure: unknown);
11
+ constructor(url: string, cause: unknown);
12
12
  }
13
13
  export declare function displayUrl(url: string | URL): string;
14
14
  export declare function backendEndpoint(backendUrl: string, path: string): URL;
package/dist/manifest.js CHANGED
@@ -47,10 +47,10 @@ const UNREACHABLE_REASONS = new Map([
47
47
  ]);
48
48
  const UNKNOWN_HOST_CODES = ["ENOTFOUND", "EAI_AGAIN"];
49
49
  class BackendUnreachableError extends cli_1.CliError {
50
- constructor(url, failure) {
51
- const cause = (hasProperties(failure) ? failure.cause : undefined) ?? failure;
52
- const code = hasProperties(cause) ? errorCode(cause) : undefined;
53
- const message = () => cause instanceof Error ? cause.message : String(cause);
50
+ constructor(url, cause) {
51
+ const reason = (hasProperties(cause) ? cause.cause : undefined) ?? cause;
52
+ const code = hasProperties(reason) ? errorCode(reason) : undefined;
53
+ const message = () => reason instanceof Error ? reason.message : String(reason);
54
54
  const detail = code
55
55
  ? (UNREACHABLE_REASONS.get(code) ?? message())
56
56
  : `The request failed: ${message()}`;
@@ -61,7 +61,7 @@ class BackendUnreachableError extends cli_1.CliError {
61
61
  title: `Cannot reach the DMS backend at ${url}`,
62
62
  reason: `${code ? `${detail} (${code})` : detail}.`,
63
63
  fixes: [fix],
64
- }, { cause: failure });
64
+ }, { cause });
65
65
  this.url = url;
66
66
  this.name = "BackendUnreachableError";
67
67
  this.code = code;
package/dist/output.d.ts CHANGED
@@ -25,7 +25,7 @@ export type Failure = {
25
25
  kind: "thrown";
26
26
  text: string;
27
27
  };
28
- export declare function classifyFailure(thrown: unknown): Failure;
28
+ export declare function classifyFailure(cause: unknown): Failure;
29
29
  export declare function failureDetails(failure: Failure, ui?: Ui): string[];
30
30
  export declare function endInterruptedTask(task: TaskHandle, error: CancelledError | undefined, stopped: string): void;
31
31
  export declare function reportStopped(stop: CancelledError, ui?: Ui): void;
package/dist/output.js CHANGED
@@ -140,12 +140,12 @@ function formatAge(iso, now = Date.now()) {
140
140
  function cachedAge(fetchedAt) {
141
141
  return fetchedAt ? ` cached ${formatAge(fetchedAt)}` : "";
142
142
  }
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) };
143
+ function classifyFailure(cause) {
144
+ if (cause instanceof cli_1.CliError)
145
+ return { kind: "cli", error: cause };
146
+ if (cause instanceof Error)
147
+ return { kind: "error", error: cause };
148
+ return { kind: "thrown", text: String(cause) };
149
149
  }
150
150
  function failureDetails(failure, ui = (0, cli_1.getProcessUi)()) {
151
151
  const { title, reason, fixes = [], details = [], } = failure.kind === "cli"
@@ -62,6 +62,9 @@ async function checkServerModulesBundle(workspace) {
62
62
  (0, ensure_1.ensure)(Array.isArray(serverModules), "The server modules bundle exports none");
63
63
  return `${(0, cli_1.pluralize)(serverModules.length, "server module")}, ${(0, output_1.formatSize)(Buffer.byteLength(javascript))} JS`;
64
64
  }
65
+ function isFunction(value) {
66
+ return typeof value === "function";
67
+ }
65
68
  const EMAIL_CASES = [
66
69
  {
67
70
  name: "EmailAdminInvite",
@@ -141,7 +144,11 @@ async function checkEmailContracts(workspace) {
141
144
  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);
142
145
  const limit = (0, output_1.formatSize)(EMAIL_BUILD_SIZE_CEILING_BYTES);
143
146
  (0, ensure_1.ensure)(emailBuildSize <= EMAIL_BUILD_SIZE_CEILING_BYTES, `The e-mail bundle is ${(0, output_1.formatSize)(emailBuildSize)} of JavaScript`, `The limit is ${limit}.`);
144
- const { renderEmail } = await Promise.resolve(`${(0, node_path_1.join)(emailRoot, "email-renderer.js")}`).then(s => __importStar(require(s)));
147
+ const emailRenderer = await Promise.resolve(`${(0, node_path_1.join)(emailRoot, "email-renderer.js")}`).then(s => __importStar(require(s)));
148
+ (0, ensure_1.ensure)((0, guards_1.isObjectLike)(emailRenderer) &&
149
+ "renderEmail" in emailRenderer &&
150
+ isFunction(emailRenderer.renderEmail), "The e-mail bundle exports no renderEmail function");
151
+ const { renderEmail } = emailRenderer;
145
152
  for (const emailCase of EMAIL_CASES) {
146
153
  const html = await renderEmail(emailCase.name, emailCase.props);
147
154
  (0, ensure_1.ensure)((0, guards_1.isText)(html) && html.startsWith("<!doctype html>"), `${emailCase.name} does not render a full HTML document`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antelopejs/dms-frontend",
3
- "version": "0.10.3",
3
+ "version": "0.10.4",
4
4
  "description": "Frontend-agnostic loader for AntelopeJS DMS, shipping the Vue 3 renderer (Vite, Inertia, SSR)",
5
5
  "keywords": [
6
6
  "antelope",
@@ -44,6 +44,10 @@
44
44
  "types": "./dist/common.d.ts",
45
45
  "default": "./dist/common.js"
46
46
  },
47
+ "./eslint-globals": {
48
+ "types": "./templates/eslint-globals.types.d.mts",
49
+ "default": "./templates/eslint-globals.mjs"
50
+ },
47
51
  "./dist/*.js": {
48
52
  "types": "./dist/*.d.ts",
49
53
  "default": "./dist/*.js"
@@ -71,6 +75,7 @@
71
75
  "knip": "knip --dependencies",
72
76
  "knip:all": "knip",
73
77
  "docs:reference": "tsx scripts/docs-reference.ts",
78
+ "eslint-globals": "tsx scripts/eslint-globals.ts",
74
79
  "docs:reference:check": "tsx scripts/docs-reference.ts --check",
75
80
  "source-checks": "tsx scripts/source-checks.ts",
76
81
  "prepare": "if [ -e .git ] && command -v git >/dev/null 2>&1 && command -v lefthook >/dev/null 2>&1 && GIT_DIR=.git GIT_WORK_TREE=. git rev-parse --git-dir >/dev/null 2>&1; then GIT_DIR=.git GIT_WORK_TREE=. lefthook install; fi",
@@ -109,6 +114,7 @@
109
114
  "knip": "^6.34.0",
110
115
  "lefthook": "^2.2.2",
111
116
  "mongodb-memory-server": "^11.3.0",
117
+ "nuxt-ui-auto-imports": "npm:@nuxt/ui@4.10.0",
112
118
  "ofetch": "^1.5.1",
113
119
  "oxfmt": "^0.66.0",
114
120
  "oxlint": "1.81.0",
@@ -0,0 +1,133 @@
1
+ /**
2
+ * ESLint flat-config globals for every name the DMS renderer auto-imports
3
+ * into a module's sources: Vue's preset, `frontend-module.ts` and Nuxt
4
+ * UI's composables. Written by `pnpm eslint-globals`.
5
+ */
6
+ export default Object.freeze({
7
+ $fetch: "readonly",
8
+ Component: "readonly",
9
+ ComponentPublicInstance: "readonly",
10
+ ComputedRef: "readonly",
11
+ DirectiveBinding: "readonly",
12
+ DmsClientOnly: "readonly",
13
+ DmsLink: "readonly",
14
+ EffectScope: "readonly",
15
+ ExtractDefaultPropTypes: "readonly",
16
+ ExtractPropTypes: "readonly",
17
+ ExtractPublicPropTypes: "readonly",
18
+ InjectionKey: "readonly",
19
+ MaybeRef: "readonly",
20
+ MaybeRefOrGetter: "readonly",
21
+ PropType: "readonly",
22
+ Ref: "readonly",
23
+ ShallowRef: "readonly",
24
+ Slot: "readonly",
25
+ Slots: "readonly",
26
+ VNode: "readonly",
27
+ WritableComputedRef: "readonly",
28
+ abortDmsNavigation: "readonly",
29
+ clearDmsError: "readonly",
30
+ computed: "readonly",
31
+ createApp: "readonly",
32
+ createDmsError: "readonly",
33
+ customRef: "readonly",
34
+ defineAsyncComponent: "readonly",
35
+ defineComponent: "readonly",
36
+ defineDmsAppConfig: "readonly",
37
+ defineDmsMiddleware: "readonly",
38
+ defineDmsPageMeta: "readonly",
39
+ defineDmsPlugin: "readonly",
40
+ defineLocale: "readonly",
41
+ defineShortcuts: "readonly",
42
+ dmsRequestKey: "readonly",
43
+ effectScope: "readonly",
44
+ extendLocale: "readonly",
45
+ extractShortcuts: "readonly",
46
+ getCurrentInstance: "readonly",
47
+ getCurrentScope: "readonly",
48
+ getCurrentWatcher: "readonly",
49
+ h: "readonly",
50
+ inject: "readonly",
51
+ isDmsHydrating: "readonly",
52
+ isProxy: "readonly",
53
+ isReactive: "readonly",
54
+ isReadonly: "readonly",
55
+ isRef: "readonly",
56
+ isShallow: "readonly",
57
+ markRaw: "readonly",
58
+ navigateDms: "readonly",
59
+ nextTick: "readonly",
60
+ onActivated: "readonly",
61
+ onBeforeMount: "readonly",
62
+ onBeforeUnmount: "readonly",
63
+ onBeforeUpdate: "readonly",
64
+ onDeactivated: "readonly",
65
+ onErrorCaptured: "readonly",
66
+ onMounted: "readonly",
67
+ onRenderTracked: "readonly",
68
+ onRenderTriggered: "readonly",
69
+ onScopeDispose: "readonly",
70
+ onServerPrefetch: "readonly",
71
+ onUnmounted: "readonly",
72
+ onUpdated: "readonly",
73
+ onWatcherCleanup: "readonly",
74
+ preloadDmsComponents: "readonly",
75
+ provide: "readonly",
76
+ provideDmsKbdPlatform: "readonly",
77
+ reactive: "readonly",
78
+ readonly: "readonly",
79
+ ref: "readonly",
80
+ refreshDmsData: "readonly",
81
+ refreshDmsPageData: "readonly",
82
+ resolveComponent: "readonly",
83
+ setDmsAsyncDataScope: "readonly",
84
+ shallowReactive: "readonly",
85
+ shallowReadonly: "readonly",
86
+ shallowRef: "readonly",
87
+ showDmsError: "readonly",
88
+ toRaw: "readonly",
89
+ toRef: "readonly",
90
+ toRefs: "readonly",
91
+ toValue: "readonly",
92
+ triggerRef: "readonly",
93
+ unref: "readonly",
94
+ useAppConfig: "readonly",
95
+ useAttrs: "readonly",
96
+ useContentSearch: "readonly",
97
+ useCssModule: "readonly",
98
+ useCssVars: "readonly",
99
+ useDmsApp: "readonly",
100
+ useDmsAppConfig: "readonly",
101
+ useDmsAsyncData: "readonly",
102
+ useDmsCookie: "readonly",
103
+ useDmsData: "readonly",
104
+ useDmsError: "readonly",
105
+ useDmsFetch: "readonly",
106
+ useDmsPageLoading: "readonly",
107
+ useDmsPagedData: "readonly",
108
+ useDmsRoute: "readonly",
109
+ useDmsRouter: "readonly",
110
+ useDmsRuntimeConfig: "readonly",
111
+ useDmsState: "readonly",
112
+ useDmsUserSession: "readonly",
113
+ useFileUpload: "readonly",
114
+ useFormField: "readonly",
115
+ useHead: "readonly",
116
+ useI18n: "readonly",
117
+ useId: "readonly",
118
+ useKbd: "readonly",
119
+ useModel: "readonly",
120
+ useOverlay: "readonly",
121
+ useResizable: "readonly",
122
+ useScrollShadow: "readonly",
123
+ useScrollspy: "readonly",
124
+ useSeoMeta: "readonly",
125
+ useSlots: "readonly",
126
+ useTemplateRef: "readonly",
127
+ useToast: "readonly",
128
+ useTour: "readonly",
129
+ watch: "readonly",
130
+ watchEffect: "readonly",
131
+ watchPostEffect: "readonly",
132
+ watchSyncEffect: "readonly",
133
+ });
@@ -0,0 +1,6 @@
1
+ /**
2
+ * ESLint flat-config globals for every name the DMS renderer auto-imports
3
+ * into a module's sources, for `languageOptions.globals`.
4
+ */
5
+ declare const eslintGlobals: Readonly<Record<string, "readonly">>;
6
+ export default eslintGlobals;
@@ -0,0 +1,54 @@
1
+ /** The names `frontend-module.ts` gives every module's sources without an import. */
2
+ const FRONTEND_MODULE_IMPORTS = [
3
+ "$fetch",
4
+ "abortDmsNavigation",
5
+ "clearDmsError",
6
+ "createDmsError",
7
+ "dmsRequestKey",
8
+ "defineDmsAppConfig",
9
+ "defineDmsPlugin",
10
+ "defineDmsMiddleware",
11
+ "defineDmsPageMeta",
12
+ "navigateDms",
13
+ "preloadDmsComponents",
14
+ "refreshDmsData",
15
+ "refreshDmsPageData",
16
+ "setDmsAsyncDataScope",
17
+ "showDmsError",
18
+ "useDmsAsyncData",
19
+ "useDmsData",
20
+ "useDmsCookie",
21
+ "useDmsFetch",
22
+ "useHead",
23
+ "useI18n",
24
+ "useDmsError",
25
+ "useDmsPagedData",
26
+ "useDmsPageLoading",
27
+ "isDmsHydrating",
28
+ "useDmsApp",
29
+ "useDmsRoute",
30
+ "useDmsRouter",
31
+ "useDmsRuntimeConfig",
32
+ "useSeoMeta",
33
+ "useDmsState",
34
+ "useDmsAppConfig",
35
+ "DmsClientOnly",
36
+ "DmsLink",
37
+ "useDmsUserSession",
38
+ "provideDmsKbdPlatform",
39
+ ];
40
+
41
+ /**
42
+ * The `imports` of the workspace's auto-importer: Vue's preset and the names
43
+ * of `frontend-module.ts`. Nuxt UI adds its own composables to them.
44
+ *
45
+ * The auto-importer inlines `frontendModule` verbatim as the specifier of the
46
+ * import it prepends to each file, inside a single-quoted JavaScript string:
47
+ * pass a POSIX path, since a Windows backslash there reads as an escape.
48
+ *
49
+ * @param {string} frontendModule The import specifier of `frontend-module.ts`.
50
+ * @returns {["vue", Record<string, string[]>]}
51
+ */
52
+ export function autoImportSources(frontendModule) {
53
+ return ["vue", { [frontendModule]: FRONTEND_MODULE_IMPORTS }];
54
+ }
@@ -295,14 +295,14 @@ function isResponse(value) {
295
295
  }
296
296
 
297
297
  /**
298
- * @param {any} result What a handler answered: any value, of which only
298
+ * @param {unknown} result What a handler answered: any value, of which only
299
299
  * `isResponse` looks
300
300
  * @returns {Response}
301
301
  */
302
302
  function asResponse(result) {
303
303
  if (isResponse(result))
304
- // oxlint-disable-next-line typescript/no-unsafe-return -- `isResponse` also accepts a `Response` of another realm by its members (`status`, `headers.get`, `body`), so it cannot be a `value is Response` predicate without claiming members it does not check.
305
- return result;
304
+ // SAFETY: `isResponse` accepts a `Response` of this realm or of another one (another copy of undici) by its `status`, `headers.get` and `body`; an answer that only mimics those members is read as a `Response` too, as it was before this assertion.
305
+ return /** @type {Response} */ (result);
306
306
  if (result === undefined || result === null)
307
307
  return new Response(null, { status: 204 });
308
308
  return Response.json(result);
@@ -222,16 +222,24 @@ function readPublicOptions() {
222
222
  */
223
223
  async function loadDeclarations(devServer) {
224
224
  if (devServer)
225
- // oxlint-disable-next-line typescript/no-unsafe-return -- `ssrLoadModule` types every module `Record<string, any>`; the loader is the generated `server-modules.generated.ts`, which exports `serverModules`.
226
- return (await devServer.ssrLoadModule(SOURCE_LOADER)).serverModules;
225
+ return declarationsOf(await devServer.ssrLoadModule(SOURCE_LOADER));
227
226
  if (!existsSync(fileURLToPath(BUILT_LOADER))) return [];
228
- builtDeclarations ??= import(BUILT_LOADER.href).then(
229
- // oxlint-disable-next-line typescript/no-unsafe-return -- the build of that same generated module is imported by a URL computed at run time, so it is untyped.
230
- (loaded) => loaded.serverModules,
231
- );
227
+ builtDeclarations ??= import(BUILT_LOADER.href).then(declarationsOf);
232
228
  return builtDeclarations;
233
229
  }
234
230
 
231
+ /**
232
+ * @param {unknown} loader The generated `server-modules.generated.ts`, from
233
+ * its source or its build
234
+ * @returns {ServerModuleDeclaration[]}
235
+ */
236
+ function declarationsOf(loader) {
237
+ // SAFETY: `ssrLoadModule` types every module `Record<string, any>` and the build is imported by a URL computed at run time; both are the generated `server-modules.generated.ts`, which exports `serverModules`, the declarations of the modules with a dms.server.ts.
238
+ return /** @type {{ serverModules: ServerModuleDeclaration[] }} */ (
239
+ loader
240
+ ).serverModules;
241
+ }
242
+
235
243
  /**
236
244
  * The declarations to serve. A module entry that fails to load in development
237
245
  * (a syntax error being typed) is reported once, and the last routes that
@@ -22,11 +22,12 @@ let productionSsrRenderer;
22
22
  * @returns {Promise<typeof import("../ssr-renderer.ts")>}
23
23
  */
24
24
  export async function ssrRenderer(devServer) {
25
- /** @type {typeof import("../ssr-renderer.ts")} */
26
- // oxlint-disable-next-line typescript/no-unsafe-assignment -- `ssrLoadModule` types every module `Record<string, any>` and the production import takes a URL computed at run time; both load this template's own `ssr-renderer.ts`, the type named above.
27
- const renderer = devServer
28
- ? await devServer.ssrLoadModule("/ssr-renderer.ts")
29
- : await (productionSsrRenderer ??= import(BUILT_SSR_RENDERER_URL.href));
25
+ // SAFETY: both load this template's own `ssr-renderer.ts`, the development server from its source and the production import from its build; `ssrLoadModule` types every module `Record<string, any>` and the built URL is computed at run time.
26
+ const renderer = /** @type {typeof import("../ssr-renderer.ts")} */ (
27
+ devServer
28
+ ? await devServer.ssrLoadModule("/ssr-renderer.ts")
29
+ : await (productionSsrRenderer ??= import(BUILT_SSR_RENDERER_URL.href))
30
+ );
30
31
  await icons.provideIconCollections(renderer);
31
32
  return renderer;
32
33
  }
@@ -18,6 +18,7 @@ import { uiKbd } from "./ui-kbd.mjs";
18
18
  import { uiLazyIcons } from "./ui-lazy-icons.mjs";
19
19
  import { uiRequestState } from "./ui-request-state.mjs";
20
20
  import { autoImportDirectories, vitePlugins } from "./frontend-build-loader.ts";
21
+ import { autoImportSources } from "./auto-imports.mjs";
21
22
  import { frontendBuilds } from "./frontend-builds.generated.ts";
22
23
  import { orderHeadForFirstPaint } from "./head-order.mjs";
23
24
  import { iconScanGlobs } from "./icon-scan.mjs";
@@ -218,56 +219,9 @@ export default defineConfig({
218
219
  autoImport: {
219
220
  dirs: importDirectories,
220
221
  dirsScanOptions: { types: true },
221
- imports: [
222
- "vue",
223
- {
224
- // This key is inlined verbatim as the module specifier of the
225
- // import the auto-importer prepends to each file. A native Windows
226
- // path would land inside a single-quoted JavaScript string with its
227
- // backslashes intact, where `\U`, `\M` and `\f` are read as escape
228
- // sequences: the specifier the bundler then resolves is a mangled
229
- // path that cannot exist. Keep it POSIX.
230
- [normalizePath(resolve(import.meta.dirname, "frontend-module.ts"))]:
231
- [
232
- "$fetch",
233
- "abortDmsNavigation",
234
- "clearDmsError",
235
- "createDmsError",
236
- "dmsRequestKey",
237
- "defineDmsAppConfig",
238
- "defineDmsPlugin",
239
- "defineDmsMiddleware",
240
- "defineDmsPageMeta",
241
- "navigateDms",
242
- "preloadDmsComponents",
243
- "refreshDmsData",
244
- "refreshDmsPageData",
245
- "setDmsAsyncDataScope",
246
- "showDmsError",
247
- "useDmsAsyncData",
248
- "useDmsData",
249
- "useDmsCookie",
250
- "useDmsFetch",
251
- "useHead",
252
- "useI18n",
253
- "useDmsError",
254
- "useDmsPagedData",
255
- "useDmsPageLoading",
256
- "isDmsHydrating",
257
- "useDmsApp",
258
- "useDmsRoute",
259
- "useDmsRouter",
260
- "useDmsRuntimeConfig",
261
- "useSeoMeta",
262
- "useDmsState",
263
- "useDmsAppConfig",
264
- "DmsClientOnly",
265
- "DmsLink",
266
- "useDmsUserSession",
267
- "provideDmsKbdPlatform",
268
- ],
269
- },
270
- ],
222
+ imports: autoImportSources(
223
+ normalizePath(resolve(import.meta.dirname, "frontend-module.ts")),
224
+ ),
271
225
  dts: "auto-imports.d.ts",
272
226
  vueTemplate: true,
273
227
  },