@antelopejs/dms-frontend 0.3.1 → 0.3.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 +33 -2
- package/dist/common.d.ts +2 -0
- package/dist/common.js +2 -0
- package/dist/derived-outputs.d.ts +22 -0
- package/dist/derived-outputs.js +296 -0
- package/dist/fs-sync.d.ts +3 -2
- package/dist/fs-sync.js +49 -2
- package/dist/layer-watch.js +31 -14
- package/dist/layers.d.ts +5 -0
- package/dist/layers.js +7 -3
- package/dist/materialize.d.ts +1 -15
- package/dist/materialize.js +4 -245
- package/dist/renderer-range.d.ts +10 -0
- package/dist/renderer-range.js +55 -0
- package/dist/verify-source-runner.js +1 -0
- package/dist/workspace-setup.js +2 -0
- package/package.json +1 -1
- package/templates/vue/frontend-module.ts +123 -53
|
@@ -299,6 +299,24 @@ interface DmsPluginRegistration {
|
|
|
299
299
|
clientOnly: boolean;
|
|
300
300
|
}
|
|
301
301
|
|
|
302
|
+
/**
|
|
303
|
+
* What the frontend modules registered through their SDK. Modules are set up
|
|
304
|
+
* by descending priority, so the first one to claim a name keeps it.
|
|
305
|
+
*/
|
|
306
|
+
interface DmsFrontendRegistry {
|
|
307
|
+
components: Map<string, DmsComponentRegistration>;
|
|
308
|
+
pages: Map<string, DmsFrontendEntry>;
|
|
309
|
+
dynamicPages: Map<string, DmsFrontendEntry>;
|
|
310
|
+
layouts: Map<string, DmsFrontendEntry>;
|
|
311
|
+
errorPage?: DmsFrontendEntry;
|
|
312
|
+
plugins: Plugin[];
|
|
313
|
+
pluginSetups: DmsPluginRegistration[];
|
|
314
|
+
middleware: DmsMiddleware[];
|
|
315
|
+
namedMiddleware: Map<string, DmsMiddleware>;
|
|
316
|
+
accessRedirects: Map<string, string>;
|
|
317
|
+
injections: Map<string | symbol, unknown>;
|
|
318
|
+
}
|
|
319
|
+
|
|
302
320
|
export interface DmsFrontendRuntime {
|
|
303
321
|
sharedState: Map<string, Ref<unknown>>;
|
|
304
322
|
asyncData: Map<string, DmsAsyncData<unknown>>;
|
|
@@ -324,17 +342,25 @@ export interface DmsFrontendRuntime {
|
|
|
324
342
|
scope: EffectScope;
|
|
325
343
|
}
|
|
326
344
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
345
|
+
/** Creates the empty registry one setup of the frontend modules fills. */
|
|
346
|
+
function createDmsFrontendRegistry(): DmsFrontendRegistry {
|
|
347
|
+
return {
|
|
348
|
+
components: new Map(),
|
|
349
|
+
pages: new Map(),
|
|
350
|
+
dynamicPages: new Map(),
|
|
351
|
+
layouts: new Map(),
|
|
352
|
+
plugins: [],
|
|
353
|
+
pluginSetups: [],
|
|
354
|
+
middleware: [],
|
|
355
|
+
namedMiddleware: new Map(),
|
|
356
|
+
accessRedirects: new Map(),
|
|
357
|
+
injections: new Map(),
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// Replaced, never refilled, by each setup of the modules: see
|
|
362
|
+
// `setupFrontendModules`.
|
|
363
|
+
let registry = createDmsFrontendRegistry();
|
|
338
364
|
const runtimeConfig = ref<DmsRuntimeConfig>({
|
|
339
365
|
public: {},
|
|
340
366
|
} as DmsRuntimeConfig);
|
|
@@ -506,9 +532,9 @@ async function runMiddleware(
|
|
|
506
532
|
const declared = Array.isArray(to.meta.middleware) ? to.meta.middleware : [];
|
|
507
533
|
const metadataNames = Object.keys(to.meta).filter((name) => to.meta[name]);
|
|
508
534
|
const declaredHandlers = [...declared, ...metadataNames]
|
|
509
|
-
.map((name) => namedMiddleware.get(String(name)))
|
|
535
|
+
.map((name) => registry.namedMiddleware.get(String(name)))
|
|
510
536
|
.filter((handler): handler is DmsMiddleware => !!handler);
|
|
511
|
-
for (const handler of [...middleware, ...declaredHandlers]) {
|
|
537
|
+
for (const handler of [...registry.middleware, ...declaredHandlers]) {
|
|
512
538
|
const runWithContext = runtimeContexts.get(runtime);
|
|
513
539
|
const result = await (runWithContext
|
|
514
540
|
? runWithContext(() => handler(to, runtime.route))
|
|
@@ -913,8 +939,8 @@ export function addDmsMiddleware(
|
|
|
913
939
|
name?: string,
|
|
914
940
|
isGlobal = false,
|
|
915
941
|
): void {
|
|
916
|
-
if (isGlobal) middleware.push(handler);
|
|
917
|
-
else if (name) namedMiddleware.set(name, handler);
|
|
942
|
+
if (isGlobal) registry.middleware.push(handler);
|
|
943
|
+
else if (name) registry.namedMiddleware.set(name, handler);
|
|
918
944
|
}
|
|
919
945
|
export const useHead = useUnhead;
|
|
920
946
|
export const useSeoMeta = useUnheadSeoMeta;
|
|
@@ -1158,13 +1184,20 @@ export function useUserSession<
|
|
|
1158
1184
|
};
|
|
1159
1185
|
}
|
|
1160
1186
|
|
|
1187
|
+
function registerDmsComponentEntry(
|
|
1188
|
+
entries: Map<string, DmsComponentRegistration>,
|
|
1189
|
+
name: string,
|
|
1190
|
+
component: Component,
|
|
1191
|
+
): void {
|
|
1192
|
+
const key = normalizeDmsName(name);
|
|
1193
|
+
if (!entries.has(key)) entries.set(key, { name, component });
|
|
1194
|
+
}
|
|
1161
1195
|
/** Registers a component unless a higher-priority module already owns its name. */
|
|
1162
1196
|
export function registerDmsComponent(name: string, component: Component): void {
|
|
1163
|
-
|
|
1164
|
-
if (!components.has(key)) components.set(key, { name, component });
|
|
1197
|
+
registerDmsComponentEntry(registry.components, name, component);
|
|
1165
1198
|
}
|
|
1166
1199
|
export function resolveDmsComponent(name: string): Component | undefined {
|
|
1167
|
-
return components.get(normalizeDmsName(name))?.component;
|
|
1200
|
+
return registry.components.get(normalizeDmsName(name))?.component;
|
|
1168
1201
|
}
|
|
1169
1202
|
export const getDmsComponent = resolveDmsComponent;
|
|
1170
1203
|
|
|
@@ -1177,7 +1210,7 @@ export const getDmsComponent = resolveDmsComponent;
|
|
|
1177
1210
|
*/
|
|
1178
1211
|
export function trackDmsAsyncComponents(app: App): Set<string> {
|
|
1179
1212
|
const names = new Map<Component, string>();
|
|
1180
|
-
components.forEach(({ component, name }) => {
|
|
1213
|
+
registry.components.forEach(({ component, name }) => {
|
|
1181
1214
|
if ((component as DmsAsyncComponent).__asyncLoader)
|
|
1182
1215
|
names.set(component, name);
|
|
1183
1216
|
});
|
|
@@ -1201,12 +1234,17 @@ export function trackDmsAsyncComponents(app: App): Set<string> {
|
|
|
1201
1234
|
* a process-wide hook registry and only unregisters there, so every server
|
|
1202
1235
|
* render of the dashboard sidebar stayed reachable, its whole component tree
|
|
1203
1236
|
* and page props with it, until the server ran out of heap.
|
|
1237
|
+
*
|
|
1238
|
+
* The component's scope is read through `getCurrentScope`: Vue makes it the
|
|
1239
|
+
* active scope before it calls `beforeCreate`, and the instance's own `scope`
|
|
1240
|
+
* field is internal, absent from the typings a generated workspace checks.
|
|
1204
1241
|
*/
|
|
1205
1242
|
export function trackDmsServerScopes(app: App): () => void {
|
|
1206
1243
|
const scopes: EffectScope[] = [];
|
|
1207
1244
|
app.mixin({
|
|
1208
|
-
beforeCreate(
|
|
1209
|
-
|
|
1245
|
+
beforeCreate() {
|
|
1246
|
+
const scope = getCurrentScope();
|
|
1247
|
+
if (scope) scopes.push(scope);
|
|
1210
1248
|
},
|
|
1211
1249
|
});
|
|
1212
1250
|
return () => {
|
|
@@ -1288,30 +1326,35 @@ function findDmsPageEntry(props: DmsPageProps): DmsFrontendEntry | undefined {
|
|
|
1288
1326
|
props.page.componentName,
|
|
1289
1327
|
props.page.route?.fullSlug,
|
|
1290
1328
|
props.path,
|
|
1291
|
-
].find(
|
|
1329
|
+
].find(
|
|
1330
|
+
(candidate) =>
|
|
1331
|
+
candidate && registry.pages.has(normalizeDmsPageKey(candidate)),
|
|
1332
|
+
);
|
|
1292
1333
|
return name
|
|
1293
|
-
? pages.get(normalizeDmsPageKey(name))
|
|
1294
|
-
: dynamicPages.get(CATCH_ALL_PAGE_KEY);
|
|
1334
|
+
? registry.pages.get(normalizeDmsPageKey(name))
|
|
1335
|
+
: registry.dynamicPages.get(CATCH_ALL_PAGE_KEY);
|
|
1295
1336
|
}
|
|
1296
1337
|
|
|
1297
1338
|
/** The path a frontend module registered for a typed backend refusal. */
|
|
1298
1339
|
export function resolveDmsAccessRedirect(code: string): string | undefined {
|
|
1299
|
-
return accessRedirects.get(code);
|
|
1340
|
+
return registry.accessRedirects.get(code);
|
|
1300
1341
|
}
|
|
1301
1342
|
export function hasDmsPage(name: string): boolean {
|
|
1302
|
-
return pages.has(normalizeDmsPageKey(name));
|
|
1343
|
+
return registry.pages.has(normalizeDmsPageKey(name));
|
|
1303
1344
|
}
|
|
1304
1345
|
export function getDmsPage(props: DmsPageProps): Component | undefined {
|
|
1305
|
-
if (props.error) return errorPage?.component;
|
|
1346
|
+
if (props.error) return registry.errorPage?.component;
|
|
1306
1347
|
return findDmsPageEntry(props)?.component;
|
|
1307
1348
|
}
|
|
1308
1349
|
export function getDmsDynamicPage(name = "default"): Component | undefined {
|
|
1309
|
-
return dynamicPages.get(name)?.component;
|
|
1350
|
+
return registry.dynamicPages.get(name)?.component;
|
|
1310
1351
|
}
|
|
1311
1352
|
export function getDmsLayout(props: DmsPageProps): Component | undefined {
|
|
1312
1353
|
const layout = props.page.layout;
|
|
1313
1354
|
const name = layout?.layout?.componentName ?? layout?.componentName;
|
|
1314
|
-
return name
|
|
1355
|
+
return name
|
|
1356
|
+
? registry.layouts.get(normalizeDmsName(name))?.component
|
|
1357
|
+
: undefined;
|
|
1315
1358
|
}
|
|
1316
1359
|
export function getDmsLayoutProps(
|
|
1317
1360
|
props: DmsPageProps,
|
|
@@ -1357,18 +1400,18 @@ export function hydrateDmsPageProps(props: DmsPageProps, url?: string): void {
|
|
|
1357
1400
|
layoutUrl && props.page.layout ? { [layoutUrl]: props.page.layout } : {};
|
|
1358
1401
|
}
|
|
1359
1402
|
export function getDmsErrorPage(): Component | undefined {
|
|
1360
|
-
return errorPage?.component;
|
|
1403
|
+
return registry.errorPage?.component;
|
|
1361
1404
|
}
|
|
1362
1405
|
|
|
1363
1406
|
export async function preloadDmsPage(props: DmsPageProps): Promise<void> {
|
|
1364
1407
|
const layoutName =
|
|
1365
1408
|
props.page.layout?.layout?.componentName ??
|
|
1366
1409
|
props.page.layout?.componentName;
|
|
1367
|
-
const page = findDmsPageEntry(props) ?? dynamicPages.get("default");
|
|
1410
|
+
const page = findDmsPageEntry(props) ?? registry.dynamicPages.get("default");
|
|
1368
1411
|
const layout = layoutName
|
|
1369
|
-
? layouts.get(normalizeDmsName(layoutName))
|
|
1412
|
+
? registry.layouts.get(normalizeDmsName(layoutName))
|
|
1370
1413
|
: undefined;
|
|
1371
|
-
const entries = props.error ? [errorPage] : [page, layout];
|
|
1414
|
+
const entries = props.error ? [registry.errorPage] : [page, layout];
|
|
1372
1415
|
// `preload` only warms the module; the async wrapper stays unresolved until
|
|
1373
1416
|
// its own loader runs. Hydrating an unresolved wrapper defers it, and the
|
|
1374
1417
|
// first parent render (Inertia's initial swap) then makes Vue drop the
|
|
@@ -1389,58 +1432,85 @@ export function useDmsInjection<T>(
|
|
|
1389
1432
|
}
|
|
1390
1433
|
|
|
1391
1434
|
function registerDmsFrontendEntry(
|
|
1392
|
-
|
|
1435
|
+
entries: Map<string, DmsFrontendEntry>,
|
|
1393
1436
|
name: string,
|
|
1394
1437
|
component: Component,
|
|
1395
1438
|
preload?: DmsComponentPreloader,
|
|
1396
1439
|
): void {
|
|
1397
|
-
if (!
|
|
1440
|
+
if (!entries.has(name)) entries.set(name, { component, preload });
|
|
1398
1441
|
}
|
|
1399
1442
|
|
|
1400
|
-
function createSdk(
|
|
1443
|
+
function createSdk(
|
|
1444
|
+
target: DmsFrontendRegistry,
|
|
1445
|
+
options: DmsModuleOptions,
|
|
1446
|
+
): DmsFrontendSdk {
|
|
1401
1447
|
return {
|
|
1402
1448
|
options,
|
|
1403
|
-
registerComponent:
|
|
1449
|
+
registerComponent: (name, component) =>
|
|
1450
|
+
registerDmsComponentEntry(target.components, name, component),
|
|
1404
1451
|
registerPage: (name, component, preload) => {
|
|
1405
1452
|
const key = normalizeDmsPageKey(name);
|
|
1406
|
-
registerDmsFrontendEntry(pages, key, component, preload);
|
|
1453
|
+
registerDmsFrontendEntry(target.pages, key, component, preload);
|
|
1407
1454
|
},
|
|
1408
1455
|
registerDynamicPage: (name, component, preload) =>
|
|
1409
|
-
registerDmsFrontendEntry(dynamicPages, name, component, preload),
|
|
1456
|
+
registerDmsFrontendEntry(target.dynamicPages, name, component, preload),
|
|
1410
1457
|
registerLayout: (name, component, preload) => {
|
|
1411
1458
|
const key = normalizeDmsName(name);
|
|
1412
|
-
registerDmsFrontendEntry(layouts, key, component, preload);
|
|
1459
|
+
registerDmsFrontendEntry(target.layouts, key, component, preload);
|
|
1413
1460
|
},
|
|
1414
1461
|
registerErrorPage: (component, preload) => {
|
|
1415
|
-
errorPage ??= { component, preload };
|
|
1462
|
+
target.errorPage ??= { component, preload };
|
|
1416
1463
|
},
|
|
1417
1464
|
registerPlugin: (setup, options = {}) =>
|
|
1418
|
-
pluginSetups.push({
|
|
1465
|
+
target.pluginSetups.push({
|
|
1466
|
+
setup,
|
|
1467
|
+
clientOnly: options.clientOnly ?? false,
|
|
1468
|
+
}),
|
|
1419
1469
|
registerMiddleware: (name, handler, options = {}) => {
|
|
1420
|
-
if (!namedMiddleware.has(name))
|
|
1421
|
-
|
|
1470
|
+
if (!target.namedMiddleware.has(name))
|
|
1471
|
+
target.namedMiddleware.set(name, handler);
|
|
1472
|
+
if (options.global) target.middleware.push(handler);
|
|
1422
1473
|
},
|
|
1423
1474
|
registerAccessRedirect: (code, path) => {
|
|
1424
|
-
if (!accessRedirects.has(code))
|
|
1475
|
+
if (!target.accessRedirects.has(code))
|
|
1476
|
+
target.accessRedirects.set(code, path);
|
|
1425
1477
|
},
|
|
1426
1478
|
provide: (key, value) => {
|
|
1427
|
-
if (!injections.has(key)) injections.set(key, value);
|
|
1479
|
+
if (!target.injections.has(key)) target.injections.set(key, value);
|
|
1428
1480
|
},
|
|
1429
|
-
use: (plugin) => plugins.push(plugin),
|
|
1481
|
+
use: (plugin) => target.plugins.push(plugin),
|
|
1430
1482
|
};
|
|
1431
1483
|
}
|
|
1432
1484
|
|
|
1433
|
-
/**
|
|
1485
|
+
/**
|
|
1486
|
+
* Sets the frontend modules up in their generated priority order, into a
|
|
1487
|
+
* registry of their own that replaces the previous one once complete.
|
|
1488
|
+
*
|
|
1489
|
+
* The browser and a production server set the modules up once. A development
|
|
1490
|
+
* server sets them up again each time Vite evaluates the server renderer anew
|
|
1491
|
+
* after a layer changes, but keeps this module and its state: registering into
|
|
1492
|
+
* the previous registry, the new components lost their names to the ones they
|
|
1493
|
+
* replace, so the server kept rendering the old ones, and every list gained the
|
|
1494
|
+
* same entries once more. A render still in progress keeps reading a complete
|
|
1495
|
+
* registry: the new one is only published once every module is set up.
|
|
1496
|
+
*/
|
|
1434
1497
|
export async function setupFrontendModules(
|
|
1435
1498
|
registrations: DmsFrontendModuleRegistration[],
|
|
1436
1499
|
): Promise<void> {
|
|
1500
|
+
const next = createDmsFrontendRegistry();
|
|
1501
|
+
// Modules read and extend these two while they are set up (the DMS layout
|
|
1502
|
+
// merges its app config into `useDmsAppConfig()`), so they restart empty
|
|
1503
|
+
// here rather than being published with the registry.
|
|
1504
|
+
runtimeConfig.value.public = {} as PublicRuntimeConfig;
|
|
1505
|
+
appConfig.value = {};
|
|
1437
1506
|
for (const registration of registrations) {
|
|
1438
1507
|
runtimeConfig.value.public = defu(
|
|
1439
1508
|
runtimeConfig.value.public,
|
|
1440
1509
|
registration.options.public,
|
|
1441
1510
|
);
|
|
1442
|
-
await registration.module.setup(createSdk(registration.options));
|
|
1511
|
+
await registration.module.setup(createSdk(next, registration.options));
|
|
1443
1512
|
}
|
|
1513
|
+
registry = next;
|
|
1444
1514
|
}
|
|
1445
1515
|
|
|
1446
1516
|
export async function installDmsPlugins(
|
|
@@ -1497,16 +1567,16 @@ export async function installDmsPlugins(
|
|
|
1497
1567
|
);
|
|
1498
1568
|
app.component("DmsLink", DmsLink);
|
|
1499
1569
|
app.component("DmsClientOnly", DmsClientOnly);
|
|
1500
|
-
components.forEach(({ component, name }) => {
|
|
1570
|
+
registry.components.forEach(({ component, name }) => {
|
|
1501
1571
|
app.component(name, component);
|
|
1502
1572
|
});
|
|
1503
|
-
injections.forEach((value, key) => {
|
|
1573
|
+
registry.injections.forEach((value, key) => {
|
|
1504
1574
|
app.provide(key, value);
|
|
1505
1575
|
});
|
|
1506
|
-
plugins.forEach((plugin) => {
|
|
1576
|
+
registry.plugins.forEach((plugin) => {
|
|
1507
1577
|
app.use(plugin);
|
|
1508
1578
|
});
|
|
1509
|
-
for (const registration of pluginSetups) {
|
|
1579
|
+
for (const registration of registry.pluginSetups) {
|
|
1510
1580
|
if (registration.clientOnly && typeof window === "undefined") continue;
|
|
1511
1581
|
await runtime.scope.run(() =>
|
|
1512
1582
|
app.runWithContext(() => registration.setup(appContext)),
|