@happyvertical/smrt-cli 0.56.1 → 0.57.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/AGENTS.md +1 -1
- package/agents/commerce-money-upgrade.md +49 -0
- package/dist/{AuditLogCollection-WDHL-_AF-x25-BNOH.js → AuditLogCollection-WDHL-_AF-BeF0-WOm.js} +1 -1
- package/dist/{OidcIdentity-BUblgQLs-HnNEVZJE.js → OidcIdentity-BUblgQLs-2SX7ODeV.js} +2 -2
- package/dist/{OidcIdentityCollection-ClOyaHeF-B6ywCED-.js → OidcIdentityCollection-ClOyaHeF-T7hWKrdm.js} +1 -1
- package/dist/{ProfileAssetCollection-CRMcjLJ--Dtcl0Z7Y.js → ProfileAssetCollection-CRMcjLJ--BG3sV1ZT.js} +3 -3
- package/dist/{ProfileCollection-C4INKh7Y-CnRSIu8K.js → ProfileCollection-C4INKh7Y-C4r3lkdr.js} +17 -17
- package/dist/{ProfileLinkCollection-DFfZRsgv-DoNRyhzW.js → ProfileLinkCollection-DFfZRsgv-ByRZpcLF.js} +2 -2
- package/dist/{ProfileMetadataCollection-BIYKy4Y3-CIcxshqJ.js → ProfileMetadataCollection-BIYKy4Y3-CfMdP5nK.js} +1 -1
- package/dist/{ProfileMetafieldCollection-Buz7gzag-Qp89uhvS.js → ProfileMetafieldCollection-Buz7gzag-C4AXpyhm.js} +1 -1
- package/dist/{ProfileRelationshipCollection-C4g_QLI4-CpdzgFU_.js → ProfileRelationshipCollection-C4g_QLI4-BvSiqB4J.js} +1 -1
- package/dist/{ProfileTypeCollection-B7kwi1mU-B_Qzmn0A.js → ProfileTypeCollection-B7kwi1mU-BpRipEQ3.js} +2 -2
- package/dist/cli-generator.d.ts.map +1 -1
- package/dist/commands/db-status.d.ts.map +1 -1
- package/dist/commands/db-upgrade-commerce-money.d.ts +23 -0
- package/dist/commands/db-upgrade-commerce-money.d.ts.map +1 -0
- package/dist/commands/utilities.d.ts.map +1 -1
- package/dist/{commands-C33Y1BAd.js → commands-D2y3p_Bn.js} +215 -247
- package/dist/dist-Cz0fd3jS.js +21 -0
- package/dist/{dist-DEgeX-y-.js → dist-D3wV_qqp.js} +107 -6
- package/dist/{dist-CinSOkIj.js → dist-DAKDqxeH.js} +4 -4
- package/dist/dist-DEpgvg2W.js +4687 -0
- package/dist/{dist-BulInGkA.js → dist-DsVQcZ6G.js} +26 -9
- package/dist/index.js +12 -12
- package/dist/loaders/git-loader.d.ts.map +1 -1
- package/dist/{oidcProvisioningPrimitives-DNP9EZlU-DRKMXFiq.js → oidcProvisioningPrimitives-DNP9EZlU-C9hYFUey.js} +3 -3
- package/dist/{resolveIdentity-CkyqvctR-lxunfjyo.js → resolveIdentity-CkyqvctR-DdiQlufB.js} +14 -14
- package/package.json +10 -10
- package/agents/commerce-money-migration.md +0 -48
- package/dist/commands/db-commerce-money.d.ts +0 -5
- package/dist/commands/db-commerce-money.d.ts.map +0 -1
- package/dist/dist-BDluiNWl.js +0 -21
- package/dist/dist-Dog5zD4-.js +0 -4620
|
@@ -13,7 +13,7 @@ import { ObjectRegistry, SchemaComparer, checkLiveSchemaParity, collectForeignKe
|
|
|
13
13
|
import { loadExternalManifestSync } from "@happyvertical/smrt-core/manifest";
|
|
14
14
|
import { execFile, execFileSync, execSync, spawn, spawnSync } from "node:child_process";
|
|
15
15
|
import { homedir, tmpdir } from "node:os";
|
|
16
|
-
import { createHash, randomBytes,
|
|
16
|
+
import { createHash, randomBytes, timingSafeEqual } from "node:crypto";
|
|
17
17
|
import { extract } from "tar";
|
|
18
18
|
import { access, cp, mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
19
19
|
import { createLogger } from "@happyvertical/logger";
|
|
@@ -2783,6 +2783,178 @@ function formatParityReport(report, options = {}) {
|
|
|
2783
2783
|
return lines;
|
|
2784
2784
|
}
|
|
2785
2785
|
//#endregion
|
|
2786
|
+
//#region src/loaders/consumer-package.ts
|
|
2787
|
+
function importTarget(value) {
|
|
2788
|
+
if (typeof value === "string") return value;
|
|
2789
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
2790
|
+
const conditions = value;
|
|
2791
|
+
return importTarget(conditions.import) ?? importTarget(conditions.node) ?? importTarget(conditions.default);
|
|
2792
|
+
}
|
|
2793
|
+
/** Resolve a package entry from the invoking consumer project, not the CLI's install. */
|
|
2794
|
+
async function resolveConsumerPackageEntry(packageName, projectRoot = process.cwd()) {
|
|
2795
|
+
const searchRoots = [];
|
|
2796
|
+
let directory = resolve(projectRoot);
|
|
2797
|
+
for (;;) {
|
|
2798
|
+
searchRoots.push(join(directory, "node_modules"));
|
|
2799
|
+
const parent = dirname(directory);
|
|
2800
|
+
if (parent === directory) break;
|
|
2801
|
+
directory = parent;
|
|
2802
|
+
}
|
|
2803
|
+
for (const root of searchRoots) {
|
|
2804
|
+
const packageRoot = join(root, ...packageName.split("/"));
|
|
2805
|
+
try {
|
|
2806
|
+
const manifest = JSON.parse(await readFile(join(packageRoot, "package.json"), "utf8"));
|
|
2807
|
+
const exportsMap = manifest.exports && typeof manifest.exports === "object" ? manifest.exports : null;
|
|
2808
|
+
const entry = importTarget(exportsMap && "." in exportsMap ? exportsMap["."] : manifest.exports) ?? manifest.module ?? manifest.main ?? null;
|
|
2809
|
+
if (!entry) throw new Error(`Package ${packageName} has no importable root entry`);
|
|
2810
|
+
const resolved = resolve(packageRoot, entry);
|
|
2811
|
+
const withinPackage = relative(packageRoot, resolved);
|
|
2812
|
+
if (isAbsolute(withinPackage) || withinPackage === ".." || withinPackage.startsWith(`..${sep}`)) throw new Error(`Package ${packageName} root export escapes its package`);
|
|
2813
|
+
return resolved;
|
|
2814
|
+
} catch (error) {
|
|
2815
|
+
if (error.code === "ENOENT") continue;
|
|
2816
|
+
throw error;
|
|
2817
|
+
}
|
|
2818
|
+
}
|
|
2819
|
+
throw new Error(`Package '${packageName}' is not installed in ${projectRoot}. Install it in the project that invokes this command.`);
|
|
2820
|
+
}
|
|
2821
|
+
/** Import an optional command provider through the consumer's package graph. */
|
|
2822
|
+
async function importConsumerPackage(packageName, projectRoot = process.cwd()) {
|
|
2823
|
+
return import(
|
|
2824
|
+
/* @vite-ignore */
|
|
2825
|
+
pathToFileURL(await resolveConsumerPackageEntry(packageName, projectRoot)).href
|
|
2826
|
+
);
|
|
2827
|
+
}
|
|
2828
|
+
//#endregion
|
|
2829
|
+
//#region src/commands/db-upgrade-commerce-money.ts
|
|
2830
|
+
var COMMERCE_PACKAGE = "@happyvertical/smrt-commerce";
|
|
2831
|
+
/** The upgrade command, as named in commerce's refusal. */
|
|
2832
|
+
var COMMERCE_MONEY_UPGRADE_COMMAND = "smrt db:upgrade-commerce-money";
|
|
2833
|
+
function loadCommerce() {
|
|
2834
|
+
return importConsumerPackage(COMMERCE_PACKAGE);
|
|
2835
|
+
}
|
|
2836
|
+
function errorMessage(error) {
|
|
2837
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2838
|
+
const code = error && typeof error === "object" && "code" in error ? error.code : void 0;
|
|
2839
|
+
return `${typeof code === "string" && code ? `[${code}] ` : ""}${message}`;
|
|
2840
|
+
}
|
|
2841
|
+
/**
|
|
2842
|
+
* `db:status` precondition: an error when the database holds commerce money
|
|
2843
|
+
* data from an earlier version. Empty when commerce is not installed.
|
|
2844
|
+
*/
|
|
2845
|
+
async function checkCommerceMoneyPreconditions(db) {
|
|
2846
|
+
let commerce;
|
|
2847
|
+
try {
|
|
2848
|
+
commerce = await loadCommerce();
|
|
2849
|
+
} catch {
|
|
2850
|
+
return [];
|
|
2851
|
+
}
|
|
2852
|
+
if (typeof commerce.findCommerceMoneyUpgradeNeeds !== "function") return [];
|
|
2853
|
+
if (db.tableExists && !await db.tableExists("invoices")) return [];
|
|
2854
|
+
let status;
|
|
2855
|
+
try {
|
|
2856
|
+
status = await commerce.findCommerceMoneyUpgradeNeeds(db);
|
|
2857
|
+
} catch (error) {
|
|
2858
|
+
return [{
|
|
2859
|
+
name: "commerce-money-upgrade",
|
|
2860
|
+
status: "warning",
|
|
2861
|
+
message: `Commerce money data could not be checked: ${redactDatabaseUrlsInText(errorMessage(error))}`,
|
|
2862
|
+
recommendation: `Run ${COMMERCE_MONEY_UPGRADE_COMMAND} --check.`,
|
|
2863
|
+
details: {}
|
|
2864
|
+
}];
|
|
2865
|
+
}
|
|
2866
|
+
const tenantless = status.tenantlessDocuments ?? [];
|
|
2867
|
+
if (status.oldSchema.length === 0 && status.tenants.length === 0 && tenantless.length === 0) return [];
|
|
2868
|
+
return [{
|
|
2869
|
+
name: "commerce-money-upgrade",
|
|
2870
|
+
status: "error",
|
|
2871
|
+
message: `COMMERCE_DATA_NEEDS_UPGRADE: commerce money data from an earlier version (${status.tenants.length} tenant(s) to convert${status.oldSchema.length ? `; old columns ${status.oldSchema.join(", ")}` : ""}${tenantless.length ? `; ${tenantless.length} document row(s) without a tenant to assign or delete` : ""}). Commerce refuses it until it is upgraded.`,
|
|
2872
|
+
recommendation: `Run ${COMMERCE_MONEY_UPGRADE_COMMAND} (add --tenant-id <id> to convert one tenant).`,
|
|
2873
|
+
details: {
|
|
2874
|
+
oldSchema: status.oldSchema,
|
|
2875
|
+
tenants: status.tenants,
|
|
2876
|
+
tenantlessDocuments: tenantless.length
|
|
2877
|
+
}
|
|
2878
|
+
}];
|
|
2879
|
+
}
|
|
2880
|
+
async function configuredDatabase() {
|
|
2881
|
+
const { getPackageConfig } = await import("@happyvertical/smrt-config");
|
|
2882
|
+
const { DEFAULT_CLI_CONFIG } = await import("./config-CdJRSMRi.js").then((n) => n.n);
|
|
2883
|
+
const config = getPackageConfig("cli", DEFAULT_CLI_CONFIG);
|
|
2884
|
+
if (!config.database?.url || config.database.url === ":memory:") throw new Error("Database configuration required for db:upgrade-commerce-money. Configure database.url in smrt.config.ts (or DATABASE_URL).");
|
|
2885
|
+
await autoDiscoverAndLoad();
|
|
2886
|
+
const { getDatabase } = await import("@happyvertical/sql");
|
|
2887
|
+
const dbType = config.database.type || "sqlite";
|
|
2888
|
+
return {
|
|
2889
|
+
db: await getDatabase({
|
|
2890
|
+
type: dbType,
|
|
2891
|
+
url: config.database.url
|
|
2892
|
+
}),
|
|
2893
|
+
dbType,
|
|
2894
|
+
dbUrl: config.database.url
|
|
2895
|
+
};
|
|
2896
|
+
}
|
|
2897
|
+
var dbUpgradeCommerceMoneyCommand = {
|
|
2898
|
+
name: "db:upgrade-commerce-money",
|
|
2899
|
+
description: "Convert commerce money data written by an earlier version to the current money model, once. Each tenant converts atomically; an issued document that does not reconcile exactly fails its tenant.",
|
|
2900
|
+
aliases: ["commerce-money:upgrade"],
|
|
2901
|
+
args: [],
|
|
2902
|
+
options: {
|
|
2903
|
+
"tenant-id": {
|
|
2904
|
+
type: "string",
|
|
2905
|
+
description: "Convert only this tenant."
|
|
2906
|
+
},
|
|
2907
|
+
check: {
|
|
2908
|
+
type: "boolean",
|
|
2909
|
+
description: "Report what needs the upgrade without changing anything.",
|
|
2910
|
+
default: false
|
|
2911
|
+
}
|
|
2912
|
+
},
|
|
2913
|
+
handler: async (_args, options) => {
|
|
2914
|
+
let db;
|
|
2915
|
+
try {
|
|
2916
|
+
const configured = await configuredDatabase();
|
|
2917
|
+
db = configured.db;
|
|
2918
|
+
const commerce = await loadCommerce();
|
|
2919
|
+
console.log("\n💰 Commerce money upgrade\n");
|
|
2920
|
+
console.log(`✓ Connected to ${formatDatabaseDisplayUrl(configured.dbType, configured.dbUrl)}\n`);
|
|
2921
|
+
if (options.check) {
|
|
2922
|
+
const status = await commerce.findCommerceMoneyUpgradeNeeds(db);
|
|
2923
|
+
for (const need of status.tenants) console.log(` ${need.tenantId}: ${need.reason}`);
|
|
2924
|
+
if (status.oldSchema.length) console.log(` old columns: ${status.oldSchema.join(", ")}`);
|
|
2925
|
+
const tenantless = status.tenantlessDocuments ?? [];
|
|
2926
|
+
for (const row of tenantless) console.log(` ${row.table} ${row.id}: no tenant (assign or delete)`);
|
|
2927
|
+
if (status.tenants.length === 0 && status.oldSchema.length === 0 && tenantless.length === 0) console.log("Nothing to upgrade.\n");
|
|
2928
|
+
else {
|
|
2929
|
+
console.log(`\n${status.tenants.length} tenant(s) need the upgrade. No database changes made.\n`);
|
|
2930
|
+
process.exitCode = 1;
|
|
2931
|
+
}
|
|
2932
|
+
return;
|
|
2933
|
+
}
|
|
2934
|
+
const tenantId = options["tenant-id"]?.trim() || void 0;
|
|
2935
|
+
const result = await commerce.upgradeCommerceMoney(db, { tenantId });
|
|
2936
|
+
for (const tenant of result.upgraded) {
|
|
2937
|
+
console.log(`✓ ${tenant.tenantId}: ${tenant.issuedBackfilled} issued document(s) backfilled, ${tenant.draftsRecomputed} draft(s) recomputed.`);
|
|
2938
|
+
for (const draft of tenant.changedDrafts) console.log(` ${draft.documentType} ${draft.documentId}: total ${draft.old.totalMinor} -> ${draft.next.totalMinor}`);
|
|
2939
|
+
if (tenant.componentsWithoutLiabilityAccount.length) console.log(` created tax components without a liability account: ${tenant.componentsWithoutLiabilityAccount.join(", ")}`);
|
|
2940
|
+
}
|
|
2941
|
+
for (const failure of result.failures) console.error(`✗ ${failure.tenantId || "(no tenant)"}${failure.documentType ? ` ${failure.documentType} ${failure.documentId}` : ""}: ${failure.reason}`);
|
|
2942
|
+
if (result.droppedSchema.length) console.log(`\n✓ Removed earlier-version columns: ${result.droppedSchema.join(", ")}`);
|
|
2943
|
+
if (result.failures.length || result.remaining.length) {
|
|
2944
|
+
console.error(`\n❌ ${result.remaining.length} tenant(s) and ${(result.tenantlessDocuments ?? []).length} row(s) without a tenant still need attention.\n`);
|
|
2945
|
+
process.exitCode = 1;
|
|
2946
|
+
return;
|
|
2947
|
+
}
|
|
2948
|
+
console.log("\nCommerce money upgrade complete.\n");
|
|
2949
|
+
} catch (error) {
|
|
2950
|
+
console.error(`\n❌ Commerce money upgrade failed: ${redactDatabaseUrlsInText(errorMessage(error))}\n`);
|
|
2951
|
+
process.exitCode = 1;
|
|
2952
|
+
} finally {
|
|
2953
|
+
await closeDatabaseConnection(db);
|
|
2954
|
+
}
|
|
2955
|
+
}
|
|
2956
|
+
};
|
|
2957
|
+
//#endregion
|
|
2786
2958
|
//#region src/commands/schema-contract.ts
|
|
2787
2959
|
var SchemaContractError = class extends Error {
|
|
2788
2960
|
report;
|
|
@@ -3458,12 +3630,16 @@ var dbStatusCommand = {
|
|
|
3458
3630
|
diff = await comparer.compare(manifestSchemas);
|
|
3459
3631
|
status.drift = summarizeSchemaDiff(diff);
|
|
3460
3632
|
status.notes = summarizeSchemaNotes(diff);
|
|
3461
|
-
status.preconditions = [
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3633
|
+
status.preconditions = [
|
|
3634
|
+
...await checkTenantIdUuidPreconditions({
|
|
3635
|
+
db,
|
|
3636
|
+
dbType,
|
|
3637
|
+
dbUrl,
|
|
3638
|
+
manifestSchemas
|
|
3639
|
+
}),
|
|
3640
|
+
...checkTenantNaturalKeyUniques(comparer.getLiveSchemaSnapshot()),
|
|
3641
|
+
...await checkCommerceMoneyPreconditions(db)
|
|
3642
|
+
];
|
|
3467
3643
|
status.failedMigrations = summarizeFailedMigrations(failed, getUnresolvedGeneratedMigrationNames(diff.changes));
|
|
3468
3644
|
if (options.parity) try {
|
|
3469
3645
|
status.parity = await checkLiveSchemaParity({
|
|
@@ -5607,6 +5783,13 @@ function countObjects(data) {
|
|
|
5607
5783
|
var logger$1 = createLogger({ level: "info" });
|
|
5608
5784
|
var tempDirectories = /* @__PURE__ */ new Set();
|
|
5609
5785
|
var cleanupHandlersRegistered = false;
|
|
5786
|
+
async function removeTempDirectory(tempDir) {
|
|
5787
|
+
await rm(tempDir, {
|
|
5788
|
+
recursive: true,
|
|
5789
|
+
force: true
|
|
5790
|
+
});
|
|
5791
|
+
tempDirectories.delete(tempDir);
|
|
5792
|
+
}
|
|
5610
5793
|
/**
|
|
5611
5794
|
* Register cleanup handlers for temporary directories
|
|
5612
5795
|
* Ensures temp directories are removed on process termination
|
|
@@ -5619,15 +5802,19 @@ function registerCleanupHandlers() {
|
|
|
5619
5802
|
const dirs = Array.from(tempDirectories);
|
|
5620
5803
|
await Promise.all(dirs.map(async (dir) => {
|
|
5621
5804
|
try {
|
|
5622
|
-
await
|
|
5623
|
-
recursive: true,
|
|
5624
|
-
force: true
|
|
5625
|
-
});
|
|
5626
|
-
tempDirectories.delete(dir);
|
|
5805
|
+
await removeTempDirectory(dir);
|
|
5627
5806
|
} catch (_error) {}
|
|
5628
5807
|
}));
|
|
5629
5808
|
};
|
|
5630
|
-
process.on("exit", () => {
|
|
5809
|
+
process.on("exit", () => {
|
|
5810
|
+
for (const dir of Array.from(tempDirectories)) try {
|
|
5811
|
+
rmSync(dir, {
|
|
5812
|
+
recursive: true,
|
|
5813
|
+
force: true
|
|
5814
|
+
});
|
|
5815
|
+
tempDirectories.delete(dir);
|
|
5816
|
+
} catch (_error) {}
|
|
5817
|
+
});
|
|
5631
5818
|
process.on("SIGINT", async () => {
|
|
5632
5819
|
await cleanup();
|
|
5633
5820
|
process.exit(130);
|
|
@@ -5840,10 +6027,11 @@ async function loadGitTemplate(gitUrl) {
|
|
|
5840
6027
|
}
|
|
5841
6028
|
}
|
|
5842
6029
|
} catch (error) {
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
|
|
6030
|
+
try {
|
|
6031
|
+
await removeTempDirectory(tempDir);
|
|
6032
|
+
} catch (cleanupError) {
|
|
6033
|
+
throw new AggregateError([error, cleanupError], `Template load failed and temporary directory cleanup failed: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
6034
|
+
}
|
|
5847
6035
|
throw error;
|
|
5848
6036
|
}
|
|
5849
6037
|
}
|
|
@@ -5864,11 +6052,13 @@ function getGitTemplateDir(config) {
|
|
|
5864
6052
|
* Cleanup temporary directory after template is used
|
|
5865
6053
|
*/
|
|
5866
6054
|
async function cleanupGitTemplate(config) {
|
|
5867
|
-
const
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
6055
|
+
const gitConfig = config;
|
|
6056
|
+
const tempDir = gitConfig.__tempDir;
|
|
6057
|
+
if (tempDir) {
|
|
6058
|
+
await removeTempDirectory(tempDir);
|
|
6059
|
+
delete gitConfig.__tempDir;
|
|
6060
|
+
delete gitConfig.__templateRoot;
|
|
6061
|
+
}
|
|
5872
6062
|
}
|
|
5873
6063
|
/**
|
|
5874
6064
|
* Validate template configuration has required fields
|
|
@@ -8061,226 +8251,6 @@ function scanProjectForUnlayeredResets(root, options = {}) {
|
|
|
8061
8251
|
};
|
|
8062
8252
|
}
|
|
8063
8253
|
//#endregion
|
|
8064
|
-
//#region src/loaders/consumer-package.ts
|
|
8065
|
-
function importTarget(value) {
|
|
8066
|
-
if (typeof value === "string") return value;
|
|
8067
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
8068
|
-
const conditions = value;
|
|
8069
|
-
return importTarget(conditions.import) ?? importTarget(conditions.node) ?? importTarget(conditions.default);
|
|
8070
|
-
}
|
|
8071
|
-
/** Resolve a package entry from the invoking consumer project, not the CLI's install. */
|
|
8072
|
-
async function resolveConsumerPackageEntry(packageName, projectRoot = process.cwd()) {
|
|
8073
|
-
const searchRoots = [];
|
|
8074
|
-
let directory = resolve(projectRoot);
|
|
8075
|
-
for (;;) {
|
|
8076
|
-
searchRoots.push(join(directory, "node_modules"));
|
|
8077
|
-
const parent = dirname(directory);
|
|
8078
|
-
if (parent === directory) break;
|
|
8079
|
-
directory = parent;
|
|
8080
|
-
}
|
|
8081
|
-
for (const root of searchRoots) {
|
|
8082
|
-
const packageRoot = join(root, ...packageName.split("/"));
|
|
8083
|
-
try {
|
|
8084
|
-
const manifest = JSON.parse(await readFile(join(packageRoot, "package.json"), "utf8"));
|
|
8085
|
-
const exportsMap = manifest.exports && typeof manifest.exports === "object" ? manifest.exports : null;
|
|
8086
|
-
const entry = importTarget(exportsMap && "." in exportsMap ? exportsMap["."] : manifest.exports) ?? manifest.module ?? manifest.main ?? null;
|
|
8087
|
-
if (!entry) throw new Error(`Package ${packageName} has no importable root entry`);
|
|
8088
|
-
const resolved = resolve(packageRoot, entry);
|
|
8089
|
-
const withinPackage = relative(packageRoot, resolved);
|
|
8090
|
-
if (isAbsolute(withinPackage) || withinPackage === ".." || withinPackage.startsWith(`..${sep}`)) throw new Error(`Package ${packageName} root export escapes its package`);
|
|
8091
|
-
return resolved;
|
|
8092
|
-
} catch (error) {
|
|
8093
|
-
if (error.code === "ENOENT") continue;
|
|
8094
|
-
throw error;
|
|
8095
|
-
}
|
|
8096
|
-
}
|
|
8097
|
-
throw new Error(`Package '${packageName}' is not installed in ${projectRoot}. Install it in the project that invokes this command.`);
|
|
8098
|
-
}
|
|
8099
|
-
/** Import an optional command provider through the consumer's package graph. */
|
|
8100
|
-
async function importConsumerPackage(packageName, projectRoot = process.cwd()) {
|
|
8101
|
-
return import(
|
|
8102
|
-
/* @vite-ignore */
|
|
8103
|
-
pathToFileURL(await resolveConsumerPackageEntry(packageName, projectRoot)).href
|
|
8104
|
-
);
|
|
8105
|
-
}
|
|
8106
|
-
//#endregion
|
|
8107
|
-
//#region src/commands/db-commerce-money.ts
|
|
8108
|
-
var COMMERCE_PACKAGE = "@happyvertical/smrt-commerce";
|
|
8109
|
-
function loadCommerceMoneyModule() {
|
|
8110
|
-
return importConsumerPackage(COMMERCE_PACKAGE);
|
|
8111
|
-
}
|
|
8112
|
-
function requiredOption(value, name) {
|
|
8113
|
-
const normalized = value?.trim();
|
|
8114
|
-
if (!normalized) throw new Error(`--${name} is required`);
|
|
8115
|
-
return normalized;
|
|
8116
|
-
}
|
|
8117
|
-
function reportOutput(options) {
|
|
8118
|
-
const jsonPath = options["json-path"]?.trim();
|
|
8119
|
-
const csvPath = options["csv-path"]?.trim();
|
|
8120
|
-
if (Boolean(jsonPath) !== Boolean(csvPath)) throw new Error("--json-path and --csv-path must be supplied together");
|
|
8121
|
-
return jsonPath && csvPath ? {
|
|
8122
|
-
jsonPath,
|
|
8123
|
-
csvPath
|
|
8124
|
-
} : void 0;
|
|
8125
|
-
}
|
|
8126
|
-
function renderReport(report) {
|
|
8127
|
-
for (const tenant of report.tenants) {
|
|
8128
|
-
const reasons = Object.entries(tenant.reasonCounts).filter(([, count]) => Number(count) > 0).map(([reason, count]) => `${reason}=${count}`).join(", ");
|
|
8129
|
-
console.log(` ${tenant.tenantId}: ${tenant.documentCount} document(s), ${tenant.changingDraftCount} changing draft(s), ${tenant.issuedUnpostedFallbackTaxCount} issued/unposted fallback-tax document(s)${reasons ? `; ${reasons}` : ""}`);
|
|
8130
|
-
}
|
|
8131
|
-
for (const document of report.documents) {
|
|
8132
|
-
if (document.reasons.length === 0) continue;
|
|
8133
|
-
console.log(` ${document.tenantId}/${document.documentType}/${document.documentId}: ${document.reasons.join(", ")}`);
|
|
8134
|
-
}
|
|
8135
|
-
}
|
|
8136
|
-
function errorMessage(error) {
|
|
8137
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
8138
|
-
const code = error && typeof error === "object" && "code" in error ? error.code : void 0;
|
|
8139
|
-
return `${typeof code === "string" && code ? `[${code}] ` : ""}${message}`;
|
|
8140
|
-
}
|
|
8141
|
-
async function configuredDatabase(command) {
|
|
8142
|
-
const { getPackageConfig } = await import("@happyvertical/smrt-config");
|
|
8143
|
-
const { DEFAULT_CLI_CONFIG } = await import("./config-CdJRSMRi.js").then((n) => n.n);
|
|
8144
|
-
const config = getPackageConfig("cli", DEFAULT_CLI_CONFIG);
|
|
8145
|
-
if (!config.database?.url || config.database.url === ":memory:") throw new Error(`Database configuration required for ${command}. Configure database.url in smrt.config.ts (or DATABASE_URL).`);
|
|
8146
|
-
await autoDiscoverAndLoad();
|
|
8147
|
-
const { getDatabase } = await import("@happyvertical/sql");
|
|
8148
|
-
const dbType = config.database.type || "sqlite";
|
|
8149
|
-
return {
|
|
8150
|
-
db: await getDatabase({
|
|
8151
|
-
type: dbType,
|
|
8152
|
-
url: config.database.url
|
|
8153
|
-
}),
|
|
8154
|
-
dbType,
|
|
8155
|
-
dbUrl: config.database.url
|
|
8156
|
-
};
|
|
8157
|
-
}
|
|
8158
|
-
function commonOptions() {
|
|
8159
|
-
return { "tenant-id": {
|
|
8160
|
-
type: "string",
|
|
8161
|
-
description: "Authoritative tenant identifier."
|
|
8162
|
-
} };
|
|
8163
|
-
}
|
|
8164
|
-
var dbPreflightCommerceMoneyCommand = {
|
|
8165
|
-
name: "db:preflight-commerce-money",
|
|
8166
|
-
description: "Read and report legacy Commerce line amounts before activating the v2 money model. Never writes database state.",
|
|
8167
|
-
aliases: ["commerce-money:preflight"],
|
|
8168
|
-
args: [],
|
|
8169
|
-
options: {
|
|
8170
|
-
...commonOptions(),
|
|
8171
|
-
"json-path": {
|
|
8172
|
-
type: "string",
|
|
8173
|
-
description: "Write the deterministic JSON report to this path."
|
|
8174
|
-
},
|
|
8175
|
-
"csv-path": {
|
|
8176
|
-
type: "string",
|
|
8177
|
-
description: "Write the deterministic CSV report to this path."
|
|
8178
|
-
}
|
|
8179
|
-
},
|
|
8180
|
-
handler: async (_args, options) => {
|
|
8181
|
-
let db;
|
|
8182
|
-
try {
|
|
8183
|
-
const out = reportOutput(options);
|
|
8184
|
-
const configured = await configuredDatabase("db:preflight-commerce-money");
|
|
8185
|
-
db = configured.db;
|
|
8186
|
-
const { preflightCommerceLineAmounts } = await loadCommerceMoneyModule();
|
|
8187
|
-
console.log("\n💰 Commerce money preflight\n");
|
|
8188
|
-
console.log(`✓ Connected to ${formatDatabaseDisplayUrl(configured.dbType, configured.dbUrl)}\n`);
|
|
8189
|
-
const tenantId = options["tenant-id"]?.trim() || void 0;
|
|
8190
|
-
const report = await preflightCommerceLineAmounts(db, {
|
|
8191
|
-
out,
|
|
8192
|
-
tenantId
|
|
8193
|
-
});
|
|
8194
|
-
renderReport(report);
|
|
8195
|
-
if (out) console.log(`\n✓ Wrote ${out.jsonPath} and ${out.csvPath}.`);
|
|
8196
|
-
console.log(`\nPreflight complete: ${report.documents.length} document(s) across ${report.tenants.length} tenant(s). No database changes made.\n`);
|
|
8197
|
-
} catch (error) {
|
|
8198
|
-
console.error(`\n❌ Commerce money preflight failed: ${redactDatabaseUrlsInText(errorMessage(error))}\n`);
|
|
8199
|
-
process.exitCode = 1;
|
|
8200
|
-
} finally {
|
|
8201
|
-
await closeDatabaseConnection(db);
|
|
8202
|
-
}
|
|
8203
|
-
}
|
|
8204
|
-
};
|
|
8205
|
-
var dbMigrateCommerceMoneyCommand = {
|
|
8206
|
-
name: "db:migrate-commerce-money",
|
|
8207
|
-
description: "Migrate one tenant to the Commerce v2 money model after reviewing preflight output.",
|
|
8208
|
-
aliases: ["commerce-money:migrate"],
|
|
8209
|
-
args: [],
|
|
8210
|
-
options: {
|
|
8211
|
-
...commonOptions(),
|
|
8212
|
-
"accept-draft-changes": {
|
|
8213
|
-
type: "boolean",
|
|
8214
|
-
description: "Accept draft total changes identified by the preflight.",
|
|
8215
|
-
default: false
|
|
8216
|
-
},
|
|
8217
|
-
"migration-id": {
|
|
8218
|
-
type: "string",
|
|
8219
|
-
description: "Resume the active tenant migration with its owner identity."
|
|
8220
|
-
}
|
|
8221
|
-
},
|
|
8222
|
-
handler: async (_args, options) => {
|
|
8223
|
-
let db;
|
|
8224
|
-
try {
|
|
8225
|
-
const tenantId = requiredOption(options["tenant-id"], "tenant-id");
|
|
8226
|
-
const configured = await configuredDatabase("db:migrate-commerce-money");
|
|
8227
|
-
db = configured.db;
|
|
8228
|
-
const { migrateCommerceLineAmounts } = await loadCommerceMoneyModule();
|
|
8229
|
-
console.log("\n💰 Commerce money migration\n");
|
|
8230
|
-
console.log(`✓ Connected to ${formatDatabaseDisplayUrl(configured.dbType, configured.dbUrl)}\n`);
|
|
8231
|
-
const migrationId = options["migration-id"]?.trim() || randomUUID();
|
|
8232
|
-
console.log(`Migration owner: ${migrationId} (reuse with --migration-id after an interrupted attempt).\n`);
|
|
8233
|
-
const result = await migrateCommerceLineAmounts(db, {
|
|
8234
|
-
tenantId,
|
|
8235
|
-
acceptDraftChanges: options["accept-draft-changes"] === true,
|
|
8236
|
-
migrationId
|
|
8237
|
-
});
|
|
8238
|
-
renderReport(result.report);
|
|
8239
|
-
console.log(`\n✓ Tenant ${result.tenantId} activated v2 money model (migration ${result.migrationId}); migrated ${result.migrated}, resumed ${result.resumed}.\n`);
|
|
8240
|
-
} catch (error) {
|
|
8241
|
-
console.error(`\n❌ Commerce money migration failed: ${redactDatabaseUrlsInText(errorMessage(error))}\n`);
|
|
8242
|
-
process.exitCode = 1;
|
|
8243
|
-
} finally {
|
|
8244
|
-
await closeDatabaseConnection(db);
|
|
8245
|
-
}
|
|
8246
|
-
}
|
|
8247
|
-
};
|
|
8248
|
-
var dbRollbackCommerceMoneyCommand = {
|
|
8249
|
-
name: "db:rollback-commerce-money",
|
|
8250
|
-
description: "Restore one Commerce tenant from its durable v2 money migration journal.",
|
|
8251
|
-
aliases: ["commerce-money:rollback"],
|
|
8252
|
-
args: [],
|
|
8253
|
-
options: {
|
|
8254
|
-
...commonOptions(),
|
|
8255
|
-
"migration-id": {
|
|
8256
|
-
type: "string",
|
|
8257
|
-
description: "Migration owner identity recorded during activation."
|
|
8258
|
-
}
|
|
8259
|
-
},
|
|
8260
|
-
handler: async (_args, options) => {
|
|
8261
|
-
let db;
|
|
8262
|
-
try {
|
|
8263
|
-
const tenantId = requiredOption(options["tenant-id"], "tenant-id");
|
|
8264
|
-
const migrationId = requiredOption(options["migration-id"], "migration-id");
|
|
8265
|
-
const configured = await configuredDatabase("db:rollback-commerce-money");
|
|
8266
|
-
db = configured.db;
|
|
8267
|
-
const { rollbackCommerceLineAmounts } = await loadCommerceMoneyModule();
|
|
8268
|
-
console.log("\n💰 Commerce money rollback\n");
|
|
8269
|
-
console.log(`✓ Connected to ${formatDatabaseDisplayUrl(configured.dbType, configured.dbUrl)}\n`);
|
|
8270
|
-
const result = await rollbackCommerceLineAmounts(db, {
|
|
8271
|
-
tenantId,
|
|
8272
|
-
migrationId
|
|
8273
|
-
});
|
|
8274
|
-
console.log(`\n✓ Tenant ${result.tenantId} migration ${result.migrationId} rolled back; restored ${result.restored}, already restored ${result.alreadyRestored}.\n`);
|
|
8275
|
-
} catch (error) {
|
|
8276
|
-
console.error(`\n❌ Commerce money rollback failed: ${redactDatabaseUrlsInText(errorMessage(error))}\n`);
|
|
8277
|
-
process.exitCode = 1;
|
|
8278
|
-
} finally {
|
|
8279
|
-
await closeDatabaseConnection(db);
|
|
8280
|
-
}
|
|
8281
|
-
}
|
|
8282
|
-
};
|
|
8283
|
-
//#endregion
|
|
8284
8254
|
//#region src/commands/db-drop-framework-base-tables.ts
|
|
8285
8255
|
/**
|
|
8286
8256
|
* db:drop-framework-base-tables Command
|
|
@@ -8432,7 +8402,7 @@ var dbMaterializeTenantHierarchyCommand = {
|
|
|
8432
8402
|
if (!config.database?.url || config.database.url === ":memory:") throw new Error("Database configuration required for db:materialize-tenant-hierarchy. Configure database.url in smrt.config.ts (or DATABASE_URL).");
|
|
8433
8403
|
const dbType = config.database.type || "sqlite";
|
|
8434
8404
|
const { getDatabase } = await import("@happyvertical/sql");
|
|
8435
|
-
const { materializeTenantHierarchy, TenantHierarchyMaterializationError } = await import("./dist-
|
|
8405
|
+
const { materializeTenantHierarchy, TenantHierarchyMaterializationError } = await import("./dist-DEpgvg2W.js");
|
|
8436
8406
|
db = await getDatabase({
|
|
8437
8407
|
type: dbType,
|
|
8438
8408
|
url: config.database.url
|
|
@@ -8641,7 +8611,7 @@ var dbMigrateLedgerAccountsCommand = {
|
|
|
8641
8611
|
if (dbType !== "postgres") throw new Error("db:migrate-ledger-accounts currently supports PostgreSQL only; no changes were made. See the smrt-ledgers README for SQLite.");
|
|
8642
8612
|
await autoDiscoverAndLoad();
|
|
8643
8613
|
const { getDatabase } = await import("@happyvertical/sql");
|
|
8644
|
-
const { migrateLedgerAccountsTable, planLedgerAccountsTableMove } = await import("./dist-
|
|
8614
|
+
const { migrateLedgerAccountsTable, planLedgerAccountsTableMove } = await import("./dist-DAKDqxeH.js");
|
|
8645
8615
|
db = await getDatabase({
|
|
8646
8616
|
type: dbType,
|
|
8647
8617
|
url: config.database.url
|
|
@@ -12615,9 +12585,7 @@ export default testManifest;
|
|
|
12615
12585
|
"db:migrate-null-equal-indexes": dbMigrateNullEqualIndexesCommand,
|
|
12616
12586
|
"db:migrate-agent-schedule-slugs": dbMigrateAgentScheduleSlugsCommand,
|
|
12617
12587
|
"db:migrate-ledger-accounts": dbMigrateLedgerAccountsCommand,
|
|
12618
|
-
"db:
|
|
12619
|
-
"db:migrate-commerce-money": dbMigrateCommerceMoneyCommand,
|
|
12620
|
-
"db:rollback-commerce-money": dbRollbackCommerceMoneyCommand,
|
|
12588
|
+
"db:upgrade-commerce-money": dbUpgradeCommerceMoneyCommand,
|
|
12621
12589
|
"db:migrate-qualified-names": dbMigrateQualifiedNamesCommand,
|
|
12622
12590
|
"db:materialize-tenant-hierarchy": dbMaterializeTenantHierarchyCommand,
|
|
12623
12591
|
"db:drop-framework-base-tables": dbDropFrameworkBaseTablesCommand,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import "./NostrIdentity-AC8fAdxe-DKxKyu_a.js";
|
|
2
|
+
import "./ApiKey-CVmlf3V6-BAeHuH48.js";
|
|
3
|
+
import "./ApiKeyCollection-CiiDNFdD-CMGF3_ul.js";
|
|
4
|
+
import "./AuditLogCollection-WDHL-_AF-BeF0-WOm.js";
|
|
5
|
+
import "./NostrIdentityCollection-CctlECpX-fkAPnK02.js";
|
|
6
|
+
import "./OidcIdentity-BUblgQLs-2SX7ODeV.js";
|
|
7
|
+
import "./OidcIdentityCollection-ClOyaHeF-T7hWKrdm.js";
|
|
8
|
+
import "./ProfileAssetCollection-CRMcjLJ--BG3sV1ZT.js";
|
|
9
|
+
import { a as ProfileCollection } from "./ProfileCollection-C4INKh7Y-C4r3lkdr.js";
|
|
10
|
+
import "./ProfileLinkCollection-DFfZRsgv-ByRZpcLF.js";
|
|
11
|
+
import "./ProfileMetadataCollection-BIYKy4Y3-CfMdP5nK.js";
|
|
12
|
+
import "./ProfileMetafieldCollection-Buz7gzag-C4AXpyhm.js";
|
|
13
|
+
import "./ProfileRelationshipCollection-C4g_QLI4-BvSiqB4J.js";
|
|
14
|
+
import "./ProfileRelationshipTermCollection-C9J7mC7P-ChIFqjCg.js";
|
|
15
|
+
import "./ProfileRelationshipType-U7IwF6Wf-DNavf24e.js";
|
|
16
|
+
import "./ProfileRelationshipTypeCollection-_n22WqTb-DiZUWvev.js";
|
|
17
|
+
import "./ProfileTypeCollection-B7kwi1mU-BpRipEQ3.js";
|
|
18
|
+
import "./oidcProvisioningPrimitives-DNP9EZlU-C9hYFUey.js";
|
|
19
|
+
import "./resolveIdentity-CkyqvctR-DdiQlufB.js";
|
|
20
|
+
import "./dist-DEpgvg2W.js";
|
|
21
|
+
export { ProfileCollection };
|