flowdular 0.2.4 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/distribution.js +593 -137
- package/dist/index.js +7737 -5521
- package/package.json +2 -2
package/dist/distribution.js
CHANGED
|
@@ -534,7 +534,7 @@ var require_inc = __commonJS({
|
|
|
534
534
|
"../../node_modules/.pnpm/semver@7.7.4/node_modules/semver/functions/inc.js"(exports, module) {
|
|
535
535
|
"use strict";
|
|
536
536
|
var SemVer = require_semver();
|
|
537
|
-
var
|
|
537
|
+
var inc2 = (version, release, options, identifier2, identifierBase) => {
|
|
538
538
|
if (typeof options === "string") {
|
|
539
539
|
identifierBase = identifier2;
|
|
540
540
|
identifier2 = options;
|
|
@@ -549,7 +549,7 @@ var require_inc = __commonJS({
|
|
|
549
549
|
return null;
|
|
550
550
|
}
|
|
551
551
|
};
|
|
552
|
-
module.exports =
|
|
552
|
+
module.exports = inc2;
|
|
553
553
|
}
|
|
554
554
|
});
|
|
555
555
|
|
|
@@ -1874,7 +1874,7 @@ var require_semver2 = __commonJS({
|
|
|
1874
1874
|
var parse = require_parse();
|
|
1875
1875
|
var valid2 = require_valid();
|
|
1876
1876
|
var clean = require_clean();
|
|
1877
|
-
var
|
|
1877
|
+
var inc2 = require_inc();
|
|
1878
1878
|
var diff = require_diff();
|
|
1879
1879
|
var major = require_major();
|
|
1880
1880
|
var minor = require_minor();
|
|
@@ -1912,7 +1912,7 @@ var require_semver2 = __commonJS({
|
|
|
1912
1912
|
parse,
|
|
1913
1913
|
valid: valid2,
|
|
1914
1914
|
clean,
|
|
1915
|
-
inc,
|
|
1915
|
+
inc: inc2,
|
|
1916
1916
|
diff,
|
|
1917
1917
|
major,
|
|
1918
1918
|
minor,
|
|
@@ -1974,132 +1974,12 @@ var RegistryError = class extends Error {
|
|
|
1974
1974
|
}
|
|
1975
1975
|
};
|
|
1976
1976
|
|
|
1977
|
+
// ../kernel/src/acl.ts
|
|
1978
|
+
var ALLOWED = Object.freeze({ allowed: true });
|
|
1979
|
+
var NO_POLICIES = Object.freeze([]);
|
|
1980
|
+
|
|
1977
1981
|
// ../kernel/src/module-compatibility.ts
|
|
1978
1982
|
var import_semver = __toESM(require_semver2(), 1);
|
|
1979
|
-
var PLATFORM_API_VERSION = "0.1.0";
|
|
1980
|
-
function satisfiesModuleVersion(version, range) {
|
|
1981
|
-
return (0, import_semver.valid)(version) !== null && (0, import_semver.validRange)(range) !== null && (0, import_semver.satisfies)(version, range);
|
|
1982
|
-
}
|
|
1983
|
-
function compareModuleVersions(left, right) {
|
|
1984
|
-
return (0, import_semver.rcompare)(left, right);
|
|
1985
|
-
}
|
|
1986
|
-
function assertModuleCompatibility(manifest, platformVersion = PLATFORM_API_VERSION) {
|
|
1987
|
-
if (!(0, import_semver.valid)(manifest.version))
|
|
1988
|
-
throw new RegistryError(
|
|
1989
|
-
"MODULE_VERSION_INVALID",
|
|
1990
|
-
`Invalid version for ${manifest.id}: ${manifest.version}`
|
|
1991
|
-
);
|
|
1992
|
-
if (manifest.platformApi !== void 0 && (!(0, import_semver.validRange)(manifest.platformApi) || platformVersion !== null && !satisfiesModuleVersion(platformVersion, manifest.platformApi))) {
|
|
1993
|
-
throw new RegistryError(
|
|
1994
|
-
"MODULE_PLATFORM_INCOMPATIBLE",
|
|
1995
|
-
`${manifest.id} requires platform API ${manifest.platformApi}; available ${PLATFORM_API_VERSION}.`
|
|
1996
|
-
);
|
|
1997
|
-
}
|
|
1998
|
-
const ids = /* @__PURE__ */ new Set();
|
|
1999
|
-
for (const dependency of manifest.dependencies) {
|
|
2000
|
-
if (!dependency.range.trim() || !(0, import_semver.validRange)(dependency.range))
|
|
2001
|
-
throw new RegistryError(
|
|
2002
|
-
"MODULE_RANGE_INVALID",
|
|
2003
|
-
`${manifest.id} declares an invalid range for ${dependency.id}: ${dependency.range}`
|
|
2004
|
-
);
|
|
2005
|
-
if (ids.has(dependency.id))
|
|
2006
|
-
throw new RegistryError(
|
|
2007
|
-
"MODULE_DEPENDENCY_DUPLICATE",
|
|
2008
|
-
`${manifest.id} declares ${dependency.id} more than once.`
|
|
2009
|
-
);
|
|
2010
|
-
ids.add(dependency.id);
|
|
2011
|
-
}
|
|
2012
|
-
}
|
|
2013
|
-
function assertModuleDependency(consumer, dependency, version) {
|
|
2014
|
-
if (!satisfiesModuleVersion(version, dependency.range)) {
|
|
2015
|
-
throw new RegistryError(
|
|
2016
|
-
"MODULE_DEPENDENCY_INCOMPATIBLE",
|
|
2017
|
-
`${consumer} requires ${dependency.id} ${dependency.range}; available ${version}.`
|
|
2018
|
-
);
|
|
2019
|
-
}
|
|
2020
|
-
}
|
|
2021
|
-
|
|
2022
|
-
// ../kernel/src/module-registry.ts
|
|
2023
|
-
function compareModules(left, right) {
|
|
2024
|
-
return left.manifest.id.localeCompare(right.manifest.id);
|
|
2025
|
-
}
|
|
2026
|
-
function visitModule(id, modules, visiting, visited, ordered) {
|
|
2027
|
-
if (visited.has(id)) return;
|
|
2028
|
-
if (visiting.has(id)) {
|
|
2029
|
-
throw new RegistryError(
|
|
2030
|
-
"MODULE_DEPENDENCY_CYCLE",
|
|
2031
|
-
`Dependency cycle detected at "${id}".`
|
|
2032
|
-
);
|
|
2033
|
-
}
|
|
2034
|
-
const current = modules.get(id);
|
|
2035
|
-
if (!current) {
|
|
2036
|
-
throw new RegistryError(
|
|
2037
|
-
"MODULE_NOT_FOUND",
|
|
2038
|
-
`Module "${id}" is not registered.`
|
|
2039
|
-
);
|
|
2040
|
-
}
|
|
2041
|
-
visiting.add(id);
|
|
2042
|
-
for (const dependency of [...current.manifest.dependencies].sort(
|
|
2043
|
-
(a, b) => a.id.localeCompare(b.id)
|
|
2044
|
-
)) {
|
|
2045
|
-
if (!modules.has(dependency.id)) {
|
|
2046
|
-
throw new RegistryError(
|
|
2047
|
-
"MODULE_DEPENDENCY_MISSING",
|
|
2048
|
-
`Module "${id}" requires missing module "${dependency.id}".`
|
|
2049
|
-
);
|
|
2050
|
-
}
|
|
2051
|
-
assertModuleDependency(
|
|
2052
|
-
id,
|
|
2053
|
-
dependency,
|
|
2054
|
-
modules.get(dependency.id).manifest.version
|
|
2055
|
-
);
|
|
2056
|
-
visitModule(dependency.id, modules, visiting, visited, ordered);
|
|
2057
|
-
}
|
|
2058
|
-
visiting.delete(id);
|
|
2059
|
-
visited.add(id);
|
|
2060
|
-
ordered.push(current);
|
|
2061
|
-
}
|
|
2062
|
-
function createModuleRegistry(input) {
|
|
2063
|
-
const byId = /* @__PURE__ */ new Map();
|
|
2064
|
-
const navigationIds = /* @__PURE__ */ new Set();
|
|
2065
|
-
for (const module of input) {
|
|
2066
|
-
assertModuleCompatibility(module.manifest);
|
|
2067
|
-
if (byId.has(module.manifest.id)) {
|
|
2068
|
-
throw new RegistryError(
|
|
2069
|
-
"MODULE_DUPLICATE",
|
|
2070
|
-
`Module "${module.manifest.id}" is registered more than once.`
|
|
2071
|
-
);
|
|
2072
|
-
}
|
|
2073
|
-
byId.set(module.manifest.id, module);
|
|
2074
|
-
for (const item of module.navigation ?? []) {
|
|
2075
|
-
if (navigationIds.has(item.id)) {
|
|
2076
|
-
throw new RegistryError(
|
|
2077
|
-
"NAVIGATION_DUPLICATE",
|
|
2078
|
-
`Navigation contribution "${item.id}" is registered more than once.`
|
|
2079
|
-
);
|
|
2080
|
-
}
|
|
2081
|
-
navigationIds.add(item.id);
|
|
2082
|
-
}
|
|
2083
|
-
}
|
|
2084
|
-
const ordered = [];
|
|
2085
|
-
const visiting = /* @__PURE__ */ new Set();
|
|
2086
|
-
const visited = /* @__PURE__ */ new Set();
|
|
2087
|
-
for (const module of [...input].sort(compareModules)) {
|
|
2088
|
-
visitModule(module.manifest.id, byId, visiting, visited, ordered);
|
|
2089
|
-
}
|
|
2090
|
-
return Object.freeze({
|
|
2091
|
-
modules: Object.freeze(ordered),
|
|
2092
|
-
get: (id) => byId.get(id),
|
|
2093
|
-
has: (id) => byId.has(id),
|
|
2094
|
-
navigation: (permissions) => Object.freeze(
|
|
2095
|
-
ordered.flatMap((module) => module.navigation ?? []).filter(
|
|
2096
|
-
(item) => !item.permission || permissions?.has(item.permission)
|
|
2097
|
-
).sort(
|
|
2098
|
-
(left, right) => (left.order ?? 1e3) - (right.order ?? 1e3) || left.id.localeCompare(right.id)
|
|
2099
|
-
)
|
|
2100
|
-
)
|
|
2101
|
-
});
|
|
2102
|
-
}
|
|
2103
1983
|
|
|
2104
1984
|
// ../contracts/schemas/blueprint.schema.json
|
|
2105
1985
|
var blueprint_schema_default = {
|
|
@@ -2315,6 +2195,31 @@ var module_schema_default = {
|
|
|
2315
2195
|
}
|
|
2316
2196
|
}
|
|
2317
2197
|
},
|
|
2198
|
+
provides: {
|
|
2199
|
+
type: "array",
|
|
2200
|
+
items: {
|
|
2201
|
+
type: "string",
|
|
2202
|
+
pattern: "^[a-z][a-z0-9-]*(\\.[a-z][a-z0-9-]*)+$"
|
|
2203
|
+
},
|
|
2204
|
+
uniqueItems: true
|
|
2205
|
+
},
|
|
2206
|
+
requires: {
|
|
2207
|
+
type: "array",
|
|
2208
|
+
items: {
|
|
2209
|
+
type: "object",
|
|
2210
|
+
additionalProperties: false,
|
|
2211
|
+
required: ["id"],
|
|
2212
|
+
properties: {
|
|
2213
|
+
id: {
|
|
2214
|
+
type: "string",
|
|
2215
|
+
pattern: "^[a-z][a-z0-9-]*(\\.[a-z][a-z0-9-]*)+$"
|
|
2216
|
+
},
|
|
2217
|
+
optional: {
|
|
2218
|
+
type: "boolean"
|
|
2219
|
+
}
|
|
2220
|
+
}
|
|
2221
|
+
}
|
|
2222
|
+
},
|
|
2318
2223
|
tenancy: {
|
|
2319
2224
|
enum: ["required", "optional", "none"]
|
|
2320
2225
|
},
|
|
@@ -2422,7 +2327,7 @@ var module_spec_schema_default = {
|
|
|
2422
2327
|
],
|
|
2423
2328
|
properties: {
|
|
2424
2329
|
$schema: { type: "string" },
|
|
2425
|
-
schemaVersion: {
|
|
2330
|
+
schemaVersion: { enum: [1, 2] },
|
|
2426
2331
|
id: {
|
|
2427
2332
|
type: "string",
|
|
2428
2333
|
pattern: "^[a-z][a-z0-9-]*(\\.[a-z][a-z0-9-]*)+$"
|
|
@@ -2463,6 +2368,29 @@ var module_spec_schema_default = {
|
|
|
2463
2368
|
}
|
|
2464
2369
|
}
|
|
2465
2370
|
},
|
|
2371
|
+
provides: {
|
|
2372
|
+
type: "array",
|
|
2373
|
+
items: {
|
|
2374
|
+
type: "string",
|
|
2375
|
+
pattern: "^[a-z][a-z0-9-]*(\\.[a-z][a-z0-9-]*)+$"
|
|
2376
|
+
},
|
|
2377
|
+
uniqueItems: true
|
|
2378
|
+
},
|
|
2379
|
+
requires: {
|
|
2380
|
+
type: "array",
|
|
2381
|
+
items: {
|
|
2382
|
+
type: "object",
|
|
2383
|
+
additionalProperties: false,
|
|
2384
|
+
required: ["id"],
|
|
2385
|
+
properties: {
|
|
2386
|
+
id: {
|
|
2387
|
+
type: "string",
|
|
2388
|
+
pattern: "^[a-z][a-z0-9-]*(\\.[a-z][a-z0-9-]*)+$"
|
|
2389
|
+
},
|
|
2390
|
+
optional: { type: "boolean" }
|
|
2391
|
+
}
|
|
2392
|
+
}
|
|
2393
|
+
},
|
|
2466
2394
|
tenancy: { enum: ["required", "optional", "none"] },
|
|
2467
2395
|
locales: {
|
|
2468
2396
|
type: "array",
|
|
@@ -2510,6 +2438,269 @@ var module_spec_schema_default = {
|
|
|
2510
2438
|
}
|
|
2511
2439
|
},
|
|
2512
2440
|
uniqueItems: true
|
|
2441
|
+
},
|
|
2442
|
+
entities: {
|
|
2443
|
+
type: "array",
|
|
2444
|
+
items: { $ref: "#/$defs/entity" },
|
|
2445
|
+
uniqueItems: true
|
|
2446
|
+
},
|
|
2447
|
+
screens: {
|
|
2448
|
+
type: "array",
|
|
2449
|
+
items: { $ref: "#/$defs/screen" },
|
|
2450
|
+
uniqueItems: true
|
|
2451
|
+
},
|
|
2452
|
+
actions: {
|
|
2453
|
+
type: "array",
|
|
2454
|
+
items: { $ref: "#/$defs/action" },
|
|
2455
|
+
uniqueItems: true
|
|
2456
|
+
},
|
|
2457
|
+
widgets: {
|
|
2458
|
+
type: "array",
|
|
2459
|
+
items: { $ref: "#/$defs/widget" },
|
|
2460
|
+
uniqueItems: true
|
|
2461
|
+
},
|
|
2462
|
+
settings: {
|
|
2463
|
+
type: "array",
|
|
2464
|
+
items: { $ref: "#/$defs/setting" },
|
|
2465
|
+
uniqueItems: true
|
|
2466
|
+
},
|
|
2467
|
+
agentTools: {
|
|
2468
|
+
type: "array",
|
|
2469
|
+
items: { $ref: "#/$defs/agentTool" },
|
|
2470
|
+
uniqueItems: true
|
|
2471
|
+
},
|
|
2472
|
+
outOfScope: {
|
|
2473
|
+
type: "array",
|
|
2474
|
+
items: { type: "string", minLength: 1 },
|
|
2475
|
+
uniqueItems: true
|
|
2476
|
+
},
|
|
2477
|
+
decisions: {
|
|
2478
|
+
type: "array",
|
|
2479
|
+
items: { $ref: "#/$defs/decision" },
|
|
2480
|
+
uniqueItems: true
|
|
2481
|
+
}
|
|
2482
|
+
},
|
|
2483
|
+
allOf: [
|
|
2484
|
+
{
|
|
2485
|
+
if: {
|
|
2486
|
+
required: ["schemaVersion"],
|
|
2487
|
+
properties: { schemaVersion: { const: 1 } }
|
|
2488
|
+
},
|
|
2489
|
+
then: {
|
|
2490
|
+
properties: {
|
|
2491
|
+
entities: false,
|
|
2492
|
+
screens: false,
|
|
2493
|
+
actions: false,
|
|
2494
|
+
widgets: false,
|
|
2495
|
+
settings: false,
|
|
2496
|
+
agentTools: false,
|
|
2497
|
+
outOfScope: false,
|
|
2498
|
+
decisions: false
|
|
2499
|
+
}
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2502
|
+
],
|
|
2503
|
+
$defs: {
|
|
2504
|
+
entityId: { type: "string", pattern: "^[a-z][a-z0-9-]*$" },
|
|
2505
|
+
fieldId: { type: "string", pattern: "^[a-z][a-zA-Z0-9]*$" },
|
|
2506
|
+
enumValue: { type: "string", pattern: "^[a-z][a-z0-9_-]*$" },
|
|
2507
|
+
entity: {
|
|
2508
|
+
type: "object",
|
|
2509
|
+
additionalProperties: false,
|
|
2510
|
+
required: ["id", "name", "fields"],
|
|
2511
|
+
properties: {
|
|
2512
|
+
id: { $ref: "#/$defs/entityId" },
|
|
2513
|
+
name: { type: "string", minLength: 1 },
|
|
2514
|
+
description: { type: "string", minLength: 1 },
|
|
2515
|
+
fields: {
|
|
2516
|
+
type: "array",
|
|
2517
|
+
minItems: 1,
|
|
2518
|
+
items: { $ref: "#/$defs/field" },
|
|
2519
|
+
uniqueItems: true
|
|
2520
|
+
},
|
|
2521
|
+
states: {
|
|
2522
|
+
type: "object",
|
|
2523
|
+
additionalProperties: false,
|
|
2524
|
+
required: ["field", "values"],
|
|
2525
|
+
properties: {
|
|
2526
|
+
field: { $ref: "#/$defs/fieldId" },
|
|
2527
|
+
values: {
|
|
2528
|
+
type: "array",
|
|
2529
|
+
minItems: 1,
|
|
2530
|
+
items: { $ref: "#/$defs/enumValue" },
|
|
2531
|
+
uniqueItems: true
|
|
2532
|
+
},
|
|
2533
|
+
transitions: {
|
|
2534
|
+
type: "array",
|
|
2535
|
+
items: {
|
|
2536
|
+
type: "object",
|
|
2537
|
+
additionalProperties: false,
|
|
2538
|
+
required: ["from", "to"],
|
|
2539
|
+
properties: {
|
|
2540
|
+
from: { type: "string", minLength: 1 },
|
|
2541
|
+
to: { type: "string", minLength: 1 },
|
|
2542
|
+
permission: { type: "string", minLength: 1 }
|
|
2543
|
+
}
|
|
2544
|
+
},
|
|
2545
|
+
uniqueItems: true
|
|
2546
|
+
}
|
|
2547
|
+
}
|
|
2548
|
+
}
|
|
2549
|
+
}
|
|
2550
|
+
},
|
|
2551
|
+
field: {
|
|
2552
|
+
type: "object",
|
|
2553
|
+
additionalProperties: false,
|
|
2554
|
+
required: ["id", "type"],
|
|
2555
|
+
properties: {
|
|
2556
|
+
id: { $ref: "#/$defs/fieldId" },
|
|
2557
|
+
type: {
|
|
2558
|
+
enum: [
|
|
2559
|
+
"string",
|
|
2560
|
+
"text",
|
|
2561
|
+
"integer",
|
|
2562
|
+
"decimal",
|
|
2563
|
+
"boolean",
|
|
2564
|
+
"date",
|
|
2565
|
+
"datetime",
|
|
2566
|
+
"enum",
|
|
2567
|
+
"reference",
|
|
2568
|
+
"json"
|
|
2569
|
+
]
|
|
2570
|
+
},
|
|
2571
|
+
required: { type: "boolean" },
|
|
2572
|
+
unique: { enum: ["tenant", "none"] },
|
|
2573
|
+
maxLength: { type: "integer", minimum: 1 },
|
|
2574
|
+
values: {
|
|
2575
|
+
type: "array",
|
|
2576
|
+
minItems: 1,
|
|
2577
|
+
items: { $ref: "#/$defs/enumValue" },
|
|
2578
|
+
uniqueItems: true
|
|
2579
|
+
},
|
|
2580
|
+
reference: {
|
|
2581
|
+
type: "string",
|
|
2582
|
+
pattern: "^[a-z][a-z0-9-]*(\\.[a-z][a-z0-9-]*)*$"
|
|
2583
|
+
},
|
|
2584
|
+
description: { type: "string", minLength: 1 }
|
|
2585
|
+
}
|
|
2586
|
+
},
|
|
2587
|
+
screen: {
|
|
2588
|
+
type: "object",
|
|
2589
|
+
additionalProperties: false,
|
|
2590
|
+
required: ["id", "kind"],
|
|
2591
|
+
properties: {
|
|
2592
|
+
id: { $ref: "#/$defs/entityId" },
|
|
2593
|
+
kind: { enum: ["list", "record", "form", "dashboard"] },
|
|
2594
|
+
entity: { $ref: "#/$defs/entityId" },
|
|
2595
|
+
title: { type: "string", minLength: 1 },
|
|
2596
|
+
columns: {
|
|
2597
|
+
type: "array",
|
|
2598
|
+
items: { $ref: "#/$defs/fieldId" },
|
|
2599
|
+
uniqueItems: true
|
|
2600
|
+
},
|
|
2601
|
+
filters: {
|
|
2602
|
+
type: "array",
|
|
2603
|
+
items: { $ref: "#/$defs/fieldId" },
|
|
2604
|
+
uniqueItems: true
|
|
2605
|
+
},
|
|
2606
|
+
navigationGroup: { type: "string", minLength: 1 }
|
|
2607
|
+
}
|
|
2608
|
+
},
|
|
2609
|
+
action: {
|
|
2610
|
+
type: "object",
|
|
2611
|
+
additionalProperties: false,
|
|
2612
|
+
required: [
|
|
2613
|
+
"id",
|
|
2614
|
+
"permission",
|
|
2615
|
+
"kind",
|
|
2616
|
+
"risk",
|
|
2617
|
+
"idempotent",
|
|
2618
|
+
"description"
|
|
2619
|
+
],
|
|
2620
|
+
properties: {
|
|
2621
|
+
id: { $ref: "#/$defs/entityId" },
|
|
2622
|
+
entity: { $ref: "#/$defs/entityId" },
|
|
2623
|
+
permission: {
|
|
2624
|
+
type: "string",
|
|
2625
|
+
pattern: "^[a-z][a-z0-9-]*(\\.[a-z][a-z0-9-]*)+$"
|
|
2626
|
+
},
|
|
2627
|
+
kind: { enum: ["create", "update", "delete", "custom"] },
|
|
2628
|
+
risk: {
|
|
2629
|
+
enum: ["read", "workspace-write", "external", "destructive"]
|
|
2630
|
+
},
|
|
2631
|
+
idempotent: { type: "boolean" },
|
|
2632
|
+
description: { type: "string", minLength: 1 }
|
|
2633
|
+
}
|
|
2634
|
+
},
|
|
2635
|
+
widget: {
|
|
2636
|
+
type: "object",
|
|
2637
|
+
additionalProperties: false,
|
|
2638
|
+
required: ["id", "slot", "description"],
|
|
2639
|
+
properties: {
|
|
2640
|
+
id: { $ref: "#/$defs/entityId" },
|
|
2641
|
+
slot: {
|
|
2642
|
+
enum: [
|
|
2643
|
+
"dashboard.metrics",
|
|
2644
|
+
"dashboard.main",
|
|
2645
|
+
"dashboard.aside",
|
|
2646
|
+
"topbar.actions"
|
|
2647
|
+
]
|
|
2648
|
+
},
|
|
2649
|
+
entity: { $ref: "#/$defs/entityId" },
|
|
2650
|
+
description: { type: "string", minLength: 1 }
|
|
2651
|
+
}
|
|
2652
|
+
},
|
|
2653
|
+
setting: {
|
|
2654
|
+
type: "object",
|
|
2655
|
+
additionalProperties: false,
|
|
2656
|
+
required: ["key", "type", "scope", "description"],
|
|
2657
|
+
properties: {
|
|
2658
|
+
key: { $ref: "#/$defs/fieldId" },
|
|
2659
|
+
type: { enum: ["string", "integer", "boolean", "enum"] },
|
|
2660
|
+
scope: { enum: ["tenant", "platform"] },
|
|
2661
|
+
default: {
|
|
2662
|
+
oneOf: [
|
|
2663
|
+
{ type: "string" },
|
|
2664
|
+
{ type: "integer" },
|
|
2665
|
+
{ type: "boolean" }
|
|
2666
|
+
]
|
|
2667
|
+
},
|
|
2668
|
+
values: {
|
|
2669
|
+
type: "array",
|
|
2670
|
+
minItems: 1,
|
|
2671
|
+
items: { type: "string", minLength: 1 },
|
|
2672
|
+
uniqueItems: true
|
|
2673
|
+
},
|
|
2674
|
+
description: { type: "string", minLength: 1 }
|
|
2675
|
+
}
|
|
2676
|
+
},
|
|
2677
|
+
agentTool: {
|
|
2678
|
+
type: "object",
|
|
2679
|
+
additionalProperties: false,
|
|
2680
|
+
required: ["id", "permission", "description", "risk"],
|
|
2681
|
+
properties: {
|
|
2682
|
+
id: {
|
|
2683
|
+
type: "string",
|
|
2684
|
+
pattern: "^[a-z][a-z0-9-]*(\\.[a-z][a-z0-9-]*)+$"
|
|
2685
|
+
},
|
|
2686
|
+
permission: {
|
|
2687
|
+
type: "string",
|
|
2688
|
+
pattern: "^[a-z][a-z0-9-]*(\\.[a-z][a-z0-9-]*)+$"
|
|
2689
|
+
},
|
|
2690
|
+
description: { type: "string", minLength: 1 },
|
|
2691
|
+
risk: { enum: ["read", "workspace-write"] }
|
|
2692
|
+
}
|
|
2693
|
+
},
|
|
2694
|
+
decision: {
|
|
2695
|
+
type: "object",
|
|
2696
|
+
additionalProperties: false,
|
|
2697
|
+
required: ["id", "question", "answer", "decidedBy"],
|
|
2698
|
+
properties: {
|
|
2699
|
+
id: { type: "string", pattern: "^[A-Z][A-Z0-9-]+$" },
|
|
2700
|
+
question: { type: "string", minLength: 1 },
|
|
2701
|
+
answer: { type: "string", minLength: 1 },
|
|
2702
|
+
decidedBy: { enum: ["user", "default"] }
|
|
2703
|
+
}
|
|
2513
2704
|
}
|
|
2514
2705
|
}
|
|
2515
2706
|
};
|
|
@@ -2923,6 +3114,172 @@ var projectSchema = project_schema_default;
|
|
|
2923
3114
|
var moduleCatalogSchema = module_catalog_schema_default;
|
|
2924
3115
|
var moduleArtifactSchema = module_artifact_schema_default;
|
|
2925
3116
|
|
|
3117
|
+
// ../contracts/src/index.ts
|
|
3118
|
+
var PLATFORM_API_VERSION = "0.1.8";
|
|
3119
|
+
|
|
3120
|
+
// ../kernel/src/module-compatibility.ts
|
|
3121
|
+
function satisfiesModuleVersion(version, range) {
|
|
3122
|
+
return (0, import_semver.valid)(version) !== null && (0, import_semver.validRange)(range) !== null && (0, import_semver.satisfies)(version, range);
|
|
3123
|
+
}
|
|
3124
|
+
function compareModuleVersions(left, right) {
|
|
3125
|
+
return (0, import_semver.rcompare)(left, right);
|
|
3126
|
+
}
|
|
3127
|
+
function assertModuleCompatibility(manifest, platformVersion = PLATFORM_API_VERSION) {
|
|
3128
|
+
if (!(0, import_semver.valid)(manifest.version))
|
|
3129
|
+
throw new RegistryError(
|
|
3130
|
+
"MODULE_VERSION_INVALID",
|
|
3131
|
+
`Invalid version for ${manifest.id}: ${manifest.version}`
|
|
3132
|
+
);
|
|
3133
|
+
if (manifest.platformApi !== void 0 && (!(0, import_semver.validRange)(manifest.platformApi) || platformVersion !== null && !satisfiesModuleVersion(platformVersion, manifest.platformApi))) {
|
|
3134
|
+
throw new RegistryError(
|
|
3135
|
+
"MODULE_PLATFORM_INCOMPATIBLE",
|
|
3136
|
+
`${manifest.id} requires platform API ${manifest.platformApi}; available ${PLATFORM_API_VERSION}.`
|
|
3137
|
+
);
|
|
3138
|
+
}
|
|
3139
|
+
const ids = /* @__PURE__ */ new Set();
|
|
3140
|
+
for (const dependency of manifest.dependencies) {
|
|
3141
|
+
if (!dependency.range.trim() || !(0, import_semver.validRange)(dependency.range))
|
|
3142
|
+
throw new RegistryError(
|
|
3143
|
+
"MODULE_RANGE_INVALID",
|
|
3144
|
+
`${manifest.id} declares an invalid range for ${dependency.id}: ${dependency.range}`
|
|
3145
|
+
);
|
|
3146
|
+
if (ids.has(dependency.id))
|
|
3147
|
+
throw new RegistryError(
|
|
3148
|
+
"MODULE_DEPENDENCY_DUPLICATE",
|
|
3149
|
+
`${manifest.id} declares ${dependency.id} more than once.`
|
|
3150
|
+
);
|
|
3151
|
+
ids.add(dependency.id);
|
|
3152
|
+
}
|
|
3153
|
+
}
|
|
3154
|
+
function assertModuleDependency(consumer, dependency, version) {
|
|
3155
|
+
if (!satisfiesModuleVersion(version, dependency.range)) {
|
|
3156
|
+
throw new RegistryError(
|
|
3157
|
+
"MODULE_DEPENDENCY_INCOMPATIBLE",
|
|
3158
|
+
`${consumer} requires ${dependency.id} ${dependency.range}; available ${version}.`
|
|
3159
|
+
);
|
|
3160
|
+
}
|
|
3161
|
+
}
|
|
3162
|
+
|
|
3163
|
+
// ../kernel/src/module-registry.ts
|
|
3164
|
+
function compareModules(left, right) {
|
|
3165
|
+
return left.manifest.id.localeCompare(right.manifest.id);
|
|
3166
|
+
}
|
|
3167
|
+
function capabilityProviders(modules) {
|
|
3168
|
+
const providers = /* @__PURE__ */ new Map();
|
|
3169
|
+
for (const module of modules) {
|
|
3170
|
+
for (const capability of module.manifest.provides ?? []) {
|
|
3171
|
+
const existing = providers.get(capability);
|
|
3172
|
+
if (existing && existing !== module.manifest.id) {
|
|
3173
|
+
throw new RegistryError(
|
|
3174
|
+
"MODULE_CAPABILITY_DUPLICATE",
|
|
3175
|
+
`Capability "${capability}" is provided by both "${existing}" and "${module.manifest.id}".`
|
|
3176
|
+
);
|
|
3177
|
+
}
|
|
3178
|
+
providers.set(capability, module.manifest.id);
|
|
3179
|
+
}
|
|
3180
|
+
}
|
|
3181
|
+
return providers;
|
|
3182
|
+
}
|
|
3183
|
+
function visitModule(id, modules, providers, visiting, visited, ordered) {
|
|
3184
|
+
if (visited.has(id)) return;
|
|
3185
|
+
if (visiting.has(id)) {
|
|
3186
|
+
throw new RegistryError(
|
|
3187
|
+
"MODULE_DEPENDENCY_CYCLE",
|
|
3188
|
+
`Dependency cycle detected at "${id}".`
|
|
3189
|
+
);
|
|
3190
|
+
}
|
|
3191
|
+
const current = modules.get(id);
|
|
3192
|
+
if (!current) {
|
|
3193
|
+
throw new RegistryError(
|
|
3194
|
+
"MODULE_NOT_FOUND",
|
|
3195
|
+
`Module "${id}" is not registered.`
|
|
3196
|
+
);
|
|
3197
|
+
}
|
|
3198
|
+
visiting.add(id);
|
|
3199
|
+
for (const dependency of [...current.manifest.dependencies].sort(
|
|
3200
|
+
(a, b) => a.id.localeCompare(b.id)
|
|
3201
|
+
)) {
|
|
3202
|
+
if (!modules.has(dependency.id)) {
|
|
3203
|
+
throw new RegistryError(
|
|
3204
|
+
"MODULE_DEPENDENCY_MISSING",
|
|
3205
|
+
`Module "${id}" requires missing module "${dependency.id}".`
|
|
3206
|
+
);
|
|
3207
|
+
}
|
|
3208
|
+
assertModuleDependency(
|
|
3209
|
+
id,
|
|
3210
|
+
dependency,
|
|
3211
|
+
modules.get(dependency.id).manifest.version
|
|
3212
|
+
);
|
|
3213
|
+
visitModule(dependency.id, modules, providers, visiting, visited, ordered);
|
|
3214
|
+
}
|
|
3215
|
+
for (const requirement of [...current.manifest.requires ?? []].sort(
|
|
3216
|
+
(a, b) => a.id.localeCompare(b.id)
|
|
3217
|
+
)) {
|
|
3218
|
+
if (requirement.optional) continue;
|
|
3219
|
+
const provider = providers.get(requirement.id);
|
|
3220
|
+
if (!provider) {
|
|
3221
|
+
throw new RegistryError(
|
|
3222
|
+
"MODULE_CAPABILITY_MISSING",
|
|
3223
|
+
`Module "${id}" requires capability "${requirement.id}" and no registered module provides it.`
|
|
3224
|
+
);
|
|
3225
|
+
}
|
|
3226
|
+
if (provider === id) continue;
|
|
3227
|
+
visitModule(provider, modules, providers, visiting, visited, ordered);
|
|
3228
|
+
}
|
|
3229
|
+
visiting.delete(id);
|
|
3230
|
+
visited.add(id);
|
|
3231
|
+
ordered.push(current);
|
|
3232
|
+
}
|
|
3233
|
+
function createModuleRegistry(input) {
|
|
3234
|
+
const byId = /* @__PURE__ */ new Map();
|
|
3235
|
+
const navigationIds = /* @__PURE__ */ new Set();
|
|
3236
|
+
for (const module of input) {
|
|
3237
|
+
assertModuleCompatibility(module.manifest);
|
|
3238
|
+
if (byId.has(module.manifest.id)) {
|
|
3239
|
+
throw new RegistryError(
|
|
3240
|
+
"MODULE_DUPLICATE",
|
|
3241
|
+
`Module "${module.manifest.id}" is registered more than once.`
|
|
3242
|
+
);
|
|
3243
|
+
}
|
|
3244
|
+
byId.set(module.manifest.id, module);
|
|
3245
|
+
for (const item of module.navigation ?? []) {
|
|
3246
|
+
if (navigationIds.has(item.id)) {
|
|
3247
|
+
throw new RegistryError(
|
|
3248
|
+
"NAVIGATION_DUPLICATE",
|
|
3249
|
+
`Navigation contribution "${item.id}" is registered more than once.`
|
|
3250
|
+
);
|
|
3251
|
+
}
|
|
3252
|
+
navigationIds.add(item.id);
|
|
3253
|
+
}
|
|
3254
|
+
}
|
|
3255
|
+
const providers = capabilityProviders(byId.values());
|
|
3256
|
+
const ordered = [];
|
|
3257
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
3258
|
+
const visited = /* @__PURE__ */ new Set();
|
|
3259
|
+
for (const module of [...input].sort(compareModules)) {
|
|
3260
|
+
visitModule(
|
|
3261
|
+
module.manifest.id,
|
|
3262
|
+
byId,
|
|
3263
|
+
providers,
|
|
3264
|
+
visiting,
|
|
3265
|
+
visited,
|
|
3266
|
+
ordered
|
|
3267
|
+
);
|
|
3268
|
+
}
|
|
3269
|
+
return Object.freeze({
|
|
3270
|
+
modules: Object.freeze(ordered),
|
|
3271
|
+
get: (id) => byId.get(id),
|
|
3272
|
+
has: (id) => byId.has(id),
|
|
3273
|
+
navigation: (permissions) => Object.freeze(
|
|
3274
|
+
ordered.flatMap((module) => module.navigation ?? []).filter(
|
|
3275
|
+
(item) => !item.permission || permissions?.has(item.permission)
|
|
3276
|
+
).sort(
|
|
3277
|
+
(left, right) => (left.order ?? 1e3) - (right.order ?? 1e3) || left.id.localeCompare(right.id)
|
|
3278
|
+
)
|
|
3279
|
+
)
|
|
3280
|
+
});
|
|
3281
|
+
}
|
|
3282
|
+
|
|
2926
3283
|
// src/validation.ts
|
|
2927
3284
|
import { readdir, readFile } from "node:fs/promises";
|
|
2928
3285
|
import { basename, dirname, join, relative } from "node:path";
|
|
@@ -3339,6 +3696,26 @@ function resolveModuleReleases(catalog, target, installed) {
|
|
|
3339
3696
|
entries.sort(
|
|
3340
3697
|
(a, b) => compareModuleVersions(a.manifest.version, b.manifest.version)
|
|
3341
3698
|
);
|
|
3699
|
+
const providers = /* @__PURE__ */ new Map();
|
|
3700
|
+
for (const entries of candidates.values())
|
|
3701
|
+
for (const release of entries)
|
|
3702
|
+
for (const capability of release.manifest.provides ?? []) {
|
|
3703
|
+
const list = providers.get(capability) ?? [];
|
|
3704
|
+
list.push(release);
|
|
3705
|
+
providers.set(capability, list);
|
|
3706
|
+
}
|
|
3707
|
+
function wanted(manifest) {
|
|
3708
|
+
return [
|
|
3709
|
+
...manifest.dependencies,
|
|
3710
|
+
...(manifest.requires ?? []).filter((requirement) => !requirement.optional).map((requirement) => ({ capability: requirement.id }))
|
|
3711
|
+
];
|
|
3712
|
+
}
|
|
3713
|
+
function platformCompatible(candidate) {
|
|
3714
|
+
return satisfiesModuleVersion(
|
|
3715
|
+
PLATFORM_API_VERSION,
|
|
3716
|
+
candidate.manifest.platformApi
|
|
3717
|
+
);
|
|
3718
|
+
}
|
|
3342
3719
|
let attempts = 0;
|
|
3343
3720
|
function search(selected2, pending) {
|
|
3344
3721
|
distributionAssert(
|
|
@@ -3348,17 +3725,31 @@ function resolveModuleReleases(catalog, target, installed) {
|
|
|
3348
3725
|
);
|
|
3349
3726
|
const [next, ...rest] = pending;
|
|
3350
3727
|
if (!next) return selected2;
|
|
3728
|
+
if ("capability" in next) {
|
|
3729
|
+
const provided = [
|
|
3730
|
+
...installed,
|
|
3731
|
+
...[...selected2.values()].map((release) => release.manifest)
|
|
3732
|
+
].some((manifest) => manifest.provides?.includes(next.capability));
|
|
3733
|
+
if (provided) return search(selected2, rest);
|
|
3734
|
+
for (const candidate of providers.get(next.capability) ?? []) {
|
|
3735
|
+
if (selected2.has(candidate.manifest.id) || existing.has(candidate.manifest.id) || !platformCompatible(candidate))
|
|
3736
|
+
continue;
|
|
3737
|
+
const found = search(
|
|
3738
|
+
new Map([...selected2, [candidate.manifest.id, candidate]]),
|
|
3739
|
+
[...wanted(candidate.manifest), ...rest]
|
|
3740
|
+
);
|
|
3741
|
+
if (found) return found;
|
|
3742
|
+
}
|
|
3743
|
+
return void 0;
|
|
3744
|
+
}
|
|
3351
3745
|
const fixed = selected2.get(next.id)?.manifest ?? existing.get(next.id);
|
|
3352
3746
|
if (fixed)
|
|
3353
3747
|
return satisfiesModuleVersion(fixed.version, next.range) ? search(selected2, rest) : void 0;
|
|
3354
3748
|
for (const candidate of candidates.get(next.id) ?? []) {
|
|
3355
|
-
if (!satisfiesModuleVersion(candidate.manifest.version, next.range) || !
|
|
3356
|
-
PLATFORM_API_VERSION,
|
|
3357
|
-
candidate.manifest.platformApi
|
|
3358
|
-
))
|
|
3749
|
+
if (!satisfiesModuleVersion(candidate.manifest.version, next.range) || !platformCompatible(candidate))
|
|
3359
3750
|
continue;
|
|
3360
3751
|
const found = search(new Map([...selected2, [next.id, candidate]]), [
|
|
3361
|
-
...candidate.manifest
|
|
3752
|
+
...wanted(candidate.manifest),
|
|
3362
3753
|
...rest
|
|
3363
3754
|
]);
|
|
3364
3755
|
if (found) return found;
|
|
@@ -3405,7 +3796,7 @@ import { dirname as dirname6, join as join6, relative as relative5 } from "node:
|
|
|
3405
3796
|
import { createRequire } from "node:module";
|
|
3406
3797
|
import { readFile as readFile5 } from "node:fs/promises";
|
|
3407
3798
|
import { dirname as dirname4, join as join3 } from "node:path";
|
|
3408
|
-
var SDK_VERSION = "0.
|
|
3799
|
+
var SDK_VERSION = "0.3.1";
|
|
3409
3800
|
function npmPackage(specifier) {
|
|
3410
3801
|
return specifier.startsWith("@") ? specifier.split("/").slice(0, 2).join("/") : specifier.split("/")[0];
|
|
3411
3802
|
}
|
|
@@ -3560,6 +3951,15 @@ async function platformIssues(moduleRoot, manifest) {
|
|
|
3560
3951
|
)
|
|
3561
3952
|
);
|
|
3562
3953
|
}
|
|
3954
|
+
if (manifest.platformApi === void 0) {
|
|
3955
|
+
issues.push(
|
|
3956
|
+
issue(
|
|
3957
|
+
"PLATFORM_API_MISSING",
|
|
3958
|
+
`module.json declares no platformApi; add "platformApi": "^${PLATFORM_API_VERSION}" so the platform contract the module was built against is checked.`,
|
|
3959
|
+
"module.json"
|
|
3960
|
+
)
|
|
3961
|
+
);
|
|
3962
|
+
}
|
|
3563
3963
|
if (packageVersion !== manifest.version) {
|
|
3564
3964
|
issues.push(
|
|
3565
3965
|
issue(
|
|
@@ -3648,6 +4048,26 @@ async function specIssues(moduleRoot, manifest, specDirectory) {
|
|
|
3648
4048
|
)
|
|
3649
4049
|
);
|
|
3650
4050
|
}
|
|
4051
|
+
if (Array.isArray(spec.dependencies)) {
|
|
4052
|
+
const declared = spec.dependencies.map((entry) => `${String(entry.id)}@${String(entry.range)}`);
|
|
4053
|
+
const actual = manifest.dependencies.map(
|
|
4054
|
+
(entry) => `${entry.id}@${entry.range}`
|
|
4055
|
+
);
|
|
4056
|
+
const drift = [
|
|
4057
|
+
...declared.filter((entry) => !actual.includes(entry)),
|
|
4058
|
+
...actual.filter((entry) => !declared.includes(entry))
|
|
4059
|
+
];
|
|
4060
|
+
if (drift.length > 0) {
|
|
4061
|
+
issues.push(
|
|
4062
|
+
issue(
|
|
4063
|
+
"SPEC_DEPENDENCY_DRIFT",
|
|
4064
|
+
`Specification dependencies differ from module.json: ${drift.join(", ")}. Run module version bump or align the ranges by hand.`,
|
|
4065
|
+
specPath,
|
|
4066
|
+
"warning"
|
|
4067
|
+
)
|
|
4068
|
+
);
|
|
4069
|
+
}
|
|
4070
|
+
}
|
|
3651
4071
|
return issues;
|
|
3652
4072
|
}
|
|
3653
4073
|
async function translationIssues(moduleRoot, manifest, projectLocales) {
|
|
@@ -4258,13 +4678,23 @@ function platformImport(id, pkg, entry) {
|
|
|
4258
4678
|
function clientImport(id, pkg) {
|
|
4259
4679
|
return `import { createClientContribution as ${identifier(id)} } from '${pkg}/client';`;
|
|
4260
4680
|
}
|
|
4681
|
+
function capabilityScope(module) {
|
|
4682
|
+
if (!module.manifest) return "";
|
|
4683
|
+
const declaration = JSON.stringify({
|
|
4684
|
+
provides: module.manifest.provides ?? [],
|
|
4685
|
+
requires: module.manifest.requires ?? []
|
|
4686
|
+
});
|
|
4687
|
+
return ` capabilities: context.capabilities.forModule('${module.id}', ${declaration}),
|
|
4688
|
+
`;
|
|
4689
|
+
}
|
|
4261
4690
|
function generateServerComposition(modules, sdk = false, mounts = [], applicationPath = "/app") {
|
|
4262
4691
|
const server = modules.filter((module) => module.server);
|
|
4692
|
+
const serverPackage = sdk ? "@flowdular/sdk/server" : "@flowdular/server";
|
|
4263
4693
|
const typeImport = `import type {
|
|
4264
4694
|
PlatformServerComposition,
|
|
4265
4695
|
PlatformServerContext,
|
|
4266
4696
|
} from '${sdk ? "@flowdular/sdk/modules/auth" : "@flowdular/module-auth"}/server';
|
|
4267
|
-
import type { WebMount } from '${
|
|
4697
|
+
import type { WebMount } from '${serverPackage}';
|
|
4268
4698
|
`;
|
|
4269
4699
|
if (server.length === 0) {
|
|
4270
4700
|
return GENERATED_HEADER + typeImport + "\nexport function composeModuleServer(\n _context: PlatformServerContext,\n): readonly PlatformServerComposition[] {\n return [];\n}\n\nexport const moduleWebMounts: readonly WebMount[] = " + JSON.stringify(mounts) + " as const;\nexport const applicationBasePath = " + JSON.stringify(applicationPath) + ";\n";
|
|
@@ -4276,9 +4706,12 @@ import type { WebMount } from '${sdk ? "@flowdular/sdk/server" : "@flowdular/ser
|
|
|
4276
4706
|
(module) => ` { ...${identifier(module.id)}({
|
|
4277
4707
|
...context,
|
|
4278
4708
|
agentDefinitions: context.agentDefinitions.forModule('${module.id}'),
|
|
4709
|
+
dataClasses: context.dataClasses.forModule('${module.id}'),
|
|
4710
|
+
` + capabilityScope(module) + ` metrics: createModuleMetrics('${module.id}'),
|
|
4279
4711
|
}), moduleId: '${module.id}' },`
|
|
4280
4712
|
).join("\n");
|
|
4281
|
-
return GENERATED_HEADER + typeImport +
|
|
4713
|
+
return GENERATED_HEADER + typeImport + `import { createModuleMetrics } from '${serverPackage}';
|
|
4714
|
+
` + imports + "\n\nexport function composeModuleServer(\n context: PlatformServerContext,\n): readonly PlatformServerComposition[] {\n return [\n" + calls + "\n ];\n}\n\nexport const moduleWebMounts: readonly WebMount[] = " + JSON.stringify(mounts) + " as const;\nexport const applicationBasePath = " + JSON.stringify(applicationPath) + ";\n";
|
|
4282
4715
|
}
|
|
4283
4716
|
function generateClientComposition(modules, sdk = false, applicationPath = "/app") {
|
|
4284
4717
|
const client = modules.filter((module) => module.client);
|
|
@@ -4324,6 +4757,11 @@ function moduleOrder(manifests, roots, includeDependencies) {
|
|
|
4324
4757
|
const visiting = [];
|
|
4325
4758
|
const visited = /* @__PURE__ */ new Set();
|
|
4326
4759
|
const ordered = [];
|
|
4760
|
+
const providers = capabilityProviders(
|
|
4761
|
+
[...manifests.values()].flatMap(
|
|
4762
|
+
(descriptor) => descriptor.manifest ? [{ manifest: descriptor.manifest }] : []
|
|
4763
|
+
)
|
|
4764
|
+
);
|
|
4327
4765
|
const visit = (id, requiredBy) => {
|
|
4328
4766
|
if (visited.has(id)) return;
|
|
4329
4767
|
const cycleStart = visiting.indexOf(id);
|
|
@@ -4357,6 +4795,24 @@ function moduleOrder(manifests, roots, includeDependencies) {
|
|
|
4357
4795
|
assertModuleDependency(id, constraint, version);
|
|
4358
4796
|
visit(dependency, id);
|
|
4359
4797
|
}
|
|
4798
|
+
for (const requirement of [...current.manifest?.requires ?? []].sort(
|
|
4799
|
+
(left, right) => left.id.localeCompare(right.id)
|
|
4800
|
+
)) {
|
|
4801
|
+
if (requirement.optional) continue;
|
|
4802
|
+
const provider = providers.get(requirement.id);
|
|
4803
|
+
if (!provider) {
|
|
4804
|
+
throw new Error(
|
|
4805
|
+
`Module "${id}" requires capability "${requirement.id}" and no module provides it.`
|
|
4806
|
+
);
|
|
4807
|
+
}
|
|
4808
|
+
if (provider === id) continue;
|
|
4809
|
+
if (!includeDependencies && !requested.has(provider)) {
|
|
4810
|
+
throw new Error(
|
|
4811
|
+
`Enabled module "${id}" requires capability "${requirement.id}" from disabled module "${provider}". Enable the provider first.`
|
|
4812
|
+
);
|
|
4813
|
+
}
|
|
4814
|
+
visit(provider, id);
|
|
4815
|
+
}
|
|
4360
4816
|
visiting.pop();
|
|
4361
4817
|
visited.add(id);
|
|
4362
4818
|
ordered.push(current);
|