@stardeck-customer-apps/compose 0.7.0 → 0.8.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.
- package/SKILL.md +16 -1
- package/dist/cli.js +71 -22
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +71 -22
- package/dist/index.mjs +71 -22
- package/package.json +2 -2
package/SKILL.md
CHANGED
|
@@ -14,6 +14,8 @@ Compose turns that declaration into the code Next.js actually builds:
|
|
|
14
14
|
- `apps/web/src/module-i18n.gen.ts`
|
|
15
15
|
- `apps/web/src/module-init.server.gen.ts`
|
|
16
16
|
- `apps/web/src/module-datastores.gen.ts`
|
|
17
|
+
- `apps/web/src/module-server.gen.ts` — `MODULE_SERVER_REGISTRATIONS`, one entry
|
|
18
|
+
per composed Module that ships `server/registrations.ts`
|
|
17
19
|
- one `page.tsx` / `route.ts` stub under `apps/web/src/app/**` per declared
|
|
18
20
|
mount and endpoint
|
|
19
21
|
|
|
@@ -101,6 +103,19 @@ a silent fallback. It holds deployment facts: gitignore it (`apps/web/.gitignore
|
|
|
101
103
|
compose as a route collision.
|
|
102
104
|
`isMountHeadless(key)` and `isHrefHeadless(href)` are exported from
|
|
103
105
|
`@/modules.gen`. Needs compose 0.7.0 or later.
|
|
106
|
+
- **Server registrations.** Per-Module server wiring that the app layer runs
|
|
107
|
+
(seeds, schedule handlers, and similar) goes in the Module's
|
|
108
|
+
`server/registrations.ts`, any Module kind. Compose imports each composed
|
|
109
|
+
Module's file as a namespace into `module-server.gen.ts`:
|
|
110
|
+
`MODULE_SERVER_REGISTRATIONS` is a
|
|
111
|
+
`readonly { module: string; registrations: Readonly<Record<string, unknown>> }[]`.
|
|
112
|
+
A Module left out by `--enabled` is not imported at all, so its server code
|
|
113
|
+
drops out of the build. App code reads that array from `@/module-server.gen`
|
|
114
|
+
and narrows the exports it expects (e.g. `registrations.seed`); it must never
|
|
115
|
+
import a Module's seed or schedules directly, or a disabled Module stays in
|
|
116
|
+
the bundle. Compose does not check the export names or shapes. The file
|
|
117
|
+
counts as `server/**/*.ts`, so the Module also needs `server/index.ts`.
|
|
118
|
+
Needs compose 0.8.0 or later.
|
|
104
119
|
- `@stardeck-customer-apps/compose/runtime` exports `isModuleEnabledByList`,
|
|
105
120
|
the single enablement rule, and imports nothing — it is safe in client
|
|
106
121
|
components.
|
|
@@ -111,5 +126,5 @@ After each run compose rewrites `apps/web/src/app/.gitignore` with one entry per
|
|
|
111
126
|
stub it emits — stubs are scattered one-per-route and cannot be globbed. Commit
|
|
112
127
|
that file: it is deterministic output, and compose rewrites it only when the set
|
|
113
128
|
of stubs changes, so an unchanged compose leaves `git status` clean. It does not
|
|
114
|
-
list the
|
|
129
|
+
list the six `src/*.gen.ts`; a static `src/*.gen.ts` line in `apps/web/.gitignore`
|
|
115
130
|
covers those. Compose refuses to touch the file if line 1 is not its own header.
|
package/dist/cli.js
CHANGED
|
@@ -3896,6 +3896,7 @@ var MODULE_CONTRIBUTIONS_GEN_PATH = `${APP_WEB_PREFIX}src/module-contributions.g
|
|
|
3896
3896
|
var MODULE_DATASTORES_GEN_PATH = `${APP_WEB_PREFIX}src/module-datastores.gen.ts`;
|
|
3897
3897
|
var MODULE_I18N_GEN_PATH = `${APP_WEB_PREFIX}src/module-i18n.gen.ts`;
|
|
3898
3898
|
var MODULE_INIT_SERVER_GEN_PATH = `${APP_WEB_PREFIX}src/module-init.server.gen.ts`;
|
|
3899
|
+
var MODULE_SERVER_GEN_PATH = `${APP_WEB_PREFIX}src/module-server.gen.ts`;
|
|
3899
3900
|
var MODULES_GEN_PATH = `${APP_WEB_PREFIX}src/modules.gen.ts`;
|
|
3900
3901
|
var APP_EXTENSIONS_PATH = `${APP_WEB_PREFIX}src/lib/modules/app-extensions.ts`;
|
|
3901
3902
|
|
|
@@ -4141,7 +4142,8 @@ var COMPOSITION_RUNTIME_GEN_PATHS = [
|
|
|
4141
4142
|
MODULE_CONTRIBUTIONS_GEN_PATH,
|
|
4142
4143
|
MODULE_I18N_GEN_PATH,
|
|
4143
4144
|
MODULE_INIT_SERVER_GEN_PATH,
|
|
4144
|
-
MODULE_DATASTORES_GEN_PATH
|
|
4145
|
+
MODULE_DATASTORES_GEN_PATH,
|
|
4146
|
+
MODULE_SERVER_GEN_PATH
|
|
4145
4147
|
];
|
|
4146
4148
|
function compareNames(a, b) {
|
|
4147
4149
|
return a < b ? -1 : a > b ? 1 : 0;
|
|
@@ -4162,6 +4164,9 @@ function formatI18nMarker() {
|
|
|
4162
4164
|
function formatInitMarker() {
|
|
4163
4165
|
return `// ${MODULE_STUB_MARKER} scope=init`;
|
|
4164
4166
|
}
|
|
4167
|
+
function formatServerMarker() {
|
|
4168
|
+
return `// ${MODULE_STUB_MARKER} scope=server`;
|
|
4169
|
+
}
|
|
4165
4170
|
function formatDatastoresMarker() {
|
|
4166
4171
|
return `// ${MODULE_STUB_MARKER} scope=datastores`;
|
|
4167
4172
|
}
|
|
@@ -4805,6 +4810,42 @@ function emitModuleInitServerGenTs(input) {
|
|
|
4805
4810
|
""
|
|
4806
4811
|
].join("\n");
|
|
4807
4812
|
}
|
|
4813
|
+
function emitModuleServerGenTs(input) {
|
|
4814
|
+
const installed = new Set(input.registry.modules.map((m) => m.name));
|
|
4815
|
+
const moduleNames = input.facts.filter((f) => f.hasServerRegistrations && installed.has(f.moduleName)).map((f) => f.moduleName).sort(compareNames);
|
|
4816
|
+
for (const name of moduleNames) {
|
|
4817
|
+
if (!isValidModuleName(name)) {
|
|
4818
|
+
throw new Error(`[ModuleRail] composition artifacts: invalid module name "${name}"`);
|
|
4819
|
+
}
|
|
4820
|
+
}
|
|
4821
|
+
const importLines = moduleNames.map(
|
|
4822
|
+
(name, index) => [
|
|
4823
|
+
`@/modules/${name}/server/registrations`,
|
|
4824
|
+
`import * as serverRegistrations${index} from ${JSON.stringify(`@/modules/${name}/server/registrations`)};`
|
|
4825
|
+
]
|
|
4826
|
+
).sort((a, b) => compareImportSpecifiers(a[0], b[0])).map(([, line]) => line);
|
|
4827
|
+
const entryLines = moduleNames.map(
|
|
4828
|
+
(name, index) => ` { module: ${JSON.stringify(name)}, registrations: serverRegistrations${index} },`
|
|
4829
|
+
);
|
|
4830
|
+
return [
|
|
4831
|
+
formatServerMarker(),
|
|
4832
|
+
"/** DO NOT EDIT \u2014 owned by the module install rail. */",
|
|
4833
|
+
"",
|
|
4834
|
+
...importLines,
|
|
4835
|
+
...importLines.length > 0 ? [""] : [],
|
|
4836
|
+
"export type ModuleServerRegistration = {",
|
|
4837
|
+
" module: string;",
|
|
4838
|
+
" registrations: Readonly<Record<string, unknown>>;",
|
|
4839
|
+
"};",
|
|
4840
|
+
"",
|
|
4841
|
+
...entryLines.length === 0 ? ["export const MODULE_SERVER_REGISTRATIONS: readonly ModuleServerRegistration[] = [];"] : [
|
|
4842
|
+
"export const MODULE_SERVER_REGISTRATIONS: readonly ModuleServerRegistration[] = [",
|
|
4843
|
+
...entryLines,
|
|
4844
|
+
"];"
|
|
4845
|
+
],
|
|
4846
|
+
""
|
|
4847
|
+
].join("\n");
|
|
4848
|
+
}
|
|
4808
4849
|
|
|
4809
4850
|
// ../../packages/lib/src/server/module-rail/composition-artifacts.ts
|
|
4810
4851
|
var COMPOSITION_ARTIFACTS_GENERATED_BY = "module-rail";
|
|
@@ -4867,6 +4908,14 @@ function formatRouteMarker(owner, nextRelativePath) {
|
|
|
4867
4908
|
function formatRegistryMarker() {
|
|
4868
4909
|
return `// ${MODULE_STUB_MARKER} scope=registry`;
|
|
4869
4910
|
}
|
|
4911
|
+
var OWNERLESS_MARKER_KINDS = [
|
|
4912
|
+
"registry",
|
|
4913
|
+
"contributions",
|
|
4914
|
+
"datastores",
|
|
4915
|
+
"i18n",
|
|
4916
|
+
"init",
|
|
4917
|
+
"server"
|
|
4918
|
+
];
|
|
4870
4919
|
function parseCompositionArtifactMarker(source) {
|
|
4871
4920
|
const firstLine = source.split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
4872
4921
|
const match = firstLine.match(
|
|
@@ -4877,26 +4926,8 @@ function parseCompositionArtifactMarker(source) {
|
|
|
4877
4926
|
if (!match) return null;
|
|
4878
4927
|
const owner = match[1];
|
|
4879
4928
|
const scope = match[2];
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
return { kind: "registry" };
|
|
4883
|
-
}
|
|
4884
|
-
if (scope === "contributions") {
|
|
4885
|
-
if (owner) return null;
|
|
4886
|
-
return { kind: "contributions" };
|
|
4887
|
-
}
|
|
4888
|
-
if (scope === "datastores") {
|
|
4889
|
-
if (owner) return null;
|
|
4890
|
-
return { kind: "datastores" };
|
|
4891
|
-
}
|
|
4892
|
-
if (scope === "i18n") {
|
|
4893
|
-
if (owner) return null;
|
|
4894
|
-
return { kind: "i18n" };
|
|
4895
|
-
}
|
|
4896
|
-
if (scope === "init") {
|
|
4897
|
-
if (owner) return null;
|
|
4898
|
-
return { kind: "init" };
|
|
4899
|
-
}
|
|
4929
|
+
const ownerless = OWNERLESS_MARKER_KINDS.find((kind) => kind === scope);
|
|
4930
|
+
if (ownerless) return owner ? null : { kind: ownerless };
|
|
4900
4931
|
if (!owner || !isValidModuleName(owner)) return null;
|
|
4901
4932
|
if (scope === "route") {
|
|
4902
4933
|
const nextRelativePath = match[3]?.trim();
|
|
@@ -5022,6 +5053,7 @@ function expectedMarkerKindForPath(path3) {
|
|
|
5022
5053
|
if (path3 === MODULE_DATASTORES_GEN_PATH) return "datastores";
|
|
5023
5054
|
if (path3 === MODULE_I18N_GEN_PATH) return "i18n";
|
|
5024
5055
|
if (path3 === MODULE_INIT_SERVER_GEN_PATH) return "init";
|
|
5056
|
+
if (path3 === MODULE_SERVER_GEN_PATH) return "server";
|
|
5025
5057
|
if (path3.startsWith(API_ROUTE_DIR_PREFIX) && path3.endsWith("/route.ts")) return "endpoint";
|
|
5026
5058
|
if (path3.startsWith(APP_DIR_PREFIX) && !path3.startsWith(API_ROUTE_DIR_PREFIX) && PAGE_FILE_SUFFIXES.some((suffix) => path3.endsWith(suffix))) {
|
|
5027
5059
|
return "route";
|
|
@@ -5621,6 +5653,7 @@ function planCompositionArtifacts(input) {
|
|
|
5621
5653
|
let datastoresContent;
|
|
5622
5654
|
let i18nContent;
|
|
5623
5655
|
let initContent;
|
|
5656
|
+
let serverContent;
|
|
5624
5657
|
try {
|
|
5625
5658
|
contributionsContent = emitModuleContributionsGenTs({
|
|
5626
5659
|
registry: input.registry,
|
|
@@ -5645,6 +5678,10 @@ function planCompositionArtifacts(input) {
|
|
|
5645
5678
|
registry: input.registry,
|
|
5646
5679
|
facts: compositionEntryFacts
|
|
5647
5680
|
});
|
|
5681
|
+
serverContent = emitModuleServerGenTs({
|
|
5682
|
+
registry: input.registry,
|
|
5683
|
+
facts: compositionEntryFacts
|
|
5684
|
+
});
|
|
5648
5685
|
} catch (error) {
|
|
5649
5686
|
return {
|
|
5650
5687
|
ok: false,
|
|
@@ -5657,6 +5694,7 @@ function planCompositionArtifacts(input) {
|
|
|
5657
5694
|
desired.set(MODULE_DATASTORES_GEN_PATH, datastoresContent);
|
|
5658
5695
|
desired.set(MODULE_I18N_GEN_PATH, i18nContent);
|
|
5659
5696
|
desired.set(MODULE_INIT_SERVER_GEN_PATH, initContent);
|
|
5697
|
+
desired.set(MODULE_SERVER_GEN_PATH, serverContent);
|
|
5660
5698
|
for (const stub of stubs.endpointStubs) desired.set(stub.path, stub.content);
|
|
5661
5699
|
for (const stub of stubs.routeStubs) desired.set(stub.path, stub.content);
|
|
5662
5700
|
const endpointStubByPath = new Map(stubs.endpointStubs.map((stub) => [stub.path, stub]));
|
|
@@ -6927,6 +6965,7 @@ function readFailurePath(error) {
|
|
|
6927
6965
|
return typeof error === "object" && error !== null && "path" in error ? String(error.path) : "unknown";
|
|
6928
6966
|
}
|
|
6929
6967
|
var CONVENTIONAL_ENTRY_KIND_PROBE_TOKEN = "conventional-entry-kind";
|
|
6968
|
+
var SERVER_REGISTRATIONS_FILE = "server/registrations.ts";
|
|
6930
6969
|
var COMPOSITION_ARTIFACT_KIND_PROBE_TOKEN = "composition-artifact-kind";
|
|
6931
6970
|
async function classifyCompositionArtifactPathKind(context, path3) {
|
|
6932
6971
|
return classifySandboxPathPresenceKind(context, path3, COMPOSITION_ARTIFACT_KIND_PROBE_TOKEN);
|
|
@@ -6964,6 +7003,10 @@ async function readConventionalEntryIfRealFile(path3, kind, presences, files) {
|
|
|
6964
7003
|
}
|
|
6965
7004
|
return source;
|
|
6966
7005
|
}
|
|
7006
|
+
function hasRealServerRegistrations(modulePath, presences) {
|
|
7007
|
+
const path3 = `${modulePath}/${SERVER_REGISTRATIONS_FILE}`;
|
|
7008
|
+
return assertRealCompositionArtifactFilePresence(path3, presences.get(path3) ?? "unreadable") === "file";
|
|
7009
|
+
}
|
|
6967
7010
|
async function readJsonObjectFile(path3, files) {
|
|
6968
7011
|
const raw = files.get(path3);
|
|
6969
7012
|
let parsed;
|
|
@@ -6987,6 +7030,9 @@ async function collectCompositionEntryFacts(context, registry) {
|
|
|
6987
7030
|
const overridesDir = `${APP_PACKAGE_DIR}/src/lib/i18n/overrides`;
|
|
6988
7031
|
const localeDirs = [substrateDir, overridesDir];
|
|
6989
7032
|
const conventionalPaths = [];
|
|
7033
|
+
const serverRegistrationPaths = registry.modules.map(
|
|
7034
|
+
(mod) => `${MODULES_SANDBOX_DIR}/${mod.name}/${SERVER_REGISTRATIONS_FILE}`
|
|
7035
|
+
);
|
|
6990
7036
|
for (const mod of registry.modules) {
|
|
6991
7037
|
const modulePath = `${MODULES_SANDBOX_DIR}/${mod.name}`;
|
|
6992
7038
|
localeDirs.push(`${modulePath}/i18n`);
|
|
@@ -7015,7 +7061,7 @@ async function collectCompositionEntryFacts(context, registry) {
|
|
|
7015
7061
|
const [conventionalPresences, localePresences] = await Promise.all([
|
|
7016
7062
|
classifySandboxPathPresenceKindMany(
|
|
7017
7063
|
context,
|
|
7018
|
-
conventionalPaths,
|
|
7064
|
+
[...conventionalPaths, ...serverRegistrationPaths],
|
|
7019
7065
|
CONVENTIONAL_ENTRY_KIND_PROBE_TOKEN
|
|
7020
7066
|
),
|
|
7021
7067
|
classifySandboxPathPresenceKindMany(context, localePaths, LOCALE_JSON_KIND_PROBE_TOKEN)
|
|
@@ -7077,6 +7123,7 @@ async function collectCompositionEntryFacts(context, registry) {
|
|
|
7077
7123
|
);
|
|
7078
7124
|
}
|
|
7079
7125
|
}
|
|
7126
|
+
const hasServerRegistrations = hasRealServerRegistrations(modulePath, conventionalPresences);
|
|
7080
7127
|
const rootLocales = localesByDir.get(`${modulePath}/i18n`);
|
|
7081
7128
|
if (rootLocales.length > 0 && !rootLocales.includes("en")) {
|
|
7082
7129
|
throw new Error(
|
|
@@ -7116,6 +7163,7 @@ async function collectCompositionEntryFacts(context, registry) {
|
|
|
7116
7163
|
moduleName: mod.name,
|
|
7117
7164
|
hasRootContributions,
|
|
7118
7165
|
hasRootSlots,
|
|
7166
|
+
hasServerRegistrations,
|
|
7119
7167
|
rootLocales,
|
|
7120
7168
|
enhancements
|
|
7121
7169
|
});
|
|
@@ -7319,6 +7367,7 @@ async function reconcileCompositionArtifacts(context, options = {}) {
|
|
|
7319
7367
|
MODULE_DATASTORES_GEN_PATH,
|
|
7320
7368
|
MODULE_I18N_GEN_PATH,
|
|
7321
7369
|
MODULE_INIT_SERVER_GEN_PATH,
|
|
7370
|
+
MODULE_SERVER_GEN_PATH,
|
|
7322
7371
|
...existingGeneratedPaths,
|
|
7323
7372
|
...Object.keys(existingAppPages),
|
|
7324
7373
|
...Object.keys(existingAppRoutes)
|
package/dist/index.d.mts
CHANGED
|
@@ -89,7 +89,7 @@ declare function assertSupportedTypescript(versionMajorMinor: string): void;
|
|
|
89
89
|
*/
|
|
90
90
|
declare function escapeGitignore(pattern: string): string;
|
|
91
91
|
/**
|
|
92
|
-
* Regenerate the Module-rail artifacts (the
|
|
92
|
+
* Regenerate the Module-rail artifacts (the six `src/*.gen.ts` files and every
|
|
93
93
|
* route/endpoint stub under `src/app`) for the app rooted at `options.cwd`.
|
|
94
94
|
*/
|
|
95
95
|
declare function compose(options: ComposeOptions): Promise<ComposeResult>;
|
package/dist/index.d.ts
CHANGED
|
@@ -89,7 +89,7 @@ declare function assertSupportedTypescript(versionMajorMinor: string): void;
|
|
|
89
89
|
*/
|
|
90
90
|
declare function escapeGitignore(pattern: string): string;
|
|
91
91
|
/**
|
|
92
|
-
* Regenerate the Module-rail artifacts (the
|
|
92
|
+
* Regenerate the Module-rail artifacts (the six `src/*.gen.ts` files and every
|
|
93
93
|
* route/endpoint stub under `src/app`) for the app rooted at `options.cwd`.
|
|
94
94
|
*/
|
|
95
95
|
declare function compose(options: ComposeOptions): Promise<ComposeResult>;
|
package/dist/index.js
CHANGED
|
@@ -4134,6 +4134,7 @@ var MODULE_CONTRIBUTIONS_GEN_PATH = `${APP_WEB_PREFIX}src/module-contributions.g
|
|
|
4134
4134
|
var MODULE_DATASTORES_GEN_PATH = `${APP_WEB_PREFIX}src/module-datastores.gen.ts`;
|
|
4135
4135
|
var MODULE_I18N_GEN_PATH = `${APP_WEB_PREFIX}src/module-i18n.gen.ts`;
|
|
4136
4136
|
var MODULE_INIT_SERVER_GEN_PATH = `${APP_WEB_PREFIX}src/module-init.server.gen.ts`;
|
|
4137
|
+
var MODULE_SERVER_GEN_PATH = `${APP_WEB_PREFIX}src/module-server.gen.ts`;
|
|
4137
4138
|
var MODULES_GEN_PATH = `${APP_WEB_PREFIX}src/modules.gen.ts`;
|
|
4138
4139
|
var APP_EXTENSIONS_PATH = `${APP_WEB_PREFIX}src/lib/modules/app-extensions.ts`;
|
|
4139
4140
|
|
|
@@ -4150,7 +4151,8 @@ var COMPOSITION_RUNTIME_GEN_PATHS = [
|
|
|
4150
4151
|
MODULE_CONTRIBUTIONS_GEN_PATH,
|
|
4151
4152
|
MODULE_I18N_GEN_PATH,
|
|
4152
4153
|
MODULE_INIT_SERVER_GEN_PATH,
|
|
4153
|
-
MODULE_DATASTORES_GEN_PATH
|
|
4154
|
+
MODULE_DATASTORES_GEN_PATH,
|
|
4155
|
+
MODULE_SERVER_GEN_PATH
|
|
4154
4156
|
];
|
|
4155
4157
|
function compareNames(a, b) {
|
|
4156
4158
|
return a < b ? -1 : a > b ? 1 : 0;
|
|
@@ -4171,6 +4173,9 @@ function formatI18nMarker() {
|
|
|
4171
4173
|
function formatInitMarker() {
|
|
4172
4174
|
return `// ${MODULE_STUB_MARKER} scope=init`;
|
|
4173
4175
|
}
|
|
4176
|
+
function formatServerMarker() {
|
|
4177
|
+
return `// ${MODULE_STUB_MARKER} scope=server`;
|
|
4178
|
+
}
|
|
4174
4179
|
function formatDatastoresMarker() {
|
|
4175
4180
|
return `// ${MODULE_STUB_MARKER} scope=datastores`;
|
|
4176
4181
|
}
|
|
@@ -4814,6 +4819,42 @@ function emitModuleInitServerGenTs(input) {
|
|
|
4814
4819
|
""
|
|
4815
4820
|
].join("\n");
|
|
4816
4821
|
}
|
|
4822
|
+
function emitModuleServerGenTs(input) {
|
|
4823
|
+
const installed = new Set(input.registry.modules.map((m) => m.name));
|
|
4824
|
+
const moduleNames = input.facts.filter((f) => f.hasServerRegistrations && installed.has(f.moduleName)).map((f) => f.moduleName).sort(compareNames);
|
|
4825
|
+
for (const name of moduleNames) {
|
|
4826
|
+
if (!isValidModuleName(name)) {
|
|
4827
|
+
throw new Error(`[ModuleRail] composition artifacts: invalid module name "${name}"`);
|
|
4828
|
+
}
|
|
4829
|
+
}
|
|
4830
|
+
const importLines = moduleNames.map(
|
|
4831
|
+
(name, index) => [
|
|
4832
|
+
`@/modules/${name}/server/registrations`,
|
|
4833
|
+
`import * as serverRegistrations${index} from ${JSON.stringify(`@/modules/${name}/server/registrations`)};`
|
|
4834
|
+
]
|
|
4835
|
+
).sort((a, b) => compareImportSpecifiers(a[0], b[0])).map(([, line]) => line);
|
|
4836
|
+
const entryLines = moduleNames.map(
|
|
4837
|
+
(name, index) => ` { module: ${JSON.stringify(name)}, registrations: serverRegistrations${index} },`
|
|
4838
|
+
);
|
|
4839
|
+
return [
|
|
4840
|
+
formatServerMarker(),
|
|
4841
|
+
"/** DO NOT EDIT \u2014 owned by the module install rail. */",
|
|
4842
|
+
"",
|
|
4843
|
+
...importLines,
|
|
4844
|
+
...importLines.length > 0 ? [""] : [],
|
|
4845
|
+
"export type ModuleServerRegistration = {",
|
|
4846
|
+
" module: string;",
|
|
4847
|
+
" registrations: Readonly<Record<string, unknown>>;",
|
|
4848
|
+
"};",
|
|
4849
|
+
"",
|
|
4850
|
+
...entryLines.length === 0 ? ["export const MODULE_SERVER_REGISTRATIONS: readonly ModuleServerRegistration[] = [];"] : [
|
|
4851
|
+
"export const MODULE_SERVER_REGISTRATIONS: readonly ModuleServerRegistration[] = [",
|
|
4852
|
+
...entryLines,
|
|
4853
|
+
"];"
|
|
4854
|
+
],
|
|
4855
|
+
""
|
|
4856
|
+
].join("\n");
|
|
4857
|
+
}
|
|
4817
4858
|
|
|
4818
4859
|
// ../../packages/lib/src/server/module-rail/composition-artifacts.ts
|
|
4819
4860
|
var COMPOSITION_ARTIFACTS_GENERATED_BY = "module-rail";
|
|
@@ -4876,6 +4917,14 @@ function formatRouteMarker(owner, nextRelativePath) {
|
|
|
4876
4917
|
function formatRegistryMarker() {
|
|
4877
4918
|
return `// ${MODULE_STUB_MARKER} scope=registry`;
|
|
4878
4919
|
}
|
|
4920
|
+
var OWNERLESS_MARKER_KINDS = [
|
|
4921
|
+
"registry",
|
|
4922
|
+
"contributions",
|
|
4923
|
+
"datastores",
|
|
4924
|
+
"i18n",
|
|
4925
|
+
"init",
|
|
4926
|
+
"server"
|
|
4927
|
+
];
|
|
4879
4928
|
function parseCompositionArtifactMarker(source) {
|
|
4880
4929
|
const firstLine = source.split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
4881
4930
|
const match = firstLine.match(
|
|
@@ -4886,26 +4935,8 @@ function parseCompositionArtifactMarker(source) {
|
|
|
4886
4935
|
if (!match) return null;
|
|
4887
4936
|
const owner = match[1];
|
|
4888
4937
|
const scope = match[2];
|
|
4889
|
-
|
|
4890
|
-
|
|
4891
|
-
return { kind: "registry" };
|
|
4892
|
-
}
|
|
4893
|
-
if (scope === "contributions") {
|
|
4894
|
-
if (owner) return null;
|
|
4895
|
-
return { kind: "contributions" };
|
|
4896
|
-
}
|
|
4897
|
-
if (scope === "datastores") {
|
|
4898
|
-
if (owner) return null;
|
|
4899
|
-
return { kind: "datastores" };
|
|
4900
|
-
}
|
|
4901
|
-
if (scope === "i18n") {
|
|
4902
|
-
if (owner) return null;
|
|
4903
|
-
return { kind: "i18n" };
|
|
4904
|
-
}
|
|
4905
|
-
if (scope === "init") {
|
|
4906
|
-
if (owner) return null;
|
|
4907
|
-
return { kind: "init" };
|
|
4908
|
-
}
|
|
4938
|
+
const ownerless = OWNERLESS_MARKER_KINDS.find((kind) => kind === scope);
|
|
4939
|
+
if (ownerless) return owner ? null : { kind: ownerless };
|
|
4909
4940
|
if (!owner || !isValidModuleName(owner)) return null;
|
|
4910
4941
|
if (scope === "route") {
|
|
4911
4942
|
const nextRelativePath = match[3]?.trim();
|
|
@@ -5031,6 +5062,7 @@ function expectedMarkerKindForPath(path3) {
|
|
|
5031
5062
|
if (path3 === MODULE_DATASTORES_GEN_PATH) return "datastores";
|
|
5032
5063
|
if (path3 === MODULE_I18N_GEN_PATH) return "i18n";
|
|
5033
5064
|
if (path3 === MODULE_INIT_SERVER_GEN_PATH) return "init";
|
|
5065
|
+
if (path3 === MODULE_SERVER_GEN_PATH) return "server";
|
|
5034
5066
|
if (path3.startsWith(API_ROUTE_DIR_PREFIX) && path3.endsWith("/route.ts")) return "endpoint";
|
|
5035
5067
|
if (path3.startsWith(APP_DIR_PREFIX) && !path3.startsWith(API_ROUTE_DIR_PREFIX) && PAGE_FILE_SUFFIXES.some((suffix) => path3.endsWith(suffix))) {
|
|
5036
5068
|
return "route";
|
|
@@ -5630,6 +5662,7 @@ function planCompositionArtifacts(input) {
|
|
|
5630
5662
|
let datastoresContent;
|
|
5631
5663
|
let i18nContent;
|
|
5632
5664
|
let initContent;
|
|
5665
|
+
let serverContent;
|
|
5633
5666
|
try {
|
|
5634
5667
|
contributionsContent = emitModuleContributionsGenTs({
|
|
5635
5668
|
registry: input.registry,
|
|
@@ -5654,6 +5687,10 @@ function planCompositionArtifacts(input) {
|
|
|
5654
5687
|
registry: input.registry,
|
|
5655
5688
|
facts: compositionEntryFacts
|
|
5656
5689
|
});
|
|
5690
|
+
serverContent = emitModuleServerGenTs({
|
|
5691
|
+
registry: input.registry,
|
|
5692
|
+
facts: compositionEntryFacts
|
|
5693
|
+
});
|
|
5657
5694
|
} catch (error) {
|
|
5658
5695
|
return {
|
|
5659
5696
|
ok: false,
|
|
@@ -5666,6 +5703,7 @@ function planCompositionArtifacts(input) {
|
|
|
5666
5703
|
desired.set(MODULE_DATASTORES_GEN_PATH, datastoresContent);
|
|
5667
5704
|
desired.set(MODULE_I18N_GEN_PATH, i18nContent);
|
|
5668
5705
|
desired.set(MODULE_INIT_SERVER_GEN_PATH, initContent);
|
|
5706
|
+
desired.set(MODULE_SERVER_GEN_PATH, serverContent);
|
|
5669
5707
|
for (const stub of stubs.endpointStubs) desired.set(stub.path, stub.content);
|
|
5670
5708
|
for (const stub of stubs.routeStubs) desired.set(stub.path, stub.content);
|
|
5671
5709
|
const endpointStubByPath = new Map(stubs.endpointStubs.map((stub) => [stub.path, stub]));
|
|
@@ -6936,6 +6974,7 @@ function readFailurePath(error) {
|
|
|
6936
6974
|
return typeof error === "object" && error !== null && "path" in error ? String(error.path) : "unknown";
|
|
6937
6975
|
}
|
|
6938
6976
|
var CONVENTIONAL_ENTRY_KIND_PROBE_TOKEN = "conventional-entry-kind";
|
|
6977
|
+
var SERVER_REGISTRATIONS_FILE = "server/registrations.ts";
|
|
6939
6978
|
var COMPOSITION_ARTIFACT_KIND_PROBE_TOKEN = "composition-artifact-kind";
|
|
6940
6979
|
async function classifyCompositionArtifactPathKind(context, path3) {
|
|
6941
6980
|
return classifySandboxPathPresenceKind(context, path3, COMPOSITION_ARTIFACT_KIND_PROBE_TOKEN);
|
|
@@ -6973,6 +7012,10 @@ async function readConventionalEntryIfRealFile(path3, kind, presences, files) {
|
|
|
6973
7012
|
}
|
|
6974
7013
|
return source;
|
|
6975
7014
|
}
|
|
7015
|
+
function hasRealServerRegistrations(modulePath, presences) {
|
|
7016
|
+
const path3 = `${modulePath}/${SERVER_REGISTRATIONS_FILE}`;
|
|
7017
|
+
return assertRealCompositionArtifactFilePresence(path3, presences.get(path3) ?? "unreadable") === "file";
|
|
7018
|
+
}
|
|
6976
7019
|
async function readJsonObjectFile(path3, files) {
|
|
6977
7020
|
const raw = files.get(path3);
|
|
6978
7021
|
let parsed;
|
|
@@ -6996,6 +7039,9 @@ async function collectCompositionEntryFacts(context, registry) {
|
|
|
6996
7039
|
const overridesDir = `${APP_PACKAGE_DIR}/src/lib/i18n/overrides`;
|
|
6997
7040
|
const localeDirs = [substrateDir, overridesDir];
|
|
6998
7041
|
const conventionalPaths = [];
|
|
7042
|
+
const serverRegistrationPaths = registry.modules.map(
|
|
7043
|
+
(mod) => `${MODULES_SANDBOX_DIR}/${mod.name}/${SERVER_REGISTRATIONS_FILE}`
|
|
7044
|
+
);
|
|
6999
7045
|
for (const mod of registry.modules) {
|
|
7000
7046
|
const modulePath = `${MODULES_SANDBOX_DIR}/${mod.name}`;
|
|
7001
7047
|
localeDirs.push(`${modulePath}/i18n`);
|
|
@@ -7024,7 +7070,7 @@ async function collectCompositionEntryFacts(context, registry) {
|
|
|
7024
7070
|
const [conventionalPresences, localePresences] = await Promise.all([
|
|
7025
7071
|
classifySandboxPathPresenceKindMany(
|
|
7026
7072
|
context,
|
|
7027
|
-
conventionalPaths,
|
|
7073
|
+
[...conventionalPaths, ...serverRegistrationPaths],
|
|
7028
7074
|
CONVENTIONAL_ENTRY_KIND_PROBE_TOKEN
|
|
7029
7075
|
),
|
|
7030
7076
|
classifySandboxPathPresenceKindMany(context, localePaths, LOCALE_JSON_KIND_PROBE_TOKEN)
|
|
@@ -7086,6 +7132,7 @@ async function collectCompositionEntryFacts(context, registry) {
|
|
|
7086
7132
|
);
|
|
7087
7133
|
}
|
|
7088
7134
|
}
|
|
7135
|
+
const hasServerRegistrations = hasRealServerRegistrations(modulePath, conventionalPresences);
|
|
7089
7136
|
const rootLocales = localesByDir.get(`${modulePath}/i18n`);
|
|
7090
7137
|
if (rootLocales.length > 0 && !rootLocales.includes("en")) {
|
|
7091
7138
|
throw new Error(
|
|
@@ -7125,6 +7172,7 @@ async function collectCompositionEntryFacts(context, registry) {
|
|
|
7125
7172
|
moduleName: mod.name,
|
|
7126
7173
|
hasRootContributions,
|
|
7127
7174
|
hasRootSlots,
|
|
7175
|
+
hasServerRegistrations,
|
|
7128
7176
|
rootLocales,
|
|
7129
7177
|
enhancements
|
|
7130
7178
|
});
|
|
@@ -7328,6 +7376,7 @@ async function reconcileCompositionArtifacts(context, options = {}) {
|
|
|
7328
7376
|
MODULE_DATASTORES_GEN_PATH,
|
|
7329
7377
|
MODULE_I18N_GEN_PATH,
|
|
7330
7378
|
MODULE_INIT_SERVER_GEN_PATH,
|
|
7379
|
+
MODULE_SERVER_GEN_PATH,
|
|
7331
7380
|
...existingGeneratedPaths,
|
|
7332
7381
|
...Object.keys(existingAppPages),
|
|
7333
7382
|
...Object.keys(existingAppRoutes)
|
package/dist/index.mjs
CHANGED
|
@@ -4119,6 +4119,7 @@ var MODULE_CONTRIBUTIONS_GEN_PATH = `${APP_WEB_PREFIX}src/module-contributions.g
|
|
|
4119
4119
|
var MODULE_DATASTORES_GEN_PATH = `${APP_WEB_PREFIX}src/module-datastores.gen.ts`;
|
|
4120
4120
|
var MODULE_I18N_GEN_PATH = `${APP_WEB_PREFIX}src/module-i18n.gen.ts`;
|
|
4121
4121
|
var MODULE_INIT_SERVER_GEN_PATH = `${APP_WEB_PREFIX}src/module-init.server.gen.ts`;
|
|
4122
|
+
var MODULE_SERVER_GEN_PATH = `${APP_WEB_PREFIX}src/module-server.gen.ts`;
|
|
4122
4123
|
var MODULES_GEN_PATH = `${APP_WEB_PREFIX}src/modules.gen.ts`;
|
|
4123
4124
|
var APP_EXTENSIONS_PATH = `${APP_WEB_PREFIX}src/lib/modules/app-extensions.ts`;
|
|
4124
4125
|
|
|
@@ -4135,7 +4136,8 @@ var COMPOSITION_RUNTIME_GEN_PATHS = [
|
|
|
4135
4136
|
MODULE_CONTRIBUTIONS_GEN_PATH,
|
|
4136
4137
|
MODULE_I18N_GEN_PATH,
|
|
4137
4138
|
MODULE_INIT_SERVER_GEN_PATH,
|
|
4138
|
-
MODULE_DATASTORES_GEN_PATH
|
|
4139
|
+
MODULE_DATASTORES_GEN_PATH,
|
|
4140
|
+
MODULE_SERVER_GEN_PATH
|
|
4139
4141
|
];
|
|
4140
4142
|
function compareNames(a, b) {
|
|
4141
4143
|
return a < b ? -1 : a > b ? 1 : 0;
|
|
@@ -4156,6 +4158,9 @@ function formatI18nMarker() {
|
|
|
4156
4158
|
function formatInitMarker() {
|
|
4157
4159
|
return `// ${MODULE_STUB_MARKER} scope=init`;
|
|
4158
4160
|
}
|
|
4161
|
+
function formatServerMarker() {
|
|
4162
|
+
return `// ${MODULE_STUB_MARKER} scope=server`;
|
|
4163
|
+
}
|
|
4159
4164
|
function formatDatastoresMarker() {
|
|
4160
4165
|
return `// ${MODULE_STUB_MARKER} scope=datastores`;
|
|
4161
4166
|
}
|
|
@@ -4799,6 +4804,42 @@ function emitModuleInitServerGenTs(input) {
|
|
|
4799
4804
|
""
|
|
4800
4805
|
].join("\n");
|
|
4801
4806
|
}
|
|
4807
|
+
function emitModuleServerGenTs(input) {
|
|
4808
|
+
const installed = new Set(input.registry.modules.map((m) => m.name));
|
|
4809
|
+
const moduleNames = input.facts.filter((f) => f.hasServerRegistrations && installed.has(f.moduleName)).map((f) => f.moduleName).sort(compareNames);
|
|
4810
|
+
for (const name of moduleNames) {
|
|
4811
|
+
if (!isValidModuleName(name)) {
|
|
4812
|
+
throw new Error(`[ModuleRail] composition artifacts: invalid module name "${name}"`);
|
|
4813
|
+
}
|
|
4814
|
+
}
|
|
4815
|
+
const importLines = moduleNames.map(
|
|
4816
|
+
(name, index) => [
|
|
4817
|
+
`@/modules/${name}/server/registrations`,
|
|
4818
|
+
`import * as serverRegistrations${index} from ${JSON.stringify(`@/modules/${name}/server/registrations`)};`
|
|
4819
|
+
]
|
|
4820
|
+
).sort((a, b) => compareImportSpecifiers(a[0], b[0])).map(([, line]) => line);
|
|
4821
|
+
const entryLines = moduleNames.map(
|
|
4822
|
+
(name, index) => ` { module: ${JSON.stringify(name)}, registrations: serverRegistrations${index} },`
|
|
4823
|
+
);
|
|
4824
|
+
return [
|
|
4825
|
+
formatServerMarker(),
|
|
4826
|
+
"/** DO NOT EDIT \u2014 owned by the module install rail. */",
|
|
4827
|
+
"",
|
|
4828
|
+
...importLines,
|
|
4829
|
+
...importLines.length > 0 ? [""] : [],
|
|
4830
|
+
"export type ModuleServerRegistration = {",
|
|
4831
|
+
" module: string;",
|
|
4832
|
+
" registrations: Readonly<Record<string, unknown>>;",
|
|
4833
|
+
"};",
|
|
4834
|
+
"",
|
|
4835
|
+
...entryLines.length === 0 ? ["export const MODULE_SERVER_REGISTRATIONS: readonly ModuleServerRegistration[] = [];"] : [
|
|
4836
|
+
"export const MODULE_SERVER_REGISTRATIONS: readonly ModuleServerRegistration[] = [",
|
|
4837
|
+
...entryLines,
|
|
4838
|
+
"];"
|
|
4839
|
+
],
|
|
4840
|
+
""
|
|
4841
|
+
].join("\n");
|
|
4842
|
+
}
|
|
4802
4843
|
|
|
4803
4844
|
// ../../packages/lib/src/server/module-rail/composition-artifacts.ts
|
|
4804
4845
|
var COMPOSITION_ARTIFACTS_GENERATED_BY = "module-rail";
|
|
@@ -4861,6 +4902,14 @@ function formatRouteMarker(owner, nextRelativePath) {
|
|
|
4861
4902
|
function formatRegistryMarker() {
|
|
4862
4903
|
return `// ${MODULE_STUB_MARKER} scope=registry`;
|
|
4863
4904
|
}
|
|
4905
|
+
var OWNERLESS_MARKER_KINDS = [
|
|
4906
|
+
"registry",
|
|
4907
|
+
"contributions",
|
|
4908
|
+
"datastores",
|
|
4909
|
+
"i18n",
|
|
4910
|
+
"init",
|
|
4911
|
+
"server"
|
|
4912
|
+
];
|
|
4864
4913
|
function parseCompositionArtifactMarker(source) {
|
|
4865
4914
|
const firstLine = source.split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
4866
4915
|
const match = firstLine.match(
|
|
@@ -4871,26 +4920,8 @@ function parseCompositionArtifactMarker(source) {
|
|
|
4871
4920
|
if (!match) return null;
|
|
4872
4921
|
const owner = match[1];
|
|
4873
4922
|
const scope = match[2];
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
return { kind: "registry" };
|
|
4877
|
-
}
|
|
4878
|
-
if (scope === "contributions") {
|
|
4879
|
-
if (owner) return null;
|
|
4880
|
-
return { kind: "contributions" };
|
|
4881
|
-
}
|
|
4882
|
-
if (scope === "datastores") {
|
|
4883
|
-
if (owner) return null;
|
|
4884
|
-
return { kind: "datastores" };
|
|
4885
|
-
}
|
|
4886
|
-
if (scope === "i18n") {
|
|
4887
|
-
if (owner) return null;
|
|
4888
|
-
return { kind: "i18n" };
|
|
4889
|
-
}
|
|
4890
|
-
if (scope === "init") {
|
|
4891
|
-
if (owner) return null;
|
|
4892
|
-
return { kind: "init" };
|
|
4893
|
-
}
|
|
4923
|
+
const ownerless = OWNERLESS_MARKER_KINDS.find((kind) => kind === scope);
|
|
4924
|
+
if (ownerless) return owner ? null : { kind: ownerless };
|
|
4894
4925
|
if (!owner || !isValidModuleName(owner)) return null;
|
|
4895
4926
|
if (scope === "route") {
|
|
4896
4927
|
const nextRelativePath = match[3]?.trim();
|
|
@@ -5016,6 +5047,7 @@ function expectedMarkerKindForPath(path3) {
|
|
|
5016
5047
|
if (path3 === MODULE_DATASTORES_GEN_PATH) return "datastores";
|
|
5017
5048
|
if (path3 === MODULE_I18N_GEN_PATH) return "i18n";
|
|
5018
5049
|
if (path3 === MODULE_INIT_SERVER_GEN_PATH) return "init";
|
|
5050
|
+
if (path3 === MODULE_SERVER_GEN_PATH) return "server";
|
|
5019
5051
|
if (path3.startsWith(API_ROUTE_DIR_PREFIX) && path3.endsWith("/route.ts")) return "endpoint";
|
|
5020
5052
|
if (path3.startsWith(APP_DIR_PREFIX) && !path3.startsWith(API_ROUTE_DIR_PREFIX) && PAGE_FILE_SUFFIXES.some((suffix) => path3.endsWith(suffix))) {
|
|
5021
5053
|
return "route";
|
|
@@ -5615,6 +5647,7 @@ function planCompositionArtifacts(input) {
|
|
|
5615
5647
|
let datastoresContent;
|
|
5616
5648
|
let i18nContent;
|
|
5617
5649
|
let initContent;
|
|
5650
|
+
let serverContent;
|
|
5618
5651
|
try {
|
|
5619
5652
|
contributionsContent = emitModuleContributionsGenTs({
|
|
5620
5653
|
registry: input.registry,
|
|
@@ -5639,6 +5672,10 @@ function planCompositionArtifacts(input) {
|
|
|
5639
5672
|
registry: input.registry,
|
|
5640
5673
|
facts: compositionEntryFacts
|
|
5641
5674
|
});
|
|
5675
|
+
serverContent = emitModuleServerGenTs({
|
|
5676
|
+
registry: input.registry,
|
|
5677
|
+
facts: compositionEntryFacts
|
|
5678
|
+
});
|
|
5642
5679
|
} catch (error) {
|
|
5643
5680
|
return {
|
|
5644
5681
|
ok: false,
|
|
@@ -5651,6 +5688,7 @@ function planCompositionArtifacts(input) {
|
|
|
5651
5688
|
desired.set(MODULE_DATASTORES_GEN_PATH, datastoresContent);
|
|
5652
5689
|
desired.set(MODULE_I18N_GEN_PATH, i18nContent);
|
|
5653
5690
|
desired.set(MODULE_INIT_SERVER_GEN_PATH, initContent);
|
|
5691
|
+
desired.set(MODULE_SERVER_GEN_PATH, serverContent);
|
|
5654
5692
|
for (const stub of stubs.endpointStubs) desired.set(stub.path, stub.content);
|
|
5655
5693
|
for (const stub of stubs.routeStubs) desired.set(stub.path, stub.content);
|
|
5656
5694
|
const endpointStubByPath = new Map(stubs.endpointStubs.map((stub) => [stub.path, stub]));
|
|
@@ -6921,6 +6959,7 @@ function readFailurePath(error) {
|
|
|
6921
6959
|
return typeof error === "object" && error !== null && "path" in error ? String(error.path) : "unknown";
|
|
6922
6960
|
}
|
|
6923
6961
|
var CONVENTIONAL_ENTRY_KIND_PROBE_TOKEN = "conventional-entry-kind";
|
|
6962
|
+
var SERVER_REGISTRATIONS_FILE = "server/registrations.ts";
|
|
6924
6963
|
var COMPOSITION_ARTIFACT_KIND_PROBE_TOKEN = "composition-artifact-kind";
|
|
6925
6964
|
async function classifyCompositionArtifactPathKind(context, path3) {
|
|
6926
6965
|
return classifySandboxPathPresenceKind(context, path3, COMPOSITION_ARTIFACT_KIND_PROBE_TOKEN);
|
|
@@ -6958,6 +6997,10 @@ async function readConventionalEntryIfRealFile(path3, kind, presences, files) {
|
|
|
6958
6997
|
}
|
|
6959
6998
|
return source;
|
|
6960
6999
|
}
|
|
7000
|
+
function hasRealServerRegistrations(modulePath, presences) {
|
|
7001
|
+
const path3 = `${modulePath}/${SERVER_REGISTRATIONS_FILE}`;
|
|
7002
|
+
return assertRealCompositionArtifactFilePresence(path3, presences.get(path3) ?? "unreadable") === "file";
|
|
7003
|
+
}
|
|
6961
7004
|
async function readJsonObjectFile(path3, files) {
|
|
6962
7005
|
const raw = files.get(path3);
|
|
6963
7006
|
let parsed;
|
|
@@ -6981,6 +7024,9 @@ async function collectCompositionEntryFacts(context, registry) {
|
|
|
6981
7024
|
const overridesDir = `${APP_PACKAGE_DIR}/src/lib/i18n/overrides`;
|
|
6982
7025
|
const localeDirs = [substrateDir, overridesDir];
|
|
6983
7026
|
const conventionalPaths = [];
|
|
7027
|
+
const serverRegistrationPaths = registry.modules.map(
|
|
7028
|
+
(mod) => `${MODULES_SANDBOX_DIR}/${mod.name}/${SERVER_REGISTRATIONS_FILE}`
|
|
7029
|
+
);
|
|
6984
7030
|
for (const mod of registry.modules) {
|
|
6985
7031
|
const modulePath = `${MODULES_SANDBOX_DIR}/${mod.name}`;
|
|
6986
7032
|
localeDirs.push(`${modulePath}/i18n`);
|
|
@@ -7009,7 +7055,7 @@ async function collectCompositionEntryFacts(context, registry) {
|
|
|
7009
7055
|
const [conventionalPresences, localePresences] = await Promise.all([
|
|
7010
7056
|
classifySandboxPathPresenceKindMany(
|
|
7011
7057
|
context,
|
|
7012
|
-
conventionalPaths,
|
|
7058
|
+
[...conventionalPaths, ...serverRegistrationPaths],
|
|
7013
7059
|
CONVENTIONAL_ENTRY_KIND_PROBE_TOKEN
|
|
7014
7060
|
),
|
|
7015
7061
|
classifySandboxPathPresenceKindMany(context, localePaths, LOCALE_JSON_KIND_PROBE_TOKEN)
|
|
@@ -7071,6 +7117,7 @@ async function collectCompositionEntryFacts(context, registry) {
|
|
|
7071
7117
|
);
|
|
7072
7118
|
}
|
|
7073
7119
|
}
|
|
7120
|
+
const hasServerRegistrations = hasRealServerRegistrations(modulePath, conventionalPresences);
|
|
7074
7121
|
const rootLocales = localesByDir.get(`${modulePath}/i18n`);
|
|
7075
7122
|
if (rootLocales.length > 0 && !rootLocales.includes("en")) {
|
|
7076
7123
|
throw new Error(
|
|
@@ -7110,6 +7157,7 @@ async function collectCompositionEntryFacts(context, registry) {
|
|
|
7110
7157
|
moduleName: mod.name,
|
|
7111
7158
|
hasRootContributions,
|
|
7112
7159
|
hasRootSlots,
|
|
7160
|
+
hasServerRegistrations,
|
|
7113
7161
|
rootLocales,
|
|
7114
7162
|
enhancements
|
|
7115
7163
|
});
|
|
@@ -7313,6 +7361,7 @@ async function reconcileCompositionArtifacts(context, options = {}) {
|
|
|
7313
7361
|
MODULE_DATASTORES_GEN_PATH,
|
|
7314
7362
|
MODULE_I18N_GEN_PATH,
|
|
7315
7363
|
MODULE_INIT_SERVER_GEN_PATH,
|
|
7364
|
+
MODULE_SERVER_GEN_PATH,
|
|
7316
7365
|
...existingGeneratedPaths,
|
|
7317
7366
|
...Object.keys(existingAppPages),
|
|
7318
7367
|
...Object.keys(existingAppRoutes)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stardeck-customer-apps/compose",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Regenerates a Stardeck app's Module-rail artifacts — the
|
|
3
|
+
"version": "0.8.0",
|
|
4
|
+
"description": "Regenerates a Stardeck app's Module-rail artifacts — the six src/*.gen.ts registries and every route/endpoint stub — from src/modules/*/module.json",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
7
7
|
"types": "dist/index.d.ts",
|