@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.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/cli.ts
2
- import { Command as Command6, program } from "commander";
2
+ import { Command as Command8, program } from "commander";
3
3
 
4
4
  // src/cms/generate/command.ts
5
5
  import { Command } from "commander";
@@ -96,20 +96,75 @@ function createSpinner() {
96
96
  }
97
97
 
98
98
  // src/lib/handle-error.ts
99
+ import * as v3 from "valibot";
100
+ import cliColor3 from "cli-color";
101
+
102
+ // src/lib/display-valibot-error.ts
99
103
  import * as v2 from "valibot";
100
104
  import cliColor2 from "cli-color";
105
+ function displayValibotError(error2) {
106
+ if (!v2.isValiError(error2)) {
107
+ return;
108
+ }
109
+ console.error(`Error: ${error2.issues.length} problem(s) found.`);
110
+ console.error(buildValiErrorMessage(error2));
111
+ }
112
+ function buildValiErrorMessage(e, options) {
113
+ const { color = true } = options ?? {};
114
+ return e.issues.map((issue) => {
115
+ const path3 = getPath(issue);
116
+ return ` ${getIssueMessage(issue.message, color)} (at ${getLocationPath(path3, color)})`;
117
+ }).join("\n");
118
+ }
119
+ function getIssueMessage(message, color) {
120
+ return color ? cliColor2.red(message) : message;
121
+ }
122
+ function getLocationPath(path3, color) {
123
+ return color ? cliColor2.yellow(path3) : path3;
124
+ }
125
+ function getPath(issue) {
126
+ const issueDotPath = v2.getDotPath(issue);
127
+ const pathInfo = issue.path;
128
+ if (!issueDotPath || !pathInfo) {
129
+ return "";
130
+ }
131
+ const pathParts = issueDotPath.split(".");
132
+ let pathInfoIndex = 0;
133
+ for (let i = 0; i < pathParts.length; i++) {
134
+ const part = pathParts[i];
135
+ if (!isNumberIndex(part)) {
136
+ continue;
137
+ }
138
+ const index = parseInt(part);
139
+ for (let j = pathInfoIndex; j < pathInfo.length; j++) {
140
+ const pathItem = pathInfo[j];
141
+ if (pathItem.type === "array" && pathItem.key === index) {
142
+ if (pathItem.value && typeof pathItem.value === "object" && "name" in pathItem.value) {
143
+ pathParts[i] = String(pathItem.value.name);
144
+ pathInfoIndex = j + 1;
145
+ break;
146
+ }
147
+ }
148
+ }
149
+ }
150
+ return pathParts.join(".");
151
+ }
152
+ function isNumberIndex(part) {
153
+ return /^\d+$/.test(part);
154
+ }
155
+
156
+ // src/lib/handle-error.ts
101
157
  function handleError(error2) {
102
158
  show();
103
- if (v2.isValiError(error2)) {
159
+ if (v3.isValiError(error2)) {
104
160
  console.error();
105
- console.error(`Error: ${error2.issues.length} problem(s) found.`);
106
- console.error(buildValiErrorMessage(error2));
161
+ displayValibotError(error2);
107
162
  console.error();
108
163
  process.exit(1);
109
164
  }
110
165
  console.error();
111
166
  console.error(
112
- cliColor2.red(
167
+ cliColor3.red(
113
168
  "Something went wrong. Please check the error below for more details."
114
169
  )
115
170
  );
@@ -118,11 +173,6 @@ function handleError(error2) {
118
173
  console.error();
119
174
  process.exit(1);
120
175
  }
121
- function buildValiErrorMessage(e) {
122
- return e.issues.map((issue) => {
123
- return ` ${cliColor2.red(issue.message)} (at ${cliColor2.yellow(v2.getDotPath(issue))})`;
124
- }).join("\n");
125
- }
126
176
 
127
177
  // src/cms/generate/generator.ts
128
178
  import { mkdir, writeFile } from "fs/promises";
@@ -130,7 +180,7 @@ import path from "path";
130
180
  import Handlebars from "handlebars";
131
181
 
132
182
  // src/cms/templates/types.ts.hbr
133
- 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";\nexport type WebhookPayload = {\n event: WebhookEvent;\n timestamp: string;\n project: string;\n} & (\n {{#each tables}}\n | {\n table: "{{this.name}}";\n content: {{toCodeTypeName this.name}};\n old?: {{toCodeTypeName this.name}};\n }\n {{/each}}\n)\n';
183
+ 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';
134
184
 
135
185
  // src/cms/templates/client.ts.hbr
136
186
  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';
@@ -144,24 +194,21 @@ function toCodeTypeName(str) {
144
194
  return str.replace(/_([a-z])/g, (g) => g[1].toUpperCase());
145
195
  }
146
196
  Handlebars.registerHelper("toCodeTypeName", toCodeTypeName);
147
- Handlebars.registerHelper(
148
- "typeName",
149
- (column) => {
150
- if (column.type === "reference") {
151
- return "string";
152
- } else if (column.type === "module") {
153
- return toCodeTypeName(column.moduleName);
154
- } else if (column.type === "module-array") {
155
- return toCodeTypeName(column.moduleName) + "[]";
156
- } else if (column.type == "json") {
157
- return "unknown";
158
- } else if (column.type === "storage") {
159
- return "StorageItemType";
160
- } else {
161
- return column.type;
162
- }
197
+ Handlebars.registerHelper("typeName", (column) => {
198
+ if (column.type === "reference") {
199
+ return "string";
200
+ } else if (column.type === "module") {
201
+ return toCodeTypeName(column.moduleName);
202
+ } else if (column.type === "module-array") {
203
+ return toCodeTypeName(column.moduleName) + "[]";
204
+ } else if (column.type == "json") {
205
+ return "unknown";
206
+ } else if (column.type === "storage") {
207
+ return "StorageItemType";
208
+ } else {
209
+ return column.type;
163
210
  }
164
- );
211
+ });
165
212
  Handlebars.registerHelper(
166
213
  "filterRefColumn",
167
214
  (columns) => {
@@ -208,7 +255,7 @@ Handlebars.registerHelper(
208
255
  }
209
256
  );
210
257
  async function generate(options) {
211
- const config = options.projectDef;
258
+ const config = options.config;
212
259
  await mkdir(options.output, { recursive: true });
213
260
  await renderTypes(config, options.output);
214
261
  await renderClient(config, options.output);
@@ -238,11 +285,11 @@ var spinner = createSpinner();
238
285
  var cmsGenerateCommand = new 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) => {
239
286
  try {
240
287
  spinner.start("Loading project schema...");
241
- const projectDef = await loadConfig(options.config);
288
+ const config = await loadConfig(options.config);
242
289
  spinner.succeed("Loaded project schema.");
243
290
  spinner.start("Generating code...");
244
291
  await generate({
245
- projectDef,
292
+ config,
246
293
  output: options.output
247
294
  });
248
295
  spinner.succeed(`Generated code to '${options.output}'`);
@@ -254,36 +301,491 @@ var cmsGenerateCommand = new Command("generate").description("generate orizm cli
254
301
  // src/cms/pull/command.ts
255
302
  import { Command as Command2 } from "commander";
256
303
 
257
- // src/api/developer-api-client.ts
258
- import createClient from "openapi-fetch";
259
- function createDeveloperAPIClient(baseUrl, apiKey) {
260
- const url = new URL(baseUrl);
261
- url.pathname = `/api/dev/v1`;
262
- return createClient({
263
- baseUrl: url.toString(),
264
- headers: {
265
- "x-api-key": apiKey
304
+ // ../../node_modules/.pnpm/openapi-fetch@0.13.5/node_modules/openapi-fetch/dist/index.js
305
+ var PATH_PARAM_RE = /\{[^{}]+\}/g;
306
+ var supportsRequestInitExt = () => {
307
+ return typeof process === "object" && Number.parseInt(process?.versions?.node?.substring(0, 2)) >= 18 && process.versions.undici;
308
+ };
309
+ function randomID() {
310
+ return Math.random().toString(36).slice(2, 11);
311
+ }
312
+ function createClient(clientOptions) {
313
+ let {
314
+ baseUrl = "",
315
+ Request: CustomRequest = globalThis.Request,
316
+ fetch: baseFetch = globalThis.fetch,
317
+ querySerializer: globalQuerySerializer,
318
+ bodySerializer: globalBodySerializer,
319
+ headers: baseHeaders,
320
+ requestInitExt = void 0,
321
+ ...baseOptions
322
+ } = { ...clientOptions };
323
+ requestInitExt = supportsRequestInitExt() ? requestInitExt : void 0;
324
+ baseUrl = removeTrailingSlash(baseUrl);
325
+ const middlewares = [];
326
+ async function coreFetch(schemaPath, fetchOptions) {
327
+ const {
328
+ baseUrl: localBaseUrl,
329
+ fetch = baseFetch,
330
+ Request = CustomRequest,
331
+ headers,
332
+ params = {},
333
+ parseAs = "json",
334
+ querySerializer: requestQuerySerializer,
335
+ bodySerializer = globalBodySerializer ?? defaultBodySerializer,
336
+ body,
337
+ ...init
338
+ } = fetchOptions || {};
339
+ if (localBaseUrl) {
340
+ baseUrl = removeTrailingSlash(localBaseUrl);
341
+ }
342
+ let querySerializer = typeof globalQuerySerializer === "function" ? globalQuerySerializer : createQuerySerializer(globalQuerySerializer);
343
+ if (requestQuerySerializer) {
344
+ querySerializer = typeof requestQuerySerializer === "function" ? requestQuerySerializer : createQuerySerializer({
345
+ ...typeof globalQuerySerializer === "object" ? globalQuerySerializer : {},
346
+ ...requestQuerySerializer
347
+ });
266
348
  }
349
+ const serializedBody = body === void 0 ? void 0 : bodySerializer(body);
350
+ const defaultHeaders = (
351
+ // with no body, we should not to set Content-Type
352
+ serializedBody === void 0 || // if serialized body is FormData; browser will correctly set Content-Type & boundary expression
353
+ serializedBody instanceof FormData ? {} : {
354
+ "Content-Type": "application/json"
355
+ }
356
+ );
357
+ const requestInit = {
358
+ redirect: "follow",
359
+ ...baseOptions,
360
+ ...init,
361
+ body: serializedBody,
362
+ headers: mergeHeaders(defaultHeaders, baseHeaders, headers, params.header)
363
+ };
364
+ let id;
365
+ let options;
366
+ let request = new CustomRequest(createFinalURL(schemaPath, { baseUrl, params, querySerializer }), requestInit);
367
+ let response;
368
+ for (const key in init) {
369
+ if (!(key in request)) {
370
+ request[key] = init[key];
371
+ }
372
+ }
373
+ if (middlewares.length) {
374
+ id = randomID();
375
+ options = Object.freeze({
376
+ baseUrl,
377
+ fetch,
378
+ parseAs,
379
+ querySerializer,
380
+ bodySerializer
381
+ });
382
+ for (const m of middlewares) {
383
+ if (m && typeof m === "object" && typeof m.onRequest === "function") {
384
+ const result = await m.onRequest({
385
+ request,
386
+ schemaPath,
387
+ params,
388
+ options,
389
+ id
390
+ });
391
+ if (result) {
392
+ if (result instanceof CustomRequest) {
393
+ request = result;
394
+ } else if (result instanceof Response) {
395
+ response = result;
396
+ break;
397
+ } else {
398
+ throw new Error("onRequest: must return new Request() or Response() when modifying the request");
399
+ }
400
+ }
401
+ }
402
+ }
403
+ }
404
+ if (!response) {
405
+ try {
406
+ response = await fetch(request, requestInitExt);
407
+ } catch (error3) {
408
+ let errorAfterMiddleware = error3;
409
+ if (middlewares.length) {
410
+ for (let i = middlewares.length - 1; i >= 0; i--) {
411
+ const m = middlewares[i];
412
+ if (m && typeof m === "object" && typeof m.onError === "function") {
413
+ const result = await m.onError({
414
+ request,
415
+ error: errorAfterMiddleware,
416
+ schemaPath,
417
+ params,
418
+ options,
419
+ id
420
+ });
421
+ if (result) {
422
+ if (result instanceof Response) {
423
+ errorAfterMiddleware = void 0;
424
+ response = result;
425
+ break;
426
+ }
427
+ if (result instanceof Error) {
428
+ errorAfterMiddleware = result;
429
+ continue;
430
+ }
431
+ throw new Error("onError: must return new Response() or instance of Error");
432
+ }
433
+ }
434
+ }
435
+ }
436
+ if (errorAfterMiddleware) {
437
+ throw errorAfterMiddleware;
438
+ }
439
+ }
440
+ if (middlewares.length) {
441
+ for (let i = middlewares.length - 1; i >= 0; i--) {
442
+ const m = middlewares[i];
443
+ if (m && typeof m === "object" && typeof m.onResponse === "function") {
444
+ const result = await m.onResponse({
445
+ request,
446
+ response,
447
+ schemaPath,
448
+ params,
449
+ options,
450
+ id
451
+ });
452
+ if (result) {
453
+ if (!(result instanceof Response)) {
454
+ throw new Error("onResponse: must return new Response() when modifying the response");
455
+ }
456
+ response = result;
457
+ }
458
+ }
459
+ }
460
+ }
461
+ }
462
+ if (response.status === 204 || response.headers.get("Content-Length") === "0") {
463
+ return response.ok ? { data: void 0, response } : { error: void 0, response };
464
+ }
465
+ if (response.ok) {
466
+ if (parseAs === "stream") {
467
+ return { data: response.body, response };
468
+ }
469
+ return { data: await response[parseAs](), response };
470
+ }
471
+ let error2 = await response.text();
472
+ try {
473
+ error2 = JSON.parse(error2);
474
+ } catch {
475
+ }
476
+ return { error: error2, response };
477
+ }
478
+ return {
479
+ request(method, url, init) {
480
+ return coreFetch(url, { ...init, method: method.toUpperCase() });
481
+ },
482
+ /** Call a GET endpoint */
483
+ GET(url, init) {
484
+ return coreFetch(url, { ...init, method: "GET" });
485
+ },
486
+ /** Call a PUT endpoint */
487
+ PUT(url, init) {
488
+ return coreFetch(url, { ...init, method: "PUT" });
489
+ },
490
+ /** Call a POST endpoint */
491
+ POST(url, init) {
492
+ return coreFetch(url, { ...init, method: "POST" });
493
+ },
494
+ /** Call a DELETE endpoint */
495
+ DELETE(url, init) {
496
+ return coreFetch(url, { ...init, method: "DELETE" });
497
+ },
498
+ /** Call a OPTIONS endpoint */
499
+ OPTIONS(url, init) {
500
+ return coreFetch(url, { ...init, method: "OPTIONS" });
501
+ },
502
+ /** Call a HEAD endpoint */
503
+ HEAD(url, init) {
504
+ return coreFetch(url, { ...init, method: "HEAD" });
505
+ },
506
+ /** Call a PATCH endpoint */
507
+ PATCH(url, init) {
508
+ return coreFetch(url, { ...init, method: "PATCH" });
509
+ },
510
+ /** Call a TRACE endpoint */
511
+ TRACE(url, init) {
512
+ return coreFetch(url, { ...init, method: "TRACE" });
513
+ },
514
+ /** Register middleware */
515
+ use(...middleware) {
516
+ for (const m of middleware) {
517
+ if (!m) {
518
+ continue;
519
+ }
520
+ if (typeof m !== "object" || !("onRequest" in m || "onResponse" in m || "onError" in m)) {
521
+ throw new Error("Middleware must be an object with one of `onRequest()`, `onResponse() or `onError()`");
522
+ }
523
+ middlewares.push(m);
524
+ }
525
+ },
526
+ /** Unregister middleware */
527
+ eject(...middleware) {
528
+ for (const m of middleware) {
529
+ const i = middlewares.indexOf(m);
530
+ if (i !== -1) {
531
+ middlewares.splice(i, 1);
532
+ }
533
+ }
534
+ }
535
+ };
536
+ }
537
+ function serializePrimitiveParam(name, value, options) {
538
+ if (value === void 0 || value === null) {
539
+ return "";
540
+ }
541
+ if (typeof value === "object") {
542
+ throw new Error(
543
+ "Deeply-nested arrays/objects aren\u2019t supported. Provide your own `querySerializer()` to handle these."
544
+ );
545
+ }
546
+ return `${name}=${options?.allowReserved === true ? value : encodeURIComponent(value)}`;
547
+ }
548
+ function serializeObjectParam(name, value, options) {
549
+ if (!value || typeof value !== "object") {
550
+ return "";
551
+ }
552
+ const values = [];
553
+ const joiner = {
554
+ simple: ",",
555
+ label: ".",
556
+ matrix: ";"
557
+ }[options.style] || "&";
558
+ if (options.style !== "deepObject" && options.explode === false) {
559
+ for (const k in value) {
560
+ values.push(k, options.allowReserved === true ? value[k] : encodeURIComponent(value[k]));
561
+ }
562
+ const final2 = values.join(",");
563
+ switch (options.style) {
564
+ case "form": {
565
+ return `${name}=${final2}`;
566
+ }
567
+ case "label": {
568
+ return `.${final2}`;
569
+ }
570
+ case "matrix": {
571
+ return `;${name}=${final2}`;
572
+ }
573
+ default: {
574
+ return final2;
575
+ }
576
+ }
577
+ }
578
+ for (const k in value) {
579
+ const finalName = options.style === "deepObject" ? `${name}[${k}]` : k;
580
+ values.push(serializePrimitiveParam(finalName, value[k], options));
581
+ }
582
+ const final = values.join(joiner);
583
+ return options.style === "label" || options.style === "matrix" ? `${joiner}${final}` : final;
584
+ }
585
+ function serializeArrayParam(name, value, options) {
586
+ if (!Array.isArray(value)) {
587
+ return "";
588
+ }
589
+ if (options.explode === false) {
590
+ const joiner2 = { form: ",", spaceDelimited: "%20", pipeDelimited: "|" }[options.style] || ",";
591
+ const final = (options.allowReserved === true ? value : value.map((v6) => encodeURIComponent(v6))).join(joiner2);
592
+ switch (options.style) {
593
+ case "simple": {
594
+ return final;
595
+ }
596
+ case "label": {
597
+ return `.${final}`;
598
+ }
599
+ case "matrix": {
600
+ return `;${name}=${final}`;
601
+ }
602
+ // case "spaceDelimited":
603
+ // case "pipeDelimited":
604
+ default: {
605
+ return `${name}=${final}`;
606
+ }
607
+ }
608
+ }
609
+ const joiner = { simple: ",", label: ".", matrix: ";" }[options.style] || "&";
610
+ const values = [];
611
+ for (const v6 of value) {
612
+ if (options.style === "simple" || options.style === "label") {
613
+ values.push(options.allowReserved === true ? v6 : encodeURIComponent(v6));
614
+ } else {
615
+ values.push(serializePrimitiveParam(name, v6, options));
616
+ }
617
+ }
618
+ return options.style === "label" || options.style === "matrix" ? `${joiner}${values.join(joiner)}` : values.join(joiner);
619
+ }
620
+ function createQuerySerializer(options) {
621
+ return function querySerializer(queryParams) {
622
+ const search = [];
623
+ if (queryParams && typeof queryParams === "object") {
624
+ for (const name in queryParams) {
625
+ const value = queryParams[name];
626
+ if (value === void 0 || value === null) {
627
+ continue;
628
+ }
629
+ if (Array.isArray(value)) {
630
+ if (value.length === 0) {
631
+ continue;
632
+ }
633
+ search.push(
634
+ serializeArrayParam(name, value, {
635
+ style: "form",
636
+ explode: true,
637
+ ...options?.array,
638
+ allowReserved: options?.allowReserved || false
639
+ })
640
+ );
641
+ continue;
642
+ }
643
+ if (typeof value === "object") {
644
+ search.push(
645
+ serializeObjectParam(name, value, {
646
+ style: "deepObject",
647
+ explode: true,
648
+ ...options?.object,
649
+ allowReserved: options?.allowReserved || false
650
+ })
651
+ );
652
+ continue;
653
+ }
654
+ search.push(serializePrimitiveParam(name, value, options));
655
+ }
656
+ }
657
+ return search.join("&");
658
+ };
659
+ }
660
+ function defaultPathSerializer(pathname, pathParams) {
661
+ let nextURL = pathname;
662
+ for (const match of pathname.match(PATH_PARAM_RE) ?? []) {
663
+ let name = match.substring(1, match.length - 1);
664
+ let explode = false;
665
+ let style = "simple";
666
+ if (name.endsWith("*")) {
667
+ explode = true;
668
+ name = name.substring(0, name.length - 1);
669
+ }
670
+ if (name.startsWith(".")) {
671
+ style = "label";
672
+ name = name.substring(1);
673
+ } else if (name.startsWith(";")) {
674
+ style = "matrix";
675
+ name = name.substring(1);
676
+ }
677
+ if (!pathParams || pathParams[name] === void 0 || pathParams[name] === null) {
678
+ continue;
679
+ }
680
+ const value = pathParams[name];
681
+ if (Array.isArray(value)) {
682
+ nextURL = nextURL.replace(match, serializeArrayParam(name, value, { style, explode }));
683
+ continue;
684
+ }
685
+ if (typeof value === "object") {
686
+ nextURL = nextURL.replace(match, serializeObjectParam(name, value, { style, explode }));
687
+ continue;
688
+ }
689
+ if (style === "matrix") {
690
+ nextURL = nextURL.replace(match, `;${serializePrimitiveParam(name, value)}`);
691
+ continue;
692
+ }
693
+ nextURL = nextURL.replace(match, style === "label" ? `.${encodeURIComponent(value)}` : encodeURIComponent(value));
694
+ }
695
+ return nextURL;
696
+ }
697
+ function defaultBodySerializer(body) {
698
+ if (body instanceof FormData) {
699
+ return body;
700
+ }
701
+ return JSON.stringify(body);
702
+ }
703
+ function createFinalURL(pathname, options) {
704
+ let finalURL = `${options.baseUrl}${pathname}`;
705
+ if (options.params?.path) {
706
+ finalURL = defaultPathSerializer(finalURL, options.params.path);
707
+ }
708
+ let search = options.querySerializer(options.params.query ?? {});
709
+ if (search.startsWith("?")) {
710
+ search = search.substring(1);
711
+ }
712
+ if (search) {
713
+ finalURL += `?${search}`;
714
+ }
715
+ return finalURL;
716
+ }
717
+ function mergeHeaders(...allHeaders) {
718
+ const finalHeaders = new Headers();
719
+ for (const h of allHeaders) {
720
+ if (!h || typeof h !== "object") {
721
+ continue;
722
+ }
723
+ const iterator = h instanceof Headers ? h.entries() : Object.entries(h);
724
+ for (const [k, v6] of iterator) {
725
+ if (v6 === null) {
726
+ finalHeaders.delete(k);
727
+ } else if (Array.isArray(v6)) {
728
+ for (const v22 of v6) {
729
+ finalHeaders.append(k, v22);
730
+ }
731
+ } else if (v6 !== void 0) {
732
+ finalHeaders.set(k, v6);
733
+ }
734
+ }
735
+ }
736
+ return finalHeaders;
737
+ }
738
+ function removeTrailingSlash(url) {
739
+ if (url.endsWith("/")) {
740
+ return url.substring(0, url.length - 1);
741
+ }
742
+ return url;
743
+ }
744
+
745
+ // ../private-api-clients/src/assert-valid-url-origin.ts
746
+ function assertValidUrlOrigin(origin) {
747
+ const url = new URL(origin);
748
+ if (url.origin !== origin) {
749
+ throw new Error(`${origin} is not a valid URL origin`);
750
+ }
751
+ }
752
+
753
+ // ../private-api-clients/src/dev-v2-api-client.ts
754
+ function createDeveloperAPIv2Client({
755
+ serverOrigin = "",
756
+ fetch,
757
+ headers
758
+ }) {
759
+ if (serverOrigin) assertValidUrlOrigin(serverOrigin);
760
+ return createClient({
761
+ baseUrl: `${serverOrigin}/api/dev/v2`,
762
+ fetch,
763
+ headers
267
764
  });
268
765
  }
269
766
 
270
- // src/lib/fetch-definition-reference.ts
271
- async function fetchDefinitionReference(options) {
272
- const client = createDeveloperAPIClient(options.baseUrl, options.apiKey);
767
+ // src/lib/fetch-current-definition.ts
768
+ async function fetchCurrentDefinition(options) {
769
+ const client = createDeveloperAPIv2Client({
770
+ serverOrigin: options.baseUrl,
771
+ headers: {
772
+ "x-api-key": options.apiKey
773
+ }
774
+ });
273
775
  const abortController = new AbortController();
274
776
  const timeout = setTimeout(() => {
275
777
  abortController.abort();
276
778
  }, 1e4);
277
779
  try {
278
780
  const response = await client.GET(
279
- "/projects/{projectName}/definitions/current/reference",
781
+ "/projects/{projectName}/definitions/current",
280
782
  {
281
783
  params: { path: { projectName: options.projectName } },
282
784
  signal: abortController.signal
283
785
  }
284
786
  );
285
787
  if (response.data) {
286
- return response.data.content;
788
+ return response.data;
287
789
  }
288
790
  if (response.response.status === 404) {
289
791
  throw new Error(`Project ${options.projectName} not found.`);
@@ -306,26 +808,26 @@ async function fetchDefinitionReference(options) {
306
808
 
307
809
  // src/lib/load-env.ts
308
810
  import fs from "fs/promises";
309
- import * as v3 from "valibot";
811
+ import * as v4 from "valibot";
310
812
  import dotenv from "dotenv";
311
813
  var DEFAULT_ENV_FILE_PATH = ".env";
312
- var EnvSchema = v3.object({
313
- ORIZM_PROJECT: v3.pipe(
314
- v3.string(),
315
- v3.minLength(1, "ORIZM_PROJECT is required"),
316
- v3.brand("ORIZM_PROJECT")
814
+ var EnvSchema = v4.object({
815
+ ORIZM_PROJECT: v4.pipe(
816
+ v4.string(),
817
+ v4.minLength(1, "ORIZM_PROJECT is required"),
818
+ v4.brand("ORIZM_PROJECT")
317
819
  ),
318
- ORIZM_BASE_URL: v3.pipe(
319
- v3.optional(v3.string(), "https://app.orizm.com"),
820
+ ORIZM_BASE_URL: v4.pipe(
821
+ v4.optional(v4.string(), "https://app.orizm.com"),
320
822
  // if null, use default value
321
- v3.transform((v4) => v4.replace(/\/$/, "")),
823
+ v4.transform((v6) => v6.replace(/\/$/, "")),
322
824
  // remove trailing slash
323
- v3.brand("ORIZM_BASE_URL")
825
+ v4.brand("ORIZM_BASE_URL")
324
826
  ),
325
- ORIZM_API_KEY: v3.pipe(
326
- v3.string(),
327
- v3.minLength(1, "ORIZM_API_KEY is required"),
328
- v3.brand("ORIZM_API_KEY")
827
+ ORIZM_API_KEY: v4.pipe(
828
+ v4.string(),
829
+ v4.minLength(1, "ORIZM_API_KEY is required"),
830
+ v4.brand("ORIZM_API_KEY")
329
831
  )
330
832
  });
331
833
  async function loadEnv(envPath) {
@@ -340,7 +842,7 @@ async function loadEnv(envPath) {
340
842
  }
341
843
  if (envFileContent !== null) {
342
844
  const dotenvParsed = dotenv.parse(envFileContent);
343
- const envParseResult = v3.safeParse(EnvSchema, dotenvParsed);
845
+ const envParseResult = v4.safeParse(EnvSchema, dotenvParsed);
344
846
  if (!envParseResult.success) {
345
847
  throw new Error(
346
848
  `Environment variables are not valid.
@@ -349,7 +851,7 @@ async function loadEnv(envPath) {
349
851
  }
350
852
  return envParseResult.output;
351
853
  }
352
- const processEnvParseResult = v3.safeParse(EnvSchema, process.env);
854
+ const processEnvParseResult = v4.safeParse(EnvSchema, process.env);
353
855
  if (!processEnvParseResult.success) {
354
856
  throw new Error(
355
857
  "Environment variables are not valid. Put .env file or set environment variables in process.env.\n" + processEnvParseResult.issues.map((issue) => issue.message).join("\n")
@@ -364,17 +866,17 @@ async function pullAction(options) {
364
866
  spinner2.start("Loading environment variables...");
365
867
  const env = await loadEnv(options.envPath);
366
868
  spinner2.succeed("Loaded environment variables.");
367
- spinner2.start("Loading project schema...");
368
- const definitionReference = await fetchDefinitionReference({
869
+ spinner2.start("Loading project config...");
870
+ const definitionReference = await fetchCurrentDefinition({
369
871
  baseUrl: env.ORIZM_BASE_URL,
370
872
  apiKey: env.ORIZM_API_KEY,
371
873
  projectName: env.ORIZM_PROJECT
372
874
  });
373
- spinner2.succeed("Loaded project schema.");
875
+ spinner2.succeed("Loaded project config.");
374
876
  spinner2.start("Generating code...");
375
877
  await generate({
376
878
  output: options.destination,
377
- projectDef: definitionReference
879
+ config: definitionReference.parsed
378
880
  });
379
881
  spinner2.succeed(`Generated code to '${options.destination}'`);
380
882
  }
@@ -403,7 +905,7 @@ import Handlebars2 from "handlebars";
403
905
  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';
404
906
 
405
907
  // src/consumer/templates/types.ts.hbr
406
- 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";\nexport type WebhookPayload = {\n event: WebhookEvent;\n timestamp: string;\n project: string;\n} & (\n {{#each tables}}\n | {\n table: "{{this.name}}";\n content: {{toCodeTypeName this.name}};\n old?: {{toCodeTypeName this.name}};\n }\n {{/each}}\n)\n';
908
+ 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';
407
909
 
408
910
  // src/consumer/pull/generate.ts
409
911
  async function generate2(options) {
@@ -440,11 +942,14 @@ Handlebars2.registerHelper("typeName", (column) => {
440
942
  return column.type;
441
943
  }
442
944
  });
443
- Handlebars2.registerHelper("filterRefColumn", (columns) => {
444
- return (columns || []).filter(
445
- (c) => c.type === "reference" && c.tableName && c.includeName || c.type === "module" && c.moduleName || c.type === "module-array" && c.moduleName
446
- );
447
- });
945
+ Handlebars2.registerHelper(
946
+ "filterRefColumn",
947
+ (columns) => {
948
+ return (columns || []).filter(
949
+ (c) => c.type === "reference" && c.tableName && c.includeName || c.type === "module" && c.moduleName || c.type === "module-array" && c.moduleName
950
+ );
951
+ }
952
+ );
448
953
  Handlebars2.registerHelper("includeName", (column) => {
449
954
  return column.type === "reference" ? column.includeName : column.name;
450
955
  });
@@ -488,9 +993,9 @@ async function renderClient2(config, output) {
488
993
  // src/consumer/generate/action.ts
489
994
  var spinner3 = createSpinner();
490
995
  async function generateAction(orizmConfigTs, destination) {
491
- spinner3.start("Loading project schema...");
996
+ spinner3.start("Loading project config...");
492
997
  const definition = await loadConfig(orizmConfigTs);
493
- spinner3.succeed("Loaded project schema.");
998
+ spinner3.succeed("Loaded project config.");
494
999
  spinner3.start("Generating code...");
495
1000
  await generate2({
496
1001
  definition,
@@ -517,16 +1022,16 @@ async function pullAction2(options) {
517
1022
  spinner4.start("Loading environment variables...");
518
1023
  const config = await loadEnv(options.envPath);
519
1024
  spinner4.succeed("Loaded environment variables.");
520
- spinner4.start("Loading project schema...");
521
- const definition = await fetchDefinitionReference({
1025
+ spinner4.start("Loading project config...");
1026
+ const definition = await fetchCurrentDefinition({
522
1027
  baseUrl: config.ORIZM_BASE_URL,
523
1028
  apiKey: config.ORIZM_API_KEY,
524
1029
  projectName: config.ORIZM_PROJECT
525
1030
  });
526
- spinner4.succeed("Loaded project schema.");
1031
+ spinner4.succeed("Loaded project config.");
527
1032
  spinner4.start("Generating code...");
528
1033
  await generate2({
529
- definition,
1034
+ definition: definition.parsed,
530
1035
  output: options.destination
531
1036
  });
532
1037
  spinner4.succeed(`Generated code to '${options.destination}'`);
@@ -546,18 +1051,19 @@ var consumerPullCommand = new Command4("pull").description("pull orizm schema an
546
1051
 
547
1052
  // src/push/command.ts
548
1053
  import { Command as Command5 } from "commander";
549
- import cliColor4 from "cli-color";
1054
+ import cliColor5 from "cli-color";
550
1055
 
551
1056
  // src/lib/developer-api.ts
552
1057
  async function applyDefinition(env, projectDef) {
553
- const client = createDeveloperAPIClient(
554
- env.ORIZM_BASE_URL,
555
- env.ORIZM_API_KEY
556
- );
1058
+ const client = createDeveloperAPIv2Client({
1059
+ serverOrigin: env.ORIZM_BASE_URL,
1060
+ headers: {
1061
+ "x-api-key": env.ORIZM_API_KEY
1062
+ }
1063
+ });
557
1064
  const response = await client.POST("/projects/{projectName}/definitions", {
558
1065
  params: { path: { projectName: env.ORIZM_PROJECT } },
559
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
560
- body: { apply: true, project: projectDef }
1066
+ body: { definition: projectDef }
561
1067
  });
562
1068
  if (!response.data) {
563
1069
  const status = response.response.status;
@@ -572,16 +1078,17 @@ async function applyDefinition(env, projectDef) {
572
1078
  }
573
1079
  }
574
1080
  var getChangeEvents = async (env, projectDef) => {
575
- const client = createDeveloperAPIClient(
576
- env.ORIZM_BASE_URL,
577
- env.ORIZM_API_KEY
578
- );
1081
+ const client = createDeveloperAPIv2Client({
1082
+ serverOrigin: env.ORIZM_BASE_URL,
1083
+ headers: {
1084
+ "x-api-key": env.ORIZM_API_KEY
1085
+ }
1086
+ });
579
1087
  const response = await client.POST(
580
1088
  "/projects/{projectName}/definitions/dry-run",
581
1089
  {
582
1090
  params: { path: { projectName: env.ORIZM_PROJECT } },
583
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
584
- body: { project: projectDef }
1091
+ body: { definition: projectDef }
585
1092
  }
586
1093
  );
587
1094
  if (!response.data) {
@@ -592,14 +1099,15 @@ var getChangeEvents = async (env, projectDef) => {
592
1099
  );
593
1100
  }
594
1101
  throw new Error(
595
- `${status} ${response.response.statusText}: Unexpected error occurred while fetching schema change events.`
1102
+ `${status} ${response.response.statusText}: Unexpected error occurred while fetching schema change events.
1103
+ ${JSON.stringify(response.error, null, 2)}`
596
1104
  );
597
1105
  }
598
1106
  return response.data;
599
1107
  };
600
1108
 
601
1109
  // src/lib/display-change-events.ts
602
- import cliColor3 from "cli-color";
1110
+ import cliColor4 from "cli-color";
603
1111
 
604
1112
  // src/lib/cli-table.ts
605
1113
  var COLORS = {
@@ -708,7 +1216,7 @@ async function displayChangeEvents(changeEvents) {
708
1216
  } = changeEvents;
709
1217
  if (tableChangeEvents.length === 0 && bucketChangeEvents.length === 0 && authorityChangeEvents.length === 0) {
710
1218
  console.log();
711
- console.log(cliColor3.green("No changes."));
1219
+ console.log(cliColor4.green("No changes."));
712
1220
  return;
713
1221
  }
714
1222
  displayTableChangeEvents(tableChangeEvents);
@@ -965,9 +1473,9 @@ var pushCommand = new Command5("push").description("apply schema to project.").o
965
1473
  spinner5.start("Loading environment variables...");
966
1474
  const env = await loadEnv(options.env);
967
1475
  spinner5.succeed("Loaded environment variables.");
968
- spinner5.start("Loading project schema...");
1476
+ spinner5.start("Loading project config...");
969
1477
  const projectDef = await loadConfig(options.config);
970
- spinner5.succeed("Loaded project schema.");
1478
+ spinner5.succeed("Loaded project config.");
971
1479
  spinner5.start("Fetch schema change events...");
972
1480
  const changeEvents = await getChangeEvents(env, projectDef);
973
1481
  spinner5.succeed("Fetch schema change events.");
@@ -981,7 +1489,7 @@ var pushCommand = new Command5("push").description("apply schema to project.").o
981
1489
  if (!options.yes) {
982
1490
  const confirm = await input("Do you want to apply schema? (y/N): ");
983
1491
  if (confirm !== "y") {
984
- console.log(cliColor4.red("Canceled."));
1492
+ console.log(cliColor5.red("Canceled."));
985
1493
  return;
986
1494
  }
987
1495
  }
@@ -993,17 +1501,202 @@ var pushCommand = new Command5("push").description("apply schema to project.").o
993
1501
  }
994
1502
  });
995
1503
 
1504
+ // src/config/validate/command.ts
1505
+ import { Command as Command6 } from "commander";
1506
+ import clc from "cli-color";
1507
+ import * as v5 from "valibot";
1508
+
1509
+ // src/config/validate/watcher.ts
1510
+ import chokidar from "chokidar";
1511
+ function watchConfigFile(configPath, onFileChange) {
1512
+ const watcher = chokidar.watch(configPath, {
1513
+ persistent: true,
1514
+ ignoreInitial: true
1515
+ });
1516
+ let isProcessing = false;
1517
+ let timeoutId = null;
1518
+ const debouncedOnChange = async () => {
1519
+ if (isProcessing) return;
1520
+ if (timeoutId) {
1521
+ clearTimeout(timeoutId);
1522
+ }
1523
+ timeoutId = setTimeout(async () => {
1524
+ isProcessing = true;
1525
+ try {
1526
+ await onFileChange();
1527
+ } catch (error2) {
1528
+ handleError(error2);
1529
+ } finally {
1530
+ isProcessing = false;
1531
+ }
1532
+ }, 300);
1533
+ };
1534
+ watcher.on("change", debouncedOnChange);
1535
+ watcher.on("add", debouncedOnChange);
1536
+ watcher.on("unlink", debouncedOnChange);
1537
+ const terminate = () => {
1538
+ watcher.close();
1539
+ process.exit(0);
1540
+ };
1541
+ process.on("SIGINT", terminate);
1542
+ process.on("SIGTERM", terminate);
1543
+ watcher.on("error", (error2) => {
1544
+ handleError(error2);
1545
+ });
1546
+ return watcher;
1547
+ }
1548
+
1549
+ // src/config/validate/command.ts
1550
+ var validateConfigCommand = new Command6("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) => {
1551
+ try {
1552
+ const validateConfig = async () => {
1553
+ try {
1554
+ if (options.watch) {
1555
+ console.clear();
1556
+ console.log(
1557
+ `\u{1F440} Watching ${options.config} for changes... (Press Ctrl+C to stop)`
1558
+ );
1559
+ console.log();
1560
+ }
1561
+ await loadConfig(options.config);
1562
+ console.log(clc.green("\u2705 Config is valid."));
1563
+ } catch (error2) {
1564
+ if (v5.isValiError(error2)) {
1565
+ console.error(clc.red("\u274C Config validation failed:"));
1566
+ displayValibotError(error2);
1567
+ return;
1568
+ }
1569
+ throw error2;
1570
+ }
1571
+ };
1572
+ await validateConfig();
1573
+ if (options.watch) {
1574
+ watchConfigFile(options.config, validateConfig);
1575
+ }
1576
+ } catch (error2) {
1577
+ handleError(error2);
1578
+ }
1579
+ });
1580
+
1581
+ // src/config/generate-erd/command.ts
1582
+ import { Command as Command7 } from "commander";
1583
+
1584
+ // src/config/generate-erd/generate.ts
1585
+ import Handlebars3 from "handlebars";
1586
+
1587
+ // src/config/generate-erd/mermaid-erd.hbr
1588
+ 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```";
1589
+
1590
+ // src/config/generate-erd/generate.ts
1591
+ function generate3(input2) {
1592
+ const template = Handlebars3.compile(mermaid_erd_default);
1593
+ return template(input2);
1594
+ }
1595
+
1596
+ // src/config/generate-erd/convert-to-input.ts
1597
+ function convertToInput(config) {
1598
+ if (!config.tables) {
1599
+ return {
1600
+ tables: [],
1601
+ relations: []
1602
+ };
1603
+ }
1604
+ const tables = [];
1605
+ const relations = [];
1606
+ for (const table of config.tables) {
1607
+ const modules = [];
1608
+ const erdTable = {
1609
+ name: table.name,
1610
+ columns: []
1611
+ };
1612
+ for (const column of table.columns) {
1613
+ erdTable.columns.push({
1614
+ name: column.name,
1615
+ type: column.type,
1616
+ isForeignKey: column.type === "reference"
1617
+ });
1618
+ if (column.type === "reference") {
1619
+ relations.push({
1620
+ from: column.tableName,
1621
+ to: table.name,
1622
+ type: RELATION.ONE_TO_MANY,
1623
+ comment: "reference"
1624
+ });
1625
+ }
1626
+ if (column.type === "module" || column.type === "module-array") {
1627
+ const module = config.tableModules?.find(
1628
+ (m) => m.name === column.moduleName
1629
+ );
1630
+ if (!module) {
1631
+ continue;
1632
+ }
1633
+ const moduleTableName = `${table.name}_${column.name}_${column.moduleName}`;
1634
+ modules.push({
1635
+ name: moduleTableName,
1636
+ columns: module?.columns.map((c) => ({
1637
+ name: c.name,
1638
+ type: c.type,
1639
+ isForeignKey: c.type === "reference"
1640
+ })) || []
1641
+ });
1642
+ relations.push({
1643
+ from: table.name,
1644
+ to: moduleTableName,
1645
+ type: column.type === "module" ? RELATION.ONE_TO_ONE : RELATION.ONE_TO_MANY,
1646
+ comment: column.type === "module" ? "module" : "module-array"
1647
+ });
1648
+ for (const moduleColumn of module.columns) {
1649
+ if (moduleColumn.type === "reference" && moduleColumn.tableName) {
1650
+ relations.push({
1651
+ from: moduleTableName,
1652
+ to: moduleColumn.tableName,
1653
+ type: RELATION.ONE_TO_MANY,
1654
+ comment: "reference"
1655
+ });
1656
+ }
1657
+ }
1658
+ }
1659
+ }
1660
+ tables.push(erdTable);
1661
+ tables.push(...modules);
1662
+ }
1663
+ return {
1664
+ tables,
1665
+ relations
1666
+ };
1667
+ }
1668
+ var RELATION = {
1669
+ ONE_TO_MANY: "||--o{",
1670
+ ONE_TO_ONE: "||--||"
1671
+ };
1672
+
1673
+ // src/config/generate-erd/command.ts
1674
+ var generateErdCommand = new Command7("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) => {
1675
+ try {
1676
+ const config = await loadConfig(options.config);
1677
+ const input2 = convertToInput(config);
1678
+ const mermaidText = generate3(input2);
1679
+ console.log(mermaidText);
1680
+ } catch (error2) {
1681
+ handleError(error2);
1682
+ }
1683
+ });
1684
+
996
1685
  // src/cli.ts
997
1686
  program.name("orizm CLI");
998
1687
  program.addCommand(pushCommand);
999
- var cmsCommands = new Command6("cms").description("cms commands.");
1688
+ var cmsCommands = new Command8("cms").description("cms commands.");
1000
1689
  cmsCommands.addCommand(cmsGenerateCommand);
1001
1690
  cmsCommands.addCommand(cmsPullCommand);
1002
1691
  program.addCommand(cmsCommands);
1003
- var consumerCommands = new Command6("consumer").description(
1692
+ var consumerCommands = new Command8("consumer").description(
1004
1693
  "consumer commands."
1005
1694
  );
1006
1695
  consumerCommands.addCommand(consumerGenerateCommand);
1007
1696
  consumerCommands.addCommand(consumerPullCommand);
1008
1697
  program.addCommand(consumerCommands);
1698
+ var configCommands = new Command8("config").description("config commands.");
1699
+ configCommands.addCommand(validateConfigCommand);
1700
+ configCommands.addCommand(generateErdCommand);
1701
+ program.addCommand(configCommands);
1009
1702
  program.parse();