@beignet/cli 0.0.47 → 0.0.49
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/CHANGELOG.md +46 -0
- package/README.md +126 -42
- package/dist/analysis/contract-factories.d.ts +17 -0
- package/dist/analysis/contract-factories.d.ts.map +1 -0
- package/dist/analysis/contract-factories.js +176 -0
- package/dist/analysis/contract-factories.js.map +1 -0
- package/dist/analysis/layers.d.ts +5 -0
- package/dist/analysis/layers.d.ts.map +1 -0
- package/dist/analysis/layers.js +172 -0
- package/dist/analysis/layers.js.map +1 -0
- package/dist/analysis/port-wiring.d.ts +23 -0
- package/dist/analysis/port-wiring.d.ts.map +1 -0
- package/dist/analysis/port-wiring.js +379 -0
- package/dist/analysis/port-wiring.js.map +1 -0
- package/dist/analysis/source-index.d.ts +5 -0
- package/dist/analysis/source-index.d.ts.map +1 -1
- package/dist/analysis/source-index.js +171 -42
- package/dist/analysis/source-index.js.map +1 -1
- package/dist/analysis/workspace.d.ts +10 -4
- package/dist/analysis/workspace.d.ts.map +1 -1
- package/dist/analysis/workspace.js +66 -6
- package/dist/analysis/workspace.js.map +1 -1
- package/dist/app-map.d.ts.map +1 -1
- package/dist/app-map.js +311 -92
- package/dist/app-map.js.map +1 -1
- package/dist/check.d.ts +8 -1
- package/dist/check.d.ts.map +1 -1
- package/dist/check.js +55 -9
- package/dist/check.js.map +1 -1
- package/dist/db.d.ts +38 -0
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +52 -0
- package/dist/db.js.map +1 -1
- package/dist/explain.js +4 -4
- package/dist/explain.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +73 -6
- package/dist/index.js.map +1 -1
- package/dist/inspect.d.ts.map +1 -1
- package/dist/inspect.js +454 -170
- package/dist/inspect.js.map +1 -1
- package/dist/lib.d.ts +2 -2
- package/dist/lib.d.ts.map +1 -1
- package/dist/lib.js +1 -1
- package/dist/lib.js.map +1 -1
- package/dist/lint.d.ts.map +1 -1
- package/dist/lint.js +309 -487
- package/dist/lint.js.map +1 -1
- package/dist/make/inbox.d.ts.map +1 -1
- package/dist/make/inbox.js +12 -5
- package/dist/make/inbox.js.map +1 -1
- package/dist/make/payments.js +3 -3
- package/dist/make/payments.js.map +1 -1
- package/dist/make/tenancy.js +1 -1
- package/dist/make/tenancy.js.map +1 -1
- package/dist/make.d.ts.map +1 -1
- package/dist/make.js +144 -8
- package/dist/make.js.map +1 -1
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +56 -19
- package/dist/mcp.js.map +1 -1
- package/dist/preflight.d.ts +11 -3
- package/dist/preflight.d.ts.map +1 -1
- package/dist/preflight.js +139 -16
- package/dist/preflight.js.map +1 -1
- package/dist/provider-add.d.ts.map +1 -1
- package/dist/provider-add.js +149 -9
- package/dist/provider-add.js.map +1 -1
- package/dist/provider-audit.d.ts +13 -0
- package/dist/provider-audit.d.ts.map +1 -1
- package/dist/provider-audit.js +122 -8
- package/dist/provider-audit.js.map +1 -1
- package/dist/registry-edits.d.ts +7 -0
- package/dist/registry-edits.d.ts.map +1 -1
- package/dist/registry-edits.js +237 -53
- package/dist/registry-edits.js.map +1 -1
- package/dist/templates/agents.d.ts.map +1 -1
- package/dist/templates/agents.js +29 -7
- package/dist/templates/agents.js.map +1 -1
- package/dist/templates/base.d.ts +1 -0
- package/dist/templates/base.d.ts.map +1 -1
- package/dist/templates/base.js +20 -6
- package/dist/templates/base.js.map +1 -1
- package/dist/templates/db/index.d.ts +1 -0
- package/dist/templates/db/index.d.ts.map +1 -1
- package/dist/templates/db/index.js.map +1 -1
- package/dist/templates/db/migration-status.d.ts +9 -0
- package/dist/templates/db/migration-status.d.ts.map +1 -0
- package/dist/templates/db/migration-status.js +117 -0
- package/dist/templates/db/migration-status.js.map +1 -0
- package/dist/templates/db/mysql.d.ts.map +1 -1
- package/dist/templates/db/mysql.js +23 -0
- package/dist/templates/db/mysql.js.map +1 -1
- package/dist/templates/db/postgres.d.ts.map +1 -1
- package/dist/templates/db/postgres.js +21 -0
- package/dist/templates/db/postgres.js.map +1 -1
- package/dist/templates/db/sqlite.d.ts.map +1 -1
- package/dist/templates/db/sqlite.js +53 -0
- package/dist/templates/db/sqlite.js.map +1 -1
- package/dist/templates/index.d.ts.map +1 -1
- package/dist/templates/index.js +5 -0
- package/dist/templates/index.js.map +1 -1
- package/dist/templates/server.d.ts.map +1 -1
- package/dist/templates/server.js +2 -0
- package/dist/templates/server.js.map +1 -1
- package/dist/templates/shared.d.ts +1 -0
- package/dist/templates/shared.d.ts.map +1 -1
- package/dist/templates/shared.js +4 -2
- package/dist/templates/shared.js.map +1 -1
- package/package.json +7 -6
- package/skills/app-structure/SKILL.md +56 -11
- package/src/analysis/contract-factories.ts +256 -0
- package/src/analysis/layers.ts +266 -0
- package/src/analysis/port-wiring.ts +506 -0
- package/src/analysis/source-index.ts +225 -57
- package/src/analysis/workspace.ts +115 -6
- package/src/app-map.ts +418 -109
- package/src/check.ts +86 -10
- package/src/db.ts +97 -0
- package/src/explain.ts +4 -4
- package/src/index.ts +108 -7
- package/src/inspect.ts +659 -216
- package/src/lib.ts +9 -1
- package/src/lint.ts +393 -643
- package/src/make/inbox.ts +12 -5
- package/src/make/payments.ts +3 -3
- package/src/make/tenancy.ts +1 -1
- package/src/make.ts +225 -8
- package/src/mcp.ts +73 -21
- package/src/preflight.ts +195 -16
- package/src/provider-add.ts +193 -9
- package/src/provider-audit.ts +210 -18
- package/src/registry-edits.ts +313 -63
- package/src/templates/agents.ts +29 -7
- package/src/templates/base.ts +21 -4
- package/src/templates/db/index.ts +1 -0
- package/src/templates/db/migration-status.ts +126 -0
- package/src/templates/db/mysql.ts +23 -0
- package/src/templates/db/postgres.ts +21 -0
- package/src/templates/db/sqlite.ts +53 -0
- package/src/templates/index.ts +5 -0
- package/src/templates/server.ts +2 -0
- package/src/templates/shared.ts +4 -2
package/src/provider-audit.ts
CHANGED
|
@@ -18,6 +18,7 @@ export type ProviderPackageJson = {
|
|
|
18
18
|
dependencies?: Record<string, string>;
|
|
19
19
|
devDependencies?: Record<string, string>;
|
|
20
20
|
peerDependencies?: Record<string, string>;
|
|
21
|
+
scripts?: Record<string, string>;
|
|
21
22
|
};
|
|
22
23
|
|
|
23
24
|
export type ProviderDoctorVariantRule = {
|
|
@@ -25,6 +26,7 @@ export type ProviderDoctorVariantRule = {
|
|
|
25
26
|
displayName: string;
|
|
26
27
|
tokens: readonly string[];
|
|
27
28
|
requiredEnv: readonly string[];
|
|
29
|
+
requiredEnvAlternatives: readonly (readonly string[])[];
|
|
28
30
|
requiredTables: readonly string[];
|
|
29
31
|
registrationSeverity?: "warning" | "hint";
|
|
30
32
|
};
|
|
@@ -35,6 +37,7 @@ export type ProviderDoctorRule = {
|
|
|
35
37
|
tokens: readonly string[];
|
|
36
38
|
appPorts?: readonly { name: string; type: string }[];
|
|
37
39
|
requiredEnv?: readonly string[];
|
|
40
|
+
requiredEnvAlternatives?: readonly (readonly string[])[];
|
|
38
41
|
requiredTables?: readonly string[];
|
|
39
42
|
watchers?: readonly string[];
|
|
40
43
|
registrationSeverity?: "warning" | "hint";
|
|
@@ -94,6 +97,14 @@ export type ProviderRequirementAudit = {
|
|
|
94
97
|
status: ProviderAuditStatus;
|
|
95
98
|
required: string[];
|
|
96
99
|
missing: string[];
|
|
100
|
+
alternatives?: string[][];
|
|
101
|
+
alternativeGroups?: Array<{
|
|
102
|
+
name: string;
|
|
103
|
+
displayName: string;
|
|
104
|
+
status: "present" | "missing";
|
|
105
|
+
alternatives: string[][];
|
|
106
|
+
missing: string[];
|
|
107
|
+
}>;
|
|
97
108
|
};
|
|
98
109
|
|
|
99
110
|
export type ProviderAppPortsAudit = {
|
|
@@ -282,6 +293,36 @@ export async function providerDoctorRulesForInstalledPackages(
|
|
|
282
293
|
return rules.filter((rule): rule is ProviderDoctorRule => Boolean(rule));
|
|
283
294
|
}
|
|
284
295
|
|
|
296
|
+
export async function detectedProviderVariantsForRules(
|
|
297
|
+
targetDir: string,
|
|
298
|
+
rules: readonly ProviderDoctorRule[],
|
|
299
|
+
): Promise<Map<string, ProviderDoctorVariantRule[]>> {
|
|
300
|
+
const variantRules = rules.filter(
|
|
301
|
+
(
|
|
302
|
+
rule,
|
|
303
|
+
): rule is ProviderDoctorRule & {
|
|
304
|
+
variants: readonly ProviderDoctorVariantRule[];
|
|
305
|
+
} => rule.variants !== undefined,
|
|
306
|
+
);
|
|
307
|
+
if (variantRules.length === 0) return new Map();
|
|
308
|
+
|
|
309
|
+
const files = await listFiles(targetDir);
|
|
310
|
+
const config = await loadBeignetConfig(targetDir, files);
|
|
311
|
+
const providerEntries = await readProviderListEntries(
|
|
312
|
+
targetDir,
|
|
313
|
+
files,
|
|
314
|
+
config,
|
|
315
|
+
new Map(),
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
return new Map(
|
|
319
|
+
variantRules.map((rule) => [
|
|
320
|
+
rule.packageName,
|
|
321
|
+
detectedProviderVariants(rule.variants, providerEntries),
|
|
322
|
+
]),
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
|
|
285
326
|
export async function readProviderPackageMetadataSource(
|
|
286
327
|
targetDir: string,
|
|
287
328
|
packageName: string,
|
|
@@ -314,6 +355,7 @@ export function providerDoctorRuleFromMetadata(
|
|
|
314
355
|
tokens: registration?.tokens ?? [],
|
|
315
356
|
appPorts: metadata.appPorts ?? [],
|
|
316
357
|
requiredEnv: metadata.requiredEnv ?? [],
|
|
358
|
+
requiredEnvAlternatives: metadata.requiredEnvAlternatives ?? [],
|
|
317
359
|
requiredTables: metadata.requiredTables ?? [],
|
|
318
360
|
watchers: metadata.watchers ?? [],
|
|
319
361
|
registrationSeverity: registrationSeverityFromMetadata(registration),
|
|
@@ -322,6 +364,7 @@ export function providerDoctorRuleFromMetadata(
|
|
|
322
364
|
displayName: variant.displayName ?? variant.name,
|
|
323
365
|
tokens: variant.registration?.tokens ?? [],
|
|
324
366
|
requiredEnv: variant.requiredEnv ?? [],
|
|
367
|
+
requiredEnvAlternatives: variant.requiredEnvAlternatives ?? [],
|
|
325
368
|
requiredTables: variant.requiredTables ?? [],
|
|
326
369
|
registrationSeverity: registrationSeverityFromMetadata(
|
|
327
370
|
variant.registration,
|
|
@@ -1061,6 +1104,15 @@ function configuredProviderRequiredEnv(
|
|
|
1061
1104
|
return envVars.filter((envVar) => !ignored.has(envVar));
|
|
1062
1105
|
}
|
|
1063
1106
|
|
|
1107
|
+
function configuredProviderRequiredEnvAlternatives(
|
|
1108
|
+
alternatives: readonly (readonly string[])[],
|
|
1109
|
+
config: ResolvedBeignetConfig,
|
|
1110
|
+
): string[][] {
|
|
1111
|
+
return alternatives.map((alternative) =>
|
|
1112
|
+
configuredProviderRequiredEnv(alternative, config),
|
|
1113
|
+
);
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1064
1116
|
function configuredProviderRequiredTables(
|
|
1065
1117
|
tableNames: readonly string[],
|
|
1066
1118
|
config: ResolvedBeignetConfig,
|
|
@@ -1187,19 +1239,23 @@ async function providerAuditEntryForRule(options: {
|
|
|
1187
1239
|
const requiredEnv =
|
|
1188
1240
|
options.rule.variants !== undefined
|
|
1189
1241
|
? aggregateVariantRequirement(variants, "requiredEnv")
|
|
1190
|
-
: await
|
|
1191
|
-
configuredProviderRequiredEnv(
|
|
1242
|
+
: await providerEnvRequirementAudit({
|
|
1243
|
+
required: configuredProviderRequiredEnv(
|
|
1192
1244
|
options.rule.requiredEnv ?? [],
|
|
1193
1245
|
options.config,
|
|
1194
1246
|
),
|
|
1195
|
-
(
|
|
1247
|
+
alternatives: configuredProviderRequiredEnvAlternatives(
|
|
1248
|
+
options.rule.requiredEnvAlternatives ?? [],
|
|
1249
|
+
options.config,
|
|
1250
|
+
),
|
|
1251
|
+
exists: (envVar) =>
|
|
1196
1252
|
providerRequiredEnvExists(
|
|
1197
1253
|
options.targetDir,
|
|
1198
1254
|
options.configFiles,
|
|
1199
1255
|
envVar,
|
|
1200
1256
|
options.sourceCache,
|
|
1201
1257
|
),
|
|
1202
|
-
);
|
|
1258
|
+
});
|
|
1203
1259
|
|
|
1204
1260
|
const requiredTables =
|
|
1205
1261
|
options.rule.variants !== undefined
|
|
@@ -1288,12 +1344,19 @@ async function providerVariantAudit(options: {
|
|
|
1288
1344
|
options.variant.requiredEnv,
|
|
1289
1345
|
options.config,
|
|
1290
1346
|
);
|
|
1347
|
+
const requiredEnvAlternatives = configuredProviderRequiredEnvAlternatives(
|
|
1348
|
+
options.variant.requiredEnvAlternatives,
|
|
1349
|
+
options.config,
|
|
1350
|
+
);
|
|
1291
1351
|
if (!options.registered) {
|
|
1292
1352
|
return {
|
|
1293
1353
|
name: options.variant.name,
|
|
1294
1354
|
displayName: options.variant.displayName,
|
|
1295
1355
|
registration: "inactive",
|
|
1296
|
-
requiredEnv:
|
|
1356
|
+
requiredEnv:
|
|
1357
|
+
requiredEnvAlternatives.length > 0
|
|
1358
|
+
? inactiveAlternativeRequirement(requiredEnvAlternatives)
|
|
1359
|
+
: inactiveRequirement(requiredEnv),
|
|
1297
1360
|
requiredTables: inactiveRequirement(options.variant.requiredTables),
|
|
1298
1361
|
};
|
|
1299
1362
|
}
|
|
@@ -1306,14 +1369,17 @@ async function providerVariantAudit(options: {
|
|
|
1306
1369
|
options.variant.registrationSeverity,
|
|
1307
1370
|
options.providerEntries,
|
|
1308
1371
|
),
|
|
1309
|
-
requiredEnv: await
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1372
|
+
requiredEnv: await providerEnvRequirementAudit({
|
|
1373
|
+
required: requiredEnv,
|
|
1374
|
+
alternatives: requiredEnvAlternatives,
|
|
1375
|
+
exists: (envVar) =>
|
|
1376
|
+
providerRequiredEnvExists(
|
|
1377
|
+
options.targetDir,
|
|
1378
|
+
options.configFiles,
|
|
1379
|
+
envVar,
|
|
1380
|
+
options.sourceCache,
|
|
1381
|
+
),
|
|
1382
|
+
}),
|
|
1317
1383
|
requiredTables: await requirementAudit(
|
|
1318
1384
|
configuredProviderRequiredTables(
|
|
1319
1385
|
options.variant.requiredTables,
|
|
@@ -1448,6 +1514,34 @@ async function requirementAudit(
|
|
|
1448
1514
|
};
|
|
1449
1515
|
}
|
|
1450
1516
|
|
|
1517
|
+
async function providerEnvRequirementAudit(options: {
|
|
1518
|
+
required: readonly string[];
|
|
1519
|
+
alternatives: readonly (readonly string[])[];
|
|
1520
|
+
exists: (requirement: string) => Promise<boolean>;
|
|
1521
|
+
}): Promise<ProviderRequirementAudit> {
|
|
1522
|
+
if (options.alternatives.length === 0) {
|
|
1523
|
+
return requirementAudit(options.required, options.exists);
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
const missingAlternatives: string[][] = [];
|
|
1527
|
+
for (const alternative of options.alternatives) {
|
|
1528
|
+
const missing: string[] = [];
|
|
1529
|
+
for (const requirement of alternative) {
|
|
1530
|
+
if (await options.exists(requirement)) continue;
|
|
1531
|
+
missing.push(requirement);
|
|
1532
|
+
}
|
|
1533
|
+
missingAlternatives.push(missing);
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
const present = missingAlternatives.some((missing) => missing.length === 0);
|
|
1537
|
+
return {
|
|
1538
|
+
status: present ? "present" : "missing",
|
|
1539
|
+
required: unique(options.alternatives.flat()),
|
|
1540
|
+
missing: present ? [] : unique(missingAlternatives.flat()),
|
|
1541
|
+
alternatives: options.alternatives.map((alternative) => [...alternative]),
|
|
1542
|
+
};
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1451
1545
|
function inactiveRequirement(
|
|
1452
1546
|
required: readonly string[],
|
|
1453
1547
|
): ProviderRequirementAudit {
|
|
@@ -1458,6 +1552,17 @@ function inactiveRequirement(
|
|
|
1458
1552
|
};
|
|
1459
1553
|
}
|
|
1460
1554
|
|
|
1555
|
+
function inactiveAlternativeRequirement(
|
|
1556
|
+
alternatives: readonly (readonly string[])[],
|
|
1557
|
+
): ProviderRequirementAudit {
|
|
1558
|
+
return {
|
|
1559
|
+
status: "inactive",
|
|
1560
|
+
required: unique(alternatives.flat()),
|
|
1561
|
+
missing: [],
|
|
1562
|
+
alternatives: alternatives.map((alternative) => [...alternative]),
|
|
1563
|
+
};
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1461
1566
|
function emptyRequirement(): ProviderRequirementAudit {
|
|
1462
1567
|
return { status: "none", required: [], missing: [] };
|
|
1463
1568
|
}
|
|
@@ -1467,21 +1572,57 @@ function aggregateVariantRequirement(
|
|
|
1467
1572
|
key: "requiredEnv" | "requiredTables",
|
|
1468
1573
|
): ProviderRequirementAudit {
|
|
1469
1574
|
const active = variants
|
|
1470
|
-
.map((variant) => variant[key])
|
|
1471
|
-
.filter((requirement) => requirement.status !== "inactive");
|
|
1575
|
+
.map((variant) => ({ variant, requirement: variant[key] }))
|
|
1576
|
+
.filter(({ requirement }) => requirement.status !== "inactive");
|
|
1472
1577
|
if (active.length === 0)
|
|
1473
1578
|
return { status: "inactive", required: [], missing: [] };
|
|
1474
1579
|
|
|
1475
1580
|
const required = unique(
|
|
1476
|
-
active.flatMap((requirement) => requirement.required),
|
|
1581
|
+
active.flatMap(({ requirement }) => requirement.required),
|
|
1582
|
+
);
|
|
1583
|
+
const missing = unique(
|
|
1584
|
+
active.flatMap(({ requirement }) => requirement.missing),
|
|
1477
1585
|
);
|
|
1478
|
-
const missing = unique(active.flatMap((requirement) => requirement.missing));
|
|
1479
1586
|
if (required.length === 0) return emptyRequirement();
|
|
1480
1587
|
|
|
1588
|
+
const hasAlternativeRequirements = active.some(
|
|
1589
|
+
({ requirement }) =>
|
|
1590
|
+
requirement.alternatives !== undefined ||
|
|
1591
|
+
requirement.alternativeGroups !== undefined,
|
|
1592
|
+
);
|
|
1593
|
+
const alternativeGroups = hasAlternativeRequirements
|
|
1594
|
+
? active.flatMap(({ variant, requirement }) => {
|
|
1595
|
+
if (requirement.status === "none") return [];
|
|
1596
|
+
if (
|
|
1597
|
+
requirement.status !== "present" &&
|
|
1598
|
+
requirement.status !== "missing"
|
|
1599
|
+
) {
|
|
1600
|
+
return [];
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
return [
|
|
1604
|
+
{
|
|
1605
|
+
name: variant.name,
|
|
1606
|
+
displayName: variant.displayName,
|
|
1607
|
+
status: requirement.status,
|
|
1608
|
+
alternatives: (
|
|
1609
|
+
requirement.alternatives ?? [requirement.required]
|
|
1610
|
+
).map((alternative) => [...alternative]),
|
|
1611
|
+
missing: [...requirement.missing],
|
|
1612
|
+
},
|
|
1613
|
+
];
|
|
1614
|
+
})
|
|
1615
|
+
: [];
|
|
1616
|
+
|
|
1481
1617
|
return {
|
|
1482
1618
|
status: missing.length === 0 ? "present" : "missing",
|
|
1483
1619
|
required,
|
|
1484
1620
|
missing,
|
|
1621
|
+
...(alternativeGroups.length === 1
|
|
1622
|
+
? { alternatives: alternativeGroups[0]?.alternatives ?? [] }
|
|
1623
|
+
: alternativeGroups.length > 0
|
|
1624
|
+
? { alternativeGroups }
|
|
1625
|
+
: {}),
|
|
1485
1626
|
};
|
|
1486
1627
|
}
|
|
1487
1628
|
|
|
@@ -1520,7 +1661,17 @@ function providerAuditNotes(input: {
|
|
|
1520
1661
|
notes.push("optional provider not registered");
|
|
1521
1662
|
}
|
|
1522
1663
|
if (input.requiredEnv.missing.length > 0) {
|
|
1523
|
-
notes.push(
|
|
1664
|
+
notes.push(
|
|
1665
|
+
input.requiredEnv.alternativeGroups
|
|
1666
|
+
? `missing env configuration groups: ${formatProviderEnvAlternativeGroups(
|
|
1667
|
+
input.requiredEnv.alternativeGroups,
|
|
1668
|
+
)}`
|
|
1669
|
+
: input.requiredEnv.alternatives
|
|
1670
|
+
? `missing env alternative: ${formatProviderEnvAlternatives(
|
|
1671
|
+
input.requiredEnv.alternatives,
|
|
1672
|
+
)}`
|
|
1673
|
+
: `missing env: ${input.requiredEnv.missing.join(", ")}`,
|
|
1674
|
+
);
|
|
1524
1675
|
}
|
|
1525
1676
|
if (input.requiredTables.missing.length > 0) {
|
|
1526
1677
|
notes.push(`missing tables: ${input.requiredTables.missing.join(", ")}`);
|
|
@@ -1863,6 +2014,21 @@ function escapeRegExp(value: string): string {
|
|
|
1863
2014
|
function requirementSummary(requirement: ProviderRequirementAudit): string {
|
|
1864
2015
|
if (requirement.status === "none") return "none";
|
|
1865
2016
|
if (requirement.status === "inactive") return "inactive";
|
|
2017
|
+
if (requirement.alternativeGroups) {
|
|
2018
|
+
const count = requirement.alternativeGroups.length;
|
|
2019
|
+
const missing = requirement.alternativeGroups.filter(
|
|
2020
|
+
(group) => group.status === "missing",
|
|
2021
|
+
).length;
|
|
2022
|
+
return requirement.status === "present"
|
|
2023
|
+
? `${count} variant groups ok`
|
|
2024
|
+
: `${missing}/${count} variant groups incomplete`;
|
|
2025
|
+
}
|
|
2026
|
+
if (requirement.alternatives) {
|
|
2027
|
+
if (requirement.status === "present") {
|
|
2028
|
+
return "alternative ok";
|
|
2029
|
+
}
|
|
2030
|
+
return `${requirement.alternatives.length} alternatives missing`;
|
|
2031
|
+
}
|
|
1866
2032
|
if (requirement.status === "present") {
|
|
1867
2033
|
return `${requirement.required.length} ok`;
|
|
1868
2034
|
}
|
|
@@ -1879,6 +2045,32 @@ function unique(values: readonly string[]): string[] {
|
|
|
1879
2045
|
return [...new Set(values)];
|
|
1880
2046
|
}
|
|
1881
2047
|
|
|
2048
|
+
export function formatProviderEnvAlternatives(
|
|
2049
|
+
alternatives: readonly (readonly string[])[],
|
|
2050
|
+
): string {
|
|
2051
|
+
return alternatives
|
|
2052
|
+
.map((alternative) =>
|
|
2053
|
+
alternative.length === 1
|
|
2054
|
+
? alternative[0]
|
|
2055
|
+
: `(${alternative.join(" + ")})`,
|
|
2056
|
+
)
|
|
2057
|
+
.join(" or ");
|
|
2058
|
+
}
|
|
2059
|
+
|
|
2060
|
+
function formatProviderEnvAlternativeGroups(
|
|
2061
|
+
groups: NonNullable<ProviderRequirementAudit["alternativeGroups"]>,
|
|
2062
|
+
): string {
|
|
2063
|
+
return groups
|
|
2064
|
+
.filter((group) => group.status === "missing")
|
|
2065
|
+
.map(
|
|
2066
|
+
(group) =>
|
|
2067
|
+
`${group.displayName}: ${formatProviderEnvAlternatives(
|
|
2068
|
+
group.alternatives,
|
|
2069
|
+
)}`,
|
|
2070
|
+
)
|
|
2071
|
+
.join(" and ");
|
|
2072
|
+
}
|
|
2073
|
+
|
|
1882
2074
|
function table(rows: string[][]): string {
|
|
1883
2075
|
const widths = rows[0].map((_, columnIndex) =>
|
|
1884
2076
|
Math.max(...rows.map((row) => row[columnIndex].length)),
|