@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
package/LICENSE ADDED
@@ -0,0 +1,17 @@
1
+ Copyright © 2026 Samarkand Industries OÜ. All rights reserved.
2
+
3
+ Estokad is proprietary software. Source code in this repository is the
4
+ confidential intellectual property of Samarkand Industries OÜ
5
+ (registered Tallinn, Estonia).
6
+
7
+ Permission to use, copy, modify, or distribute this software is granted
8
+ only under a separate written agreement signed by Samarkand Industries
9
+ OÜ. Without such agreement, no license is granted, expressed or implied.
10
+
11
+ Public-facing components — the SDK packages published to npm under the
12
+ `@estokad/*` scope, and the SDKs' published documentation — are licensed
13
+ separately. See the LICENSE file inside each `packages/*` directory or
14
+ the package's npm registry page for the terms that apply to that
15
+ specific package.
16
+
17
+ Contact: legal@samarkandindustries.com
package/README.md ADDED
@@ -0,0 +1,85 @@
1
+ ## @estokad/cli
2
+
3
+ The customer-side CLI. Loads `schemas/*.ts`, compiles to JSON IR via `@estokad/schema`, and pushes to the management API.
4
+
5
+ ## Status
6
+
7
+ M1.2: `init`, `push`, `status` shipped. `pull` and `diff` land in M1.2b once the Library and editor surfaces are in.
8
+
9
+ ## Install (in a customer repo)
10
+
11
+ ```bash
12
+ pnpm add -D @estokad/cli @estokad/schema
13
+ pnpm estokad init # scaffolds estokad.config.ts and schemas/
14
+ ```
15
+
16
+ `estokad init` writes:
17
+
18
+ ```
19
+ estokad.config.ts # workspace, region, apiUrl, paths
20
+ schemas/index.ts # re-export entry point
21
+ schemas/site-settings.ts # tiny singleton, smoke test the loop
22
+ .estokad/.gitignore
23
+ ```
24
+
25
+ ## Configure
26
+
27
+ Three sources, highest precedence first: CLI flags → env vars → `estokad.config.ts`.
28
+
29
+ | Setting | Env var | Default |
30
+ | --------- | ------------------- | -------------------------------- |
31
+ | workspace | `ESTOKAD_WORKSPACE` | (required) |
32
+ | apiUrl | `ESTOKAD_API_URL` | (required) |
33
+ | apiKey | `ESTOKAD_API_KEY` | (required, never in config file) |
34
+ | region | `ESTOKAD_REGION` | `eu-fra-1` |
35
+ | schemas | — | `./schemas` |
36
+ | state | — | `./.estokad/schema-state.json` |
37
+
38
+ The state file maps type/field names to UUIDs across runs so renames stay stable in the IR. **Commit it** so your team shares identity.
39
+
40
+ ## Commands
41
+
42
+ ### `estokad init`
43
+
44
+ Scaffolds the customer repo. `--force` overwrites existing files.
45
+
46
+ ### `estokad push`
47
+
48
+ ```
49
+ $ estokad push
50
+ workspace default @ http://localhost:3001
51
+ ✓ loaded 12 definitions from ./schemas
52
+ ✓ compiled to JSON IR (12 types)
53
+ ✓ pushed to default@eu-fra-1 (12 types)
54
+ ✓ state saved to ./.estokad/schema-state.json
55
+ ```
56
+
57
+ Exit codes: `0` success · `2` config or schema-load error · `3` API rejected the push.
58
+
59
+ ### `estokad status`
60
+
61
+ ```
62
+ $ estokad status
63
+ estokad status
64
+ workspace default @ http://localhost:3001
65
+ region eu-fra-1
66
+ local 12 types · 7c8b...
67
+ remote 12 types · 7c8b...
68
+ drift in sync
69
+ ```
70
+
71
+ Local hash is a stable hash of the compiled IR. Remote hash is the join of every type's `schema_hash` from the API.
72
+
73
+ ## What this package does not do
74
+
75
+ - File watching / hot reload — run `estokad push` explicitly.
76
+ - `--migrate` prompts for breaking changes — M1.3 (server-side validation against existing entries) gates this.
77
+ - Studio writeback to Git — Phase 2+ (the Studio's job, not the CLI's).
78
+
79
+ ## Documentation
80
+
81
+ Full reference at [`docs.estokad.com/cli`](https://docs.estokad.com/docs/cli) and [`docs.estokad.com/schema`](https://docs.estokad.com/docs/schema).
82
+
83
+ ## License
84
+
85
+ Apache-2.0. Estokad is a Samarkand Industries OÜ product.
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env node
2
+ // estokad — the developer CLI.
3
+ //
4
+ // Bin entry. Commander parses args, dispatches to one of the commands in
5
+ // ./commands/. Each command does its own config loading + output; this file
6
+ // stays small.
7
+ import { Command } from 'commander';
8
+ import kleur from 'kleur';
9
+ import { runCodegen } from './commands/codegen.js';
10
+ import { runDiff } from './commands/diff.js';
11
+ import { runInit } from './commands/init.js';
12
+ import { runPull } from './commands/pull.js';
13
+ import { runPush } from './commands/push.js';
14
+ import { runStatus } from './commands/status.js';
15
+ const program = new Command();
16
+ program
17
+ .name('estokad')
18
+ .description('estokad — schema-as-code CLI for the Estokad CMS')
19
+ .version('0.0.0');
20
+ program
21
+ .command('init')
22
+ .description('Scaffold estokad.config.ts and a starter schema in the current repo')
23
+ .option('--force', 'Overwrite existing files', false)
24
+ .action(async (options) => {
25
+ const opts = { cwd: process.cwd() };
26
+ if (options.force)
27
+ opts.force = true;
28
+ await runInit(opts);
29
+ });
30
+ program
31
+ .command('push')
32
+ .description('Compile local schemas and push them to the workspace')
33
+ .option('-w, --workspace <slug>', 'Workspace slug (overrides config)')
34
+ .option('--api-url <url>', 'Management API base URL (overrides config)')
35
+ .option('--migrate', 'Push even when existing entries fail the new schema (M1.2c)', false)
36
+ .action(async (options) => {
37
+ const overrides = {};
38
+ if (options.workspace)
39
+ overrides.workspace = options.workspace;
40
+ if (options.apiUrl)
41
+ overrides.apiUrl = options.apiUrl;
42
+ const code = await runPush(process.cwd(), overrides, { migrate: options.migrate ?? false });
43
+ process.exit(code);
44
+ });
45
+ program
46
+ .command('pull')
47
+ .description('Fetch the workspace content types and write schemas/index.ts')
48
+ .option('-w, --workspace <slug>', 'Workspace slug (overrides config)')
49
+ .option('--api-url <url>', 'Management API base URL (overrides config)')
50
+ .action(async (options) => {
51
+ const overrides = {};
52
+ if (options.workspace)
53
+ overrides.workspace = options.workspace;
54
+ if (options.apiUrl)
55
+ overrides.apiUrl = options.apiUrl;
56
+ const code = await runPull(process.cwd(), overrides);
57
+ process.exit(code);
58
+ });
59
+ program
60
+ .command('diff')
61
+ .description('Show what would change without pushing')
62
+ .option('-w, --workspace <slug>', 'Workspace slug (overrides config)')
63
+ .option('--api-url <url>', 'Management API base URL (overrides config)')
64
+ .action(async (options) => {
65
+ const overrides = {};
66
+ if (options.workspace)
67
+ overrides.workspace = options.workspace;
68
+ if (options.apiUrl)
69
+ overrides.apiUrl = options.apiUrl;
70
+ const code = await runDiff(process.cwd(), overrides);
71
+ process.exit(code);
72
+ });
73
+ program
74
+ .command('codegen')
75
+ .description('Emit a TypeScript declaration-merge for @estokad/sdk (M2.2d)')
76
+ .option('-w, --workspace <slug>', 'Workspace slug (overrides config)')
77
+ .option('--api-url <url>', 'Management API base URL (overrides config)')
78
+ .option('-o, --output <path>', 'Output file path (default .estokad/sdk-types.ts)')
79
+ .action(async (options) => {
80
+ const overrides = {};
81
+ if (options.workspace)
82
+ overrides.workspace = options.workspace;
83
+ if (options.apiUrl)
84
+ overrides.apiUrl = options.apiUrl;
85
+ const cmd = {};
86
+ if (options.output)
87
+ cmd.output = options.output;
88
+ const code = await runCodegen(process.cwd(), overrides, cmd);
89
+ process.exit(code);
90
+ });
91
+ program
92
+ .command('status')
93
+ .description('Show local vs remote schema state and drift')
94
+ .option('-w, --workspace <slug>', 'Workspace slug (overrides config)')
95
+ .option('--api-url <url>', 'Management API base URL (overrides config)')
96
+ .action(async (options) => {
97
+ const overrides = {};
98
+ if (options.workspace)
99
+ overrides.workspace = options.workspace;
100
+ if (options.apiUrl)
101
+ overrides.apiUrl = options.apiUrl;
102
+ const code = await runStatus(process.cwd(), overrides);
103
+ process.exit(code);
104
+ });
105
+ program.parseAsync(process.argv).catch((err) => {
106
+ if (err instanceof Error) {
107
+ console.error(kleur.red(err.message));
108
+ if (process.env['DEBUG'])
109
+ console.error(err.stack);
110
+ }
111
+ else {
112
+ console.error(kleur.red(String(err)));
113
+ }
114
+ process.exit(1);
115
+ });
116
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,+BAA+B;AAC/B,EAAE;AACF,yEAAyE;AACzE,4EAA4E;AAC5E,eAAe;AAEf,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAEhD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAA;AAE7B,OAAO;KACJ,IAAI,CAAC,SAAS,CAAC;KACf,WAAW,CAAC,kDAAkD,CAAC;KAC/D,OAAO,CAAC,OAAO,CAAC,CAAA;AAEnB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,qEAAqE,CAAC;KAClF,MAAM,CAAC,SAAS,EAAE,0BAA0B,EAAE,KAAK,CAAC;KACpD,MAAM,CAAC,KAAK,EAAE,OAA4B,EAAE,EAAE;IAC7C,MAAM,IAAI,GAAqC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,CAAA;IACrE,IAAI,OAAO,CAAC,KAAK;QAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAA;IACpC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;AACrB,CAAC,CAAC,CAAA;AAEJ,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,sDAAsD,CAAC;KACnE,MAAM,CAAC,wBAAwB,EAAE,mCAAmC,CAAC;KACrE,MAAM,CAAC,iBAAiB,EAAE,4CAA4C,CAAC;KACvE,MAAM,CAAC,WAAW,EAAE,6DAA6D,EAAE,KAAK,CAAC;KACzF,MAAM,CAAC,KAAK,EAAE,OAAmE,EAAE,EAAE;IACpF,MAAM,SAAS,GAA4C,EAAE,CAAA;IAC7D,IAAI,OAAO,CAAC,SAAS;QAAE,SAAS,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAA;IAC9D,IAAI,OAAO,CAAC,MAAM;QAAE,SAAS,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAA;IACrD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,KAAK,EAAE,CAAC,CAAA;IAC3F,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACpB,CAAC,CAAC,CAAA;AAEJ,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,8DAA8D,CAAC;KAC3E,MAAM,CAAC,wBAAwB,EAAE,mCAAmC,CAAC;KACrE,MAAM,CAAC,iBAAiB,EAAE,4CAA4C,CAAC;KACvE,MAAM,CAAC,KAAK,EAAE,OAAgD,EAAE,EAAE;IACjE,MAAM,SAAS,GAA4C,EAAE,CAAA;IAC7D,IAAI,OAAO,CAAC,SAAS;QAAE,SAAS,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAA;IAC9D,IAAI,OAAO,CAAC,MAAM;QAAE,SAAS,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAA;IACrD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAA;IACpD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACpB,CAAC,CAAC,CAAA;AAEJ,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,wCAAwC,CAAC;KACrD,MAAM,CAAC,wBAAwB,EAAE,mCAAmC,CAAC;KACrE,MAAM,CAAC,iBAAiB,EAAE,4CAA4C,CAAC;KACvE,MAAM,CAAC,KAAK,EAAE,OAAgD,EAAE,EAAE;IACjE,MAAM,SAAS,GAA4C,EAAE,CAAA;IAC7D,IAAI,OAAO,CAAC,SAAS;QAAE,SAAS,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAA;IAC9D,IAAI,OAAO,CAAC,MAAM;QAAE,SAAS,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAA;IACrD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAA;IACpD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACpB,CAAC,CAAC,CAAA;AAEJ,OAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,8DAA8D,CAAC;KAC3E,MAAM,CAAC,wBAAwB,EAAE,mCAAmC,CAAC;KACrE,MAAM,CAAC,iBAAiB,EAAE,4CAA4C,CAAC;KACvE,MAAM,CAAC,qBAAqB,EAAE,kDAAkD,CAAC;KACjF,MAAM,CAAC,KAAK,EAAE,OAAiE,EAAE,EAAE;IAClF,MAAM,SAAS,GAA4C,EAAE,CAAA;IAC7D,IAAI,OAAO,CAAC,SAAS;QAAE,SAAS,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAA;IAC9D,IAAI,OAAO,CAAC,MAAM;QAAE,SAAS,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAA;IACrD,MAAM,GAAG,GAAwB,EAAE,CAAA;IACnC,IAAI,OAAO,CAAC,MAAM;QAAE,GAAG,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAA;IAC/C,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,GAAG,CAAC,CAAA;IAC5D,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACpB,CAAC,CAAC,CAAA;AAEJ,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,6CAA6C,CAAC;KAC1D,MAAM,CAAC,wBAAwB,EAAE,mCAAmC,CAAC;KACrE,MAAM,CAAC,iBAAiB,EAAE,4CAA4C,CAAC;KACvE,MAAM,CAAC,KAAK,EAAE,OAAgD,EAAE,EAAE;IACjE,MAAM,SAAS,GAA4C,EAAE,CAAA;IAC7D,IAAI,OAAO,CAAC,SAAS;QAAE,SAAS,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAA;IAC9D,IAAI,OAAO,CAAC,MAAM;QAAE,SAAS,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAA;IACrD,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAA;IACtD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACpB,CAAC,CAAC,CAAA;AAEJ,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IACtD,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;QACzB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAA;QACrC,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;YAAE,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IACpD,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IACvC,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC,CAAC,CAAA"}
@@ -0,0 +1,6 @@
1
+ import { type ConfigOverrides } from '../lib/config.js';
2
+ export interface CodegenOptions {
3
+ readonly output?: string;
4
+ }
5
+ export declare function runCodegen(cwd: string, overrides: ConfigOverrides, options?: CodegenOptions): Promise<number>;
6
+ //# sourceMappingURL=codegen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../../src/commands/codegen.ts"],"names":[],"mappings":"AAwBA,OAAO,EAA2B,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAIhF,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,wBAAsB,UAAU,CAC9B,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,eAAe,EAC1B,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,MAAM,CAAC,CAgDjB"}
@@ -0,0 +1,64 @@
1
+ // `estokad codegen` — emit a TypeScript declaration-merge augmentation
2
+ // for `@estokad/sdk` (M2.2d).
3
+ //
4
+ // Reads the workspace's content types from the management API and
5
+ // writes `<output>` (default `.estokad/sdk-types.ts`) with:
6
+ // * one `interface` per content type
7
+ // * a `declare module '@estokad/sdk' { interface ContentTypes { … } }`
8
+ // block populated from those interfaces
9
+ //
10
+ // Customers import the generated file once in their app:
11
+ //
12
+ // import './estokad/sdk-types' // side-effect-only declaration merge
13
+ //
14
+ // and `client.pressRelease.get(...)` becomes fully typed without
15
+ // hand-writing the `ContentTypes` block. Re-run after schema changes;
16
+ // commit the result.
17
+ import { mkdir, writeFile } from 'node:fs/promises';
18
+ import { dirname, resolve } from 'node:path';
19
+ import { generateContentTypesAugmentation } from '@estokad/schema';
20
+ import kleur from 'kleur';
21
+ import { ApiError, createApiClient } from '../lib/api.js';
22
+ import { ConfigError, loadConfig } from '../lib/config.js';
23
+ const DEFAULT_OUTPUT = '.estokad/sdk-types.ts';
24
+ export async function runCodegen(cwd, overrides, options = {}) {
25
+ let config;
26
+ try {
27
+ config = await loadConfig(cwd, overrides);
28
+ }
29
+ catch (err) {
30
+ if (err instanceof ConfigError) {
31
+ console.error(kleur.red(' ' + err.message));
32
+ return 2;
33
+ }
34
+ throw err;
35
+ }
36
+ console.warn(kleur.dim(` workspace ${config.workspace} @ ${config.apiUrl}`));
37
+ const api = createApiClient({
38
+ apiUrl: config.apiUrl,
39
+ workspace: config.workspace,
40
+ apiKey: config.apiKey,
41
+ });
42
+ let remoteTypes;
43
+ try {
44
+ remoteTypes = await api.listContentTypes();
45
+ }
46
+ catch (err) {
47
+ if (err instanceof ApiError) {
48
+ console.error(kleur.red(` ✗ codegen failed (${err.status}): ${err.body}`));
49
+ return 3;
50
+ }
51
+ throw err;
52
+ }
53
+ const ir = remoteTypes.map((t) => t.schema);
54
+ const output = generateContentTypesAugmentation(ir);
55
+ const outputPath = resolve(cwd, options.output ?? DEFAULT_OUTPUT);
56
+ await mkdir(dirname(outputPath), { recursive: true });
57
+ await writeFile(outputPath, output, 'utf8');
58
+ const topLevelCount = ir.filter((t) => !t.isEmbedded).length;
59
+ console.warn(kleur.cyan(' ✓ ') +
60
+ `wrote ${topLevelCount} type${topLevelCount === 1 ? '' : 's'} to ${outputPath}`);
61
+ console.warn(kleur.dim(` Add \`import '${options.output ?? DEFAULT_OUTPUT}'\` to your app for the typed client.`));
62
+ return 0;
63
+ }
64
+ //# sourceMappingURL=codegen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codegen.js","sourceRoot":"","sources":["../../src/commands/codegen.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { type ConfigOverrides } from '../lib/config.js';
2
+ export declare function runDiff(cwd: string, overrides: ConfigOverrides): Promise<number>;
3
+ //# sourceMappingURL=diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/commands/diff.ts"],"names":[],"mappings":"AAUA,OAAO,EAA2B,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAKhF,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAsDtF"}
@@ -0,0 +1,66 @@
1
+ // `estokad diff` — show what would change without pushing.
2
+ //
3
+ // Loads local schemas the same way `push` does (so the diff matches what a
4
+ // push would actually emit), fetches the remote IR, runs the pure
5
+ // diffIR() function, prints a human-readable summary.
6
+ import { compile } from '@estokad/schema';
7
+ import kleur from 'kleur';
8
+ import { ApiError, createApiClient } from '../lib/api.js';
9
+ import { ConfigError, loadConfig } from '../lib/config.js';
10
+ import { diffIR, formatDiff } from '../lib/diff.js';
11
+ import { loadSchemas, SchemaLoadError } from '../lib/schemas.js';
12
+ import { readState } from '../lib/state.js';
13
+ export async function runDiff(cwd, overrides) {
14
+ let config;
15
+ try {
16
+ config = await loadConfig(cwd, overrides);
17
+ }
18
+ catch (err) {
19
+ if (err instanceof ConfigError) {
20
+ console.error(kleur.red(' ' + err.message));
21
+ return 2;
22
+ }
23
+ throw err;
24
+ }
25
+ console.warn(kleur.dim(` workspace ${config.workspace} @ ${config.apiUrl}`));
26
+ // Local IR.
27
+ let localIR;
28
+ try {
29
+ const definitions = await loadSchemas(config.schemas);
30
+ const state = await readState(config.state);
31
+ localIR = compile(definitions, state ? { state } : {});
32
+ }
33
+ catch (err) {
34
+ if (err instanceof SchemaLoadError) {
35
+ console.error(kleur.red(' ' + err.message));
36
+ return 2;
37
+ }
38
+ throw err;
39
+ }
40
+ // Remote IR.
41
+ const api = createApiClient({
42
+ apiUrl: config.apiUrl,
43
+ workspace: config.workspace,
44
+ apiKey: config.apiKey,
45
+ });
46
+ let remoteIR;
47
+ try {
48
+ const remote = await api.listContentTypes();
49
+ remoteIR = remote.map((t) => t.schema).filter((s) => s !== undefined && s !== null);
50
+ }
51
+ catch (err) {
52
+ if (err instanceof ApiError) {
53
+ console.error(kleur.red(` ✗ remote unreachable (${err.status}): ${err.body}`));
54
+ return 3;
55
+ }
56
+ throw err;
57
+ }
58
+ const result = diffIR(localIR, remoteIR);
59
+ if (result.entries.length === 0) {
60
+ console.warn(kleur.green(' ✓ in sync'));
61
+ return 0;
62
+ }
63
+ console.warn(formatDiff(result));
64
+ return 0;
65
+ }
66
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/commands/diff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ interface InitOptions {
2
+ readonly cwd: string;
3
+ readonly force?: boolean;
4
+ }
5
+ export declare function runInit(options: InitOptions): Promise<void>;
6
+ export {};
7
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAiBA,UAAU,WAAW;IACnB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CACzB;AAED,wBAAsB,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBjE"}
@@ -0,0 +1,72 @@
1
+ // `estokad init` — scaffold a new repo to use Estokad as its CMS.
2
+ //
3
+ // Writes:
4
+ // * estokad.config.ts — workspace, region, API URL pointers
5
+ // * schemas/index.ts — re-export entry point
6
+ // * schemas/site-settings.ts — a tiny example singleton to verify the loop
7
+ // * .estokad/.gitignore — keep state file local (it's checked in but the
8
+ // directory may accumulate caches later)
9
+ //
10
+ // The example schema is a singleton because it's the smallest viable type
11
+ // and writes a file the user can immediately push to verify connectivity.
12
+ import { existsSync } from 'node:fs';
13
+ import { mkdir, writeFile } from 'node:fs/promises';
14
+ import { resolve } from 'node:path';
15
+ import kleur from 'kleur';
16
+ export async function runInit(options) {
17
+ const files = [
18
+ { path: 'estokad.config.ts', content: configTemplate() },
19
+ { path: 'schemas/index.ts', content: indexTemplate() },
20
+ { path: 'schemas/site-settings.ts', content: siteSettingsTemplate() },
21
+ { path: '.estokad/.gitignore', content: '*.cache\n' },
22
+ ];
23
+ for (const file of files) {
24
+ const path = resolve(options.cwd, file.path);
25
+ if (existsSync(path) && !options.force) {
26
+ console.warn(kleur.yellow(` skipping (exists): ${file.path}`));
27
+ continue;
28
+ }
29
+ await mkdir(resolve(path, '..'), { recursive: true });
30
+ await writeFile(path, file.content, 'utf8');
31
+ console.warn(kleur.cyan(' wrote ') + file.path);
32
+ }
33
+ console.warn('');
34
+ console.warn(kleur.bold(' Next steps:'));
35
+ console.warn(` 1. Edit ${kleur.cyan('estokad.config.ts')} with your workspace + API URL.`);
36
+ console.warn(` 2. Set ${kleur.cyan('ESTOKAD_API_KEY')} in your env.`);
37
+ console.warn(` 3. Run ${kleur.cyan('estokad push')} to register the schema.`);
38
+ }
39
+ function configTemplate() {
40
+ return `import type { Config } from '@estokad/cli'
41
+
42
+ const config: Config = {
43
+ workspace: 'default',
44
+ region: 'eu-fra-1',
45
+ apiUrl: 'http://localhost:3001',
46
+ schemas: './schemas',
47
+ state: './.estokad/schema-state.json',
48
+ }
49
+
50
+ export default config
51
+ `;
52
+ }
53
+ function indexTemplate() {
54
+ return `export * from './site-settings.js'
55
+ `;
56
+ }
57
+ function siteSettingsTemplate() {
58
+ return `import { defineType } from '@estokad/schema'
59
+
60
+ // A singleton lives once per workspace. Useful for global config.
61
+ export const siteSettings = defineType({
62
+ name: 'siteSettings',
63
+ title: 'Site settings',
64
+ isSingleton: true,
65
+ fields: [
66
+ { name: 'siteName', type: 'text', required: true },
67
+ { name: 'tagline', type: 'text' },
68
+ ],
69
+ })
70
+ `;
71
+ }
72
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,EAAE;AACF,UAAU;AACV,gEAAgE;AAChE,kDAAkD;AAClD,6EAA6E;AAC7E,2EAA2E;AAC3E,6CAA6C;AAC7C,EAAE;AACF,0EAA0E;AAC1E,0EAA0E;AAE1E,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACpC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,KAAK,MAAM,OAAO,CAAA;AAOzB,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,OAAoB;IAChD,MAAM,KAAK,GAA6C;QACtD,EAAE,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,cAAc,EAAE,EAAE;QACxD,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,aAAa,EAAE,EAAE;QACtD,EAAE,IAAI,EAAE,0BAA0B,EAAE,OAAO,EAAE,oBAAoB,EAAE,EAAE;QACrE,EAAE,IAAI,EAAE,qBAAqB,EAAE,OAAO,EAAE,WAAW,EAAE;KACtD,CAAA;IAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA;QAC5C,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACvC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,wBAAwB,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;YAC/D,SAAQ;QACV,CAAC;QACD,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QACrD,MAAM,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QAC3C,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAA;IAClD,CAAC;IAED,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAChB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAA;IACzC,OAAO,CAAC,IAAI,CAAC,eAAe,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,iCAAiC,CAAC,CAAA;IAC7F,OAAO,CAAC,IAAI,CAAC,cAAc,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,eAAe,CAAC,CAAA;IACxE,OAAO,CAAC,IAAI,CAAC,cAAc,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,0BAA0B,CAAC,CAAA;AAClF,CAAC;AAED,SAAS,cAAc;IACrB,OAAO;;;;;;;;;;;CAWR,CAAA;AACD,CAAC;AAED,SAAS,aAAa;IACpB,OAAO;CACR,CAAA;AACD,CAAC;AAED,SAAS,oBAAoB;IAC3B,OAAO;;;;;;;;;;;;CAYR,CAAA;AACD,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type ConfigOverrides } from '../lib/config.js';
2
+ export declare function runPull(cwd: string, overrides: ConfigOverrides): Promise<number>;
3
+ //# sourceMappingURL=pull.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":"AAmBA,OAAO,EAA2B,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAGhF,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAiDtF"}
@@ -0,0 +1,64 @@
1
+ // `estokad pull` — fetch the workspace's content types and write them to
2
+ // the local schemas/ directory.
3
+ //
4
+ // Per docs/schema-system.md § 7 the generated TypeScript is opinionated
5
+ // (matches defineType()/defineEmbedded() shape, sorted fields, no comments
6
+ // preserved). Customers who want comments treat code as source-of-truth and
7
+ // disable Studio writeback.
8
+ //
9
+ // M1.2b writes a single schemas/index.ts file with all types (embedded
10
+ // first, then top-level alphabetical). Per-file split is a refinement that
11
+ // can come later — splitting requires deciding how to thread imports
12
+ // between files, which is its own opinion.
13
+ import { generateTypeScript } from '@estokad/schema';
14
+ import { mkdir, writeFile } from 'node:fs/promises';
15
+ import { dirname, resolve } from 'node:path';
16
+ import kleur from 'kleur';
17
+ import { ApiError, createApiClient } from '../lib/api.js';
18
+ import { ConfigError, loadConfig } from '../lib/config.js';
19
+ import { writeState } from '../lib/state.js';
20
+ export async function runPull(cwd, overrides) {
21
+ let config;
22
+ try {
23
+ config = await loadConfig(cwd, overrides);
24
+ }
25
+ catch (err) {
26
+ if (err instanceof ConfigError) {
27
+ console.error(kleur.red(' ' + err.message));
28
+ return 2;
29
+ }
30
+ throw err;
31
+ }
32
+ console.warn(kleur.dim(` workspace ${config.workspace} @ ${config.apiUrl}`));
33
+ const api = createApiClient({
34
+ apiUrl: config.apiUrl,
35
+ workspace: config.workspace,
36
+ apiKey: config.apiKey,
37
+ });
38
+ let remote;
39
+ try {
40
+ remote = await api.listContentTypes();
41
+ }
42
+ catch (err) {
43
+ if (err instanceof ApiError) {
44
+ console.error(kleur.red(` ✗ pull failed (${err.status}): ${err.body}`));
45
+ return 3;
46
+ }
47
+ throw err;
48
+ }
49
+ const ir = remote.map((t) => t.schema).filter((s) => s !== undefined && s !== null);
50
+ if (ir.length === 0) {
51
+ console.warn(kleur.yellow(' no content types in workspace; nothing to write'));
52
+ return 0;
53
+ }
54
+ const indexPath = resolve(config.schemas, 'index.ts');
55
+ const ts = generateTypeScript(ir);
56
+ await mkdir(dirname(indexPath), { recursive: true });
57
+ await writeFile(indexPath, ts, 'utf8');
58
+ console.warn(kleur.cyan(' ✓ ') + `wrote ${ir.length} types to ${indexPath}`);
59
+ // Persist the IR's UUIDs so a subsequent push preserves identity.
60
+ await writeState(config.state, ir);
61
+ console.warn(kleur.cyan(' ✓ ') + `state saved to ${config.state}`);
62
+ return 0;
63
+ }
64
+ //# sourceMappingURL=pull.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull.js","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { type ConfigOverrides } from '../lib/config.js';
2
+ export interface PushOptions {
3
+ readonly migrate?: boolean;
4
+ }
5
+ export declare function runPush(cwd: string, overrides: ConfigOverrides, options?: PushOptions): Promise<number>;
6
+ //# sourceMappingURL=push.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../src/commands/push.ts"],"names":[],"mappings":"AAqBA,OAAO,EAA2B,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAIhF,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED,wBAAsB,OAAO,CAC3B,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,eAAe,EAC1B,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,MAAM,CAAC,CAwFjB"}