@orizm/cli 1.0.2 → 1.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 (73) hide show
  1. package/dist/cli.cjs +1726 -0
  2. package/dist/cli.d.ts +2 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +791 -98
  5. package/dist/cms/generate/command.d.ts +3 -0
  6. package/dist/cms/generate/command.d.ts.map +1 -0
  7. package/dist/cms/generate/generator.d.ts +8 -0
  8. package/dist/cms/generate/generator.d.ts.map +1 -0
  9. package/dist/cms/pull/action.d.ts +5 -0
  10. package/dist/cms/pull/action.d.ts.map +1 -0
  11. package/dist/cms/pull/command.d.ts +3 -0
  12. package/dist/cms/pull/command.d.ts.map +1 -0
  13. package/dist/config/functions.d.ts +38 -0
  14. package/dist/config/functions.d.ts.map +1 -0
  15. package/dist/config/functions.test.d.ts +2 -0
  16. package/dist/config/functions.test.d.ts.map +1 -0
  17. package/dist/config/generate-erd/command.d.ts +3 -0
  18. package/dist/config/generate-erd/command.d.ts.map +1 -0
  19. package/dist/config/generate-erd/convert-to-input.d.ts +23 -0
  20. package/dist/config/generate-erd/convert-to-input.d.ts.map +1 -0
  21. package/dist/config/generate-erd/convert-to-input.test.d.ts +2 -0
  22. package/dist/config/generate-erd/convert-to-input.test.d.ts.map +1 -0
  23. package/dist/config/generate-erd/generate.d.ts +3 -0
  24. package/dist/config/generate-erd/generate.d.ts.map +1 -0
  25. package/dist/config/index.cjs +107 -0
  26. package/dist/config/index.d.ts +2 -0
  27. package/dist/config/index.d.ts.map +1 -0
  28. package/dist/config/index.js +80 -0
  29. package/dist/config/validate/command.d.ts +3 -0
  30. package/dist/config/validate/command.d.ts.map +1 -0
  31. package/dist/config/validate/watcher.d.ts +2 -0
  32. package/dist/config/validate/watcher.d.ts.map +1 -0
  33. package/dist/consumer/generate/action.d.ts +2 -0
  34. package/dist/consumer/generate/action.d.ts.map +1 -0
  35. package/dist/consumer/generate/command.d.ts +3 -0
  36. package/dist/consumer/generate/command.d.ts.map +1 -0
  37. package/dist/consumer/pull/action.d.ts +5 -0
  38. package/dist/consumer/pull/action.d.ts.map +1 -0
  39. package/dist/consumer/pull/command.d.ts +3 -0
  40. package/dist/consumer/pull/command.d.ts.map +1 -0
  41. package/dist/consumer/pull/generate.d.ts +7 -0
  42. package/dist/consumer/pull/generate.d.ts.map +1 -0
  43. package/dist/lib/cli-cursor.d.ts +3 -0
  44. package/dist/lib/cli-cursor.d.ts.map +1 -0
  45. package/dist/lib/cli-input.d.ts +2 -0
  46. package/dist/lib/cli-input.d.ts.map +1 -0
  47. package/dist/lib/cli-spinner.d.ts +13 -0
  48. package/dist/lib/cli-spinner.d.ts.map +1 -0
  49. package/dist/lib/cli-symbol.d.ts +3 -0
  50. package/dist/lib/cli-symbol.d.ts.map +1 -0
  51. package/dist/lib/cli-table.d.ts +16 -0
  52. package/dist/lib/cli-table.d.ts.map +1 -0
  53. package/dist/lib/developer-api.d.ts +7 -0
  54. package/dist/lib/developer-api.d.ts.map +1 -0
  55. package/dist/lib/display-change-events.d.ts +5 -0
  56. package/dist/lib/display-change-events.d.ts.map +1 -0
  57. package/dist/lib/display-valibot-error.d.ts +6 -0
  58. package/dist/lib/display-valibot-error.d.ts.map +1 -0
  59. package/dist/lib/display-valibot-error.test.d.ts +2 -0
  60. package/dist/lib/display-valibot-error.test.d.ts.map +1 -0
  61. package/dist/lib/fetch-current-definition.d.ts +7 -0
  62. package/dist/lib/fetch-current-definition.d.ts.map +1 -0
  63. package/dist/lib/handle-error.d.ts +2 -0
  64. package/dist/lib/handle-error.d.ts.map +1 -0
  65. package/dist/lib/load-config.d.ts +3 -0
  66. package/dist/lib/load-config.d.ts.map +1 -0
  67. package/dist/lib/load-env.d.ts +10 -0
  68. package/dist/lib/load-env.d.ts.map +1 -0
  69. package/dist/push/command.d.ts +3 -0
  70. package/dist/push/command.d.ts.map +1 -0
  71. package/dist/types.d.ts +22 -0
  72. package/dist/types.d.ts.map +1 -0
  73. package/package.json +20 -8
package/dist/cli.cjs ADDED
@@ -0,0 +1,1726 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (let key of __getOwnPropNames(from))
11
+ if (!__hasOwnProp.call(to, key) && key !== except)
12
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
13
+ }
14
+ return to;
15
+ };
16
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
17
+ // If the importer is in node compatibility mode or this is not an ESM
18
+ // file that has been converted to a CommonJS file using a Babel-
19
+ // compatible transform (i.e. "__esModule" has not been set), then set
20
+ // "default" to the CommonJS "module.exports" for node compatibility.
21
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
+ mod
23
+ ));
24
+
25
+ // src/cli.ts
26
+ var import_commander8 = require("commander");
27
+
28
+ // src/cms/generate/command.ts
29
+ var import_commander = require("commander");
30
+
31
+ // src/lib/load-config.ts
32
+ var import_esbuild = __toESM(require("esbuild"), 1);
33
+ var import_config_validator = require("@orizm/common/config-validator");
34
+ var v = __toESM(require("valibot"), 1);
35
+ async function loadConfig(configFile) {
36
+ const buildResult = await import_esbuild.default.build({
37
+ entryPoints: [configFile],
38
+ bundle: true,
39
+ write: false,
40
+ format: "esm",
41
+ target: "node16",
42
+ platform: "node"
43
+ });
44
+ const moduleURL = `data:text/javascript,${encodeURIComponent(
45
+ buildResult.outputFiles[0].text
46
+ )}`;
47
+ const { default: orizmConfigRaw } = await import(moduleURL);
48
+ return v.parse(import_config_validator.OrizmConfigDef, orizmConfigRaw);
49
+ }
50
+
51
+ // src/lib/cli-spinner.ts
52
+ var import_readline = __toESM(require("readline"), 1);
53
+
54
+ // src/lib/cli-symbol.ts
55
+ var import_cli_color = __toESM(require("cli-color"), 1);
56
+ var success = import_cli_color.default.green("\u2713");
57
+ var error = import_cli_color.default.red("\u2717");
58
+
59
+ // src/lib/cli-cursor.ts
60
+ function hide() {
61
+ process.stdout.write("\x1B[?25l");
62
+ }
63
+ function show() {
64
+ process.stdout.write("\x1B[?25h");
65
+ }
66
+
67
+ // src/lib/cli-spinner.ts
68
+ var FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
69
+ var FRAME_INTERVAL = 80;
70
+ var Spinner = class {
71
+ text = "";
72
+ currentFrame = 0;
73
+ timer = null;
74
+ isSpinning = false;
75
+ start(text) {
76
+ if (text) {
77
+ this.text = text;
78
+ }
79
+ if (this.isSpinning) {
80
+ return this;
81
+ }
82
+ this.isSpinning = true;
83
+ this.currentFrame = 0;
84
+ hide();
85
+ this.render();
86
+ this.timer = setInterval(() => {
87
+ this.render();
88
+ }, FRAME_INTERVAL);
89
+ return this;
90
+ }
91
+ stop() {
92
+ if (!this.isSpinning) {
93
+ return this;
94
+ }
95
+ this.isSpinning = false;
96
+ if (this.timer) {
97
+ clearInterval(this.timer);
98
+ this.timer = null;
99
+ }
100
+ import_readline.default.clearLine(process.stdout, 0);
101
+ import_readline.default.cursorTo(process.stdout, 0);
102
+ show();
103
+ return this;
104
+ }
105
+ succeed(text) {
106
+ this.stop();
107
+ const finalText = text || this.text;
108
+ console.log(`${success} ${finalText}`);
109
+ }
110
+ render() {
111
+ const frame = FRAMES[this.currentFrame];
112
+ this.currentFrame = (this.currentFrame + 1) % FRAMES.length;
113
+ import_readline.default.clearLine(process.stdout, 0);
114
+ import_readline.default.cursorTo(process.stdout, 0);
115
+ process.stdout.write(`${frame} ${this.text}`);
116
+ }
117
+ };
118
+ function createSpinner() {
119
+ return new Spinner();
120
+ }
121
+
122
+ // src/lib/handle-error.ts
123
+ var v3 = __toESM(require("valibot"), 1);
124
+ var import_cli_color3 = __toESM(require("cli-color"), 1);
125
+
126
+ // src/lib/display-valibot-error.ts
127
+ var v2 = __toESM(require("valibot"), 1);
128
+ var import_cli_color2 = __toESM(require("cli-color"), 1);
129
+ function displayValibotError(error2) {
130
+ if (!v2.isValiError(error2)) {
131
+ return;
132
+ }
133
+ console.error(`Error: ${error2.issues.length} problem(s) found.`);
134
+ console.error(buildValiErrorMessage(error2));
135
+ }
136
+ function buildValiErrorMessage(e, options) {
137
+ const { color = true } = options ?? {};
138
+ return e.issues.map((issue) => {
139
+ const path3 = getPath(issue);
140
+ return ` ${getIssueMessage(issue.message, color)} (at ${getLocationPath(path3, color)})`;
141
+ }).join("\n");
142
+ }
143
+ function getIssueMessage(message, color) {
144
+ return color ? import_cli_color2.default.red(message) : message;
145
+ }
146
+ function getLocationPath(path3, color) {
147
+ return color ? import_cli_color2.default.yellow(path3) : path3;
148
+ }
149
+ function getPath(issue) {
150
+ const issueDotPath = v2.getDotPath(issue);
151
+ const pathInfo = issue.path;
152
+ if (!issueDotPath || !pathInfo) {
153
+ return "";
154
+ }
155
+ const pathParts = issueDotPath.split(".");
156
+ let pathInfoIndex = 0;
157
+ for (let i = 0; i < pathParts.length; i++) {
158
+ const part = pathParts[i];
159
+ if (!isNumberIndex(part)) {
160
+ continue;
161
+ }
162
+ const index = parseInt(part);
163
+ for (let j = pathInfoIndex; j < pathInfo.length; j++) {
164
+ const pathItem = pathInfo[j];
165
+ if (pathItem.type === "array" && pathItem.key === index) {
166
+ if (pathItem.value && typeof pathItem.value === "object" && "name" in pathItem.value) {
167
+ pathParts[i] = String(pathItem.value.name);
168
+ pathInfoIndex = j + 1;
169
+ break;
170
+ }
171
+ }
172
+ }
173
+ }
174
+ return pathParts.join(".");
175
+ }
176
+ function isNumberIndex(part) {
177
+ return /^\d+$/.test(part);
178
+ }
179
+
180
+ // src/lib/handle-error.ts
181
+ function handleError(error2) {
182
+ show();
183
+ if (v3.isValiError(error2)) {
184
+ console.error();
185
+ displayValibotError(error2);
186
+ console.error();
187
+ process.exit(1);
188
+ }
189
+ console.error();
190
+ console.error(
191
+ import_cli_color3.default.red(
192
+ "Something went wrong. Please check the error below for more details."
193
+ )
194
+ );
195
+ console.error();
196
+ console.error(error2);
197
+ console.error();
198
+ process.exit(1);
199
+ }
200
+
201
+ // src/cms/generate/generator.ts
202
+ var import_promises = require("fs/promises");
203
+ var import_path = __toESM(require("path"), 1);
204
+ var import_handlebars = __toESM(require("handlebars"), 1);
205
+
206
+ // src/cms/templates/types.ts.hbr
207
+ var types_ts_default = '// This file was automatically generated and should not be edited.\n\nimport { FormValidationRules, StorageItemType } from "@orizm/common";\n\n// Utilities\ntype _ModuleRef<T> = T & _ModuleDescriptor;\ntype _ModuleDescriptor = {\n isModule: true;\n};\ntype _ArrayModuleRef<T> = T & _ArrayModuleDescriptor;\ntype _ArrayModuleDescriptor = {\n isModuleArray: true;\n};\n\n// Tables\n{{#each tables}}\nexport type {{toCodeTypeName this.name}} = {\n id: string;\n createdAt: string;\n updatedAt: string;\n {{#unless this.isSubmissions}}\n group?: string;\n publishedAt?: string;\n _draft?: boolean;\n _published?: boolean;\n scheduledPublishAt?: string | null;\n scheduledUnpublishAt?: string | null;\n {{else}}\n _formId: string;\n _content: unknown;\n _formSchema: unknown;\n _attachments: StorageItemType[];\n {{/unless}}\n {{#each this.columns}}\n {{this.name}}{{#unless this.required}}?{{/unless}}: {{typeName this}};\n {{/each}}\n {{#if this.enableForm}}\n formSchema: FormValidationRules;\n {{/if}}\n};\n\nexport type {{toCodeTypeName this.name}}CreateInput = {\n {{#unless this.isSubmissions}}\n group?: string;\n publishedAt?: string;\n scheduledPublishAt?: string | null;\n scheduledUnpublishAt?: string | null;\n createdAt?: string;\n {{/unless}}\n {{#each this.columns}}\n {{this.name}}{{#unless this.required}}?{{/unless}}: {{typeName this}};\n {{/each}}\n {{#if this.enableForm}}\n formSchema: FormValidationRules;\n {{/if}}\n};\n\nexport type {{toCodeTypeName this.name}}UpdateInput = {\n {{#each this.columns}}\n {{#unless this.readOnly}}{{this.name}}?: {{typeName this}}{{#unless this.required}} | null{{/unless}};{{/unless}}\n {{/each}}\n {{#unless this.isSubmissions}}\n publishedAt?: string;\n scheduledPublishAt?: string | null;\n scheduledUnpublishAt?: string | null;\n createdAt?: string;\n {{/unless}}\n {{#if this.enableForm}}\n formSchema: FormValidationRules;\n {{/if}}\n};\n{{/each}}\n\n// Module types\n{{#each tableModules}}\nexport type {{toCodeTypeName this.name}} = {\n id?: string;\n {{#each this.columns}}\n {{this.name}}{{#unless this.required}}?{{/unless}}: {{typeName this}};\n {{/each}}\n};\n{{/each}}\n\n\n// Descriptor types\n{{#each tables}}\nexport type {{toCodeTypeName this.name}}__Descriptor = {\n row: {{toCodeTypeName this.name}};\n create: {{toCodeTypeName this.name}}CreateInput;\n update: {{toCodeTypeName this.name}}UpdateInput;\n {{#if (filterRefColumn this.columns)}}\n refs: {\n {{#each (filterRefColumn this.columns)}}\n {{includeName this}}: {{{includeType this}}};\n {{/each}}\n }\n {{/if}}\n {{#unless (filterRefColumn this.columns)}}\n refs: object;\n {{/unless}}\n {{#if (filterUniqueIndexes this.indexes)}}\n unique: [\n {{#each (filterUniqueIndexes this.indexes)}}\n { {{#each (getIndexColumns ../this this)}}{{this.name}}:{{typeName this}},{{/each}} },\n {{/each}}\n ]\n {{/if}}\n {{#unless (filterUniqueIndexes this.indexes)}}\n unique: [];\n {{/unless}}\n {{#if this.enableDrafts}}\n enableDrafts: true;\n {{/if}}\n {{#if this.enableForm}}\n submissionDescriptor: {{toCodeTypeName this.name}}_Submission__Descriptor;\n {{else}}\n submissionDescriptor: never;\n {{/if}}\n};\n{{/each}}\n\n\n{{#each tableModules}}\nexport type {{toCodeTypeName this.name}}__Descriptor = {\n row: {{toCodeTypeName this.name}};\n {{#if (filterRefColumn this.columns)}}\n refs: {\n {{#each (filterRefColumn this.columns)}}\n {{includeName this}}: {{{includeType this}}};\n {{/each}}\n }\n {{/if}}\n {{#unless (filterRefColumn this.columns)}}\n refs: object;\n {{/unless}}\n unique:[]\n};\n{{/each}}\n\n\n// Webhook types\nexport type WebhookEvent = "content.create" | "content.update" | "content.delete";\ntype WebhookPayloadBase = {\n event: WebhookEvent;\n timestamp: string;\n project: string;\n};\n{{#if tables}}\nexport type WebhookPayload = WebhookPayloadBase & (\n {{#each tables}}\n | {\n table: "{{this.name}}";\n content: {{toCodeTypeName this.name}};\n old?: {{toCodeTypeName this.name}};\n }\n {{/each}}\n);\n{{else}}\nexport type WebhookPayload = WebhookPayloadBase;\n{{/if}}\n';
208
+
209
+ // src/cms/templates/client.ts.hbr
210
+ var client_ts_default = '// This file was automatically generated and should not be edited.\n\nimport { OrizmCMSClient } from "@orizm/cms-sdk";\n\nimport * as Models from "./types";\n\nexport class CMSClient {\n constructor(protected client: OrizmCMSClient) {\n this.tables = {\n {{#each tables}}\n {{toEndpointName this.name}}: this.client.getTableClient<Models.{{toCodeTypeName this.name}}__Descriptor>("{{toEndpointName this.name}}"),\n {{/each}}\n };\n\n this.buckets = {\n {{#each buckets}}\n {{toEndpointName this.name}}: this.client.getBucketClient("{{toEndpointName this.name}}"),\n {{/each}}\n };\n\n this.userManagement = this.client.userManagement;\n \n this.userinfo = this.client.userinfo;\n \n this.auth = this.client.auth;\n }\n\n readonly tables;\n readonly buckets;\n readonly userManagement;\n readonly userinfo;\n readonly auth;\n}\n';
211
+
212
+ // src/cms/generate/generator.ts
213
+ import_handlebars.default.registerHelper("toEndpointName", (str) => {
214
+ return str;
215
+ });
216
+ function toCodeTypeName(str) {
217
+ str = str.charAt(0).toUpperCase() + str.slice(1);
218
+ return str.replace(/_([a-z])/g, (g) => g[1].toUpperCase());
219
+ }
220
+ import_handlebars.default.registerHelper("toCodeTypeName", toCodeTypeName);
221
+ import_handlebars.default.registerHelper("typeName", (column) => {
222
+ if (column.type === "reference") {
223
+ return "string";
224
+ } else if (column.type === "module") {
225
+ return toCodeTypeName(column.moduleName);
226
+ } else if (column.type === "module-array") {
227
+ return toCodeTypeName(column.moduleName) + "[]";
228
+ } else if (column.type == "json") {
229
+ return "unknown";
230
+ } else if (column.type === "storage") {
231
+ return "StorageItemType";
232
+ } else {
233
+ return column.type;
234
+ }
235
+ });
236
+ import_handlebars.default.registerHelper(
237
+ "filterRefColumn",
238
+ (columns) => {
239
+ return (columns || []).filter(
240
+ (c) => c.type === "reference" && c.tableName && c.includeName || c.type === "module" && c.moduleName || c.type === "module-array" && c.moduleName
241
+ );
242
+ }
243
+ );
244
+ import_handlebars.default.registerHelper(
245
+ "includeName",
246
+ (column) => {
247
+ return column.type === "reference" ? column.includeName : column.name;
248
+ }
249
+ );
250
+ import_handlebars.default.registerHelper(
251
+ "includeType",
252
+ (column) => {
253
+ if (column.type === "reference")
254
+ return toCodeTypeName(column.tableName) + "__Descriptor";
255
+ if (column.type === "module")
256
+ return `_ModuleRef<${toCodeTypeName(column.moduleName)}__Descriptor>`;
257
+ if (column.type === "module-array")
258
+ return `_ArrayModuleRef<${toCodeTypeName(
259
+ column.moduleName
260
+ )}__Descriptor>`;
261
+ }
262
+ );
263
+ import_handlebars.default.registerHelper(
264
+ "filterUniqueIndexes",
265
+ (indexes) => {
266
+ return (indexes || []).filter((i) => i.unique);
267
+ }
268
+ );
269
+ import_handlebars.default.registerHelper(
270
+ "getIndexColumns",
271
+ (table, index) => {
272
+ return index.columns.map((i) => {
273
+ const column = table.columns.find((c) => c.name === i);
274
+ if (!column) {
275
+ throw new Error(`column ${i} not found`);
276
+ }
277
+ return column;
278
+ });
279
+ }
280
+ );
281
+ async function generate(options) {
282
+ const config = options.config;
283
+ await (0, import_promises.mkdir)(options.output, { recursive: true });
284
+ await renderTypes(config, options.output);
285
+ await renderClient(config, options.output);
286
+ }
287
+ async function renderTypes(config, output) {
288
+ const submissionTables = config.tables.filter((t) => t.enableForm).map((t) => ({
289
+ name: t.name + "__submission",
290
+ columns: t.formOptions?.submissionColumns || [],
291
+ isSubmissions: true
292
+ }));
293
+ const renderParams = {
294
+ ...config,
295
+ tables: [...config.tables, ...submissionTables]
296
+ };
297
+ const rendered = import_handlebars.default.compile(types_ts_default)(renderParams);
298
+ const targetPath = import_path.default.join(output, "types.ts");
299
+ await (0, import_promises.writeFile)(targetPath, rendered, "utf-8");
300
+ }
301
+ async function renderClient(config, output) {
302
+ const rendered = import_handlebars.default.compile(client_ts_default)(config);
303
+ const targetPath = import_path.default.join(output, "client.ts");
304
+ await (0, import_promises.writeFile)(targetPath, rendered, "utf-8");
305
+ }
306
+
307
+ // src/cms/generate/command.ts
308
+ var spinner = createSpinner();
309
+ var cmsGenerateCommand = new import_commander.Command("generate").description("generate orizm client and types.").option("-c, --config <path>", "orizm config file path.", "orizm.config.ts").option("-o, --output <path>", "output directory.", "./src/orizm").action(async (options) => {
310
+ try {
311
+ spinner.start("Loading project schema...");
312
+ const config = await loadConfig(options.config);
313
+ spinner.succeed("Loaded project schema.");
314
+ spinner.start("Generating code...");
315
+ await generate({
316
+ config,
317
+ output: options.output
318
+ });
319
+ spinner.succeed(`Generated code to '${options.output}'`);
320
+ } catch (error2) {
321
+ handleError(error2);
322
+ }
323
+ });
324
+
325
+ // src/cms/pull/command.ts
326
+ var import_commander2 = require("commander");
327
+
328
+ // ../../node_modules/.pnpm/openapi-fetch@0.13.5/node_modules/openapi-fetch/dist/index.js
329
+ var PATH_PARAM_RE = /\{[^{}]+\}/g;
330
+ var supportsRequestInitExt = () => {
331
+ return typeof process === "object" && Number.parseInt(process?.versions?.node?.substring(0, 2)) >= 18 && process.versions.undici;
332
+ };
333
+ function randomID() {
334
+ return Math.random().toString(36).slice(2, 11);
335
+ }
336
+ function createClient(clientOptions) {
337
+ let {
338
+ baseUrl = "",
339
+ Request: CustomRequest = globalThis.Request,
340
+ fetch: baseFetch = globalThis.fetch,
341
+ querySerializer: globalQuerySerializer,
342
+ bodySerializer: globalBodySerializer,
343
+ headers: baseHeaders,
344
+ requestInitExt = void 0,
345
+ ...baseOptions
346
+ } = { ...clientOptions };
347
+ requestInitExt = supportsRequestInitExt() ? requestInitExt : void 0;
348
+ baseUrl = removeTrailingSlash(baseUrl);
349
+ const middlewares = [];
350
+ async function coreFetch(schemaPath, fetchOptions) {
351
+ const {
352
+ baseUrl: localBaseUrl,
353
+ fetch = baseFetch,
354
+ Request = CustomRequest,
355
+ headers,
356
+ params = {},
357
+ parseAs = "json",
358
+ querySerializer: requestQuerySerializer,
359
+ bodySerializer = globalBodySerializer ?? defaultBodySerializer,
360
+ body,
361
+ ...init
362
+ } = fetchOptions || {};
363
+ if (localBaseUrl) {
364
+ baseUrl = removeTrailingSlash(localBaseUrl);
365
+ }
366
+ let querySerializer = typeof globalQuerySerializer === "function" ? globalQuerySerializer : createQuerySerializer(globalQuerySerializer);
367
+ if (requestQuerySerializer) {
368
+ querySerializer = typeof requestQuerySerializer === "function" ? requestQuerySerializer : createQuerySerializer({
369
+ ...typeof globalQuerySerializer === "object" ? globalQuerySerializer : {},
370
+ ...requestQuerySerializer
371
+ });
372
+ }
373
+ const serializedBody = body === void 0 ? void 0 : bodySerializer(body);
374
+ const defaultHeaders = (
375
+ // with no body, we should not to set Content-Type
376
+ serializedBody === void 0 || // if serialized body is FormData; browser will correctly set Content-Type & boundary expression
377
+ serializedBody instanceof FormData ? {} : {
378
+ "Content-Type": "application/json"
379
+ }
380
+ );
381
+ const requestInit = {
382
+ redirect: "follow",
383
+ ...baseOptions,
384
+ ...init,
385
+ body: serializedBody,
386
+ headers: mergeHeaders(defaultHeaders, baseHeaders, headers, params.header)
387
+ };
388
+ let id;
389
+ let options;
390
+ let request = new CustomRequest(createFinalURL(schemaPath, { baseUrl, params, querySerializer }), requestInit);
391
+ let response;
392
+ for (const key in init) {
393
+ if (!(key in request)) {
394
+ request[key] = init[key];
395
+ }
396
+ }
397
+ if (middlewares.length) {
398
+ id = randomID();
399
+ options = Object.freeze({
400
+ baseUrl,
401
+ fetch,
402
+ parseAs,
403
+ querySerializer,
404
+ bodySerializer
405
+ });
406
+ for (const m of middlewares) {
407
+ if (m && typeof m === "object" && typeof m.onRequest === "function") {
408
+ const result = await m.onRequest({
409
+ request,
410
+ schemaPath,
411
+ params,
412
+ options,
413
+ id
414
+ });
415
+ if (result) {
416
+ if (result instanceof CustomRequest) {
417
+ request = result;
418
+ } else if (result instanceof Response) {
419
+ response = result;
420
+ break;
421
+ } else {
422
+ throw new Error("onRequest: must return new Request() or Response() when modifying the request");
423
+ }
424
+ }
425
+ }
426
+ }
427
+ }
428
+ if (!response) {
429
+ try {
430
+ response = await fetch(request, requestInitExt);
431
+ } catch (error3) {
432
+ let errorAfterMiddleware = error3;
433
+ if (middlewares.length) {
434
+ for (let i = middlewares.length - 1; i >= 0; i--) {
435
+ const m = middlewares[i];
436
+ if (m && typeof m === "object" && typeof m.onError === "function") {
437
+ const result = await m.onError({
438
+ request,
439
+ error: errorAfterMiddleware,
440
+ schemaPath,
441
+ params,
442
+ options,
443
+ id
444
+ });
445
+ if (result) {
446
+ if (result instanceof Response) {
447
+ errorAfterMiddleware = void 0;
448
+ response = result;
449
+ break;
450
+ }
451
+ if (result instanceof Error) {
452
+ errorAfterMiddleware = result;
453
+ continue;
454
+ }
455
+ throw new Error("onError: must return new Response() or instance of Error");
456
+ }
457
+ }
458
+ }
459
+ }
460
+ if (errorAfterMiddleware) {
461
+ throw errorAfterMiddleware;
462
+ }
463
+ }
464
+ if (middlewares.length) {
465
+ for (let i = middlewares.length - 1; i >= 0; i--) {
466
+ const m = middlewares[i];
467
+ if (m && typeof m === "object" && typeof m.onResponse === "function") {
468
+ const result = await m.onResponse({
469
+ request,
470
+ response,
471
+ schemaPath,
472
+ params,
473
+ options,
474
+ id
475
+ });
476
+ if (result) {
477
+ if (!(result instanceof Response)) {
478
+ throw new Error("onResponse: must return new Response() when modifying the response");
479
+ }
480
+ response = result;
481
+ }
482
+ }
483
+ }
484
+ }
485
+ }
486
+ if (response.status === 204 || response.headers.get("Content-Length") === "0") {
487
+ return response.ok ? { data: void 0, response } : { error: void 0, response };
488
+ }
489
+ if (response.ok) {
490
+ if (parseAs === "stream") {
491
+ return { data: response.body, response };
492
+ }
493
+ return { data: await response[parseAs](), response };
494
+ }
495
+ let error2 = await response.text();
496
+ try {
497
+ error2 = JSON.parse(error2);
498
+ } catch {
499
+ }
500
+ return { error: error2, response };
501
+ }
502
+ return {
503
+ request(method, url, init) {
504
+ return coreFetch(url, { ...init, method: method.toUpperCase() });
505
+ },
506
+ /** Call a GET endpoint */
507
+ GET(url, init) {
508
+ return coreFetch(url, { ...init, method: "GET" });
509
+ },
510
+ /** Call a PUT endpoint */
511
+ PUT(url, init) {
512
+ return coreFetch(url, { ...init, method: "PUT" });
513
+ },
514
+ /** Call a POST endpoint */
515
+ POST(url, init) {
516
+ return coreFetch(url, { ...init, method: "POST" });
517
+ },
518
+ /** Call a DELETE endpoint */
519
+ DELETE(url, init) {
520
+ return coreFetch(url, { ...init, method: "DELETE" });
521
+ },
522
+ /** Call a OPTIONS endpoint */
523
+ OPTIONS(url, init) {
524
+ return coreFetch(url, { ...init, method: "OPTIONS" });
525
+ },
526
+ /** Call a HEAD endpoint */
527
+ HEAD(url, init) {
528
+ return coreFetch(url, { ...init, method: "HEAD" });
529
+ },
530
+ /** Call a PATCH endpoint */
531
+ PATCH(url, init) {
532
+ return coreFetch(url, { ...init, method: "PATCH" });
533
+ },
534
+ /** Call a TRACE endpoint */
535
+ TRACE(url, init) {
536
+ return coreFetch(url, { ...init, method: "TRACE" });
537
+ },
538
+ /** Register middleware */
539
+ use(...middleware) {
540
+ for (const m of middleware) {
541
+ if (!m) {
542
+ continue;
543
+ }
544
+ if (typeof m !== "object" || !("onRequest" in m || "onResponse" in m || "onError" in m)) {
545
+ throw new Error("Middleware must be an object with one of `onRequest()`, `onResponse() or `onError()`");
546
+ }
547
+ middlewares.push(m);
548
+ }
549
+ },
550
+ /** Unregister middleware */
551
+ eject(...middleware) {
552
+ for (const m of middleware) {
553
+ const i = middlewares.indexOf(m);
554
+ if (i !== -1) {
555
+ middlewares.splice(i, 1);
556
+ }
557
+ }
558
+ }
559
+ };
560
+ }
561
+ function serializePrimitiveParam(name, value, options) {
562
+ if (value === void 0 || value === null) {
563
+ return "";
564
+ }
565
+ if (typeof value === "object") {
566
+ throw new Error(
567
+ "Deeply-nested arrays/objects aren\u2019t supported. Provide your own `querySerializer()` to handle these."
568
+ );
569
+ }
570
+ return `${name}=${options?.allowReserved === true ? value : encodeURIComponent(value)}`;
571
+ }
572
+ function serializeObjectParam(name, value, options) {
573
+ if (!value || typeof value !== "object") {
574
+ return "";
575
+ }
576
+ const values = [];
577
+ const joiner = {
578
+ simple: ",",
579
+ label: ".",
580
+ matrix: ";"
581
+ }[options.style] || "&";
582
+ if (options.style !== "deepObject" && options.explode === false) {
583
+ for (const k in value) {
584
+ values.push(k, options.allowReserved === true ? value[k] : encodeURIComponent(value[k]));
585
+ }
586
+ const final2 = values.join(",");
587
+ switch (options.style) {
588
+ case "form": {
589
+ return `${name}=${final2}`;
590
+ }
591
+ case "label": {
592
+ return `.${final2}`;
593
+ }
594
+ case "matrix": {
595
+ return `;${name}=${final2}`;
596
+ }
597
+ default: {
598
+ return final2;
599
+ }
600
+ }
601
+ }
602
+ for (const k in value) {
603
+ const finalName = options.style === "deepObject" ? `${name}[${k}]` : k;
604
+ values.push(serializePrimitiveParam(finalName, value[k], options));
605
+ }
606
+ const final = values.join(joiner);
607
+ return options.style === "label" || options.style === "matrix" ? `${joiner}${final}` : final;
608
+ }
609
+ function serializeArrayParam(name, value, options) {
610
+ if (!Array.isArray(value)) {
611
+ return "";
612
+ }
613
+ if (options.explode === false) {
614
+ const joiner2 = { form: ",", spaceDelimited: "%20", pipeDelimited: "|" }[options.style] || ",";
615
+ const final = (options.allowReserved === true ? value : value.map((v6) => encodeURIComponent(v6))).join(joiner2);
616
+ switch (options.style) {
617
+ case "simple": {
618
+ return final;
619
+ }
620
+ case "label": {
621
+ return `.${final}`;
622
+ }
623
+ case "matrix": {
624
+ return `;${name}=${final}`;
625
+ }
626
+ // case "spaceDelimited":
627
+ // case "pipeDelimited":
628
+ default: {
629
+ return `${name}=${final}`;
630
+ }
631
+ }
632
+ }
633
+ const joiner = { simple: ",", label: ".", matrix: ";" }[options.style] || "&";
634
+ const values = [];
635
+ for (const v6 of value) {
636
+ if (options.style === "simple" || options.style === "label") {
637
+ values.push(options.allowReserved === true ? v6 : encodeURIComponent(v6));
638
+ } else {
639
+ values.push(serializePrimitiveParam(name, v6, options));
640
+ }
641
+ }
642
+ return options.style === "label" || options.style === "matrix" ? `${joiner}${values.join(joiner)}` : values.join(joiner);
643
+ }
644
+ function createQuerySerializer(options) {
645
+ return function querySerializer(queryParams) {
646
+ const search = [];
647
+ if (queryParams && typeof queryParams === "object") {
648
+ for (const name in queryParams) {
649
+ const value = queryParams[name];
650
+ if (value === void 0 || value === null) {
651
+ continue;
652
+ }
653
+ if (Array.isArray(value)) {
654
+ if (value.length === 0) {
655
+ continue;
656
+ }
657
+ search.push(
658
+ serializeArrayParam(name, value, {
659
+ style: "form",
660
+ explode: true,
661
+ ...options?.array,
662
+ allowReserved: options?.allowReserved || false
663
+ })
664
+ );
665
+ continue;
666
+ }
667
+ if (typeof value === "object") {
668
+ search.push(
669
+ serializeObjectParam(name, value, {
670
+ style: "deepObject",
671
+ explode: true,
672
+ ...options?.object,
673
+ allowReserved: options?.allowReserved || false
674
+ })
675
+ );
676
+ continue;
677
+ }
678
+ search.push(serializePrimitiveParam(name, value, options));
679
+ }
680
+ }
681
+ return search.join("&");
682
+ };
683
+ }
684
+ function defaultPathSerializer(pathname, pathParams) {
685
+ let nextURL = pathname;
686
+ for (const match of pathname.match(PATH_PARAM_RE) ?? []) {
687
+ let name = match.substring(1, match.length - 1);
688
+ let explode = false;
689
+ let style = "simple";
690
+ if (name.endsWith("*")) {
691
+ explode = true;
692
+ name = name.substring(0, name.length - 1);
693
+ }
694
+ if (name.startsWith(".")) {
695
+ style = "label";
696
+ name = name.substring(1);
697
+ } else if (name.startsWith(";")) {
698
+ style = "matrix";
699
+ name = name.substring(1);
700
+ }
701
+ if (!pathParams || pathParams[name] === void 0 || pathParams[name] === null) {
702
+ continue;
703
+ }
704
+ const value = pathParams[name];
705
+ if (Array.isArray(value)) {
706
+ nextURL = nextURL.replace(match, serializeArrayParam(name, value, { style, explode }));
707
+ continue;
708
+ }
709
+ if (typeof value === "object") {
710
+ nextURL = nextURL.replace(match, serializeObjectParam(name, value, { style, explode }));
711
+ continue;
712
+ }
713
+ if (style === "matrix") {
714
+ nextURL = nextURL.replace(match, `;${serializePrimitiveParam(name, value)}`);
715
+ continue;
716
+ }
717
+ nextURL = nextURL.replace(match, style === "label" ? `.${encodeURIComponent(value)}` : encodeURIComponent(value));
718
+ }
719
+ return nextURL;
720
+ }
721
+ function defaultBodySerializer(body) {
722
+ if (body instanceof FormData) {
723
+ return body;
724
+ }
725
+ return JSON.stringify(body);
726
+ }
727
+ function createFinalURL(pathname, options) {
728
+ let finalURL = `${options.baseUrl}${pathname}`;
729
+ if (options.params?.path) {
730
+ finalURL = defaultPathSerializer(finalURL, options.params.path);
731
+ }
732
+ let search = options.querySerializer(options.params.query ?? {});
733
+ if (search.startsWith("?")) {
734
+ search = search.substring(1);
735
+ }
736
+ if (search) {
737
+ finalURL += `?${search}`;
738
+ }
739
+ return finalURL;
740
+ }
741
+ function mergeHeaders(...allHeaders) {
742
+ const finalHeaders = new Headers();
743
+ for (const h of allHeaders) {
744
+ if (!h || typeof h !== "object") {
745
+ continue;
746
+ }
747
+ const iterator = h instanceof Headers ? h.entries() : Object.entries(h);
748
+ for (const [k, v6] of iterator) {
749
+ if (v6 === null) {
750
+ finalHeaders.delete(k);
751
+ } else if (Array.isArray(v6)) {
752
+ for (const v22 of v6) {
753
+ finalHeaders.append(k, v22);
754
+ }
755
+ } else if (v6 !== void 0) {
756
+ finalHeaders.set(k, v6);
757
+ }
758
+ }
759
+ }
760
+ return finalHeaders;
761
+ }
762
+ function removeTrailingSlash(url) {
763
+ if (url.endsWith("/")) {
764
+ return url.substring(0, url.length - 1);
765
+ }
766
+ return url;
767
+ }
768
+
769
+ // ../private-api-clients/src/assert-valid-url-origin.ts
770
+ function assertValidUrlOrigin(origin) {
771
+ const url = new URL(origin);
772
+ if (url.origin !== origin) {
773
+ throw new Error(`${origin} is not a valid URL origin`);
774
+ }
775
+ }
776
+
777
+ // ../private-api-clients/src/dev-v2-api-client.ts
778
+ function createDeveloperAPIv2Client({
779
+ serverOrigin = "",
780
+ fetch,
781
+ headers
782
+ }) {
783
+ if (serverOrigin) assertValidUrlOrigin(serverOrigin);
784
+ return createClient({
785
+ baseUrl: `${serverOrigin}/api/dev/v2`,
786
+ fetch,
787
+ headers
788
+ });
789
+ }
790
+
791
+ // src/lib/fetch-current-definition.ts
792
+ async function fetchCurrentDefinition(options) {
793
+ const client = createDeveloperAPIv2Client({
794
+ serverOrigin: options.baseUrl,
795
+ headers: {
796
+ "x-api-key": options.apiKey
797
+ }
798
+ });
799
+ const abortController = new AbortController();
800
+ const timeout = setTimeout(() => {
801
+ abortController.abort();
802
+ }, 1e4);
803
+ try {
804
+ const response = await client.GET(
805
+ "/projects/{projectName}/definitions/current",
806
+ {
807
+ params: { path: { projectName: options.projectName } },
808
+ signal: abortController.signal
809
+ }
810
+ );
811
+ if (response.data) {
812
+ return response.data;
813
+ }
814
+ if (response.response.status === 404) {
815
+ throw new Error(`Project ${options.projectName} not found.`);
816
+ }
817
+ if (response.response.status === 401) {
818
+ throw new Error(`API Key is invalid.`);
819
+ }
820
+ throw new Error(
821
+ `Unknown error occurred when fetching definitions for project ${options.projectName}.`
822
+ );
823
+ } catch (error2) {
824
+ if (error2 instanceof Error && error2.name === "AbortError") {
825
+ throw new Error("Request timed out.");
826
+ }
827
+ throw error2;
828
+ } finally {
829
+ clearTimeout(timeout);
830
+ }
831
+ }
832
+
833
+ // src/lib/load-env.ts
834
+ var import_promises2 = __toESM(require("fs/promises"), 1);
835
+ var v4 = __toESM(require("valibot"), 1);
836
+ var import_dotenv = __toESM(require("dotenv"), 1);
837
+ var DEFAULT_ENV_FILE_PATH = ".env";
838
+ var EnvSchema = v4.object({
839
+ ORIZM_PROJECT: v4.pipe(
840
+ v4.string(),
841
+ v4.minLength(1, "ORIZM_PROJECT is required"),
842
+ v4.brand("ORIZM_PROJECT")
843
+ ),
844
+ ORIZM_BASE_URL: v4.pipe(
845
+ v4.optional(v4.string(), "https://app.orizm.com"),
846
+ // if null, use default value
847
+ v4.transform((v6) => v6.replace(/\/$/, "")),
848
+ // remove trailing slash
849
+ v4.brand("ORIZM_BASE_URL")
850
+ ),
851
+ ORIZM_API_KEY: v4.pipe(
852
+ v4.string(),
853
+ v4.minLength(1, "ORIZM_API_KEY is required"),
854
+ v4.brand("ORIZM_API_KEY")
855
+ )
856
+ });
857
+ async function loadEnv(envPath) {
858
+ let envFileContent;
859
+ if (envPath) {
860
+ envFileContent = await import_promises2.default.readFile(envPath, "utf-8").catch(() => null);
861
+ if (!envFileContent) {
862
+ throw new Error(`Environment variables file: '${envPath}' is not found.`);
863
+ }
864
+ } else {
865
+ envFileContent = await import_promises2.default.readFile(DEFAULT_ENV_FILE_PATH, "utf-8").catch(() => null);
866
+ }
867
+ if (envFileContent !== null) {
868
+ const dotenvParsed = import_dotenv.default.parse(envFileContent);
869
+ const envParseResult = v4.safeParse(EnvSchema, dotenvParsed);
870
+ if (!envParseResult.success) {
871
+ throw new Error(
872
+ `Environment variables are not valid.
873
+ ` + envParseResult.issues.map((issue) => issue.message).join("\n")
874
+ );
875
+ }
876
+ return envParseResult.output;
877
+ }
878
+ const processEnvParseResult = v4.safeParse(EnvSchema, process.env);
879
+ if (!processEnvParseResult.success) {
880
+ throw new Error(
881
+ "Environment variables are not valid. Put .env file or set environment variables in process.env.\n" + processEnvParseResult.issues.map((issue) => issue.message).join("\n")
882
+ );
883
+ }
884
+ return processEnvParseResult.output;
885
+ }
886
+
887
+ // src/cms/pull/action.ts
888
+ var spinner2 = createSpinner();
889
+ async function pullAction(options) {
890
+ spinner2.start("Loading environment variables...");
891
+ const env = await loadEnv(options.envPath);
892
+ spinner2.succeed("Loaded environment variables.");
893
+ spinner2.start("Loading project config...");
894
+ const definitionReference = await fetchCurrentDefinition({
895
+ baseUrl: env.ORIZM_BASE_URL,
896
+ apiKey: env.ORIZM_API_KEY,
897
+ projectName: env.ORIZM_PROJECT
898
+ });
899
+ spinner2.succeed("Loaded project config.");
900
+ spinner2.start("Generating code...");
901
+ await generate({
902
+ output: options.destination,
903
+ config: definitionReference.parsed
904
+ });
905
+ spinner2.succeed(`Generated code to '${options.destination}'`);
906
+ }
907
+
908
+ // src/cms/pull/command.ts
909
+ var cmsPullCommand = new import_commander2.Command("pull").description("pull orizm schema and generate client and types.").option("-e, --env [path]", "env file path.").option("-o, --output <path>", "output directory.", "./src/orizm").action(async (options) => {
910
+ try {
911
+ await pullAction({
912
+ destination: options.output,
913
+ envPath: options.env
914
+ });
915
+ } catch (error2) {
916
+ handleError(error2);
917
+ }
918
+ });
919
+
920
+ // src/consumer/generate/command.ts
921
+ var import_commander3 = require("commander");
922
+
923
+ // src/consumer/pull/generate.ts
924
+ var import_promises3 = require("fs/promises");
925
+ var import_path2 = __toESM(require("path"), 1);
926
+ var import_handlebars2 = __toESM(require("handlebars"), 1);
927
+
928
+ // src/consumer/templates/client.ts.hbr
929
+ var client_ts_default2 = '// This file was automatically generated and should not be edited.\n\nimport { ConsumerClientOptions, OrizmConsumerClientBase } from "@orizm/consumer-sdk";\nimport * as Models from "./types";\n\nexport class OrizmClient extends OrizmConsumerClientBase {\n constructor(options: ConsumerClientOptions) {\n super(options);\n }\n\n readonly tables = {\n {{#each tables}}\n {{toEndpointName this.name}}: this.getTableClient<Models.{{toCodeTypeName this.name}}__Descriptor>("{{toEndpointName this.name}}"),\n {{/each}}\n };\n}\n';
930
+
931
+ // src/consumer/templates/types.ts.hbr
932
+ var types_ts_default2 = '// This file was automatically generated and should not be edited.\n\nimport { FormValidationRules, StorageItemType } from "@orizm/common";\n\n// Utilities\ntype _ModuleRef<T> = T & _ModuleDescriptor;\ntype _ModuleDescriptor = {\n isModule: true;\n};\ntype _ArrayModuleRef<T> = T & _ArrayModuleDescriptor;\ntype _ArrayModuleDescriptor = {\n isModuleArray: true;\n};\n\n\n// Tables\n{{#each tables}}\nexport type {{toCodeTypeName this.name}} = {\n id: string;\n createdAt: string;\n updatedAt: string;\n group?: string;\n publishedAt?: string;\n _draft?: boolean;\n _published?: boolean;\n {{#each this.columns}}\n {{this.name}}{{#unless this.required}}?{{/unless}}: {{typeName this}};\n {{/each}}\n {{#if this.enableForm}}\n formSchema: FormValidationRules;\n {{/if}}\n}\n\n{{/each}}\n\n{{#each tableModules}}\nexport type {{toCodeTypeName this.name}} = {\n {{#each this.columns}}\n {{this.name}}{{#unless this.required}}?{{/unless}}: {{typeName this}};\n {{/each}}\n};\n{{/each}}\n\n// Descriptor types\n{{#each tables}}\nexport type {{toCodeTypeName this.name}}__Descriptor = {\n row: {{toCodeTypeName this.name}};\n {{#if (filterRefColumn this.columns)}}\n refs: {\n {{#each (filterRefColumn this.columns)}}\n {{includeName this}}: {{{includeType this}}};\n {{/each}}\n }\n {{/if}}\n {{#unless (filterRefColumn this.columns)}}\n refs: object;\n {{/unless}}\n {{#if (filterUniqueIndexes this.indexes)}}\n unique: [\n {{#each (filterUniqueIndexes this.indexes)}}\n { {{#each (getIndexColumns ../this this)}}{{this.name}}:{{typeName this}},{{/each}} },\n {{/each}}\n ]\n {{/if}}\n {{#unless (filterUniqueIndexes this.indexes)}}\n unique: [];\n {{/unless}}\n {{#if this.enableDrafts}}\n enableDrafts: true;\n {{/if}}\n};\n{{/each}}\n\n\n{{#each tableModules}}\nexport type {{toCodeTypeName this.name}}__Descriptor = {\n row: {{toCodeTypeName this.name}};\n {{#if (filterRefColumn this.columns)}}\n refs: {\n {{#each (filterRefColumn this.columns)}}\n {{includeName this}}: {{{includeType this}}};\n {{/each}}\n }\n {{/if}}\n {{#unless (filterRefColumn this.columns)}}\n refs: object;\n {{/unless}}\n unique:[]\n};\n{{/each}}\n\n\n// Webhook types\nexport type WebhookEvent = "content.create" | "content.update" | "content.delete";\ntype WebhookPayloadBase = {\n event: WebhookEvent;\n timestamp: string;\n project: string;\n};\n{{#if tables}}\nexport type WebhookPayload = WebhookPayloadBase & (\n {{#each tables}}\n | {\n table: "{{this.name}}";\n content: {{toCodeTypeName this.name}};\n old?: {{toCodeTypeName this.name}};\n }\n {{/each}}\n);\n{{else}}\nexport type WebhookPayload = WebhookPayloadBase;\n{{/if}}\n';
933
+
934
+ // src/consumer/pull/generate.ts
935
+ async function generate2(options) {
936
+ await (0, import_promises3.mkdir)(options.output, { recursive: true });
937
+ await renderTypes2(options.definition, options.output);
938
+ await renderClient2(options.definition, options.output);
939
+ }
940
+ import_handlebars2.default.registerHelper("toEndpointName", (str) => {
941
+ return str;
942
+ });
943
+ function toCodeTypeName2(str) {
944
+ str = str.charAt(0).toUpperCase() + str.slice(1);
945
+ return str.replace(/_([a-z])/g, (g) => g[1].toUpperCase());
946
+ }
947
+ import_handlebars2.default.registerHelper("toCodeTypeName", toCodeTypeName2);
948
+ import_handlebars2.default.registerHelper("typeName", (column) => {
949
+ if (column.type === "reference") {
950
+ return "string";
951
+ } else if (column.type == "json") {
952
+ return "unknown";
953
+ } else if (column.type === "module") {
954
+ if (!column.moduleName) {
955
+ console.warn("moduleName is not defined", column.name);
956
+ }
957
+ return toCodeTypeName2(column.moduleName || "unknown");
958
+ } else if (column.type === "module-array") {
959
+ if (!column.moduleName) {
960
+ console.warn("moduleName is not defined", column.name);
961
+ }
962
+ return toCodeTypeName2(column.moduleName || "unknown") + "[]";
963
+ } else if (column.type === "storage") {
964
+ return "StorageItemType";
965
+ } else {
966
+ return column.type;
967
+ }
968
+ });
969
+ import_handlebars2.default.registerHelper(
970
+ "filterRefColumn",
971
+ (columns) => {
972
+ return (columns || []).filter(
973
+ (c) => c.type === "reference" && c.tableName && c.includeName || c.type === "module" && c.moduleName || c.type === "module-array" && c.moduleName
974
+ );
975
+ }
976
+ );
977
+ import_handlebars2.default.registerHelper("includeName", (column) => {
978
+ return column.type === "reference" ? column.includeName : column.name;
979
+ });
980
+ import_handlebars2.default.registerHelper("includeType", (column) => {
981
+ if (column.type === "reference" && column.tableName)
982
+ return toCodeTypeName2(column.tableName) + "__Descriptor";
983
+ if (column.type === "module" && column.moduleName)
984
+ return `_ModuleRef<${toCodeTypeName2(column.moduleName)}__Descriptor>`;
985
+ if (column.type === "module-array" && column.moduleName)
986
+ return `_ArrayModuleRef<${toCodeTypeName2(column.moduleName)}__Descriptor>`;
987
+ });
988
+ import_handlebars2.default.registerHelper(
989
+ "filterUniqueIndexes",
990
+ (indexes) => {
991
+ return (indexes || []).filter((i) => i.unique);
992
+ }
993
+ );
994
+ import_handlebars2.default.registerHelper(
995
+ "getIndexColumns",
996
+ (table, index) => {
997
+ return index.columns.map((i) => {
998
+ const column = table.columns.find((c) => c.name === i);
999
+ if (!column) {
1000
+ throw new Error(`column ${i} not found`);
1001
+ }
1002
+ return column;
1003
+ });
1004
+ }
1005
+ );
1006
+ async function renderTypes2(config, output) {
1007
+ const rendered = import_handlebars2.default.compile(types_ts_default2)(config);
1008
+ const targetPath = import_path2.default.join(output, "types.ts");
1009
+ await (0, import_promises3.writeFile)(targetPath, rendered, "utf-8");
1010
+ }
1011
+ async function renderClient2(config, output) {
1012
+ const rendered = import_handlebars2.default.compile(client_ts_default2)(config);
1013
+ const targetPath = import_path2.default.join(output, "client.ts");
1014
+ await (0, import_promises3.writeFile)(targetPath, rendered, "utf-8");
1015
+ }
1016
+
1017
+ // src/consumer/generate/action.ts
1018
+ var spinner3 = createSpinner();
1019
+ async function generateAction(orizmConfigTs, destination) {
1020
+ spinner3.start("Loading project config...");
1021
+ const definition = await loadConfig(orizmConfigTs);
1022
+ spinner3.succeed("Loaded project config.");
1023
+ spinner3.start("Generating code...");
1024
+ await generate2({
1025
+ definition,
1026
+ output: destination
1027
+ });
1028
+ spinner3.succeed(`Generated code to '${destination}'`);
1029
+ }
1030
+
1031
+ // src/consumer/generate/command.ts
1032
+ var consumerGenerateCommand = new import_commander3.Command("generate").description("generate orizm client and types.").option("-c, --config <path>", "orizm config file path.", "orizm.config.ts").option("-o, --output <path>", "output directory.", "./src/orizm").action(async (options) => {
1033
+ try {
1034
+ await generateAction(options.config, options.output);
1035
+ } catch (error2) {
1036
+ handleError(error2);
1037
+ }
1038
+ });
1039
+
1040
+ // src/consumer/pull/command.ts
1041
+ var import_commander4 = require("commander");
1042
+
1043
+ // src/consumer/pull/action.ts
1044
+ var spinner4 = createSpinner();
1045
+ async function pullAction2(options) {
1046
+ spinner4.start("Loading environment variables...");
1047
+ const config = await loadEnv(options.envPath);
1048
+ spinner4.succeed("Loaded environment variables.");
1049
+ spinner4.start("Loading project config...");
1050
+ const definition = await fetchCurrentDefinition({
1051
+ baseUrl: config.ORIZM_BASE_URL,
1052
+ apiKey: config.ORIZM_API_KEY,
1053
+ projectName: config.ORIZM_PROJECT
1054
+ });
1055
+ spinner4.succeed("Loaded project config.");
1056
+ spinner4.start("Generating code...");
1057
+ await generate2({
1058
+ definition: definition.parsed,
1059
+ output: options.destination
1060
+ });
1061
+ spinner4.succeed(`Generated code to '${options.destination}'`);
1062
+ }
1063
+
1064
+ // src/consumer/pull/command.ts
1065
+ var consumerPullCommand = new import_commander4.Command("pull").description("pull orizm schema and generate client and types.").option("-e, --env [path]", "env file path.").option("-o, --output <path>", "output directory.", "./src/orizm").action(async (options) => {
1066
+ try {
1067
+ await pullAction2({
1068
+ destination: options.output,
1069
+ envPath: options.env
1070
+ });
1071
+ } catch (error2) {
1072
+ handleError(error2);
1073
+ }
1074
+ });
1075
+
1076
+ // src/push/command.ts
1077
+ var import_commander5 = require("commander");
1078
+ var import_cli_color5 = __toESM(require("cli-color"), 1);
1079
+
1080
+ // src/lib/developer-api.ts
1081
+ async function applyDefinition(env, projectDef) {
1082
+ const client = createDeveloperAPIv2Client({
1083
+ serverOrigin: env.ORIZM_BASE_URL,
1084
+ headers: {
1085
+ "x-api-key": env.ORIZM_API_KEY
1086
+ }
1087
+ });
1088
+ const response = await client.POST("/projects/{projectName}/definitions", {
1089
+ params: { path: { projectName: env.ORIZM_PROJECT } },
1090
+ body: { definition: projectDef }
1091
+ });
1092
+ if (!response.data) {
1093
+ const status = response.response.status;
1094
+ if (status === 401) {
1095
+ throw new Error(
1096
+ "401 Unauthorized. Please check your Developer API key and try again."
1097
+ );
1098
+ }
1099
+ throw new Error(
1100
+ `${status} ${response.response.statusText}: Unexpected error occurred while applying schema.`
1101
+ );
1102
+ }
1103
+ }
1104
+ var getChangeEvents = async (env, projectDef) => {
1105
+ const client = createDeveloperAPIv2Client({
1106
+ serverOrigin: env.ORIZM_BASE_URL,
1107
+ headers: {
1108
+ "x-api-key": env.ORIZM_API_KEY
1109
+ }
1110
+ });
1111
+ const response = await client.POST(
1112
+ "/projects/{projectName}/definitions/dry-run",
1113
+ {
1114
+ params: { path: { projectName: env.ORIZM_PROJECT } },
1115
+ body: { definition: projectDef }
1116
+ }
1117
+ );
1118
+ if (!response.data) {
1119
+ const status = response.response.status;
1120
+ if (status === 401) {
1121
+ throw new Error(
1122
+ "401 Unauthorized. Please check your Developer API key and try again."
1123
+ );
1124
+ }
1125
+ throw new Error(
1126
+ `${status} ${response.response.statusText}: Unexpected error occurred while fetching schema change events.
1127
+ ${JSON.stringify(response.error, null, 2)}`
1128
+ );
1129
+ }
1130
+ return response.data;
1131
+ };
1132
+
1133
+ // src/lib/display-change-events.ts
1134
+ var import_cli_color4 = __toESM(require("cli-color"), 1);
1135
+
1136
+ // src/lib/cli-table.ts
1137
+ var COLORS = {
1138
+ reset: "\x1B[0m",
1139
+ green: "\x1B[32m",
1140
+ red: "\x1B[31m"
1141
+ };
1142
+ var CliTable = class {
1143
+ headers = [];
1144
+ rows = [];
1145
+ columnWidths = [];
1146
+ rowColors = [];
1147
+ // 各行の色を保持する配列
1148
+ constructor(headers) {
1149
+ this.headers = headers;
1150
+ this.updateColumnWidths(headers);
1151
+ }
1152
+ // データ行を追加
1153
+ addRow(row, options) {
1154
+ if (row.length !== this.headers.length) {
1155
+ throw new Error(
1156
+ `The length of the row (${row.length}) does not match the length of the header (${this.headers.length})`
1157
+ );
1158
+ }
1159
+ this.rows.push(row);
1160
+ if (options?.color) {
1161
+ this.rowColors.push(COLORS[options.color]);
1162
+ } else {
1163
+ this.rowColors.push(null);
1164
+ }
1165
+ this.updateColumnWidths(row);
1166
+ }
1167
+ // 列幅を更新
1168
+ updateColumnWidths(row) {
1169
+ for (let i = 0; i < row.length; i++) {
1170
+ const cellLength = row[i].length;
1171
+ if (!this.columnWidths[i] || cellLength > this.columnWidths[i]) {
1172
+ this.columnWidths[i] = cellLength;
1173
+ }
1174
+ }
1175
+ }
1176
+ // 水平線を生成
1177
+ createHorizontalLine(position) {
1178
+ let line = "";
1179
+ if (position === "top") line += "\u250C";
1180
+ else if (position === "middle") line += "\u251C";
1181
+ else if (position === "bottom") line += "\u2514";
1182
+ for (let i = 0; i < this.columnWidths.length; i++) {
1183
+ line += "\u2500".repeat(this.columnWidths[i] + 2);
1184
+ if (i < this.columnWidths.length - 1) {
1185
+ if (position === "top") line += "\u252C";
1186
+ else if (position === "middle") line += "\u253C";
1187
+ else if (position === "bottom") line += "\u2534";
1188
+ } else {
1189
+ if (position === "top") line += "\u2510";
1190
+ else if (position === "middle") line += "\u2524";
1191
+ else if (position === "bottom") line += "\u2518";
1192
+ }
1193
+ }
1194
+ return line;
1195
+ }
1196
+ // 行を整形
1197
+ formatRow(row, color) {
1198
+ let formattedRow = "\u2502";
1199
+ for (let i = 0; i < row.length; i++) {
1200
+ const cell = row[i];
1201
+ const padding = " ".repeat(this.columnWidths[i] - cell.length);
1202
+ if (color) {
1203
+ formattedRow += ` ${color}${cell}${COLORS.reset}${padding} \u2502`;
1204
+ } else {
1205
+ formattedRow += ` ${cell}${padding} \u2502`;
1206
+ }
1207
+ }
1208
+ return formattedRow;
1209
+ }
1210
+ // テーブルを文字列として取得
1211
+ toString() {
1212
+ if (this.headers.length === 0) {
1213
+ return "";
1214
+ }
1215
+ const topLine = this.createHorizontalLine("top");
1216
+ const middleLine = this.createHorizontalLine("middle");
1217
+ const bottomLine = this.createHorizontalLine("bottom");
1218
+ let table = topLine + "\n";
1219
+ table += this.formatRow(this.headers, null) + "\n";
1220
+ table += middleLine + "\n";
1221
+ for (let i = 0; i < this.rows.length; i++) {
1222
+ const color = this.rowColors[i] || null;
1223
+ table += this.formatRow(this.rows[i], color) + "\n";
1224
+ }
1225
+ table += bottomLine;
1226
+ return table;
1227
+ }
1228
+ // テーブルを出力
1229
+ print() {
1230
+ console.log(this.toString());
1231
+ }
1232
+ };
1233
+
1234
+ // src/lib/display-change-events.ts
1235
+ async function displayChangeEvents(changeEvents) {
1236
+ const {
1237
+ tableChangeEvents = [],
1238
+ bucketChangeEvents = [],
1239
+ authorityChangeEvents = []
1240
+ } = changeEvents;
1241
+ if (tableChangeEvents.length === 0 && bucketChangeEvents.length === 0 && authorityChangeEvents.length === 0) {
1242
+ console.log();
1243
+ console.log(import_cli_color4.default.green("No changes."));
1244
+ return;
1245
+ }
1246
+ displayTableChangeEvents(tableChangeEvents);
1247
+ displayBucketChangeEvents(bucketChangeEvents);
1248
+ displayAuthorityChangeEvents(authorityChangeEvents);
1249
+ console.log();
1250
+ }
1251
+ function displayTableChangeEvents(tableChangeEvents) {
1252
+ if (tableChangeEvents.length === 0) {
1253
+ return;
1254
+ }
1255
+ const eventsByTable = /* @__PURE__ */ new Map();
1256
+ for (const event of tableChangeEvents) {
1257
+ const tableName = event.tableDef.name;
1258
+ const tableEvents = eventsByTable.get(tableName) ?? [];
1259
+ tableEvents.push(event);
1260
+ eventsByTable.set(tableName, tableEvents);
1261
+ }
1262
+ for (const [tableName, events] of eventsByTable.entries()) {
1263
+ console.log();
1264
+ console.log(`\u26AB\uFE0ETable: ${tableName}`);
1265
+ const table = new CliTable(["Type", "Name", "Event", "Detail"]);
1266
+ for (const event of events) {
1267
+ const eventName = event.event;
1268
+ switch (eventName) {
1269
+ case "table:create":
1270
+ case "table:update": {
1271
+ table.addRow(["table", event.tableDef.name, eventName, ""], {
1272
+ color: "green"
1273
+ });
1274
+ break;
1275
+ }
1276
+ case "table:delete": {
1277
+ table.addRow(["table", event.tableDef.name, eventName, ""], {
1278
+ color: "red"
1279
+ });
1280
+ break;
1281
+ }
1282
+ case "column:create":
1283
+ case "column:update": {
1284
+ table.addRow(
1285
+ [
1286
+ "column",
1287
+ event.columnDef.name,
1288
+ eventName,
1289
+ JSON.stringify(event.columnDef)
1290
+ ],
1291
+ { color: "green" }
1292
+ );
1293
+ break;
1294
+ }
1295
+ case "column:delete": {
1296
+ table.addRow(
1297
+ [
1298
+ "column",
1299
+ event.columnDef.name,
1300
+ eventName,
1301
+ JSON.stringify(event.columnDef)
1302
+ ],
1303
+ {
1304
+ color: "red"
1305
+ }
1306
+ );
1307
+ break;
1308
+ }
1309
+ case "index:create":
1310
+ case "index:update": {
1311
+ table.addRow(
1312
+ [
1313
+ "index",
1314
+ event.indexDef.columns.join(", "),
1315
+ eventName,
1316
+ JSON.stringify(event.indexDef)
1317
+ ],
1318
+ { color: "green" }
1319
+ );
1320
+ break;
1321
+ }
1322
+ case "index:delete": {
1323
+ table.addRow(
1324
+ [
1325
+ "index",
1326
+ event.indexDef.columns.join(", "),
1327
+ eventName,
1328
+ JSON.stringify(event.indexDef)
1329
+ ],
1330
+ { color: "red" }
1331
+ );
1332
+ break;
1333
+ }
1334
+ case "module:create":
1335
+ case "module:update": {
1336
+ table.addRow(
1337
+ [
1338
+ "module",
1339
+ event.columnDef.name,
1340
+ eventName,
1341
+ JSON.stringify(event.columnDef)
1342
+ ],
1343
+ {
1344
+ color: "green"
1345
+ }
1346
+ );
1347
+ break;
1348
+ }
1349
+ case "module:delete": {
1350
+ table.addRow(
1351
+ [
1352
+ "module",
1353
+ event.columnDef.name,
1354
+ eventName,
1355
+ JSON.stringify(event.columnDef)
1356
+ ],
1357
+ {
1358
+ color: "red"
1359
+ }
1360
+ );
1361
+ break;
1362
+ }
1363
+ case "search:enable":
1364
+ case "search:update": {
1365
+ table.addRow(["table", event.tableDef.name, eventName, ""], {
1366
+ color: "green"
1367
+ });
1368
+ break;
1369
+ }
1370
+ case "search:disable": {
1371
+ table.addRow(["table", event.tableDef.name, eventName, ""], {
1372
+ color: "red"
1373
+ });
1374
+ break;
1375
+ }
1376
+ case "history:enable": {
1377
+ table.addRow(["table", event.tableDef.name, eventName, ""], {
1378
+ color: "green"
1379
+ });
1380
+ break;
1381
+ }
1382
+ case "history:disable": {
1383
+ table.addRow(["table", event.tableDef.name, eventName, ""], {
1384
+ color: "red"
1385
+ });
1386
+ break;
1387
+ }
1388
+ case "formSubmissions:create":
1389
+ case "formSubmissions:update": {
1390
+ table.addRow(["table", event.tableDef.name, eventName, ""], {
1391
+ color: "green"
1392
+ });
1393
+ break;
1394
+ }
1395
+ case "formSubmissions:delete": {
1396
+ table.addRow(["table", event.tableDef.name, eventName, ""], {
1397
+ color: "red"
1398
+ });
1399
+ break;
1400
+ }
1401
+ }
1402
+ }
1403
+ table.print();
1404
+ }
1405
+ }
1406
+ function displayBucketChangeEvents(bucketChangeEvents) {
1407
+ if (bucketChangeEvents.length === 0) {
1408
+ return;
1409
+ }
1410
+ const eventsByBucket = /* @__PURE__ */ new Map();
1411
+ for (const event of bucketChangeEvents) {
1412
+ const bucketName = event.bucketDef.name;
1413
+ const bucketEvents = eventsByBucket.get(bucketName) ?? [];
1414
+ bucketEvents.push(event);
1415
+ eventsByBucket.set(bucketName, bucketEvents);
1416
+ }
1417
+ const table = new CliTable(["Type", "Name", "Event", "Detail"]);
1418
+ console.log();
1419
+ console.log("\u26AB\uFE0EBuckets");
1420
+ for (const [_, events] of eventsByBucket.entries()) {
1421
+ for (const event of events) {
1422
+ const eventName = event.event;
1423
+ switch (eventName) {
1424
+ case "bucket:create":
1425
+ case "bucket:update": {
1426
+ table.addRow(
1427
+ [
1428
+ "bucket",
1429
+ event.bucketDef.name,
1430
+ eventName,
1431
+ JSON.stringify(event.bucketDef)
1432
+ ],
1433
+ {
1434
+ color: "green"
1435
+ }
1436
+ );
1437
+ break;
1438
+ }
1439
+ case "bucket:delete": {
1440
+ table.addRow(
1441
+ [
1442
+ "bucket",
1443
+ event.bucketDef.name,
1444
+ eventName,
1445
+ JSON.stringify(event.bucketDef)
1446
+ ],
1447
+ {
1448
+ color: "red"
1449
+ }
1450
+ );
1451
+ break;
1452
+ }
1453
+ }
1454
+ }
1455
+ }
1456
+ table.print();
1457
+ }
1458
+ function displayAuthorityChangeEvents(authorityChangeEvents) {
1459
+ if (authorityChangeEvents.length === 0) {
1460
+ return;
1461
+ }
1462
+ const table = new CliTable(["Type", "Event", "Detail"]);
1463
+ console.log();
1464
+ console.log("\u26AB\uFE0EAuthorities");
1465
+ for (const event of authorityChangeEvents) {
1466
+ const eventName = event.event;
1467
+ switch (eventName) {
1468
+ case "authority:update": {
1469
+ table.addRow(
1470
+ ["authority", eventName, JSON.stringify(event.authorityDef)],
1471
+ { color: "green" }
1472
+ );
1473
+ break;
1474
+ }
1475
+ }
1476
+ }
1477
+ table.print();
1478
+ }
1479
+
1480
+ // src/lib/cli-input.ts
1481
+ var import_promises4 = require("readline/promises");
1482
+ async function input(prompt) {
1483
+ const rl = (0, import_promises4.createInterface)({
1484
+ input: process.stdin,
1485
+ output: process.stdout
1486
+ });
1487
+ const input2 = await rl.question(prompt).finally(() => {
1488
+ rl.close();
1489
+ });
1490
+ return input2.trim();
1491
+ }
1492
+
1493
+ // src/push/command.ts
1494
+ var spinner5 = createSpinner();
1495
+ var pushCommand = new import_commander5.Command("push").description("apply schema to project.").option("-e, --env <path>", "env file path.").option("-c, --config <path>", "orizm config file path.", "orizm.config.ts").option("--dry-run", "display change-events without applying schema.", false).option("-y, --yes", "apply schema without confirmation.", false).action(async (options) => {
1496
+ try {
1497
+ spinner5.start("Loading environment variables...");
1498
+ const env = await loadEnv(options.env);
1499
+ spinner5.succeed("Loaded environment variables.");
1500
+ spinner5.start("Loading project config...");
1501
+ const projectDef = await loadConfig(options.config);
1502
+ spinner5.succeed("Loaded project config.");
1503
+ spinner5.start("Fetch schema change events...");
1504
+ const changeEvents = await getChangeEvents(env, projectDef);
1505
+ spinner5.succeed("Fetch schema change events.");
1506
+ await displayChangeEvents(changeEvents);
1507
+ if (changeEvents.tableChangeEvents.length === 0 && changeEvents.bucketChangeEvents.length === 0 && changeEvents.authorityChangeEvents.length === 0) {
1508
+ return;
1509
+ }
1510
+ if (options.dryRun) {
1511
+ return;
1512
+ }
1513
+ if (!options.yes) {
1514
+ const confirm = await input("Do you want to apply schema? (y/N): ");
1515
+ if (confirm !== "y") {
1516
+ console.log(import_cli_color5.default.red("Canceled."));
1517
+ return;
1518
+ }
1519
+ }
1520
+ spinner5.start("Applying schema...");
1521
+ await applyDefinition(env, projectDef);
1522
+ spinner5.succeed("Schema applied.");
1523
+ } catch (error2) {
1524
+ handleError(error2);
1525
+ }
1526
+ });
1527
+
1528
+ // src/config/validate/command.ts
1529
+ var import_commander6 = require("commander");
1530
+ var import_cli_color6 = __toESM(require("cli-color"), 1);
1531
+ var v5 = __toESM(require("valibot"), 1);
1532
+
1533
+ // src/config/validate/watcher.ts
1534
+ var import_chokidar = __toESM(require("chokidar"), 1);
1535
+ function watchConfigFile(configPath, onFileChange) {
1536
+ const watcher = import_chokidar.default.watch(configPath, {
1537
+ persistent: true,
1538
+ ignoreInitial: true
1539
+ });
1540
+ let isProcessing = false;
1541
+ let timeoutId = null;
1542
+ const debouncedOnChange = async () => {
1543
+ if (isProcessing) return;
1544
+ if (timeoutId) {
1545
+ clearTimeout(timeoutId);
1546
+ }
1547
+ timeoutId = setTimeout(async () => {
1548
+ isProcessing = true;
1549
+ try {
1550
+ await onFileChange();
1551
+ } catch (error2) {
1552
+ handleError(error2);
1553
+ } finally {
1554
+ isProcessing = false;
1555
+ }
1556
+ }, 300);
1557
+ };
1558
+ watcher.on("change", debouncedOnChange);
1559
+ watcher.on("add", debouncedOnChange);
1560
+ watcher.on("unlink", debouncedOnChange);
1561
+ const terminate = () => {
1562
+ watcher.close();
1563
+ process.exit(0);
1564
+ };
1565
+ process.on("SIGINT", terminate);
1566
+ process.on("SIGTERM", terminate);
1567
+ watcher.on("error", (error2) => {
1568
+ handleError(error2);
1569
+ });
1570
+ return watcher;
1571
+ }
1572
+
1573
+ // src/config/validate/command.ts
1574
+ var validateConfigCommand = new import_commander6.Command("validate").description("validate orizm.config.ts for validation errors").option("-c, --config <path>", "Path to config file", "./orizm.config.ts").option("-w, --watch", "Watch for file changes and re-validate").action(async (options) => {
1575
+ try {
1576
+ const validateConfig = async () => {
1577
+ try {
1578
+ if (options.watch) {
1579
+ console.clear();
1580
+ console.log(
1581
+ `\u{1F440} Watching ${options.config} for changes... (Press Ctrl+C to stop)`
1582
+ );
1583
+ console.log();
1584
+ }
1585
+ await loadConfig(options.config);
1586
+ console.log(import_cli_color6.default.green("\u2705 Config is valid."));
1587
+ } catch (error2) {
1588
+ if (v5.isValiError(error2)) {
1589
+ console.error(import_cli_color6.default.red("\u274C Config validation failed:"));
1590
+ displayValibotError(error2);
1591
+ return;
1592
+ }
1593
+ throw error2;
1594
+ }
1595
+ };
1596
+ await validateConfig();
1597
+ if (options.watch) {
1598
+ watchConfigFile(options.config, validateConfig);
1599
+ }
1600
+ } catch (error2) {
1601
+ handleError(error2);
1602
+ }
1603
+ });
1604
+
1605
+ // src/config/generate-erd/command.ts
1606
+ var import_commander7 = require("commander");
1607
+
1608
+ // src/config/generate-erd/generate.ts
1609
+ var import_handlebars3 = __toESM(require("handlebars"), 1);
1610
+
1611
+ // src/config/generate-erd/mermaid-erd.hbr
1612
+ var mermaid_erd_default = "generated by @orizm/cli\n\n```mermaid\nerDiagram\n{{#each tables}}\n {{name}} {\n id string PK\n{{#each columns}}\n {{name}} {{type}}{{#if isForeignKey}} FK{{/if}}\n{{/each}}\n }\n{{/each}}\n\n{{#each relations}}\n {{from}} {{type}} {{to}} : {{comment}}\n{{/each}}\n```";
1613
+
1614
+ // src/config/generate-erd/generate.ts
1615
+ function generate3(input2) {
1616
+ const template = import_handlebars3.default.compile(mermaid_erd_default);
1617
+ return template(input2);
1618
+ }
1619
+
1620
+ // src/config/generate-erd/convert-to-input.ts
1621
+ function convertToInput(config) {
1622
+ if (!config.tables) {
1623
+ return {
1624
+ tables: [],
1625
+ relations: []
1626
+ };
1627
+ }
1628
+ const tables = [];
1629
+ const relations = [];
1630
+ for (const table of config.tables) {
1631
+ const modules = [];
1632
+ const erdTable = {
1633
+ name: table.name,
1634
+ columns: []
1635
+ };
1636
+ for (const column of table.columns) {
1637
+ erdTable.columns.push({
1638
+ name: column.name,
1639
+ type: column.type,
1640
+ isForeignKey: column.type === "reference"
1641
+ });
1642
+ if (column.type === "reference") {
1643
+ relations.push({
1644
+ from: column.tableName,
1645
+ to: table.name,
1646
+ type: RELATION.ONE_TO_MANY,
1647
+ comment: "reference"
1648
+ });
1649
+ }
1650
+ if (column.type === "module" || column.type === "module-array") {
1651
+ const module2 = config.tableModules?.find(
1652
+ (m) => m.name === column.moduleName
1653
+ );
1654
+ if (!module2) {
1655
+ continue;
1656
+ }
1657
+ const moduleTableName = `${table.name}_${column.name}_${column.moduleName}`;
1658
+ modules.push({
1659
+ name: moduleTableName,
1660
+ columns: module2?.columns.map((c) => ({
1661
+ name: c.name,
1662
+ type: c.type,
1663
+ isForeignKey: c.type === "reference"
1664
+ })) || []
1665
+ });
1666
+ relations.push({
1667
+ from: table.name,
1668
+ to: moduleTableName,
1669
+ type: column.type === "module" ? RELATION.ONE_TO_ONE : RELATION.ONE_TO_MANY,
1670
+ comment: column.type === "module" ? "module" : "module-array"
1671
+ });
1672
+ for (const moduleColumn of module2.columns) {
1673
+ if (moduleColumn.type === "reference" && moduleColumn.tableName) {
1674
+ relations.push({
1675
+ from: moduleTableName,
1676
+ to: moduleColumn.tableName,
1677
+ type: RELATION.ONE_TO_MANY,
1678
+ comment: "reference"
1679
+ });
1680
+ }
1681
+ }
1682
+ }
1683
+ }
1684
+ tables.push(erdTable);
1685
+ tables.push(...modules);
1686
+ }
1687
+ return {
1688
+ tables,
1689
+ relations
1690
+ };
1691
+ }
1692
+ var RELATION = {
1693
+ ONE_TO_MANY: "||--o{",
1694
+ ONE_TO_ONE: "||--||"
1695
+ };
1696
+
1697
+ // src/config/generate-erd/command.ts
1698
+ var generateErdCommand = new import_commander7.Command("generate-erd").description("generate er diagram in mermaid format from orizm.config.ts").option("-c, --config <path>", "orizm config file path.", "orizm.config.ts").action(async (options) => {
1699
+ try {
1700
+ const config = await loadConfig(options.config);
1701
+ const input2 = convertToInput(config);
1702
+ const mermaidText = generate3(input2);
1703
+ console.log(mermaidText);
1704
+ } catch (error2) {
1705
+ handleError(error2);
1706
+ }
1707
+ });
1708
+
1709
+ // src/cli.ts
1710
+ import_commander8.program.name("orizm CLI");
1711
+ import_commander8.program.addCommand(pushCommand);
1712
+ var cmsCommands = new import_commander8.Command("cms").description("cms commands.");
1713
+ cmsCommands.addCommand(cmsGenerateCommand);
1714
+ cmsCommands.addCommand(cmsPullCommand);
1715
+ import_commander8.program.addCommand(cmsCommands);
1716
+ var consumerCommands = new import_commander8.Command("consumer").description(
1717
+ "consumer commands."
1718
+ );
1719
+ consumerCommands.addCommand(consumerGenerateCommand);
1720
+ consumerCommands.addCommand(consumerPullCommand);
1721
+ import_commander8.program.addCommand(consumerCommands);
1722
+ var configCommands = new import_commander8.Command("config").description("config commands.");
1723
+ configCommands.addCommand(validateConfigCommand);
1724
+ configCommands.addCommand(generateErdCommand);
1725
+ import_commander8.program.addCommand(configCommands);
1726
+ import_commander8.program.parse();