@antelopejs/dms-frontend 0.9.1 → 0.9.3
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 +9 -1
- package/dist/cancellation.js +2 -1
- package/dist/config.js +11 -7
- package/dist/derived-outputs.js +6 -113
- package/dist/dev-modules.js +3 -2
- package/dist/discovery.js +19 -12
- package/dist/fs-sync.js +1 -2
- package/dist/internal/guards.d.ts +5 -0
- package/dist/internal/guards.js +22 -0
- package/dist/internal/locale-catalogs.d.ts +6 -0
- package/dist/internal/locale-catalogs.js +115 -0
- package/dist/layer-aliases.js +2 -1
- package/dist/layers.js +2 -1
- package/dist/locale-files.js +9 -4
- package/dist/manifest-secrets.js +11 -4
- package/dist/manifest.js +11 -5
- package/dist/materialize.js +6 -5
- package/dist/module-set.js +2 -4
- package/dist/ports.js +8 -1
- package/dist/private-values.js +26 -17
- package/dist/project-modules.js +17 -11
- package/dist/renderer-range.js +2 -1
- package/dist/server-process.js +17 -16
- package/dist/update-check.js +23 -16
- package/dist/verify-source-runner.js +2 -2
- package/dist/workspace-setup.js +1 -2
- package/dist/workspace.js +11 -10
- package/package.json +7 -4
- package/skills/dms-frontend/SKILL.md +1 -1
- package/skills/dms-frontend/cases.json +77 -0
- package/templates/vue/app-runtime.ts +88 -7
- package/templates/vue/client-chunking.mjs +0 -5
- package/templates/vue/client-server-guard.mjs +10 -13
- package/templates/vue/entry-weight.mjs +12 -14
- package/templates/vue/frontend-module.ts +159 -3563
- package/templates/vue/frontend-runtime/async-data-entry.ts +320 -0
- package/templates/vue/frontend-runtime/async-data.ts +404 -0
- package/templates/vue/frontend-runtime/components.ts +386 -0
- package/templates/vue/frontend-runtime/cookies.ts +125 -0
- package/templates/vue/frontend-runtime/data-access.ts +132 -0
- package/templates/vue/frontend-runtime/dms-error.ts +11 -0
- package/templates/vue/frontend-runtime/errors.ts +145 -0
- package/templates/vue/frontend-runtime/fetch.ts +306 -0
- package/templates/vue/frontend-runtime/module-registration.ts +247 -0
- package/templates/vue/frontend-runtime/paged-data.ts +191 -0
- package/templates/vue/frontend-runtime/payload.ts +172 -0
- package/templates/vue/frontend-runtime/route.ts +328 -0
- package/templates/vue/frontend-runtime/sdk.ts +300 -0
- package/templates/vue/frontend-runtime/state.ts +167 -0
- package/templates/vue/frontend-runtime/types.ts +361 -0
- package/templates/vue/frontend-runtime/ui.ts +247 -0
- package/templates/vue/globals.d.ts +5 -0
- package/templates/vue/head-order.mjs +11 -13
- package/templates/vue/icon-bundle.ts +31 -0
- package/templates/vue/message-subset.ts +65 -0
- package/templates/vue/network-error.ts +4 -0
- package/templates/vue/prepare-types.mjs +0 -8
- package/templates/vue/server/auth/backend.mjs +4 -2
- package/templates/vue/server/auth/establish-endpoints.mjs +14 -9
- package/templates/vue/server/auth/session.mjs +4 -3
- package/templates/vue/server/auth-hooks.mjs +6 -6
- package/templates/vue/server/backend-proxies.mjs +6 -6
- package/templates/vue/server/backend-response.mjs +15 -14
- package/templates/vue/server/built-files.mjs +10 -8
- package/templates/vue/server/cli-report.mjs +7 -5
- package/templates/vue/server/client-error.mjs +11 -8
- package/templates/vue/server/client-manifest.mjs +9 -8
- package/templates/vue/server/content.mjs +2 -1
- package/templates/vue/server/dev-private-files.mjs +20 -15
- package/templates/vue/server/dev-styles.mjs +22 -25
- package/templates/vue/server/email-bundle-watch.mjs +0 -12
- package/templates/vue/server/email.mjs +20 -15
- package/templates/vue/server/favicon.mjs +12 -11
- package/templates/vue/server/homepage.mjs +8 -10
- package/templates/vue/server/icons.mjs +18 -9
- package/templates/vue/server/in-place-render.mjs +6 -8
- package/templates/vue/server/listen-host.mjs +2 -2
- package/templates/vue/server/module-event.mjs +5 -5
- package/templates/vue/server/module-routes.mjs +11 -7
- package/templates/vue/server/module-server.mjs +8 -7
- package/templates/vue/server/module-testing.mjs +7 -7
- package/templates/vue/server/page-props.mjs +14 -14
- package/templates/vue/server/path-patterns.mjs +4 -4
- package/templates/vue/server/proxy-compression.mjs +21 -13
- package/templates/vue/server/proxy-headers.mjs +5 -3
- package/templates/vue/server/proxy-redirects.mjs +7 -6
- package/templates/vue/server/proxy-transfers.mjs +15 -11
- package/templates/vue/server/public-endpoints.mjs +27 -19
- package/templates/vue/server/public-options.mjs +9 -7
- package/templates/vue/server/request-failure.mjs +4 -6
- package/templates/vue/server/request-routing.mjs +8 -11
- package/templates/vue/server/request-target.mjs +6 -6
- package/templates/vue/server/route-rules.mjs +7 -5
- package/templates/vue/server/static-files.mjs +19 -10
- package/templates/vue/server/web-body.mjs +3 -4
- package/templates/vue/server.mjs +32 -19
- package/templates/vue/sfc-global-types.mjs +27 -24
- package/templates/vue/ssr-renderer.ts +10 -1
- package/templates/vue/ui-inertia-page.mjs +7 -7
- package/templates/vue/ui-kbd.mjs +10 -10
- package/templates/vue/ui-lazy-icons.mjs +44 -0
- package/templates/vue/ui-request-state.mjs +9 -9
- package/templates/vue/vite.config.ts +2 -0
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
<a href="https://www.npmjs.com/package/@antelopejs/dms-frontend"><img alt="npm" src="https://img.shields.io/npm/v/@antelopejs/dms-frontend?style=for-the-badge&labelColor=000000&color=000000"></a>
|
|
11
11
|
<a href="./LICENSE"><img alt="License" src="https://img.shields.io/npm/l/@antelopejs/dms-frontend?style=for-the-badge&labelColor=000000&color=000000"></a>
|
|
12
|
-
<a href="https://discord.gg/
|
|
12
|
+
<a href="https://discord.gg/g4pFt6eXqu"><img alt="Discord" src="https://img.shields.io/badge/Discord-18181B?logo=discord&style=for-the-badge&color=000000"></a>
|
|
13
13
|
<a href="https://dms.antelopejs.com/docs/frontend"><img alt="Documentation" src="https://img.shields.io/badge/Docs-18181B?style=for-the-badge&color=000000"></a>
|
|
14
14
|
|
|
15
15
|
**The frontend of the AntelopeJS DMS: the `ajs dms` CLI, the Vue renderer and the frontend-module SDK.**
|
|
@@ -55,6 +55,14 @@ pnpm exec ajs dms start -b https://api.example.com -p 3001
|
|
|
55
55
|
|
|
56
56
|
## Compatibility
|
|
57
57
|
|
|
58
|
+
<!-- antelopejs-docs-compat:start -->
|
|
59
|
+
|
|
60
|
+
| Package | Supported | Tested with |
|
|
61
|
+
| ------------------ | ------------- | ----------- |
|
|
62
|
+
| `@antelopejs/core` | `>=1.16.0 <2` | `1.16.0` |
|
|
63
|
+
|
|
64
|
+
<!-- antelopejs-docs-compat:end -->
|
|
65
|
+
|
|
58
66
|
| `@antelopejs/dms` | `@antelopejs/dms-frontend` |
|
|
59
67
|
| --- | --- |
|
|
60
68
|
| 0.9.1 and later | `>=0.6.1 <0.7.0` |
|
package/dist/cancellation.js
CHANGED
|
@@ -4,9 +4,10 @@ exports.CancelledError = void 0;
|
|
|
4
4
|
exports.exitCodeForSignal = exitCodeForSignal;
|
|
5
5
|
const node_os_1 = require("node:os");
|
|
6
6
|
const cli_1 = require("@antelopejs/core/cli");
|
|
7
|
+
const guards_1 = require("./internal/guards");
|
|
7
8
|
function exitCodeForSignal(signal) {
|
|
8
9
|
const number = node_os_1.constants.signals[signal];
|
|
9
|
-
return 128 + (
|
|
10
|
+
return 128 + ((0, guards_1.isNumber)(number) ? number : 15);
|
|
10
11
|
}
|
|
11
12
|
class CancelledError extends Error {
|
|
12
13
|
constructor(signal, stopped = "Stopped", context) {
|
package/dist/config.js
CHANGED
|
@@ -50,15 +50,18 @@ exports.TEMPLATE_FILES = [
|
|
|
50
50
|
["index.html", "index.html"],
|
|
51
51
|
["main.ts", "main.ts"],
|
|
52
52
|
["app-runtime.ts", "app-runtime.ts"],
|
|
53
|
+
["message-subset.ts", "message-subset.ts"],
|
|
53
54
|
["network-error.ts", "network-error.ts"],
|
|
54
55
|
["ui-app-config.ts", "ui-app-config.ts"],
|
|
55
56
|
["layer-app-config.ts", "layer-app-config.ts"],
|
|
56
57
|
["ssr-renderer.ts", "ssr-renderer.ts"],
|
|
57
58
|
["frontend-module.ts", "frontend-module.ts"],
|
|
59
|
+
["frontend-runtime", "frontend-runtime"],
|
|
58
60
|
["frontend-build.ts", "frontend-build.ts"],
|
|
59
61
|
["frontend-build-loader.ts", "frontend-build-loader.ts"],
|
|
60
62
|
["server-module.ts", "server-module.ts"],
|
|
61
63
|
["icon-hydration.ts", "icon-hydration.ts"],
|
|
64
|
+
["icon-bundle.ts", "icon-bundle.ts"],
|
|
62
65
|
["globals.d.ts", "globals.d.ts"],
|
|
63
66
|
["compress-assets.mjs", "compress-assets.mjs"],
|
|
64
67
|
["head-order.mjs", "head-order.mjs"],
|
|
@@ -71,6 +74,7 @@ exports.TEMPLATE_FILES = [
|
|
|
71
74
|
["icon-api.mjs", "icon-api.mjs"],
|
|
72
75
|
["icon-scan.mjs", "icon-scan.mjs"],
|
|
73
76
|
["ui-kbd.mjs", "ui-kbd.mjs"],
|
|
77
|
+
["ui-lazy-icons.mjs", "ui-lazy-icons.mjs"],
|
|
74
78
|
["email-renderer.ts", "email-renderer.ts"],
|
|
75
79
|
["email-runtime.ts", "email-runtime.ts"],
|
|
76
80
|
["email-locales.ts", "email-locales.ts"],
|
|
@@ -202,16 +206,16 @@ exports.Options = {
|
|
|
202
206
|
};
|
|
203
207
|
const HEADER_SAFE_CREDENTIAL = /^[\x21-\x7e]+$/;
|
|
204
208
|
const HEADER_UNSAFE_CHARACTER = /[^\x21-\x7e]/u;
|
|
205
|
-
const UNSAFE_CHARACTER_NAMES =
|
|
206
|
-
" "
|
|
207
|
-
"\t"
|
|
208
|
-
"\r"
|
|
209
|
-
"\n"
|
|
210
|
-
|
|
209
|
+
const UNSAFE_CHARACTER_NAMES = new Map([
|
|
210
|
+
[" ", "a space"],
|
|
211
|
+
["\t", "a tab"],
|
|
212
|
+
["\r", "a line break"],
|
|
213
|
+
["\n", "a line break"],
|
|
214
|
+
]);
|
|
211
215
|
const LAST_ASCII_CODE_POINT = 0x7f;
|
|
212
216
|
function describeUnsafeCharacter(value) {
|
|
213
217
|
const char = HEADER_UNSAFE_CHARACTER.exec(value)?.[0] ?? "";
|
|
214
|
-
const named = UNSAFE_CHARACTER_NAMES
|
|
218
|
+
const named = UNSAFE_CHARACTER_NAMES.get(char);
|
|
215
219
|
if (named)
|
|
216
220
|
return named;
|
|
217
221
|
return (char.codePointAt(0) ?? 0) > LAST_ASCII_CODE_POINT
|
package/dist/derived-outputs.js
CHANGED
|
@@ -14,6 +14,7 @@ const layer_aliases_1 = require("./layer-aliases");
|
|
|
14
14
|
const layers_1 = require("./layers");
|
|
15
15
|
const project_modules_1 = require("./project-modules");
|
|
16
16
|
const fs_sync_1 = require("./fs-sync");
|
|
17
|
+
const locale_catalogs_1 = require("./internal/locale-catalogs");
|
|
17
18
|
const GENERATED_MODULE_ID = /^[A-Za-z0-9_-]+$/;
|
|
18
19
|
function validateFrontendModuleRegistry(registry, workspaceDir) {
|
|
19
20
|
const ids = new Set();
|
|
@@ -136,20 +137,6 @@ function discoverAssets(registry, directory, extensions) {
|
|
|
136
137
|
});
|
|
137
138
|
});
|
|
138
139
|
}
|
|
139
|
-
function isRecord(value) {
|
|
140
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
141
|
-
}
|
|
142
|
-
function mergeLocaleMessages(source, existing) {
|
|
143
|
-
const merged = { ...source };
|
|
144
|
-
for (const [key, value] of Object.entries(existing)) {
|
|
145
|
-
const sourceValue = merged[key];
|
|
146
|
-
merged[key] =
|
|
147
|
-
isRecord(sourceValue) && isRecord(value)
|
|
148
|
-
? mergeLocaleMessages(sourceValue, value)
|
|
149
|
-
: value;
|
|
150
|
-
}
|
|
151
|
-
return merged;
|
|
152
|
-
}
|
|
153
140
|
const LOCALE_DIRECTORY = "i18n/locales";
|
|
154
141
|
function readLocaleMessages(assets, registry) {
|
|
155
142
|
const roots = new Map(registry.modules.map((module) => [module.id, module.root]));
|
|
@@ -160,107 +147,13 @@ function readLocaleMessages(assets, registry) {
|
|
|
160
147
|
if (!locale || !root)
|
|
161
148
|
continue;
|
|
162
149
|
const value = (0, locale_files_1.readLocaleFile)((0, node_path_1.join)(root, asset.relativePath));
|
|
163
|
-
messages[locale] = mergeLocaleMessages(value, messages[locale] ?? {});
|
|
150
|
+
messages[locale] = (0, locale_catalogs_1.mergeLocaleMessages)(value, messages[locale] ?? {});
|
|
164
151
|
}
|
|
165
152
|
return messages;
|
|
166
153
|
}
|
|
167
154
|
function affectsLocaleMessages(relativePath) {
|
|
168
155
|
return (0, asset_roots_1.affectsAssetDirectory)(LOCALE_DIRECTORY, relativePath);
|
|
169
156
|
}
|
|
170
|
-
const FALLBACK_LOCALE = "en";
|
|
171
|
-
const RENDERER_TRANSLATED_KEYS = ["error.network"];
|
|
172
|
-
function withoutMessage(messages, key) {
|
|
173
|
-
const [head, ...rest] = key.split(".");
|
|
174
|
-
if (!(head in messages))
|
|
175
|
-
return messages;
|
|
176
|
-
const { [head]: value, ...others } = messages;
|
|
177
|
-
if (!rest.length)
|
|
178
|
-
return others;
|
|
179
|
-
if (!isRecord(value))
|
|
180
|
-
return messages;
|
|
181
|
-
const remaining = withoutMessage(value, rest.join("."));
|
|
182
|
-
return Object.keys(remaining).length
|
|
183
|
-
? { ...others, [head]: remaining }
|
|
184
|
-
: others;
|
|
185
|
-
}
|
|
186
|
-
function localeModuleSource(supportedLocales) {
|
|
187
|
-
const loaders = supportedLocales.map((locale) => ` ${JSON.stringify(locale)}: () => import(${JSON.stringify(`./locales.generated/${locale}`)}),`);
|
|
188
|
-
const fallback = supportedLocales.includes(FALLBACK_LOCALE)
|
|
189
|
-
? FALLBACK_LOCALE
|
|
190
|
-
: supportedLocales[0];
|
|
191
|
-
return `type LocaleMessages = Record<string, unknown>;
|
|
192
|
-
type LocaleLoader = () => Promise<{ default: LocaleMessages }>;
|
|
193
|
-
interface LocaleMessagesTarget {
|
|
194
|
-
setLocaleMessage(locale: string, messages: LocaleMessages): void;
|
|
195
|
-
}
|
|
196
|
-
interface LocaleState {
|
|
197
|
-
messages: Record<string, LocaleMessages>;
|
|
198
|
-
targets: Set<LocaleMessagesTarget>;
|
|
199
|
-
version: number;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
export const supportedLocales = ${JSON.stringify(supportedLocales)};
|
|
203
|
-
const fallbackLocale: string | undefined = ${JSON.stringify(fallback)};
|
|
204
|
-
const localeLoaders: Record<string, LocaleLoader> = {
|
|
205
|
-
${loaders.join("\n")}
|
|
206
|
-
};
|
|
207
|
-
const shared: LocaleState | undefined = import.meta.hot?.data.state;
|
|
208
|
-
const state: LocaleState = shared ?? {
|
|
209
|
-
messages: {},
|
|
210
|
-
targets: new Set(),
|
|
211
|
-
version: 0,
|
|
212
|
-
};
|
|
213
|
-
export const localeMessages = state.messages;
|
|
214
|
-
|
|
215
|
-
async function readLocaleMessages(locale: string): Promise<LocaleMessages> {
|
|
216
|
-
return (await localeLoaders[locale]()).default;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* The catalog that serves \`locale\`: its own when the application has one,
|
|
221
|
-
* else the fallback locale's.
|
|
222
|
-
*/
|
|
223
|
-
export function catalogLocale(locale: string): string | undefined {
|
|
224
|
-
const normalized = locale.slice(0, 2);
|
|
225
|
-
return normalized in localeLoaders ? normalized : fallbackLocale;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
export async function loadLocaleMessages(locale: string): Promise<LocaleMessages> {
|
|
229
|
-
const catalog = catalogLocale(locale);
|
|
230
|
-
if (!catalog) return {};
|
|
231
|
-
localeMessages[catalog] ??= await readLocaleMessages(catalog);
|
|
232
|
-
return localeMessages[catalog];
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/** Development only: applies every regenerated catalog to \`target\`. */
|
|
236
|
-
export function syncLocaleMessages(target: LocaleMessagesTarget): void {
|
|
237
|
-
if (import.meta.hot) state.targets.add(target);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
async function refreshLocaleMessages(): Promise<void> {
|
|
241
|
-
const version = ++state.version;
|
|
242
|
-
const locales = Object.keys(localeMessages).filter(
|
|
243
|
-
(locale) => locale in localeLoaders,
|
|
244
|
-
);
|
|
245
|
-
const catalogs = await Promise.all(locales.map(readLocaleMessages));
|
|
246
|
-
if (version !== state.version) return;
|
|
247
|
-
locales.forEach((locale, index) => {
|
|
248
|
-
localeMessages[locale] = catalogs[index];
|
|
249
|
-
for (const target of state.targets)
|
|
250
|
-
target.setLocaleMessage(locale, catalogs[index]);
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
if (import.meta.hot) {
|
|
255
|
-
import.meta.hot.data.state = state;
|
|
256
|
-
if (shared) void refreshLocaleMessages();
|
|
257
|
-
import.meta.hot.accept((next) => {
|
|
258
|
-
if (next?.supportedLocales.join() !== supportedLocales.join())
|
|
259
|
-
import.meta.hot?.invalidate("the list of locales changed");
|
|
260
|
-
});
|
|
261
|
-
}
|
|
262
|
-
`;
|
|
263
|
-
}
|
|
264
157
|
function writeLocaleMessages(workspaceDir, registry) {
|
|
265
158
|
const locales = discoverAssets(registry, LOCALE_DIRECTORY, [".json"]);
|
|
266
159
|
const messages = readLocaleMessages(locales, registry);
|
|
@@ -271,19 +164,19 @@ function writeLocaleMessages(workspaceDir, registry) {
|
|
|
271
164
|
changed = (0, fs_sync_1.applyContent)(content, path) || changed;
|
|
272
165
|
};
|
|
273
166
|
(0, node_fs_1.mkdirSync)(outputDir, { recursive: true });
|
|
274
|
-
const fallback = RENDERER_TRANSLATED_KEYS.reduce(withoutMessage, messages[FALLBACK_LOCALE] ?? {});
|
|
167
|
+
const fallback = locale_catalogs_1.RENDERER_TRANSLATED_KEYS.reduce(locale_catalogs_1.withoutMessage, messages[locale_catalogs_1.FALLBACK_LOCALE] ?? {});
|
|
275
168
|
for (const [locale, value] of Object.entries(messages)) {
|
|
276
169
|
const catalog = JSON.stringify(value);
|
|
277
|
-
const complete = locale === FALLBACK_LOCALE
|
|
170
|
+
const complete = locale === locale_catalogs_1.FALLBACK_LOCALE
|
|
278
171
|
? catalog
|
|
279
|
-
: JSON.stringify(mergeLocaleMessages(fallback, value));
|
|
172
|
+
: JSON.stringify((0, locale_catalogs_1.mergeLocaleMessages)(fallback, value));
|
|
280
173
|
apply(catalog, (0, node_path_1.join)(outputDir, `${locale}.json`));
|
|
281
174
|
apply(`const messages = ${complete};\nexport default messages;\n`, (0, node_path_1.join)(outputDir, `${locale}.ts`));
|
|
282
175
|
outputs.add(`${locale}.json`).add(`${locale}.ts`);
|
|
283
176
|
}
|
|
284
177
|
const supportedLocales = Object.keys(messages);
|
|
285
178
|
apply(JSON.stringify(supportedLocales), (0, node_path_1.join)(workspaceDir, "email-locales.generated.json"));
|
|
286
|
-
apply(localeModuleSource(supportedLocales), (0, node_path_1.join)(workspaceDir, "locales.generated.ts"));
|
|
179
|
+
apply((0, locale_catalogs_1.localeModuleSource)(supportedLocales), (0, node_path_1.join)(workspaceDir, "locales.generated.ts"));
|
|
287
180
|
for (const name of (0, node_fs_1.readdirSync)(outputDir)) {
|
|
288
181
|
if (outputs.has(name))
|
|
289
182
|
continue;
|
package/dist/dev-modules.js
CHANGED
|
@@ -6,6 +6,7 @@ exports.withBackendValues = withBackendValues;
|
|
|
6
6
|
const node_child_process_1 = require("node:child_process");
|
|
7
7
|
const cli_1 = require("@antelopejs/core/cli");
|
|
8
8
|
const private_values_1 = require("./private-values");
|
|
9
|
+
const guards_1 = require("./internal/guards");
|
|
9
10
|
function readProjectModulesFresh(options) {
|
|
10
11
|
return new Promise((resolve, reject) => {
|
|
11
12
|
const child = (0, node_child_process_1.fork)(require.resolve("./project-modules-child"), [], {
|
|
@@ -48,11 +49,11 @@ function rewriteOrigins(options, rewrites) {
|
|
|
48
49
|
.join("|");
|
|
49
50
|
const pattern = new RegExp(`(?:${alternation})${URL_BOUNDARY}`, "g");
|
|
50
51
|
const rewrite = (value) => {
|
|
51
|
-
if (
|
|
52
|
+
if ((0, guards_1.isText)(value))
|
|
52
53
|
return value.replace(pattern, (match) => replacements.get(match) ?? match);
|
|
53
54
|
if (Array.isArray(value))
|
|
54
55
|
return value.map(rewrite);
|
|
55
|
-
if (
|
|
56
|
+
if ((0, guards_1.isObjectLike)(value))
|
|
56
57
|
return rewriteObject(value);
|
|
57
58
|
return value;
|
|
58
59
|
};
|
package/dist/discovery.js
CHANGED
|
@@ -9,6 +9,7 @@ exports.readDevBootstrapCredential = readDevBootstrapCredential;
|
|
|
9
9
|
const node_fs_1 = require("node:fs");
|
|
10
10
|
const node_path_1 = require("node:path");
|
|
11
11
|
const output_1 = require("./output");
|
|
12
|
+
const guards_1 = require("./internal/guards");
|
|
12
13
|
exports.DEV_REGISTRY_RELATIVE_PATH = (0, node_path_1.join)(".antelope", "dev.json");
|
|
13
14
|
function isPidAlive(pid) {
|
|
14
15
|
if (!Number.isInteger(pid) || pid <= 0)
|
|
@@ -21,15 +22,18 @@ function isPidAlive(pid) {
|
|
|
21
22
|
return err?.code === "EPERM";
|
|
22
23
|
}
|
|
23
24
|
}
|
|
25
|
+
function isDevRegistry(value) {
|
|
26
|
+
return ((0, guards_1.isObjectLike)(value) &&
|
|
27
|
+
"pid" in value &&
|
|
28
|
+
typeof value.pid === "number" &&
|
|
29
|
+
"servers" in value &&
|
|
30
|
+
typeof value.servers === "object" &&
|
|
31
|
+
value.servers !== null);
|
|
32
|
+
}
|
|
24
33
|
function parseRegistry(file) {
|
|
25
34
|
try {
|
|
26
35
|
const parsed = JSON.parse((0, node_fs_1.readFileSync)(file, "utf-8"));
|
|
27
|
-
|
|
28
|
-
typeof parsed?.servers !== "object" ||
|
|
29
|
-
parsed.servers === null) {
|
|
30
|
-
return undefined;
|
|
31
|
-
}
|
|
32
|
-
return parsed;
|
|
36
|
+
return isDevRegistry(parsed) ? parsed : undefined;
|
|
33
37
|
}
|
|
34
38
|
catch {
|
|
35
39
|
return undefined;
|
|
@@ -114,15 +118,18 @@ function describeDiscoveryFailure(result) {
|
|
|
114
118
|
}
|
|
115
119
|
}
|
|
116
120
|
exports.DEV_HANDSHAKE_RELATIVE_PATH = (0, node_path_1.join)(".antelope", "dms-dev.json");
|
|
121
|
+
function isDevHandshake(value) {
|
|
122
|
+
return ((0, guards_1.isObjectLike)(value) &&
|
|
123
|
+
"pid" in value &&
|
|
124
|
+
typeof value.pid === "number" &&
|
|
125
|
+
"bootstrapSecret" in value &&
|
|
126
|
+
typeof value.bootstrapSecret === "string" &&
|
|
127
|
+
value.bootstrapSecret !== "");
|
|
128
|
+
}
|
|
117
129
|
function parseHandshake(file) {
|
|
118
130
|
try {
|
|
119
131
|
const parsed = JSON.parse((0, node_fs_1.readFileSync)(file, "utf-8"));
|
|
120
|
-
|
|
121
|
-
typeof parsed?.bootstrapSecret !== "string" ||
|
|
122
|
-
!parsed.bootstrapSecret) {
|
|
123
|
-
return undefined;
|
|
124
|
-
}
|
|
125
|
-
return parsed;
|
|
132
|
+
return isDevHandshake(parsed) ? parsed : undefined;
|
|
126
133
|
}
|
|
127
134
|
catch {
|
|
128
135
|
return undefined;
|
package/dist/fs-sync.js
CHANGED
|
@@ -68,8 +68,7 @@ function applyContent(content, destPath) {
|
|
|
68
68
|
if ((0, node_fs_1.readFileSync)(destPath).equals(buf))
|
|
69
69
|
return false;
|
|
70
70
|
}
|
|
71
|
-
catch {
|
|
72
|
-
}
|
|
71
|
+
catch { }
|
|
73
72
|
}
|
|
74
73
|
(0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(destPath), { recursive: true });
|
|
75
74
|
const tmp = `${destPath}.ajs-dms-tmp-${process.pid}-${Date.now()}`;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function isText(value: unknown): value is string;
|
|
2
|
+
export declare function isNumber(value: unknown): value is number;
|
|
3
|
+
export declare function isFlag(value: unknown): value is boolean;
|
|
4
|
+
export declare function isCallable(value: unknown): value is (...args: never[]) => void;
|
|
5
|
+
export declare function isObjectLike(value: unknown): value is object;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isText = isText;
|
|
4
|
+
exports.isNumber = isNumber;
|
|
5
|
+
exports.isFlag = isFlag;
|
|
6
|
+
exports.isCallable = isCallable;
|
|
7
|
+
exports.isObjectLike = isObjectLike;
|
|
8
|
+
function isText(value) {
|
|
9
|
+
return typeof value === "string";
|
|
10
|
+
}
|
|
11
|
+
function isNumber(value) {
|
|
12
|
+
return typeof value === "number";
|
|
13
|
+
}
|
|
14
|
+
function isFlag(value) {
|
|
15
|
+
return typeof value === "boolean";
|
|
16
|
+
}
|
|
17
|
+
function isCallable(value) {
|
|
18
|
+
return typeof value === "function";
|
|
19
|
+
}
|
|
20
|
+
function isObjectLike(value) {
|
|
21
|
+
return typeof value === "object" && value !== null;
|
|
22
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function isRecord(value: unknown): value is Record<string, unknown>;
|
|
2
|
+
export declare function mergeLocaleMessages(source: Record<string, unknown>, existing: Record<string, unknown>): Record<string, unknown>;
|
|
3
|
+
export declare const FALLBACK_LOCALE = "en";
|
|
4
|
+
export declare const RENDERER_TRANSLATED_KEYS: string[];
|
|
5
|
+
export declare function withoutMessage(messages: Record<string, unknown>, key: string): Record<string, unknown>;
|
|
6
|
+
export declare function localeModuleSource(supportedLocales: string[]): string;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RENDERER_TRANSLATED_KEYS = exports.FALLBACK_LOCALE = void 0;
|
|
4
|
+
exports.isRecord = isRecord;
|
|
5
|
+
exports.mergeLocaleMessages = mergeLocaleMessages;
|
|
6
|
+
exports.withoutMessage = withoutMessage;
|
|
7
|
+
exports.localeModuleSource = localeModuleSource;
|
|
8
|
+
function isRecord(value) {
|
|
9
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
10
|
+
}
|
|
11
|
+
function mergeLocaleMessages(source, existing) {
|
|
12
|
+
const merged = { ...source };
|
|
13
|
+
for (const [key, value] of Object.entries(existing)) {
|
|
14
|
+
const sourceValue = merged[key];
|
|
15
|
+
merged[key] =
|
|
16
|
+
isRecord(sourceValue) && isRecord(value)
|
|
17
|
+
? mergeLocaleMessages(sourceValue, value)
|
|
18
|
+
: value;
|
|
19
|
+
}
|
|
20
|
+
return merged;
|
|
21
|
+
}
|
|
22
|
+
exports.FALLBACK_LOCALE = "en";
|
|
23
|
+
exports.RENDERER_TRANSLATED_KEYS = ["error.network"];
|
|
24
|
+
function withoutMessage(messages, key) {
|
|
25
|
+
const [head, ...rest] = key.split(".");
|
|
26
|
+
if (!(head in messages))
|
|
27
|
+
return messages;
|
|
28
|
+
const { [head]: value, ...others } = messages;
|
|
29
|
+
if (!rest.length)
|
|
30
|
+
return others;
|
|
31
|
+
if (!isRecord(value))
|
|
32
|
+
return messages;
|
|
33
|
+
const remaining = withoutMessage(value, rest.join("."));
|
|
34
|
+
return Object.keys(remaining).length
|
|
35
|
+
? { ...others, [head]: remaining }
|
|
36
|
+
: others;
|
|
37
|
+
}
|
|
38
|
+
function localeModuleSource(supportedLocales) {
|
|
39
|
+
const loaders = supportedLocales.map((locale) => ` ${JSON.stringify(locale)}: () => import(${JSON.stringify(`./locales.generated/${locale}`)}),`);
|
|
40
|
+
const fallback = supportedLocales.includes(exports.FALLBACK_LOCALE)
|
|
41
|
+
? exports.FALLBACK_LOCALE
|
|
42
|
+
: supportedLocales[0];
|
|
43
|
+
return `type LocaleMessages = Record<string, unknown>;
|
|
44
|
+
type LocaleLoader = () => Promise<{ default: LocaleMessages }>;
|
|
45
|
+
interface LocaleMessagesTarget {
|
|
46
|
+
setLocaleMessage(locale: string, messages: LocaleMessages): void;
|
|
47
|
+
}
|
|
48
|
+
interface LocaleState {
|
|
49
|
+
messages: Record<string, LocaleMessages>;
|
|
50
|
+
targets: Set<LocaleMessagesTarget>;
|
|
51
|
+
version: number;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export const supportedLocales = ${JSON.stringify(supportedLocales)};
|
|
55
|
+
const fallbackLocale: string | undefined = ${JSON.stringify(fallback)};
|
|
56
|
+
const localeLoaders: Record<string, LocaleLoader> = {
|
|
57
|
+
${loaders.join("\n")}
|
|
58
|
+
};
|
|
59
|
+
const shared: LocaleState | undefined = import.meta.hot?.data.state;
|
|
60
|
+
const state: LocaleState = shared ?? {
|
|
61
|
+
messages: {},
|
|
62
|
+
targets: new Set(),
|
|
63
|
+
version: 0,
|
|
64
|
+
};
|
|
65
|
+
export const localeMessages = state.messages;
|
|
66
|
+
|
|
67
|
+
async function readLocaleMessages(locale: string): Promise<LocaleMessages> {
|
|
68
|
+
return (await localeLoaders[locale]()).default;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* The catalog that serves \`locale\`: its own when the application has one,
|
|
73
|
+
* else the fallback locale's.
|
|
74
|
+
*/
|
|
75
|
+
export function catalogLocale(locale: string): string | undefined {
|
|
76
|
+
const normalized = locale.slice(0, 2);
|
|
77
|
+
return normalized in localeLoaders ? normalized : fallbackLocale;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export async function loadLocaleMessages(locale: string): Promise<LocaleMessages> {
|
|
81
|
+
const catalog = catalogLocale(locale);
|
|
82
|
+
if (!catalog) return {};
|
|
83
|
+
localeMessages[catalog] ??= await readLocaleMessages(catalog);
|
|
84
|
+
return localeMessages[catalog];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Development only: applies every regenerated catalog to \`target\`. */
|
|
88
|
+
export function syncLocaleMessages(target: LocaleMessagesTarget): void {
|
|
89
|
+
if (import.meta.hot) state.targets.add(target);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async function refreshLocaleMessages(): Promise<void> {
|
|
93
|
+
const version = ++state.version;
|
|
94
|
+
const locales = Object.keys(localeMessages).filter(
|
|
95
|
+
(locale) => locale in localeLoaders,
|
|
96
|
+
);
|
|
97
|
+
const catalogs = await Promise.all(locales.map(readLocaleMessages));
|
|
98
|
+
if (version !== state.version) return;
|
|
99
|
+
locales.forEach((locale, index) => {
|
|
100
|
+
localeMessages[locale] = catalogs[index];
|
|
101
|
+
for (const target of state.targets)
|
|
102
|
+
target.setLocaleMessage(locale, catalogs[index]);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (import.meta.hot) {
|
|
107
|
+
import.meta.hot.data.state = state;
|
|
108
|
+
if (shared) void refreshLocaleMessages();
|
|
109
|
+
import.meta.hot.accept((next) => {
|
|
110
|
+
if (next?.supportedLocales.join() !== supportedLocales.join())
|
|
111
|
+
import.meta.hot?.invalidate("the list of locales changed");
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
`;
|
|
115
|
+
}
|
package/dist/layer-aliases.js
CHANGED
|
@@ -7,6 +7,7 @@ exports.frontendLayerTypePaths = frontendLayerTypePaths;
|
|
|
7
7
|
const node_fs_1 = require("node:fs");
|
|
8
8
|
const node_path_1 = require("node:path");
|
|
9
9
|
const fs_sync_1 = require("./fs-sync");
|
|
10
|
+
const guards_1 = require("./internal/guards");
|
|
10
11
|
exports.MODULE_LAYERS_DIRNAME = "layers";
|
|
11
12
|
const LAYER_ALIAS_PREFIX = "#";
|
|
12
13
|
function isDirectory(path) {
|
|
@@ -30,7 +31,7 @@ function readModuleLayers(moduleRoot) {
|
|
|
30
31
|
.filter((layer) => isDirectory(layer.directory));
|
|
31
32
|
}
|
|
32
33
|
function resolveFrontendLayers(moduleRoots) {
|
|
33
|
-
const roots =
|
|
34
|
+
const roots = (0, guards_1.isText)(moduleRoots) ? [moduleRoots] : moduleRoots;
|
|
34
35
|
const layers = new Map();
|
|
35
36
|
for (const root of roots) {
|
|
36
37
|
for (const layer of readModuleLayers(root)) {
|
package/dist/layers.js
CHANGED
|
@@ -11,6 +11,7 @@ const cli_1 = require("@antelopejs/core/cli");
|
|
|
11
11
|
const manifest_1 = require("./manifest");
|
|
12
12
|
const config_1 = require("./config");
|
|
13
13
|
const output_1 = require("./output");
|
|
14
|
+
const guards_1 = require("./internal/guards");
|
|
14
15
|
const BUILD_FIX = "A remote or production backend never sends them: build the frontend from the project instead, with `ajs dms build`";
|
|
15
16
|
function assertLayerPathsServed(modules, backendUrl, { bootstrapSecret, cache } = {}) {
|
|
16
17
|
const pathless = modules.filter((mod) => !mod.path);
|
|
@@ -63,7 +64,7 @@ function readLayerPackage(layerPath) {
|
|
|
63
64
|
}
|
|
64
65
|
function readLayerPackageName(layerPath) {
|
|
65
66
|
const name = readLayerPackage(layerPath)?.name;
|
|
66
|
-
return
|
|
67
|
+
return (0, guards_1.isText)(name) ? name : undefined;
|
|
67
68
|
}
|
|
68
69
|
function resolveLayer(layerPath, mod) {
|
|
69
70
|
return {
|
package/dist/locale-files.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.InvalidLocaleFileError = void 0;
|
|
|
4
4
|
exports.readLocaleFile = readLocaleFile;
|
|
5
5
|
const node_fs_1 = require("node:fs");
|
|
6
6
|
const message_compiler_1 = require("@intlify/message-compiler");
|
|
7
|
+
const guards_1 = require("./internal/guards");
|
|
7
8
|
class InvalidLocaleFileError extends Error {
|
|
8
9
|
constructor(path, reason) {
|
|
9
10
|
super(`Invalid locale file ${path}: ${reason}`);
|
|
@@ -19,10 +20,14 @@ const LITERAL_ESCAPES = {
|
|
|
19
20
|
"}": "{'}'}",
|
|
20
21
|
"|": "{'|'}",
|
|
21
22
|
};
|
|
23
|
+
function isReservedCharacter(character) {
|
|
24
|
+
return Object.prototype.hasOwnProperty.call(LITERAL_ESCAPES, character);
|
|
25
|
+
}
|
|
22
26
|
function reservedCharacterAt(message, offset) {
|
|
23
27
|
for (let index = Math.min(offset, message.length - 1); index >= 0; index--) {
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
const character = message[index];
|
|
29
|
+
if (isReservedCharacter(character))
|
|
30
|
+
return character;
|
|
26
31
|
}
|
|
27
32
|
return null;
|
|
28
33
|
}
|
|
@@ -46,11 +51,11 @@ function firstCompileError(message) {
|
|
|
46
51
|
return first;
|
|
47
52
|
}
|
|
48
53
|
function messageProblems(value, key) {
|
|
49
|
-
if (
|
|
54
|
+
if ((0, guards_1.isText)(value)) {
|
|
50
55
|
const error = firstCompileError(value);
|
|
51
56
|
return error ? [{ key, message: value, error }] : [];
|
|
52
57
|
}
|
|
53
|
-
if (
|
|
58
|
+
if (!(0, guards_1.isObjectLike)(value))
|
|
54
59
|
return [];
|
|
55
60
|
return Object.entries(value).flatMap(([child, nested]) => messageProblems(nested, key ? `${key}.${child}` : child));
|
|
56
61
|
}
|
package/dist/manifest-secrets.js
CHANGED
|
@@ -7,11 +7,15 @@ exports.formatSecretConflicts = formatSecretConflicts;
|
|
|
7
7
|
exports.describeSecretSources = describeSecretSources;
|
|
8
8
|
exports.reportManifestSecrets = reportManifestSecrets;
|
|
9
9
|
const cli_1 = require("@antelopejs/core/cli");
|
|
10
|
+
const guards_1 = require("./internal/guards");
|
|
10
11
|
exports.MANIFEST_SECRET_ENV = {
|
|
11
12
|
DMS_HTML_RENDER_SECRET: ["htmlRender", "serviceSecret"],
|
|
12
13
|
DMS_OAUTH_RELAY_SECRET: ["oauth", "relaySecret"],
|
|
13
14
|
};
|
|
14
|
-
|
|
15
|
+
function isSecretName(name) {
|
|
16
|
+
return Object.prototype.hasOwnProperty.call(exports.MANIFEST_SECRET_ENV, name);
|
|
17
|
+
}
|
|
18
|
+
const SECRET_NAMES = Object.keys(exports.MANIFEST_SECRET_ENV).filter(isSecretName);
|
|
15
19
|
const UNSET_CONSEQUENCE = {
|
|
16
20
|
DMS_HTML_RENDER_SECRET: "e-mail renders will be refused",
|
|
17
21
|
DMS_OAUTH_RELAY_SECRET: "OAuth sign-in will be refused by the backend",
|
|
@@ -19,7 +23,7 @@ const UNSET_CONSEQUENCE = {
|
|
|
19
23
|
function readPath(options, path) {
|
|
20
24
|
let value = options;
|
|
21
25
|
for (const key of path) {
|
|
22
|
-
if (!
|
|
26
|
+
if (!(0, guards_1.isObjectLike)(value) || Array.isArray(value))
|
|
23
27
|
return undefined;
|
|
24
28
|
value = value[key];
|
|
25
29
|
}
|
|
@@ -36,7 +40,7 @@ function collectManifestSecrets(modules) {
|
|
|
36
40
|
const ignored = [];
|
|
37
41
|
for (const module of ordered) {
|
|
38
42
|
const value = readPath(module.privateOptions, exports.MANIFEST_SECRET_ENV[name]);
|
|
39
|
-
if (
|
|
43
|
+
if (!(0, guards_1.isText)(value) || value === "")
|
|
40
44
|
continue;
|
|
41
45
|
const first = published[name];
|
|
42
46
|
if (!first)
|
|
@@ -53,7 +57,10 @@ function collectManifestSecrets(modules) {
|
|
|
53
57
|
function resolveManifestSecrets(secrets, env = process.env) {
|
|
54
58
|
const resolved = {
|
|
55
59
|
env: {},
|
|
56
|
-
sources: {
|
|
60
|
+
sources: {
|
|
61
|
+
DMS_HTML_RENDER_SECRET: "not set",
|
|
62
|
+
DMS_OAUTH_RELAY_SECRET: "not set",
|
|
63
|
+
},
|
|
57
64
|
conflicts: [],
|
|
58
65
|
};
|
|
59
66
|
for (const name of SECRET_NAMES) {
|
package/dist/manifest.js
CHANGED
|
@@ -16,6 +16,7 @@ const cli_1 = require("@antelopejs/core/cli");
|
|
|
16
16
|
const config_1 = require("./config");
|
|
17
17
|
const output_1 = require("./output");
|
|
18
18
|
const workspace_1 = require("./workspace");
|
|
19
|
+
const guards_1 = require("./internal/guards");
|
|
19
20
|
class ManifestUnauthorizedError extends cli_1.CliError {
|
|
20
21
|
constructor(url, status, credentialSent) {
|
|
21
22
|
super({
|
|
@@ -44,7 +45,7 @@ const UNREACHABLE_REASONS = {
|
|
|
44
45
|
const UNKNOWN_HOST_CODES = ["ENOTFOUND", "EAI_AGAIN"];
|
|
45
46
|
class BackendUnreachableError extends cli_1.CliError {
|
|
46
47
|
constructor(url, failure) {
|
|
47
|
-
const cause = failure
|
|
48
|
+
const cause = (hasProperties(failure) ? failure.cause : undefined) ?? failure;
|
|
48
49
|
const code = errorCode(cause);
|
|
49
50
|
const detail = code
|
|
50
51
|
? (UNREACHABLE_REASONS[code] ?? errorMessage(cause))
|
|
@@ -63,9 +64,14 @@ class BackendUnreachableError extends cli_1.CliError {
|
|
|
63
64
|
}
|
|
64
65
|
}
|
|
65
66
|
exports.BackendUnreachableError = BackendUnreachableError;
|
|
67
|
+
function hasProperties(value) {
|
|
68
|
+
return (value !== null && (typeof value === "object" || typeof value === "function"));
|
|
69
|
+
}
|
|
66
70
|
function errorCode(err) {
|
|
67
|
-
|
|
68
|
-
|
|
71
|
+
if (!hasProperties(err))
|
|
72
|
+
return undefined;
|
|
73
|
+
const { code, errors } = err;
|
|
74
|
+
if ((0, guards_1.isText)(code))
|
|
69
75
|
return code;
|
|
70
76
|
return Array.isArray(errors) ? errorCode(errors[0]) : undefined;
|
|
71
77
|
}
|
|
@@ -101,7 +107,7 @@ async function fetchFromBackend(backendUrl, url, bootstrapSecret) {
|
|
|
101
107
|
}
|
|
102
108
|
class ManifestRefusedError extends cli_1.CliError {
|
|
103
109
|
constructor(problem) {
|
|
104
|
-
super(
|
|
110
|
+
super((0, guards_1.isText)(problem) ? { title: problem } : problem);
|
|
105
111
|
this.name = "ManifestRefusedError";
|
|
106
112
|
}
|
|
107
113
|
}
|
|
@@ -112,7 +118,7 @@ const LOADER_UPDATE_COMMAND = "ajs update dms";
|
|
|
112
118
|
function describeManifestVersion(version) {
|
|
113
119
|
const loader = `${OWN_RELEASE.name} ${OWN_RELEASE.version}`;
|
|
114
120
|
const supported = `This loader reads version ${workspace_1.FRONTEND_MANIFEST_VERSION}`;
|
|
115
|
-
if (
|
|
121
|
+
if (!(0, guards_1.isNumber)(version)) {
|
|
116
122
|
return {
|
|
117
123
|
title: "The backend served a frontend manifest without a protocol version",
|
|
118
124
|
reason: `${supported}; the answer does not look like one from ${BACKEND_PACKAGE}.`,
|