@intelligo-dev/cli 1.0.0-beta.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.
Files changed (65) hide show
  1. package/LICENSE +201 -0
  2. package/dist/bin.d.ts +14 -0
  3. package/dist/bin.d.ts.map +1 -0
  4. package/dist/bin.js +149 -0
  5. package/dist/bin.js.map +1 -0
  6. package/dist/commands/add.d.ts +48 -0
  7. package/dist/commands/add.d.ts.map +1 -0
  8. package/dist/commands/add.js +83 -0
  9. package/dist/commands/add.js.map +1 -0
  10. package/dist/commands/create.d.ts +33 -0
  11. package/dist/commands/create.d.ts.map +1 -0
  12. package/dist/commands/create.js +61 -0
  13. package/dist/commands/create.js.map +1 -0
  14. package/dist/commands/doctor.d.ts +23 -0
  15. package/dist/commands/doctor.d.ts.map +1 -0
  16. package/dist/commands/doctor.js +129 -0
  17. package/dist/commands/doctor.js.map +1 -0
  18. package/dist/commands/migrate-check.d.ts +44 -0
  19. package/dist/commands/migrate-check.d.ts.map +1 -0
  20. package/dist/commands/migrate-check.js +92 -0
  21. package/dist/commands/migrate-check.js.map +1 -0
  22. package/dist/commands/upgrade-check.d.ts +40 -0
  23. package/dist/commands/upgrade-check.d.ts.map +1 -0
  24. package/dist/commands/upgrade-check.js +91 -0
  25. package/dist/commands/upgrade-check.js.map +1 -0
  26. package/dist/index.d.ts +10 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +10 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/manifest.d.ts +58 -0
  31. package/dist/manifest.d.ts.map +1 -0
  32. package/dist/manifest.js +65 -0
  33. package/dist/manifest.js.map +1 -0
  34. package/dist/migrations-dir.d.ts +13 -0
  35. package/dist/migrations-dir.d.ts.map +1 -0
  36. package/dist/migrations-dir.js +25 -0
  37. package/dist/migrations-dir.js.map +1 -0
  38. package/dist/migrations.d.ts +41 -0
  39. package/dist/migrations.d.ts.map +1 -0
  40. package/dist/migrations.js +99 -0
  41. package/dist/migrations.js.map +1 -0
  42. package/package.json +44 -0
  43. package/templates/admin-page/admin-page.tsx.tpl +56 -0
  44. package/templates/app-scaffold/assistant-route.ts.tpl +66 -0
  45. package/templates/app-scaffold/components.json.tpl +23 -0
  46. package/templates/app-scaffold/env.example.tpl +13 -0
  47. package/templates/app-scaffold/globals.css.tpl +329 -0
  48. package/templates/app-scaffold/i18n-navigation.ts.tpl +10 -0
  49. package/templates/app-scaffold/i18n-request.ts.tpl +51 -0
  50. package/templates/app-scaffold/i18n-routing.ts.tpl +13 -0
  51. package/templates/app-scaffold/intelligo.ts.tpl +84 -0
  52. package/templates/app-scaffold/layout.tsx.tpl +53 -0
  53. package/templates/app-scaffold/lib-utils.ts.tpl +6 -0
  54. package/templates/app-scaffold/messages-en-app.json.tpl +4 -0
  55. package/templates/app-scaffold/middleware.ts.tpl +11 -0
  56. package/templates/app-scaffold/next.config.mjs.tpl +19 -0
  57. package/templates/app-scaffold/package.json.tpl +42 -0
  58. package/templates/app-scaffold/plans.ts.tpl +43 -0
  59. package/templates/app-scaffold/postcss.config.mjs.tpl +7 -0
  60. package/templates/app-scaffold/sonner.tsx.tpl +50 -0
  61. package/templates/app-scaffold/theme-provider.tsx.tpl +28 -0
  62. package/templates/app-scaffold/tsconfig.json.tpl +12 -0
  63. package/templates/billing-page/billing-page.tsx.tpl +72 -0
  64. package/templates/manifest.json +116 -0
  65. package/templates/usage-page/usage-page.tsx.tpl +60 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAYH,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,IAAI,GAAG,MAAM,GAAG,OAAO,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,iEAAiE;IACjE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB,CAAC;AASF,wBAAgB,SAAS,CAAC,OAAO,GAAE,aAAkB,GAAG,WAAW,EAAE,CAkHpE;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,MAAM,CAK5D;AAED,0DAA0D;AAC1D,wBAAgB,WAAW,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,MAAM,CAE1D"}
@@ -0,0 +1,129 @@
1
+ /**
2
+ * `intelligo doctor` — report the problems that are invisible until
3
+ * they are an incident.
4
+ *
5
+ * The checks here were each chosen because something in this codebase
6
+ * actually went wrong that way, not because they sounded thorough.
7
+ */
8
+ import path from "node:path";
9
+ import { existsSync } from "node:fs";
10
+ import { inspectMigrationChain, readMigrationChain } from "../migrations.js";
11
+ import { readManifest } from "../manifest.js";
12
+ import { MIGRATION_LOCATIONS, resolveMigrationsDir, } from "../migrations-dir.js";
13
+ /** Variables the app cannot boot without. */
14
+ const REQUIRED_ENV = [
15
+ "DATABASE_URL",
16
+ "BETTER_AUTH_SECRET",
17
+ "NEXT_PUBLIC_APP_URL",
18
+ ];
19
+ export function runChecks(options = {}) {
20
+ const root = options.root ?? process.cwd();
21
+ const env = options.env ?? process.env;
22
+ const results = [];
23
+ // 1. Migration chain — the journal/disk drift that made the .sql
24
+ // files documentation rather than a provisioning mechanism.
25
+ const migrationsDir = resolveMigrationsDir(root);
26
+ if (!migrationsDir) {
27
+ results.push({
28
+ name: "migrations",
29
+ status: "warn",
30
+ detail: `No migrations directory (looked in ${MIGRATION_LOCATIONS.join(", ")}) — run from the workspace root, with @intelligo-dev/core installed?`,
31
+ });
32
+ }
33
+ else {
34
+ const chain = readMigrationChain(migrationsDir);
35
+ const problems = inspectMigrationChain(chain);
36
+ if (problems.length === 0) {
37
+ results.push({
38
+ name: "migrations",
39
+ status: "ok",
40
+ detail: `${chain.files.length} migrations, all registered in the journal`,
41
+ });
42
+ }
43
+ else {
44
+ for (const p of problems) {
45
+ results.push({
46
+ name: "migrations",
47
+ status: p.level === "error" ? "error" : "warn",
48
+ detail: p.message,
49
+ });
50
+ }
51
+ }
52
+ }
53
+ // 2. Required environment.
54
+ const missing = REQUIRED_ENV.filter((k) => !env[k]);
55
+ results.push(missing.length === 0
56
+ ? {
57
+ name: "env",
58
+ status: "ok",
59
+ detail: `${REQUIRED_ENV.length} required variables present`,
60
+ }
61
+ : {
62
+ name: "env",
63
+ status: "error",
64
+ detail: `Missing: ${missing.join(", ")}`,
65
+ });
66
+ // 3. Billing product. The engine has no built-in default since the
67
+ // Career catalogue moved out; an unset product means every plan
68
+ // lookup returns nothing and quotas silently read as zero.
69
+ results.push(env.INTELLIGO_BILLING_PRODUCT
70
+ ? {
71
+ name: "billing",
72
+ status: "ok",
73
+ detail: `Product: ${env.INTELLIGO_BILLING_PRODUCT}`,
74
+ }
75
+ : {
76
+ name: "billing",
77
+ status: "warn",
78
+ detail: "INTELLIGO_BILLING_PRODUCT unset — the composition root must call " +
79
+ "setDefaultProductSlug(), or plan lookups resolve to nothing",
80
+ });
81
+ // 4. Chat route's scaffold contract. The registry's chat item ships
82
+ // app/api/chat/route.ts, which imports @/lib/intelligo (the
83
+ // composition root) and expects @/lib/plans to have registered a
84
+ // plan catalogue — both are scaffold-provided consumer files, not
85
+ // registry files. Installing chat into a hand-rolled app without
86
+ // them is a build error that only shows up at `next build`.
87
+ const chatRoute = path.join(root, "app/api/chat/route.ts");
88
+ if (existsSync(chatRoute)) {
89
+ const missingScaffold = ["lib/intelligo.ts", "lib/plans.ts"].filter((rel) => !existsSync(path.join(root, rel)));
90
+ results.push(missingScaffold.length === 0
91
+ ? {
92
+ name: "chat",
93
+ status: "ok",
94
+ detail: "app/api/chat/route.ts has lib/intelligo.ts + lib/plans.ts",
95
+ }
96
+ : {
97
+ name: "chat",
98
+ status: "error",
99
+ detail: `app/api/chat/route.ts needs ${missingScaffold.join(" and ")} — ` +
100
+ "create them from the CLI's app-scaffold templates " +
101
+ "(packages/cli/templates/app-scaffold)",
102
+ });
103
+ }
104
+ // 5. Generated source. A conflict — template and consumer both
105
+ // moved — is the one state an upgrade cannot resolve on its own.
106
+ const manifest = readManifest(root);
107
+ if (manifest) {
108
+ const features = Object.keys(manifest.features);
109
+ results.push({
110
+ name: "generated",
111
+ status: "ok",
112
+ detail: features.length === 0
113
+ ? "manifest present, no features generated"
114
+ : `${features.length} feature(s): ${features.join(", ")} — run \`intelligo upgrade --check\` for detail`,
115
+ });
116
+ }
117
+ return results;
118
+ }
119
+ export function formatResults(results) {
120
+ const icon = { ok: "✓", warn: "!", error: "✗" };
121
+ return results
122
+ .map((r) => `${icon[r.status]} ${r.name.padEnd(12)} ${r.detail}`)
123
+ .join("\n");
124
+ }
125
+ /** Process exit code: non-zero when any check errored. */
126
+ export function exitCodeFor(results) {
127
+ return results.some((r) => r.status === "error") ? 1 : 0;
128
+ }
129
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * `intelligo migrate --check`
3
+ *
4
+ * Answers "would deploying this code against that database work?"
5
+ * without changing anything. Two failure modes matter and neither is
6
+ * visible from the code alone:
7
+ *
8
+ * - migrations the database has not applied yet (deploying now runs
9
+ * code against an older schema);
10
+ * - migrations the database has applied that this checkout does not
11
+ * contain (the database is ahead — usually a rollback in progress).
12
+ *
13
+ * Drizzle records applied migrations in `drizzle.__drizzle_migrations`
14
+ * by content hash. A database provisioned with `db:push` has the
15
+ * schema but no rows there at all, which this reports distinctly:
16
+ * "unmanaged" is a different problem from "behind", and baselining is
17
+ * the fix (see the migrations README).
18
+ */
19
+ export type MigrateCheckResult = {
20
+ /** Journal tags this checkout knows about, in order. */
21
+ chain: string[];
22
+ /** Applied according to the database. */
23
+ applied: string[];
24
+ /** In the chain but not applied — a deploy would run against an older schema. */
25
+ pending: string[];
26
+ /** Applied but absent from this checkout — the database is ahead. */
27
+ unknown: string[];
28
+ /**
29
+ * True when the migrations table is empty or missing while the
30
+ * schema exists — a push-provisioned database that needs baselining.
31
+ */
32
+ unmanaged: boolean;
33
+ };
34
+ /** Drizzle hashes the file contents with sha256. */
35
+ export declare function hashMigration(sql: string): string;
36
+ type QueryFn = (sql: string) => Promise<Array<{
37
+ hash: string;
38
+ }>>;
39
+ export declare function migrateCheck(migrationsDir: string, query: QueryFn): Promise<MigrateCheckResult>;
40
+ export declare function formatMigrateCheck(r: MigrateCheckResult): string;
41
+ /** Non-zero when deploying this code would run against a stale schema. */
42
+ export declare function migrateCheckExitCode(r: MigrateCheckResult): number;
43
+ export {};
44
+ //# sourceMappingURL=migrate-check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate-check.d.ts","sourceRoot":"","sources":["../../src/commands/migrate-check.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAQH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,wDAAwD;IACxD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,yCAAyC;IACzC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,iFAAiF;IACjF,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,qEAAqE;IACrE,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB;;;OAGG;IACH,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,oDAAoD;AACpD,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,KAAK,OAAO,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAAC;AAEjE,wBAAsB,YAAY,CAChC,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,OAAO,GACb,OAAO,CAAC,kBAAkB,CAAC,CA2C7B;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,kBAAkB,GAAG,MAAM,CA4BhE;AAED,0EAA0E;AAC1E,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,kBAAkB,GAAG,MAAM,CAElE"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * `intelligo migrate --check`
3
+ *
4
+ * Answers "would deploying this code against that database work?"
5
+ * without changing anything. Two failure modes matter and neither is
6
+ * visible from the code alone:
7
+ *
8
+ * - migrations the database has not applied yet (deploying now runs
9
+ * code against an older schema);
10
+ * - migrations the database has applied that this checkout does not
11
+ * contain (the database is ahead — usually a rollback in progress).
12
+ *
13
+ * Drizzle records applied migrations in `drizzle.__drizzle_migrations`
14
+ * by content hash. A database provisioned with `db:push` has the
15
+ * schema but no rows there at all, which this reports distinctly:
16
+ * "unmanaged" is a different problem from "behind", and baselining is
17
+ * the fix (see the migrations README).
18
+ */
19
+ import { createHash } from "node:crypto";
20
+ import { readFileSync } from "node:fs";
21
+ import path from "node:path";
22
+ import { readMigrationChain } from "../migrations.js";
23
+ /** Drizzle hashes the file contents with sha256. */
24
+ export function hashMigration(sql) {
25
+ return createHash("sha256").update(sql).digest("hex");
26
+ }
27
+ export async function migrateCheck(migrationsDir, query) {
28
+ const chain = readMigrationChain(migrationsDir);
29
+ const hashToTag = new Map();
30
+ for (const tag of chain.journalTags) {
31
+ const file = path.join(migrationsDir, `${tag}.sql`);
32
+ try {
33
+ hashToTag.set(hashMigration(readFileSync(file, "utf8")), tag);
34
+ }
35
+ catch {
36
+ // readMigrationChain already reports files the journal names but
37
+ // that are not on disk; nothing to hash here.
38
+ }
39
+ }
40
+ let rows = [];
41
+ let tableMissing = false;
42
+ try {
43
+ rows = await query(`SELECT hash FROM drizzle.__drizzle_migrations ORDER BY created_at`);
44
+ }
45
+ catch {
46
+ tableMissing = true;
47
+ }
48
+ const appliedHashes = new Set(rows.map((r) => r.hash));
49
+ const applied = [];
50
+ const unknown = [];
51
+ for (const hash of appliedHashes) {
52
+ const tag = hashToTag.get(hash);
53
+ if (tag)
54
+ applied.push(tag);
55
+ else
56
+ unknown.push(hash.slice(0, 12));
57
+ }
58
+ const appliedTags = new Set(applied);
59
+ const pending = chain.journalTags.filter((t) => !appliedTags.has(t));
60
+ return {
61
+ chain: chain.journalTags,
62
+ applied,
63
+ pending,
64
+ unknown,
65
+ unmanaged: tableMissing || appliedHashes.size === 0,
66
+ };
67
+ }
68
+ export function formatMigrateCheck(r) {
69
+ const lines = [];
70
+ if (r.unmanaged) {
71
+ lines.push(`! This database has no migration records. If it was provisioned with ` +
72
+ `db:push, baseline it before running migrate — otherwise migrate will ` +
73
+ `try to apply all ${r.chain.length} migrations. See ` +
74
+ `packages/core/src/db/migrations/README.md`);
75
+ }
76
+ if (r.unknown.length > 0) {
77
+ lines.push(`✗ Database is ahead: ${r.unknown.length} applied migration(s) are not in ` +
78
+ `this checkout (${r.unknown.join(", ")})`);
79
+ }
80
+ if (r.pending.length > 0) {
81
+ lines.push(`✗ ${r.pending.length} migration(s) pending: ${r.pending.join(", ")}`);
82
+ }
83
+ else if (!r.unmanaged) {
84
+ lines.push(`✓ Up to date (${r.applied.length}/${r.chain.length} applied)`);
85
+ }
86
+ return lines.join("\n");
87
+ }
88
+ /** Non-zero when deploying this code would run against a stale schema. */
89
+ export function migrateCheckExitCode(r) {
90
+ return r.pending.length > 0 || r.unknown.length > 0 ? 1 : 0;
91
+ }
92
+ //# sourceMappingURL=migrate-check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate-check.js","sourceRoot":"","sources":["../../src/commands/migrate-check.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * `intelligo upgrade --check`
3
+ *
4
+ * Reports what a template upgrade would do, and does nothing. The
5
+ * promise in ADR-0002 is that dependency upgrades never overwrite
6
+ * consumer source, so the interesting output is not "these files
7
+ * changed upstream" but "these changed upstream AND you have edited
8
+ * them" — the set where the consumer has to make a decision.
9
+ */
10
+ export type UpgradeItem = {
11
+ feature: string;
12
+ path: string;
13
+ /**
14
+ * - `current` — generated file matches the current template
15
+ * - `outdated` — template changed; the local copy is untouched, so
16
+ * re-generating is safe
17
+ * - `conflict` — template changed AND the consumer edited the file
18
+ * - `customized` — consumer edited it; template unchanged
19
+ * - `deleted` — consumer removed it
20
+ */
21
+ state: "current" | "outdated" | "conflict" | "customized" | "deleted";
22
+ };
23
+ export type UpgradeReport = {
24
+ installedVersion: Record<string, string>;
25
+ templateVersion: Record<string, string>;
26
+ items: UpgradeItem[];
27
+ };
28
+ export type UpgradeCheckOptions = {
29
+ appRoot: string;
30
+ templatesDir: string;
31
+ };
32
+ export declare function upgradeCheck(options: UpgradeCheckOptions): UpgradeReport;
33
+ export declare function formatUpgradeReport(r: UpgradeReport): string;
34
+ /**
35
+ * Non-zero only on conflicts. An outdated-but-untouched file is not a
36
+ * problem to fail a build over; a file that changed on both sides is a
37
+ * decision someone has to make.
38
+ */
39
+ export declare function upgradeCheckExitCode(r: UpgradeReport): number;
40
+ //# sourceMappingURL=upgrade-check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upgrade-check.d.ts","sourceRoot":"","sources":["../../src/commands/upgrade-check.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAQH,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;;OAOG;IACH,KAAK,EAAE,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,YAAY,GAAG,SAAS,CAAC;CACvE,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,KAAK,EAAE,WAAW,EAAE,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,aAAa,CAwDxE;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,aAAa,GAAG,MAAM,CA0B5D;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,aAAa,GAAG,MAAM,CAE7D"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * `intelligo upgrade --check`
3
+ *
4
+ * Reports what a template upgrade would do, and does nothing. The
5
+ * promise in ADR-0002 is that dependency upgrades never overwrite
6
+ * consumer source, so the interesting output is not "these files
7
+ * changed upstream" but "these changed upstream AND you have edited
8
+ * them" — the set where the consumer has to make a decision.
9
+ */
10
+ import { existsSync, readFileSync } from "node:fs";
11
+ import path from "node:path";
12
+ import { readCatalogue } from "./add.js";
13
+ import { hashContents, readManifest } from "../manifest.js";
14
+ export function upgradeCheck(options) {
15
+ const manifest = readManifest(options.appRoot);
16
+ if (!manifest) {
17
+ return { installedVersion: {}, templateVersion: {}, items: [] };
18
+ }
19
+ const catalogue = readCatalogue(options.templatesDir);
20
+ const report = {
21
+ installedVersion: {},
22
+ templateVersion: {},
23
+ items: [],
24
+ };
25
+ for (const [feature, entry] of Object.entries(manifest.features)) {
26
+ const spec = catalogue[feature];
27
+ report.installedVersion[feature] = entry.templateVersion;
28
+ if (spec)
29
+ report.templateVersion[feature] = spec.templateVersion;
30
+ const targetToTemplate = new Map((spec?.files ?? []).map((f) => [f.target, f.template]));
31
+ for (const file of entry.files) {
32
+ const abs = path.join(options.appRoot, file.path);
33
+ if (!existsSync(abs)) {
34
+ report.items.push({ feature, path: file.path, state: "deleted" });
35
+ continue;
36
+ }
37
+ const localHash = hashContents(readFileSync(abs, "utf8"));
38
+ const customized = localHash !== file.hash;
39
+ const templateRel = targetToTemplate.get(file.path);
40
+ let templateChanged = false;
41
+ if (templateRel) {
42
+ const templateHash = hashContents(readFileSync(path.join(options.templatesDir, templateRel), "utf8"));
43
+ templateChanged = templateHash !== file.hash;
44
+ }
45
+ report.items.push({
46
+ feature,
47
+ path: file.path,
48
+ state: templateChanged
49
+ ? customized
50
+ ? "conflict"
51
+ : "outdated"
52
+ : customized
53
+ ? "customized"
54
+ : "current",
55
+ });
56
+ }
57
+ }
58
+ return report;
59
+ }
60
+ export function formatUpgradeReport(r) {
61
+ if (r.items.length === 0) {
62
+ return "No generated files recorded — nothing to upgrade.";
63
+ }
64
+ const label = {
65
+ current: "✓ up to date",
66
+ outdated: "↑ template changed — safe to re-run `intelligo add`",
67
+ conflict: "! template changed AND you edited it — review the diff",
68
+ customized: "= yours (template unchanged)",
69
+ deleted: "✗ removed by you",
70
+ };
71
+ const lines = [];
72
+ for (const [feature, installed] of Object.entries(r.installedVersion)) {
73
+ const latest = r.templateVersion[feature];
74
+ lines.push(latest && latest !== installed
75
+ ? `${feature}: ${installed} → ${latest}`
76
+ : `${feature}: ${installed}`);
77
+ for (const item of r.items.filter((i) => i.feature === feature)) {
78
+ lines.push(` ${label[item.state]} ${item.path}`);
79
+ }
80
+ }
81
+ return lines.join("\n");
82
+ }
83
+ /**
84
+ * Non-zero only on conflicts. An outdated-but-untouched file is not a
85
+ * problem to fail a build over; a file that changed on both sides is a
86
+ * decision someone has to make.
87
+ */
88
+ export function upgradeCheckExitCode(r) {
89
+ return r.items.some((i) => i.state === "conflict") ? 1 : 0;
90
+ }
91
+ //# sourceMappingURL=upgrade-check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upgrade-check.js","sourceRoot":"","sources":["../../src/commands/upgrade-check.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @intelligo-dev/cli — operational commands for an Intelligo application.
3
+ *
4
+ * Exported as functions as well as a binary so CI can call the checks
5
+ * directly (see the migration-chain gate) without shelling out.
6
+ */
7
+ export { runChecks, formatResults, exitCodeFor, type CheckResult, type DoctorOptions, } from "./commands/doctor.js";
8
+ export { migrateCheck, hashMigration, formatMigrateCheck, migrateCheckExitCode, type MigrateCheckResult, } from "./commands/migrate-check.js";
9
+ export { readMigrationChain, inspectMigrationChain, type MigrationChain, type ChainProblem, } from "./migrations.js";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,SAAS,EACT,aAAa,EACb,WAAW,EACX,KAAK,WAAW,EAChB,KAAK,aAAa,GACnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,oBAAoB,EACpB,KAAK,kBAAkB,GACxB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,KAAK,cAAc,EACnB,KAAK,YAAY,GAClB,MAAM,iBAAiB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @intelligo-dev/cli — operational commands for an Intelligo application.
3
+ *
4
+ * Exported as functions as well as a binary so CI can call the checks
5
+ * directly (see the migration-chain gate) without shelling out.
6
+ */
7
+ export { runChecks, formatResults, exitCodeFor, } from "./commands/doctor.js";
8
+ export { migrateCheck, hashMigration, formatMigrateCheck, migrateCheckExitCode, } from "./commands/migrate-check.js";
9
+ export { readMigrationChain, inspectMigrationChain, } from "./migrations.js";
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,SAAS,EACT,aAAa,EACb,WAAW,GAGZ,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,oBAAoB,GAErB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EACL,kBAAkB,EAClB,qBAAqB,GAGtB,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Generated-source manifest.
3
+ *
4
+ * Intelligo generates starting source into the consumer's repository
5
+ * and then stops owning it (ADR-0002). That promise needs a mechanism,
6
+ * because "never overwrite a customized file" requires knowing which
7
+ * files were generated, from which template version, and whether the
8
+ * consumer has since edited them.
9
+ *
10
+ * The manifest records a content hash per generated file at the moment
11
+ * it was written. A file whose hash still matches was not touched and
12
+ * can be re-generated safely; one whose hash differs is the consumer's
13
+ * code now, and an upgrade may only show them a diff.
14
+ *
15
+ * Deliberately not a lockfile of package versions: it tracks template
16
+ * provenance, not dependencies.
17
+ */
18
+ export declare const MANIFEST_FILE = "intelligo.manifest.json";
19
+ export type GeneratedFile = {
20
+ /** Path relative to the consumer application root. */
21
+ path: string;
22
+ /** sha256 of the contents Intelligo wrote. */
23
+ hash: string;
24
+ };
25
+ export type FeatureEntry = {
26
+ templateVersion: string;
27
+ files: GeneratedFile[];
28
+ };
29
+ export type Manifest = {
30
+ schemaVersion: 1;
31
+ frameworkVersion: string;
32
+ features: Record<string, FeatureEntry>;
33
+ };
34
+ export declare function hashContents(contents: string): string;
35
+ export declare function emptyManifest(frameworkVersion: string): Manifest;
36
+ export declare function readManifest(appRoot: string): Manifest | null;
37
+ export declare function writeManifest(appRoot: string, manifest: Manifest): void;
38
+ /**
39
+ * What happened to a generated file since it was written.
40
+ *
41
+ * `customized` is the state the whole mechanism exists to detect: the
42
+ * consumer owns that file now, and an upgrade must not touch it.
43
+ */
44
+ export type FileState = "unchanged" | "customized" | "deleted";
45
+ export type FileStatus = {
46
+ path: string;
47
+ state: FileState;
48
+ };
49
+ export declare function inspectFile(appRoot: string, file: GeneratedFile): FileStatus;
50
+ export declare function inspectFeature(appRoot: string, entry: FeatureEntry): FileStatus[];
51
+ /**
52
+ * Record a feature's generated files, replacing any previous entry for
53
+ * the same feature — re-generating is how a consumer accepts a new
54
+ * template version, and the recorded hashes must then describe what is
55
+ * actually on disk.
56
+ */
57
+ export declare function recordFeature(manifest: Manifest, feature: string, templateVersion: string, files: GeneratedFile[]): Manifest;
58
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,eAAO,MAAM,aAAa,4BAA4B,CAAC;AAEvD,MAAM,MAAM,aAAa,GAAG;IAC1B,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,aAAa,EAAE,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,aAAa,EAAE,CAAC,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CACxC,CAAC;AAEF,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,aAAa,CAAC,gBAAgB,EAAE,MAAM,GAAG,QAAQ,CAEhE;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAI7D;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAKvE;AAED;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG,WAAW,GAAG,YAAY,GAAG,SAAS,CAAC;AAE/D,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,SAAS,CAAC;CAClB,CAAC;AAEF,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,UAAU,CAS5E;AAED,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,YAAY,GAClB,UAAU,EAAE,CAEd;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,MAAM,EACvB,KAAK,EAAE,aAAa,EAAE,GACrB,QAAQ,CAQV"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Generated-source manifest.
3
+ *
4
+ * Intelligo generates starting source into the consumer's repository
5
+ * and then stops owning it (ADR-0002). That promise needs a mechanism,
6
+ * because "never overwrite a customized file" requires knowing which
7
+ * files were generated, from which template version, and whether the
8
+ * consumer has since edited them.
9
+ *
10
+ * The manifest records a content hash per generated file at the moment
11
+ * it was written. A file whose hash still matches was not touched and
12
+ * can be re-generated safely; one whose hash differs is the consumer's
13
+ * code now, and an upgrade may only show them a diff.
14
+ *
15
+ * Deliberately not a lockfile of package versions: it tracks template
16
+ * provenance, not dependencies.
17
+ */
18
+ import { createHash } from "node:crypto";
19
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
20
+ import path from "node:path";
21
+ export const MANIFEST_FILE = "intelligo.manifest.json";
22
+ export function hashContents(contents) {
23
+ return createHash("sha256").update(contents).digest("hex");
24
+ }
25
+ export function emptyManifest(frameworkVersion) {
26
+ return { schemaVersion: 1, frameworkVersion, features: {} };
27
+ }
28
+ export function readManifest(appRoot) {
29
+ const file = path.join(appRoot, MANIFEST_FILE);
30
+ if (!existsSync(file))
31
+ return null;
32
+ return JSON.parse(readFileSync(file, "utf8"));
33
+ }
34
+ export function writeManifest(appRoot, manifest) {
35
+ writeFileSync(path.join(appRoot, MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}\n`);
36
+ }
37
+ export function inspectFile(appRoot, file) {
38
+ const abs = path.join(appRoot, file.path);
39
+ if (!existsSync(abs))
40
+ return { path: file.path, state: "deleted" };
41
+ const current = hashContents(readFileSync(abs, "utf8"));
42
+ return {
43
+ path: file.path,
44
+ state: current === file.hash ? "unchanged" : "customized",
45
+ };
46
+ }
47
+ export function inspectFeature(appRoot, entry) {
48
+ return entry.files.map((f) => inspectFile(appRoot, f));
49
+ }
50
+ /**
51
+ * Record a feature's generated files, replacing any previous entry for
52
+ * the same feature — re-generating is how a consumer accepts a new
53
+ * template version, and the recorded hashes must then describe what is
54
+ * actually on disk.
55
+ */
56
+ export function recordFeature(manifest, feature, templateVersion, files) {
57
+ return {
58
+ ...manifest,
59
+ features: {
60
+ ...manifest.features,
61
+ [feature]: { templateVersion, files },
62
+ },
63
+ };
64
+ }
65
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,CAAC,MAAM,aAAa,GAAG,yBAAyB,CAAC;AAoBvD,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,gBAAwB;IACpD,OAAO,EAAE,aAAa,EAAE,CAAC,EAAE,gBAAgB,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;IAC/C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAa,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAe,EAAE,QAAkB;IAC/D,aAAa,CACX,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,EACjC,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CACzC,CAAC;AACJ,CAAC;AAeD,MAAM,UAAU,WAAW,CAAC,OAAe,EAAE,IAAmB;IAC9D,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1C,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAEnE,MAAM,OAAO,GAAG,YAAY,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC;IACxD,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY;KAC1D,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,OAAe,EACf,KAAmB;IAEnB,OAAO,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;AACzD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAC3B,QAAkB,EAClB,OAAe,EACf,eAAuB,EACvB,KAAsB;IAEtB,OAAO;QACL,GAAG,QAAQ;QACX,QAAQ,EAAE;YACR,GAAG,QAAQ,CAAC,QAAQ;YACpB,CAAC,OAAO,CAAC,EAAE,EAAE,eAAe,EAAE,KAAK,EAAE;SACtC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Where the framework's migration chain lives, relative to the
3
+ * directory the CLI is run from.
4
+ *
5
+ * Two layouts are real: the framework repository itself, where core is
6
+ * a workspace package, and a consumer application, where core arrives
7
+ * from the registry and ships its migrations inside the package (they
8
+ * are in `files`, next to `dist`). The first match wins, so a checkout
9
+ * that has both — the framework repo — reads its own source.
10
+ */
11
+ export declare const MIGRATION_LOCATIONS: readonly ["packages/core/src/db/migrations", "node_modules/@intelligo-dev/core/src/db/migrations"];
12
+ export declare function resolveMigrationsDir(root: string): string | null;
13
+ //# sourceMappingURL=migrations-dir.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrations-dir.d.ts","sourceRoot":"","sources":["../src/migrations-dir.ts"],"names":[],"mappings":"AAGA;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB,oGAGtB,CAAC;AAEX,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMhE"}
@@ -0,0 +1,25 @@
1
+ import { existsSync } from "node:fs";
2
+ import path from "node:path";
3
+ /**
4
+ * Where the framework's migration chain lives, relative to the
5
+ * directory the CLI is run from.
6
+ *
7
+ * Two layouts are real: the framework repository itself, where core is
8
+ * a workspace package, and a consumer application, where core arrives
9
+ * from the registry and ships its migrations inside the package (they
10
+ * are in `files`, next to `dist`). The first match wins, so a checkout
11
+ * that has both — the framework repo — reads its own source.
12
+ */
13
+ export const MIGRATION_LOCATIONS = [
14
+ "packages/core/src/db/migrations",
15
+ "node_modules/@intelligo-dev/core/src/db/migrations",
16
+ ];
17
+ export function resolveMigrationsDir(root) {
18
+ for (const relative of MIGRATION_LOCATIONS) {
19
+ const dir = path.join(root, relative);
20
+ if (existsSync(dir))
21
+ return dir;
22
+ }
23
+ return null;
24
+ }
25
+ //# sourceMappingURL=migrations-dir.js.map