@chidchanun/bcp 0.3.1 → 0.3.2
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/docs/api-freeze-snapshot.json +13 -2
- package/docs/api-manifest.json +22 -14
- package/docs/docs-web-manifest.json +6 -4
- package/docs/module-system-v2.md +386 -0
- package/docs/platform-manifest.json +19 -4
- package/docs/releases/0.3.2.md +125 -0
- package/package.json +7 -1
- package/packages/bundler/src/client-boundary.ts +1 -0
- package/packages/client/src/application.mjs +434 -30
- package/packages/client/src/modules.mjs +392 -0
- package/packages/client/src/modules.ts +17 -0
- package/packages/server/src/application.ts +58 -9
- package/packages/server/src/modules.ts +682 -0
|
@@ -1082,6 +1082,382 @@ function withTimeout(promise, timeoutMs, label) {
|
|
|
1082
1082
|
);
|
|
1083
1083
|
}
|
|
1084
1084
|
|
|
1085
|
+
// packages/server/src/modules.ts
|
|
1086
|
+
var MODULE_V2_KIND = "bcp-module-v2";
|
|
1087
|
+
var ModuleDependencyError = class extends Error {
|
|
1088
|
+
constructor(message) {
|
|
1089
|
+
super(message);
|
|
1090
|
+
this.name = "ModuleDependencyError";
|
|
1091
|
+
}
|
|
1092
|
+
};
|
|
1093
|
+
var ModuleLifecycleError = class extends Error {
|
|
1094
|
+
module;
|
|
1095
|
+
phase;
|
|
1096
|
+
cause;
|
|
1097
|
+
constructor(moduleName, phase, cause) {
|
|
1098
|
+
super(
|
|
1099
|
+
`BCP Modules: ${phase} failed for module "${moduleName}": ${formatError(cause)}`
|
|
1100
|
+
);
|
|
1101
|
+
this.name = "ModuleLifecycleError";
|
|
1102
|
+
this.module = moduleName;
|
|
1103
|
+
this.phase = phase;
|
|
1104
|
+
this.cause = cause;
|
|
1105
|
+
}
|
|
1106
|
+
};
|
|
1107
|
+
function isModuleDefinition(value) {
|
|
1108
|
+
return Boolean(
|
|
1109
|
+
value && typeof value === "object" && value.kind === MODULE_V2_KIND
|
|
1110
|
+
);
|
|
1111
|
+
}
|
|
1112
|
+
function composeModules(roots = []) {
|
|
1113
|
+
const ordered = resolveModuleOrder(roots);
|
|
1114
|
+
const providers = [];
|
|
1115
|
+
const plugins = [];
|
|
1116
|
+
const services = [];
|
|
1117
|
+
const resources = [];
|
|
1118
|
+
const serviceKeys = /* @__PURE__ */ new Set();
|
|
1119
|
+
for (const module of ordered) {
|
|
1120
|
+
providers.push(
|
|
1121
|
+
...module.providers ?? []
|
|
1122
|
+
);
|
|
1123
|
+
plugins.push(
|
|
1124
|
+
...module.plugins ?? []
|
|
1125
|
+
);
|
|
1126
|
+
resources.push(
|
|
1127
|
+
...module.resources ?? []
|
|
1128
|
+
);
|
|
1129
|
+
for (const entry of module.services ?? []) {
|
|
1130
|
+
const [key] = entry;
|
|
1131
|
+
if (serviceKeys.has(key)) {
|
|
1132
|
+
throw new ModuleDependencyError(
|
|
1133
|
+
`BCP Modules: duplicate shared service ${formatServiceKey(key)} while composing module "${module.name}".`
|
|
1134
|
+
);
|
|
1135
|
+
}
|
|
1136
|
+
serviceKeys.add(key);
|
|
1137
|
+
services.push(entry);
|
|
1138
|
+
}
|
|
1139
|
+
validateModuleExports(
|
|
1140
|
+
module
|
|
1141
|
+
);
|
|
1142
|
+
}
|
|
1143
|
+
return {
|
|
1144
|
+
modules: ordered,
|
|
1145
|
+
providers,
|
|
1146
|
+
plugins,
|
|
1147
|
+
services,
|
|
1148
|
+
resources,
|
|
1149
|
+
records() {
|
|
1150
|
+
return ordered.map(
|
|
1151
|
+
(module) => ({
|
|
1152
|
+
name: module.name,
|
|
1153
|
+
...module.version ? {
|
|
1154
|
+
version: module.version
|
|
1155
|
+
} : {},
|
|
1156
|
+
imports: (module.imports ?? []).map(
|
|
1157
|
+
(dependency) => dependency.name
|
|
1158
|
+
),
|
|
1159
|
+
providers: (module.providers ?? []).map(
|
|
1160
|
+
(provider) => provider.token.description
|
|
1161
|
+
),
|
|
1162
|
+
exports: (module.exports ?? []).map(
|
|
1163
|
+
(token) => token.description
|
|
1164
|
+
),
|
|
1165
|
+
plugins: (module.plugins ?? []).map(
|
|
1166
|
+
(plugin) => plugin.name
|
|
1167
|
+
),
|
|
1168
|
+
resources: (module.resources ?? []).map(
|
|
1169
|
+
(resource) => resource.name
|
|
1170
|
+
)
|
|
1171
|
+
})
|
|
1172
|
+
);
|
|
1173
|
+
},
|
|
1174
|
+
exportedTokens(moduleName) {
|
|
1175
|
+
const normalized = normalizeName3(
|
|
1176
|
+
moduleName,
|
|
1177
|
+
"module name"
|
|
1178
|
+
);
|
|
1179
|
+
const module = ordered.find(
|
|
1180
|
+
(entry) => entry.name === normalized
|
|
1181
|
+
);
|
|
1182
|
+
if (!module) {
|
|
1183
|
+
throw new ModuleDependencyError(
|
|
1184
|
+
`BCP Modules: module "${normalized}" is not part of this composition.`
|
|
1185
|
+
);
|
|
1186
|
+
}
|
|
1187
|
+
return [
|
|
1188
|
+
...module.exports ?? []
|
|
1189
|
+
];
|
|
1190
|
+
},
|
|
1191
|
+
createLifecycleResources(context) {
|
|
1192
|
+
return ordered.flatMap(
|
|
1193
|
+
(module) => [
|
|
1194
|
+
...module.resources ?? [],
|
|
1195
|
+
createModuleLifecycleResource(
|
|
1196
|
+
module,
|
|
1197
|
+
context
|
|
1198
|
+
)
|
|
1199
|
+
]
|
|
1200
|
+
);
|
|
1201
|
+
}
|
|
1202
|
+
};
|
|
1203
|
+
}
|
|
1204
|
+
function resolveModuleOrder(roots) {
|
|
1205
|
+
const byName = /* @__PURE__ */ new Map();
|
|
1206
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
1207
|
+
const visited = /* @__PURE__ */ new Set();
|
|
1208
|
+
const order = [];
|
|
1209
|
+
const visit = (module, path) => {
|
|
1210
|
+
validateModuleDefinition(module);
|
|
1211
|
+
const name = module.name;
|
|
1212
|
+
const existing = byName.get(name);
|
|
1213
|
+
if (existing && existing !== module) {
|
|
1214
|
+
throw new ModuleDependencyError(
|
|
1215
|
+
`BCP Modules: duplicate module name "${name}" refers to different definitions.`
|
|
1216
|
+
);
|
|
1217
|
+
}
|
|
1218
|
+
byName.set(name, module);
|
|
1219
|
+
if (visited.has(name)) {
|
|
1220
|
+
return;
|
|
1221
|
+
}
|
|
1222
|
+
if (visiting.has(name)) {
|
|
1223
|
+
throw new ModuleDependencyError(
|
|
1224
|
+
`BCP Modules: circular module dependency detected: ${[
|
|
1225
|
+
...path,
|
|
1226
|
+
name
|
|
1227
|
+
].join(" -> ")}.`
|
|
1228
|
+
);
|
|
1229
|
+
}
|
|
1230
|
+
visiting.add(name);
|
|
1231
|
+
for (const dependency of module.imports ?? []) {
|
|
1232
|
+
visit(
|
|
1233
|
+
dependency,
|
|
1234
|
+
[
|
|
1235
|
+
...path,
|
|
1236
|
+
name
|
|
1237
|
+
]
|
|
1238
|
+
);
|
|
1239
|
+
}
|
|
1240
|
+
visiting.delete(name);
|
|
1241
|
+
visited.add(name);
|
|
1242
|
+
order.push(module);
|
|
1243
|
+
};
|
|
1244
|
+
for (const root of roots) {
|
|
1245
|
+
visit(root, []);
|
|
1246
|
+
}
|
|
1247
|
+
return order;
|
|
1248
|
+
}
|
|
1249
|
+
function createModuleLifecycleResource(module, shared) {
|
|
1250
|
+
const config = parseModuleConfig(
|
|
1251
|
+
module.schema,
|
|
1252
|
+
module.config
|
|
1253
|
+
);
|
|
1254
|
+
const context = {
|
|
1255
|
+
name: module.name,
|
|
1256
|
+
config,
|
|
1257
|
+
container: shared.container,
|
|
1258
|
+
services: shared.services,
|
|
1259
|
+
hooks: shared.hooks
|
|
1260
|
+
};
|
|
1261
|
+
let setupComplete = false;
|
|
1262
|
+
let disposed = false;
|
|
1263
|
+
return {
|
|
1264
|
+
name: `bcp:module:${module.name}`,
|
|
1265
|
+
async start() {
|
|
1266
|
+
try {
|
|
1267
|
+
if (!setupComplete) {
|
|
1268
|
+
await runModuleHook(
|
|
1269
|
+
module,
|
|
1270
|
+
"setup",
|
|
1271
|
+
module.setup,
|
|
1272
|
+
context
|
|
1273
|
+
);
|
|
1274
|
+
setupComplete = true;
|
|
1275
|
+
}
|
|
1276
|
+
await runModuleHook(
|
|
1277
|
+
module,
|
|
1278
|
+
"start",
|
|
1279
|
+
module.start,
|
|
1280
|
+
context
|
|
1281
|
+
);
|
|
1282
|
+
} catch (error) {
|
|
1283
|
+
if (!disposed) {
|
|
1284
|
+
disposed = true;
|
|
1285
|
+
try {
|
|
1286
|
+
await runModuleHook(
|
|
1287
|
+
module,
|
|
1288
|
+
"dispose",
|
|
1289
|
+
module.dispose,
|
|
1290
|
+
context
|
|
1291
|
+
);
|
|
1292
|
+
} catch (disposeError) {
|
|
1293
|
+
throw new AggregateError(
|
|
1294
|
+
[
|
|
1295
|
+
error,
|
|
1296
|
+
disposeError
|
|
1297
|
+
],
|
|
1298
|
+
`BCP Modules: startup and cleanup failed for module "${module.name}".`
|
|
1299
|
+
);
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
throw error;
|
|
1303
|
+
}
|
|
1304
|
+
},
|
|
1305
|
+
ready() {
|
|
1306
|
+
return true;
|
|
1307
|
+
},
|
|
1308
|
+
async stop() {
|
|
1309
|
+
const errors = [];
|
|
1310
|
+
try {
|
|
1311
|
+
await runModuleHook(
|
|
1312
|
+
module,
|
|
1313
|
+
"stop",
|
|
1314
|
+
module.stop,
|
|
1315
|
+
context
|
|
1316
|
+
);
|
|
1317
|
+
} catch (error) {
|
|
1318
|
+
errors.push(error);
|
|
1319
|
+
}
|
|
1320
|
+
if (!disposed) {
|
|
1321
|
+
disposed = true;
|
|
1322
|
+
try {
|
|
1323
|
+
await runModuleHook(
|
|
1324
|
+
module,
|
|
1325
|
+
"dispose",
|
|
1326
|
+
module.dispose,
|
|
1327
|
+
context
|
|
1328
|
+
);
|
|
1329
|
+
} catch (error) {
|
|
1330
|
+
errors.push(error);
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
if (errors.length > 0) {
|
|
1334
|
+
throw new AggregateError(
|
|
1335
|
+
errors,
|
|
1336
|
+
`BCP Modules: shutdown failed for module "${module.name}".`
|
|
1337
|
+
);
|
|
1338
|
+
}
|
|
1339
|
+
},
|
|
1340
|
+
diagnostics() {
|
|
1341
|
+
return {
|
|
1342
|
+
name: module.name,
|
|
1343
|
+
...module.version ? {
|
|
1344
|
+
version: module.version
|
|
1345
|
+
} : {},
|
|
1346
|
+
imports: (module.imports ?? []).map(
|
|
1347
|
+
(dependency) => dependency.name
|
|
1348
|
+
),
|
|
1349
|
+
exports: (module.exports ?? []).map(
|
|
1350
|
+
(token) => token.description
|
|
1351
|
+
)
|
|
1352
|
+
};
|
|
1353
|
+
}
|
|
1354
|
+
};
|
|
1355
|
+
}
|
|
1356
|
+
async function runModuleHook(module, phase, hook, context) {
|
|
1357
|
+
if (!hook) {
|
|
1358
|
+
return;
|
|
1359
|
+
}
|
|
1360
|
+
try {
|
|
1361
|
+
await hook(context);
|
|
1362
|
+
} catch (error) {
|
|
1363
|
+
throw new ModuleLifecycleError(
|
|
1364
|
+
module.name,
|
|
1365
|
+
phase,
|
|
1366
|
+
error
|
|
1367
|
+
);
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
function validateModuleDefinition(module) {
|
|
1371
|
+
if (!module || typeof module !== "object") {
|
|
1372
|
+
throw new TypeError(
|
|
1373
|
+
"BCP Modules: module must be an object."
|
|
1374
|
+
);
|
|
1375
|
+
}
|
|
1376
|
+
if (module.kind !== MODULE_V2_KIND) {
|
|
1377
|
+
throw new TypeError(
|
|
1378
|
+
`BCP Modules: module kind must be "${MODULE_V2_KIND}". Use defineModule().`
|
|
1379
|
+
);
|
|
1380
|
+
}
|
|
1381
|
+
normalizeName3(
|
|
1382
|
+
module.name,
|
|
1383
|
+
"module name"
|
|
1384
|
+
);
|
|
1385
|
+
for (const [label, value] of [
|
|
1386
|
+
["imports", module.imports],
|
|
1387
|
+
["providers", module.providers],
|
|
1388
|
+
["exports", module.exports],
|
|
1389
|
+
["plugins", module.plugins],
|
|
1390
|
+
["resources", module.resources]
|
|
1391
|
+
]) {
|
|
1392
|
+
if (value !== void 0 && !Array.isArray(value)) {
|
|
1393
|
+
throw new TypeError(
|
|
1394
|
+
`BCP Modules: ${label} must be an array.`
|
|
1395
|
+
);
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
for (const [phase, hook] of [
|
|
1399
|
+
["setup", module.setup],
|
|
1400
|
+
["start", module.start],
|
|
1401
|
+
["stop", module.stop],
|
|
1402
|
+
["dispose", module.dispose]
|
|
1403
|
+
]) {
|
|
1404
|
+
if (hook !== void 0 && typeof hook !== "function") {
|
|
1405
|
+
throw new TypeError(
|
|
1406
|
+
`BCP Modules: ${phase} must be a function.`
|
|
1407
|
+
);
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
function validateModuleExports(module) {
|
|
1412
|
+
const available = /* @__PURE__ */ new Set();
|
|
1413
|
+
for (const provider of module.providers ?? []) {
|
|
1414
|
+
available.add(
|
|
1415
|
+
provider.token.id
|
|
1416
|
+
);
|
|
1417
|
+
}
|
|
1418
|
+
for (const dependency of module.imports ?? []) {
|
|
1419
|
+
for (const token of dependency.exports ?? []) {
|
|
1420
|
+
available.add(token.id);
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
for (const token of module.exports ?? []) {
|
|
1424
|
+
if (!available.has(token.id)) {
|
|
1425
|
+
throw new ModuleDependencyError(
|
|
1426
|
+
`BCP Modules: module "${module.name}" exports "${token.description}" but does not provide or import it.`
|
|
1427
|
+
);
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
function parseModuleConfig(parser, value) {
|
|
1432
|
+
if (!parser) {
|
|
1433
|
+
return value;
|
|
1434
|
+
}
|
|
1435
|
+
if (typeof parser === "function") {
|
|
1436
|
+
return parser(value);
|
|
1437
|
+
}
|
|
1438
|
+
return parser.parse(value);
|
|
1439
|
+
}
|
|
1440
|
+
function normalizeName3(value, label) {
|
|
1441
|
+
if (typeof value !== "string") {
|
|
1442
|
+
throw new TypeError(
|
|
1443
|
+
`BCP Modules: ${label} must be a string.`
|
|
1444
|
+
);
|
|
1445
|
+
}
|
|
1446
|
+
const normalized = value.trim();
|
|
1447
|
+
if (!normalized) {
|
|
1448
|
+
throw new TypeError(
|
|
1449
|
+
`BCP Modules: ${label} cannot be empty.`
|
|
1450
|
+
);
|
|
1451
|
+
}
|
|
1452
|
+
return normalized;
|
|
1453
|
+
}
|
|
1454
|
+
function formatServiceKey(key) {
|
|
1455
|
+
return typeof key === "symbol" ? key.description ? `Symbol(${key.description})` : key.toString() : key;
|
|
1456
|
+
}
|
|
1457
|
+
function formatError(value) {
|
|
1458
|
+
return value instanceof Error ? value.message : String(value);
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1085
1461
|
// packages/server/src/plugins.ts
|
|
1086
1462
|
var PluginDependencyError = class extends Error {
|
|
1087
1463
|
constructor(message) {
|
|
@@ -1095,7 +1471,7 @@ var PluginLifecycleError = class extends Error {
|
|
|
1095
1471
|
cause;
|
|
1096
1472
|
constructor(plugin, phase, cause) {
|
|
1097
1473
|
super(
|
|
1098
|
-
`BCP Plugins: ${phase} failed for plugin "${plugin}": ${
|
|
1474
|
+
`BCP Plugins: ${phase} failed for plugin "${plugin}": ${formatError2(cause)}`
|
|
1099
1475
|
);
|
|
1100
1476
|
this.name = "PluginLifecycleError";
|
|
1101
1477
|
this.plugin = plugin;
|
|
@@ -1109,7 +1485,7 @@ function defineModule(module) {
|
|
|
1109
1485
|
"BCP Plugins: module must be an object."
|
|
1110
1486
|
);
|
|
1111
1487
|
}
|
|
1112
|
-
|
|
1488
|
+
normalizeName4(
|
|
1113
1489
|
module.name,
|
|
1114
1490
|
"module name"
|
|
1115
1491
|
);
|
|
@@ -1130,7 +1506,7 @@ function createPluginServiceRegistry(initial) {
|
|
|
1130
1506
|
assertServiceKey(key);
|
|
1131
1507
|
if (values.has(key)) {
|
|
1132
1508
|
throw new Error(
|
|
1133
|
-
`BCP Plugins: duplicate initial service ${
|
|
1509
|
+
`BCP Plugins: duplicate initial service ${formatServiceKey2(key)}.`
|
|
1134
1510
|
);
|
|
1135
1511
|
}
|
|
1136
1512
|
values.set(key, value);
|
|
@@ -1141,7 +1517,7 @@ function createPluginServiceRegistry(initial) {
|
|
|
1141
1517
|
assertServiceKey(key);
|
|
1142
1518
|
if (values.has(key) && !options.replace) {
|
|
1143
1519
|
throw new Error(
|
|
1144
|
-
`BCP Plugins: service ${
|
|
1520
|
+
`BCP Plugins: service ${formatServiceKey2(key)} is already registered.`
|
|
1145
1521
|
);
|
|
1146
1522
|
}
|
|
1147
1523
|
values.set(key, value);
|
|
@@ -1150,7 +1526,7 @@ function createPluginServiceRegistry(initial) {
|
|
|
1150
1526
|
assertServiceKey(key);
|
|
1151
1527
|
if (!values.has(key)) {
|
|
1152
1528
|
throw new Error(
|
|
1153
|
-
`BCP Plugins: service ${
|
|
1529
|
+
`BCP Plugins: service ${formatServiceKey2(key)} is not registered.`
|
|
1154
1530
|
);
|
|
1155
1531
|
}
|
|
1156
1532
|
return values.get(key);
|
|
@@ -1179,7 +1555,7 @@ function createPluginHookBus() {
|
|
|
1179
1555
|
const hooks = /* @__PURE__ */ new Map();
|
|
1180
1556
|
const bus = {
|
|
1181
1557
|
on(name, handler) {
|
|
1182
|
-
const normalized =
|
|
1558
|
+
const normalized = normalizeName4(
|
|
1183
1559
|
name,
|
|
1184
1560
|
"hook name"
|
|
1185
1561
|
);
|
|
@@ -1209,7 +1585,7 @@ function createPluginHookBus() {
|
|
|
1209
1585
|
};
|
|
1210
1586
|
},
|
|
1211
1587
|
async emit(name, payload) {
|
|
1212
|
-
const normalized =
|
|
1588
|
+
const normalized = normalizeName4(
|
|
1213
1589
|
name,
|
|
1214
1590
|
"hook name"
|
|
1215
1591
|
);
|
|
@@ -1225,7 +1601,7 @@ function createPluginHookBus() {
|
|
|
1225
1601
|
},
|
|
1226
1602
|
listenerCount(name) {
|
|
1227
1603
|
return hooks.get(
|
|
1228
|
-
|
|
1604
|
+
normalizeName4(
|
|
1229
1605
|
name,
|
|
1230
1606
|
"hook name"
|
|
1231
1607
|
)
|
|
@@ -1237,7 +1613,7 @@ function createPluginHookBus() {
|
|
|
1237
1613
|
return;
|
|
1238
1614
|
}
|
|
1239
1615
|
hooks.delete(
|
|
1240
|
-
|
|
1616
|
+
normalizeName4(
|
|
1241
1617
|
name,
|
|
1242
1618
|
"hook name"
|
|
1243
1619
|
)
|
|
@@ -1470,7 +1846,7 @@ function createPluginHost(options = {}) {
|
|
|
1470
1846
|
},
|
|
1471
1847
|
plugin(name) {
|
|
1472
1848
|
const entry = entries.get(
|
|
1473
|
-
|
|
1849
|
+
normalizeName4(
|
|
1474
1850
|
name,
|
|
1475
1851
|
"plugin name"
|
|
1476
1852
|
)
|
|
@@ -1504,7 +1880,7 @@ function createPluginHost(options = {}) {
|
|
|
1504
1880
|
validatePluginDefinition(
|
|
1505
1881
|
definition
|
|
1506
1882
|
);
|
|
1507
|
-
const name =
|
|
1883
|
+
const name = normalizeName4(
|
|
1508
1884
|
definition.name,
|
|
1509
1885
|
"plugin name"
|
|
1510
1886
|
);
|
|
@@ -1721,7 +2097,7 @@ function validatePluginDefinition(definition) {
|
|
|
1721
2097
|
"BCP Plugins: plugin definition must be an object."
|
|
1722
2098
|
);
|
|
1723
2099
|
}
|
|
1724
|
-
const name =
|
|
2100
|
+
const name = normalizeName4(
|
|
1725
2101
|
definition.name,
|
|
1726
2102
|
"plugin name"
|
|
1727
2103
|
);
|
|
@@ -1764,7 +2140,7 @@ function normalizeDependencyList(value, plugin, field) {
|
|
|
1764
2140
|
);
|
|
1765
2141
|
}
|
|
1766
2142
|
const normalized = value.map(
|
|
1767
|
-
(item) =>
|
|
2143
|
+
(item) => normalizeName4(
|
|
1768
2144
|
item,
|
|
1769
2145
|
`${field} dependency`
|
|
1770
2146
|
)
|
|
@@ -1805,7 +2181,7 @@ function requireContext(entry) {
|
|
|
1805
2181
|
}
|
|
1806
2182
|
function markFailed(entry, error) {
|
|
1807
2183
|
entry.record.state = "failed";
|
|
1808
|
-
entry.record.error =
|
|
2184
|
+
entry.record.error = formatError2(error);
|
|
1809
2185
|
}
|
|
1810
2186
|
function cloneRecord(record) {
|
|
1811
2187
|
return {
|
|
@@ -1825,7 +2201,7 @@ function isPluginModule(value) {
|
|
|
1825
2201
|
)
|
|
1826
2202
|
);
|
|
1827
2203
|
}
|
|
1828
|
-
function
|
|
2204
|
+
function normalizeName4(value, field) {
|
|
1829
2205
|
const text = String(value ?? "").trim();
|
|
1830
2206
|
if (!text) {
|
|
1831
2207
|
throw new TypeError(
|
|
@@ -1843,14 +2219,14 @@ function normalizeOptionalVersion(value) {
|
|
|
1843
2219
|
if (value === void 0) {
|
|
1844
2220
|
return void 0;
|
|
1845
2221
|
}
|
|
1846
|
-
return
|
|
2222
|
+
return normalizeName4(
|
|
1847
2223
|
value,
|
|
1848
2224
|
"plugin version"
|
|
1849
2225
|
);
|
|
1850
2226
|
}
|
|
1851
2227
|
function assertServiceKey(key) {
|
|
1852
2228
|
if (typeof key === "string") {
|
|
1853
|
-
|
|
2229
|
+
normalizeName4(
|
|
1854
2230
|
key,
|
|
1855
2231
|
"service key"
|
|
1856
2232
|
);
|
|
@@ -1862,10 +2238,10 @@ function assertServiceKey(key) {
|
|
|
1862
2238
|
);
|
|
1863
2239
|
}
|
|
1864
2240
|
}
|
|
1865
|
-
function
|
|
2241
|
+
function formatServiceKey2(key) {
|
|
1866
2242
|
return typeof key === "symbol" ? String(key) : `"${key}"`;
|
|
1867
2243
|
}
|
|
1868
|
-
function
|
|
2244
|
+
function formatError2(error) {
|
|
1869
2245
|
if (error instanceof Error) {
|
|
1870
2246
|
return error.message || error.name;
|
|
1871
2247
|
}
|
|
@@ -1889,7 +2265,7 @@ var ApplicationLifecycleError = class extends Error {
|
|
|
1889
2265
|
cause;
|
|
1890
2266
|
constructor(phase, cause) {
|
|
1891
2267
|
super(
|
|
1892
|
-
`BCP Application: ${phase} failed: ${
|
|
2268
|
+
`BCP Application: ${phase} failed: ${formatError3(cause)}`
|
|
1893
2269
|
);
|
|
1894
2270
|
this.name = "ApplicationLifecycleError";
|
|
1895
2271
|
this.phase = phase;
|
|
@@ -1902,7 +2278,7 @@ function defineApp(definition) {
|
|
|
1902
2278
|
}
|
|
1903
2279
|
function createApp(definition) {
|
|
1904
2280
|
defineApp(definition);
|
|
1905
|
-
const name =
|
|
2281
|
+
const name = normalizeName5(
|
|
1906
2282
|
definition.name,
|
|
1907
2283
|
"application name"
|
|
1908
2284
|
);
|
|
@@ -1913,15 +2289,33 @@ function createApp(definition) {
|
|
|
1913
2289
|
definition.schema,
|
|
1914
2290
|
definition.config
|
|
1915
2291
|
);
|
|
2292
|
+
const moduleInputs = definition.modules ?? [];
|
|
2293
|
+
const modules = composeModules(
|
|
2294
|
+
moduleInputs.filter(
|
|
2295
|
+
isModuleDefinition
|
|
2296
|
+
)
|
|
2297
|
+
);
|
|
2298
|
+
const legacyModules = moduleInputs.filter(
|
|
2299
|
+
(module) => !isModuleDefinition(module)
|
|
2300
|
+
);
|
|
1916
2301
|
const container = createServiceContainer({
|
|
1917
2302
|
name: `${name}:container`,
|
|
1918
|
-
providers:
|
|
2303
|
+
providers: [
|
|
2304
|
+
...modules.providers,
|
|
2305
|
+
...definition.providers ?? []
|
|
2306
|
+
]
|
|
1919
2307
|
});
|
|
1920
2308
|
const plugins = createPluginHost({
|
|
1921
|
-
plugins:
|
|
1922
|
-
|
|
2309
|
+
plugins: [
|
|
2310
|
+
...modules.plugins,
|
|
2311
|
+
...definition.plugins ?? []
|
|
2312
|
+
],
|
|
2313
|
+
modules: legacyModules,
|
|
1923
2314
|
configs: definition.pluginConfigs,
|
|
1924
|
-
services:
|
|
2315
|
+
services: [
|
|
2316
|
+
...modules.services,
|
|
2317
|
+
...definition.services ?? []
|
|
2318
|
+
]
|
|
1925
2319
|
});
|
|
1926
2320
|
const deployment = createDeploymentRuntime({
|
|
1927
2321
|
...definition.deployment ?? {},
|
|
@@ -1944,6 +2338,7 @@ function createApp(definition) {
|
|
|
1944
2338
|
} : {},
|
|
1945
2339
|
config,
|
|
1946
2340
|
container,
|
|
2341
|
+
modules,
|
|
1947
2342
|
services: plugins.services,
|
|
1948
2343
|
hooks: plugins.hooks,
|
|
1949
2344
|
plugins,
|
|
@@ -1999,6 +2394,13 @@ function createApp(definition) {
|
|
|
1999
2394
|
};
|
|
2000
2395
|
}
|
|
2001
2396
|
});
|
|
2397
|
+
for (const resource of modules.createLifecycleResources({
|
|
2398
|
+
container,
|
|
2399
|
+
services: plugins.services,
|
|
2400
|
+
hooks: plugins.hooks
|
|
2401
|
+
})) {
|
|
2402
|
+
deployment.addResource(resource);
|
|
2403
|
+
}
|
|
2002
2404
|
for (const resource of definition.resources ?? []) {
|
|
2003
2405
|
deployment.addResource(resource);
|
|
2004
2406
|
}
|
|
@@ -2010,6 +2412,7 @@ function createApp(definition) {
|
|
|
2010
2412
|
config,
|
|
2011
2413
|
context,
|
|
2012
2414
|
container,
|
|
2415
|
+
modules,
|
|
2013
2416
|
services: plugins.services,
|
|
2014
2417
|
hooks: plugins.hooks,
|
|
2015
2418
|
plugins,
|
|
@@ -2272,11 +2675,12 @@ function createApp(definition) {
|
|
|
2272
2675
|
} : {},
|
|
2273
2676
|
state,
|
|
2274
2677
|
services: plugins.services.keys().map(
|
|
2275
|
-
|
|
2678
|
+
formatServiceKey3
|
|
2276
2679
|
),
|
|
2277
2680
|
containerProviders: container.graph().map(
|
|
2278
2681
|
(node) => node.description
|
|
2279
2682
|
),
|
|
2683
|
+
modules: modules.records(),
|
|
2280
2684
|
pluginCount: plugins.plugins().length
|
|
2281
2685
|
};
|
|
2282
2686
|
}
|
|
@@ -2358,7 +2762,7 @@ function validateDefinition(definition) {
|
|
|
2358
2762
|
"BCP Application: definition must be an object."
|
|
2359
2763
|
);
|
|
2360
2764
|
}
|
|
2361
|
-
|
|
2765
|
+
normalizeName5(
|
|
2362
2766
|
definition.name,
|
|
2363
2767
|
"application name"
|
|
2364
2768
|
);
|
|
@@ -2398,7 +2802,7 @@ function validateDefinition(definition) {
|
|
|
2398
2802
|
}
|
|
2399
2803
|
}
|
|
2400
2804
|
}
|
|
2401
|
-
function
|
|
2805
|
+
function normalizeName5(value, label) {
|
|
2402
2806
|
if (typeof value !== "string") {
|
|
2403
2807
|
throw new TypeError(
|
|
2404
2808
|
`BCP Application: ${label} must be a string.`
|
|
@@ -2423,10 +2827,10 @@ function normalizeOptionalText2(value) {
|
|
|
2423
2827
|
}
|
|
2424
2828
|
return value.trim() || void 0;
|
|
2425
2829
|
}
|
|
2426
|
-
function
|
|
2830
|
+
function formatServiceKey3(key) {
|
|
2427
2831
|
return typeof key === "symbol" ? key.description ? `Symbol(${key.description})` : key.toString() : key;
|
|
2428
2832
|
}
|
|
2429
|
-
function
|
|
2833
|
+
function formatError3(value) {
|
|
2430
2834
|
if (value instanceof Error) {
|
|
2431
2835
|
return value.message;
|
|
2432
2836
|
}
|