@estokad/cli 0.1.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.
Files changed (55) hide show
  1. package/LICENSE +17 -0
  2. package/README.md +85 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +116 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/commands/codegen.d.ts +6 -0
  8. package/dist/commands/codegen.d.ts.map +1 -0
  9. package/dist/commands/codegen.js +64 -0
  10. package/dist/commands/codegen.js.map +1 -0
  11. package/dist/commands/diff.d.ts +3 -0
  12. package/dist/commands/diff.d.ts.map +1 -0
  13. package/dist/commands/diff.js +66 -0
  14. package/dist/commands/diff.js.map +1 -0
  15. package/dist/commands/init.d.ts +7 -0
  16. package/dist/commands/init.d.ts.map +1 -0
  17. package/dist/commands/init.js +72 -0
  18. package/dist/commands/init.js.map +1 -0
  19. package/dist/commands/pull.d.ts +3 -0
  20. package/dist/commands/pull.d.ts.map +1 -0
  21. package/dist/commands/pull.js +64 -0
  22. package/dist/commands/pull.js.map +1 -0
  23. package/dist/commands/push.d.ts +6 -0
  24. package/dist/commands/push.d.ts.map +1 -0
  25. package/dist/commands/push.js +92 -0
  26. package/dist/commands/push.js.map +1 -0
  27. package/dist/commands/status.d.ts +3 -0
  28. package/dist/commands/status.d.ts.map +1 -0
  29. package/dist/commands/status.js +104 -0
  30. package/dist/commands/status.js.map +1 -0
  31. package/dist/index.d.ts +22 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +14 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/lib/api.d.ts +34 -0
  36. package/dist/lib/api.d.ts.map +1 -0
  37. package/dist/lib/api.js +55 -0
  38. package/dist/lib/api.js.map +1 -0
  39. package/dist/lib/config.d.ts +21 -0
  40. package/dist/lib/config.d.ts.map +1 -0
  41. package/dist/lib/config.js +69 -0
  42. package/dist/lib/config.js.map +1 -0
  43. package/dist/lib/diff.d.ts +36 -0
  44. package/dist/lib/diff.d.ts.map +1 -0
  45. package/dist/lib/diff.js +191 -0
  46. package/dist/lib/diff.js.map +1 -0
  47. package/dist/lib/schemas.d.ts +6 -0
  48. package/dist/lib/schemas.d.ts.map +1 -0
  49. package/dist/lib/schemas.js +70 -0
  50. package/dist/lib/schemas.js.map +1 -0
  51. package/dist/lib/state.d.ts +4 -0
  52. package/dist/lib/state.d.ts.map +1 -0
  53. package/dist/lib/state.js +32 -0
  54. package/dist/lib/state.js.map +1 -0
  55. package/package.json +40 -0
@@ -0,0 +1,191 @@
1
+ // IR vs IR diff. Pure function; the CLI command formats the output, the
2
+ // tests assert the structure.
3
+ //
4
+ // Match strategy: types are matched by `id` first, then by `name` if the
5
+ // local state file is missing. Fields are matched the same way per docs/
6
+ // schema-system.md § 10 (rename detection).
7
+ export function diffIR(local, remote) {
8
+ const entries = [];
9
+ // Index by id (primary) and name (fallback).
10
+ const remoteById = new Map(remote.map((t) => [t.id, t]));
11
+ const localByName = new Map(local.map((t) => [t.name, t]));
12
+ const remoteByName = new Map(remote.map((t) => [t.name, t]));
13
+ // Track which remote types we've already paired off so removals don't
14
+ // double-count.
15
+ const pairedRemoteIds = new Set();
16
+ for (const localType of local) {
17
+ const remoteType = remoteById.get(localType.id) ?? remoteByName.get(localType.name);
18
+ if (!remoteType) {
19
+ entries.push({ kind: 'type-added', name: localType.name });
20
+ continue;
21
+ }
22
+ pairedRemoteIds.add(remoteType.id);
23
+ if (localType.name !== remoteType.name) {
24
+ entries.push({ kind: 'type-renamed', from: remoteType.name, to: localType.name });
25
+ }
26
+ diffFields(localType, remoteType, entries);
27
+ }
28
+ // Anything in remote that wasn't paired is a removal from the local view.
29
+ for (const remoteType of remote) {
30
+ if (pairedRemoteIds.has(remoteType.id))
31
+ continue;
32
+ if (localByName.has(remoteType.name))
33
+ continue;
34
+ entries.push({ kind: 'type-removed', name: remoteType.name });
35
+ }
36
+ return { entries };
37
+ }
38
+ function diffFields(localType, remoteType, entries) {
39
+ const remoteById = new Map(remoteType.fields.map((f) => [f.id, f]));
40
+ const remoteByName = new Map(remoteType.fields.map((f) => [f.name, f]));
41
+ const localByName = new Map(localType.fields.map((f) => [f.name, f]));
42
+ const pairedRemoteIds = new Set();
43
+ for (const localField of localType.fields) {
44
+ const remoteField = remoteById.get(localField.id) ?? remoteByName.get(localField.name);
45
+ if (!remoteField) {
46
+ entries.push({ kind: 'field-added', type: localType.name, field: localField });
47
+ continue;
48
+ }
49
+ pairedRemoteIds.add(remoteField.id);
50
+ if (localField.name !== remoteField.name) {
51
+ entries.push({
52
+ kind: 'field-renamed',
53
+ type: localType.name,
54
+ from: remoteField.name,
55
+ to: localField.name,
56
+ });
57
+ }
58
+ const details = compareFieldShape(localField, remoteField);
59
+ if (details.length > 0) {
60
+ entries.push({ kind: 'field-changed', type: localType.name, field: localField.name, details });
61
+ }
62
+ }
63
+ for (const remoteField of remoteType.fields) {
64
+ if (pairedRemoteIds.has(remoteField.id))
65
+ continue;
66
+ if (localByName.has(remoteField.name))
67
+ continue;
68
+ entries.push({ kind: 'field-removed', type: localType.name, field: remoteField });
69
+ }
70
+ }
71
+ function compareFieldShape(local, remote) {
72
+ const out = [];
73
+ if (local.type !== remote.type) {
74
+ out.push(`type: ${remote.type} → ${local.type}`);
75
+ }
76
+ if ((local.required ?? false) !== (remote.required ?? false)) {
77
+ out.push(`required: ${remote.required ?? false} → ${local.required ?? false}`);
78
+ }
79
+ if ((local.localized ?? false) !== (remote.localized ?? false)) {
80
+ out.push(`localized: ${remote.localized ?? false} → ${local.localized ?? false}`);
81
+ }
82
+ // Type-specific options worth surfacing in the diff.
83
+ const specifics = compareSpecifics(local, remote);
84
+ out.push(...specifics);
85
+ return out;
86
+ }
87
+ function compareSpecifics(local, remote) {
88
+ if (local.type !== remote.type)
89
+ return [];
90
+ const out = [];
91
+ switch (local.type) {
92
+ case 'text':
93
+ case 'markdown': {
94
+ const lt = local;
95
+ const rt = remote;
96
+ if (lt.max !== rt.max)
97
+ out.push(`max: ${rt.max ?? 'none'} → ${lt.max ?? 'none'}`);
98
+ if (lt.min !== rt.min)
99
+ out.push(`min: ${rt.min ?? 'none'} → ${lt.min ?? 'none'}`);
100
+ break;
101
+ }
102
+ case 'number': {
103
+ const lt = local;
104
+ const rt = remote;
105
+ if (lt.min !== rt.min)
106
+ out.push(`min: ${rt.min ?? 'none'} → ${lt.min ?? 'none'}`);
107
+ if (lt.max !== rt.max)
108
+ out.push(`max: ${rt.max ?? 'none'} → ${lt.max ?? 'none'}`);
109
+ break;
110
+ }
111
+ case 'enum': {
112
+ const lt = local;
113
+ const rt = remote;
114
+ const added = lt.options.filter((o) => !rt.options.includes(o));
115
+ const removed = rt.options.filter((o) => !lt.options.includes(o));
116
+ for (const o of added)
117
+ out.push(`enum option added: '${o}'`);
118
+ for (const o of removed)
119
+ out.push(`enum option removed: '${o}'`);
120
+ break;
121
+ }
122
+ case 'reference':
123
+ case 'referenceList': {
124
+ const lt = local;
125
+ const rt = remote;
126
+ if (lt.to !== rt.to)
127
+ out.push(`to: ${rt.to} → ${lt.to}`);
128
+ if ((lt.crossSpace ?? false) !== (rt.crossSpace ?? false)) {
129
+ out.push(`crossSpace: ${rt.crossSpace ?? false} → ${lt.crossSpace ?? false}`);
130
+ }
131
+ break;
132
+ }
133
+ case 'embedded': {
134
+ const lt = local;
135
+ const rt = remote;
136
+ if (lt.of !== rt.of)
137
+ out.push(`of: ${rt.of} → ${lt.of}`);
138
+ break;
139
+ }
140
+ default:
141
+ break;
142
+ }
143
+ return out;
144
+ }
145
+ // --- formatter for the CLI command --------------------------------------
146
+ export function formatDiff(result) {
147
+ if (result.entries.length === 0)
148
+ return '(no changes)';
149
+ const byType = new Map();
150
+ const topLevel = [];
151
+ for (const e of result.entries) {
152
+ if (e.kind === 'type-added' || e.kind === 'type-removed' || e.kind === 'type-renamed') {
153
+ topLevel.push(e);
154
+ }
155
+ else {
156
+ const list = byType.get(e.type) ?? [];
157
+ list.push(e);
158
+ byType.set(e.type, list);
159
+ }
160
+ }
161
+ const lines = [];
162
+ for (const e of topLevel) {
163
+ if (e.kind === 'type-added')
164
+ lines.push(`+ ${e.name}`);
165
+ if (e.kind === 'type-removed')
166
+ lines.push(`- ${e.name}`);
167
+ if (e.kind === 'type-renamed')
168
+ lines.push(`~ ${e.from} → ${e.to}`);
169
+ }
170
+ for (const [typeName, fieldEntries] of byType) {
171
+ lines.push(`~ ${typeName}`);
172
+ for (const e of fieldEntries) {
173
+ if (e.kind === 'field-added') {
174
+ lines.push(` + new field: ${e.field.name} (${e.field.type})`);
175
+ }
176
+ else if (e.kind === 'field-removed') {
177
+ lines.push(` - removed field: ${e.field.name} (${e.field.type})`);
178
+ }
179
+ else if (e.kind === 'field-renamed') {
180
+ lines.push(` ~ renamed: ${e.from} → ${e.to}`);
181
+ }
182
+ else if (e.kind === 'field-changed') {
183
+ for (const d of e.details) {
184
+ lines.push(` ~ field '${e.field}': ${d}`);
185
+ }
186
+ }
187
+ }
188
+ }
189
+ return lines.join('\n');
190
+ }
191
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/lib/diff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { AnyDefinition } from '@estokad/schema';
2
+ export declare function loadSchemas(directory: string): Promise<AnyDefinition[]>;
3
+ export declare class SchemaLoadError extends Error {
4
+ constructor(message: string);
5
+ }
6
+ //# sourceMappingURL=schemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/lib/schemas.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAIpD,wBAAsB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAwB7E;AAkCD,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM;CAI5B"}
@@ -0,0 +1,70 @@
1
+ // Load the user's schema definitions from a directory of TS/JS files.
2
+ //
3
+ // jiti is what Drizzle Kit and Nuxt use for runtime TS — handles the customer
4
+ // repo's tsconfig + their imports of @estokad/schema without a compile step.
5
+ // Every exported defineType()/defineEmbedded() result is collected.
6
+ import { readdir } from 'node:fs/promises';
7
+ import { extname, resolve } from 'node:path';
8
+ import { createJiti } from 'jiti';
9
+ const ACCEPTED = ['.ts', '.mts', '.tsx', '.js', '.mjs'];
10
+ export async function loadSchemas(directory) {
11
+ const files = await collectFiles(directory);
12
+ if (files.length === 0) {
13
+ throw new SchemaLoadError(`No schema files found in ${directory}. Run 'estokad init' to scaffold the directory.`);
14
+ }
15
+ const jiti = createJiti(import.meta.url, { interopDefault: false });
16
+ const collected = [];
17
+ const seen = new Set();
18
+ for (const file of files) {
19
+ const mod = (await jiti.import(file)) ?? {};
20
+ for (const value of Object.values(mod)) {
21
+ if (isDefinition(value)) {
22
+ if (seen.has(value.name))
23
+ continue;
24
+ seen.add(value.name);
25
+ collected.push(value);
26
+ }
27
+ }
28
+ }
29
+ return collected;
30
+ }
31
+ async function collectFiles(directory) {
32
+ let entries;
33
+ try {
34
+ entries = await readdir(directory, { withFileTypes: true, encoding: 'utf8' });
35
+ }
36
+ catch {
37
+ throw new SchemaLoadError(`Schemas directory '${directory}' does not exist. Run 'estokad init' to scaffold it.`);
38
+ }
39
+ const files = [];
40
+ for (const entry of entries) {
41
+ if (!entry.isFile())
42
+ continue;
43
+ if (!ACCEPTED.includes(extname(entry.name)))
44
+ continue;
45
+ if (entry.name.startsWith('.'))
46
+ continue;
47
+ if (entry.name === 'index.ts' || entry.name === 'index.js') {
48
+ // index re-exports may double-count the same defineType result;
49
+ // we still load it so users can choose either pattern.
50
+ files.unshift(resolve(directory, entry.name));
51
+ }
52
+ else {
53
+ files.push(resolve(directory, entry.name));
54
+ }
55
+ }
56
+ return files;
57
+ }
58
+ function isDefinition(value) {
59
+ if (!value || typeof value !== 'object')
60
+ return false;
61
+ const kind = value.__kind;
62
+ return kind === 'type' || kind === 'embedded';
63
+ }
64
+ export class SchemaLoadError extends Error {
65
+ constructor(message) {
66
+ super(message);
67
+ this.name = 'SchemaLoadError';
68
+ }
69
+ }
70
+ //# sourceMappingURL=schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../src/lib/schemas.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { SchemaState, TypeIR } from '@estokad/schema';
2
+ export declare function readState(path: string): Promise<SchemaState | undefined>;
3
+ export declare function writeState(path: string, ir: ReadonlyArray<TypeIR>): Promise<void>;
4
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/lib/state.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAE1D,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAS9E;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAevF"}
@@ -0,0 +1,32 @@
1
+ // Read/write the local schema-state file (default `.estokad/schema-state.json`).
2
+ // Maps type/field names to UUIDs so renames in code don't lose identity in
3
+ // the IR — see docs/schema-system.md § 5.
4
+ import { existsSync } from 'node:fs';
5
+ import { mkdir, readFile, writeFile } from 'node:fs/promises';
6
+ import { dirname } from 'node:path';
7
+ export async function readState(path) {
8
+ if (!existsSync(path))
9
+ return undefined;
10
+ const raw = await readFile(path, 'utf8');
11
+ try {
12
+ const parsed = JSON.parse(raw);
13
+ return parsed;
14
+ }
15
+ catch {
16
+ return undefined;
17
+ }
18
+ }
19
+ export async function writeState(path, ir) {
20
+ const state = {
21
+ types: Object.fromEntries(ir.map((type) => [
22
+ type.name,
23
+ {
24
+ id: type.id,
25
+ fields: Object.fromEntries(type.fields.map((f) => [f.name, f.id])),
26
+ },
27
+ ])),
28
+ };
29
+ await mkdir(dirname(path), { recursive: true });
30
+ await writeFile(path, JSON.stringify(state, null, 2) + '\n', 'utf8');
31
+ }
32
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/lib/state.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,2EAA2E;AAC3E,0CAA0C;AAE1C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACpC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAInC,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAY;IAC1C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAA;IACvC,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IACxC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAgB,CAAA;QAC7C,OAAO,MAAM,CAAA;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY,EAAE,EAAyB;IACtE,MAAM,KAAK,GAAgB;QACzB,KAAK,EAAE,MAAM,CAAC,WAAW,CACvB,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;YACf,IAAI,CAAC,IAAI;YACT;gBACE,EAAE,EAAE,IAAI,CAAC,EAAE;gBACX,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;aACnE;SACF,CAAC,CACH;KACF,CAAA;IAED,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC/C,MAAM,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAA;AACtE,CAAC"}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@estokad/cli",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "Customer-side CLI: estokad push, pull, diff, init, status.",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/ELIASspaceMercer/estokad.git",
10
+ "directory": "packages/cli"
11
+ },
12
+ "homepage": "https://docs.estokad.com/docs/cli",
13
+ "publishConfig": {
14
+ "access": "public"
15
+ },
16
+ "main": "./dist/index.js",
17
+ "bin": {
18
+ "estokad": "./dist/cli.js"
19
+ },
20
+ "files": [
21
+ "dist"
22
+ ],
23
+ "dependencies": {
24
+ "commander": "^12.1.0",
25
+ "jiti": "^2.4.0",
26
+ "kleur": "^4.1.5",
27
+ "@estokad/schema": "0.1.0"
28
+ },
29
+ "devDependencies": {
30
+ "@types/node": "^22.10.0",
31
+ "typescript": "^5.7.0",
32
+ "vitest": "^2.1.0"
33
+ },
34
+ "scripts": {
35
+ "build": "tsc -p tsconfig.json",
36
+ "typecheck": "tsc -p tsconfig.json --noEmit",
37
+ "test": "vitest run",
38
+ "lint": "eslint ."
39
+ }
40
+ }