appwrite-cli 13.1.0-rc.3 → 13.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Change Log
2
2
 
3
+ ## 13.1.0
4
+
5
+ - Mark `appwrite generate` command as stable
6
+ - Improve permissions param to be a typesafe callback
7
+ - Fix relationship handling in generated code
8
+ - Fix `appwrite client` properly hanlding `--key` parameter
9
+ - Fix `init site` not working on Windows
10
+
3
11
  ## 13.1.0-rc.3
4
12
 
5
13
  - Allow generation of server side CRUD operations on databases and tables
package/README.md CHANGED
@@ -29,7 +29,7 @@ Once the installation is complete, you can verify the install using
29
29
 
30
30
  ```sh
31
31
  $ appwrite -v
32
- 13.1.0-rc.3
32
+ 13.1.0
33
33
  ```
34
34
 
35
35
  ### Install using prebuilt binaries
@@ -60,7 +60,7 @@ $ scoop install https://raw.githubusercontent.com/appwrite/sdk-for-cli/master/sc
60
60
  Once the installation completes, you can verify your install using
61
61
  ```
62
62
  $ appwrite -v
63
- 13.1.0-rc.3
63
+ 13.1.0
64
64
  ```
65
65
 
66
66
  ## Getting Started
@@ -93398,7 +93398,7 @@ var package_default = {
93398
93398
  type: "module",
93399
93399
  homepage: "https://appwrite.io/support",
93400
93400
  description: "Appwrite is an open-source self-hosted backend server that abstracts and simplifies complex and repetitive development tasks behind a very simple REST API",
93401
- version: "13.1.0-rc.3",
93401
+ version: "13.1.0",
93402
93402
  license: "BSD-3-Clause",
93403
93403
  main: "dist/index.js",
93404
93404
  types: "dist/index.d.ts",
@@ -93437,7 +93437,6 @@ var package_default = {
93437
93437
  dotenv: "^16.4.5",
93438
93438
  ejs: "^3.1.9",
93439
93439
  handlebars: "^4.7.7",
93440
- "form-data": "^4.0.0",
93441
93440
  ignore: "^7.0.5",
93442
93441
  inquirer: "^8.2.4",
93443
93442
  "inquirer-search-list": "^1.2.6",
@@ -107649,7 +107648,7 @@ import childProcess from "child_process";
107649
107648
  // lib/constants.ts
107650
107649
  var SDK_TITLE = "Appwrite";
107651
107650
  var SDK_TITLE_LOWER = "appwrite";
107652
- var SDK_VERSION = "13.1.0-rc.3";
107651
+ var SDK_VERSION = "13.1.0";
107653
107652
  var SDK_NAME = "Command Line";
107654
107653
  var SDK_PLATFORM = "console";
107655
107654
  var SDK_LANGUAGE = "cli";
@@ -133108,6 +133107,7 @@ var commandDescriptions = {
133108
133107
  push: `The push command provides a convenient wrapper for pushing your functions, collections, buckets, teams, and messaging-topics.`,
133109
133108
  run: `The run command allows you to run the project locally to allow easy development and quick debugging.`,
133110
133109
  functions: `The functions command allows you to view, create, and manage your Cloud Functions.`,
133110
+ generate: `The generate command allows you to generate a type-safe SDK from your ${SDK_TITLE} project configuration.`,
133111
133111
  health: `The health command allows you to both validate and monitor your ${SDK_TITLE} server's health.`,
133112
133112
  pull: `The pull command helps you pull your ${SDK_TITLE} project, functions, collections, buckets, teams, and messaging-topics`,
133113
133113
  locale: `The locale command allows you to customize your app based on your users' location.`,
@@ -136225,23 +136225,19 @@ var initSite = async () => {
136225
136225
  let selected = {
136226
136226
  template: templateDetails.frameworks[0].providerRootDirectory
136227
136227
  };
136228
- let gitCloneCommands = "";
136228
+ let dirSetupCommands = "";
136229
136229
  const sparse = selected.template.startsWith("./") ? selected.template.substring(2) : selected.template;
136230
136230
  log("Fetching site code ...");
136231
136231
  if (selected.template === "./") {
136232
- gitCloneCommands = `
136233
- mkdir -p .
136234
- cd .
136232
+ dirSetupCommands = `
136233
+ cd ${templatesDir}
136235
136234
  git init
136236
136235
  git remote add origin ${repo}
136237
- git config --global init.defaultBranch main
136238
- git fetch --depth=1 origin refs/tags/$(git ls-remote --tags origin "${templateDetails.providerVersion}" | tail -n 1 | awk -F '/' '{print $3}')
136239
- git checkout FETCH_HEAD
136236
+ git config --global init.defaultBranch main
136240
136237
  `.trim();
136241
136238
  } else {
136242
- gitCloneCommands = `
136243
- mkdir -p .
136244
- cd .
136239
+ dirSetupCommands = `
136240
+ cd ${templatesDir}
136245
136241
  git init
136246
136242
  git remote add origin ${repo}
136247
136243
  git config --global init.defaultBranch main
@@ -136249,17 +136245,29 @@ var initSite = async () => {
136249
136245
  echo "${sparse}" >> .git/info/sparse-checkout
136250
136246
  git config --add remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'
136251
136247
  git config remote.origin.tagopt --no-tags
136252
- git fetch --depth=1 origin refs/tags/$(git ls-remote --tags origin "${templateDetails.providerVersion}" | tail -n 1 | awk -F '/' '{print $3}')
136253
- git checkout FETCH_HEAD
136254
136248
  `.trim();
136255
136249
  }
136250
+ let windowsGitCloneCommands = `
136251
+ $tag = (git ls-remote --tags origin "${templateDetails.providerVersion}" | Select-Object -Last 1) -replace '.*refs/tags/', ''
136252
+ git fetch --depth=1 origin "refs/tags/$tag"
136253
+ git checkout FETCH_HEAD
136254
+ `.trim();
136255
+ let unixGitCloneCommands = `
136256
+ git fetch --depth=1 origin refs/tags/$(git ls-remote --tags origin "${templateDetails.providerVersion}" | tail -n 1 | awk -F '/' '{print $3}')
136257
+ git checkout FETCH_HEAD
136258
+ `.trim();
136259
+ let usedShell = null;
136256
136260
  if (process.platform === "win32") {
136257
- gitCloneCommands = 'cmd /c "' + gitCloneCommands + '"';
136261
+ dirSetupCommands = dirSetupCommands + "\n" + windowsGitCloneCommands;
136262
+ usedShell = "powershell.exe";
136263
+ } else {
136264
+ dirSetupCommands = dirSetupCommands + "\n" + unixGitCloneCommands;
136258
136265
  }
136259
136266
  try {
136260
- childProcess2.execSync(gitCloneCommands, {
136267
+ childProcess2.execSync(dirSetupCommands, {
136261
136268
  stdio: "pipe",
136262
- cwd: templatesDir
136269
+ cwd: templatesDir,
136270
+ shell: usedShell
136263
136271
  });
136264
136272
  } catch (err) {
136265
136273
  if (err.message.includes("error: unknown option")) {
@@ -136280,28 +136288,11 @@ Suggestion: It appears that git is not installed, try installing git then trying
136280
136288
  throw err;
136281
136289
  }
136282
136290
  }
136283
- fs5.rmSync(path4.join(templatesDir, ".git"), { recursive: true });
136284
- const copyRecursiveSync = (src, dest) => {
136285
- let exists = fs5.existsSync(src);
136286
- let stats = exists && fs5.statSync(src);
136287
- let isDirectory = exists && stats && stats.isDirectory();
136288
- if (isDirectory) {
136289
- if (!fs5.existsSync(dest)) {
136290
- fs5.mkdirSync(dest);
136291
- }
136292
- fs5.readdirSync(src).forEach(function(childItemName) {
136293
- copyRecursiveSync(
136294
- path4.join(src, childItemName),
136295
- path4.join(dest, childItemName)
136296
- );
136297
- });
136298
- } else {
136299
- fs5.copyFileSync(src, dest);
136300
- }
136301
- };
136302
- copyRecursiveSync(
136291
+ fs5.rmSync(path4.join(templatesDir, ".git"), { recursive: true, force: true });
136292
+ fs5.cpSync(
136303
136293
  selected.template === "./" ? templatesDir : path4.join(templatesDir, selected.template),
136304
- siteDir
136294
+ siteDir,
136295
+ { recursive: true, force: true }
136305
136296
  );
136306
136297
  fs5.rmSync(templatesDir, { recursive: true, force: true });
136307
136298
  const readmePath = path4.join(process.cwd(), "sites", siteName, "README.md");
@@ -136612,7 +136603,7 @@ class <%- toPascalCase(collection.name) %> {
136612
136603
  // lib/shared/typescript-type-utils.ts
136613
136604
  import * as fs7 from "fs";
136614
136605
  import * as path6 from "path";
136615
- function getTypeScriptType(attribute, entities, entityName) {
136606
+ function getTypeScriptType(attribute, entities, entityName, forCreate = false) {
136616
136607
  let type = "";
136617
136608
  switch (attribute.type) {
136618
136609
  case "string":
@@ -136637,7 +136628,8 @@ function getTypeScriptType(attribute, entities, entityName) {
136637
136628
  if (!relatedEntity) {
136638
136629
  throw new Error(`Related entity with ID '${relatedId}' not found.`);
136639
136630
  }
136640
- type = LanguageMeta.toPascalCase(relatedEntity.name);
136631
+ const baseName = LanguageMeta.toPascalCase(relatedEntity.name);
136632
+ type = forCreate ? `((${baseName}Create & { $id?: string; $permissions?: string[] }) | string)` : baseName;
136641
136633
  if (attribute.relationType === "oneToMany" && attribute.side === "parent" || attribute.relationType === "manyToOne" && attribute.side === "child" || attribute.relationType === "manyToMany") {
136642
136634
  type = `${type}[]`;
136643
136635
  }
@@ -142167,6 +142159,9 @@ var BaseDatabasesGenerator = class {
142167
142159
  if (!fs15.existsSync(fileDir)) {
142168
142160
  fs15.mkdirSync(fileDir, { recursive: true });
142169
142161
  }
142162
+ if (relativePath === "constants.ts" && fs15.existsSync(filePath)) {
142163
+ continue;
142164
+ }
142170
142165
  fs15.writeFileSync(filePath, content, "utf-8");
142171
142166
  }
142172
142167
  }
@@ -142178,10 +142173,10 @@ var BaseDatabasesGenerator = class {
142178
142173
  };
142179
142174
 
142180
142175
  // lib/commands/generators/typescript/templates/types.ts.hbs
142181
- var types_ts_default = "import { type Models, Permission } from '{{appwriteDep}}';\n\n{{{ENUMS}}}{{{TYPES}}}\nexport type QueryValue = string | number | boolean;\n\nexport type ExtractQueryValue<T> = T extends (infer U)[]\n ? U extends QueryValue ? U : never\n : T extends QueryValue | null ? NonNullable<T> : never;\n\nexport type QueryableKeys<T> = {\n [K in keyof T]: ExtractQueryValue<T[K]> extends never ? never : K;\n}[keyof T];\n\nexport type QueryBuilder<T> = {\n equal: <K extends QueryableKeys<T>>(field: K, value: ExtractQueryValue<T[K]>) => string;\n notEqual: <K extends QueryableKeys<T>>(field: K, value: ExtractQueryValue<T[K]>) => string;\n lessThan: <K extends QueryableKeys<T>>(field: K, value: ExtractQueryValue<T[K]>) => string;\n lessThanEqual: <K extends QueryableKeys<T>>(field: K, value: ExtractQueryValue<T[K]>) => string;\n greaterThan: <K extends QueryableKeys<T>>(field: K, value: ExtractQueryValue<T[K]>) => string;\n greaterThanEqual: <K extends QueryableKeys<T>>(field: K, value: ExtractQueryValue<T[K]>) => string;\n contains: <K extends QueryableKeys<T>>(field: K, value: ExtractQueryValue<T[K]>) => string;\n search: <K extends QueryableKeys<T>>(field: K, value: string) => string;\n isNull: <K extends QueryableKeys<T>>(field: K) => string;\n isNotNull: <K extends QueryableKeys<T>>(field: K) => string;\n startsWith: <K extends QueryableKeys<T>>(field: K, value: string) => string;\n endsWith: <K extends QueryableKeys<T>>(field: K, value: string) => string;\n between: <K extends QueryableKeys<T>>(field: K, start: ExtractQueryValue<T[K]>, end: ExtractQueryValue<T[K]>) => string;\n select: <K extends keyof T>(fields: K[]) => string;\n orderAsc: <K extends keyof T>(field: K) => string;\n orderDesc: <K extends keyof T>(field: K) => string;\n limit: (value: number) => string;\n offset: (value: number) => string;\n cursorAfter: (documentId: string) => string;\n cursorBefore: (documentId: string) => string;\n or: (...queries: string[]) => string;\n and: (...queries: string[]) => string;\n}\n\nexport type DatabaseId = {{{databaseIdType}}};\n\n{{{DATABASE_TABLES_TYPE}}}\n";
142176
+ var types_ts_default = "import { type Models } from '{{appwriteDep}}';\n\n{{{ENUMS}}}{{{TYPES}}}\ndeclare const __roleStringBrand: unique symbol;\nexport type RoleString = string & { readonly [__roleStringBrand]: never };\n\nexport type RoleBuilder = {\n any: () => RoleString;\n user: (userId: string, status?: string) => RoleString;\n users: (status?: string) => RoleString;\n guests: () => RoleString;\n team: (teamId: string, role?: string) => RoleString;\n member: (memberId: string) => RoleString;\n label: (label: string) => RoleString;\n}\n\nexport type PermissionBuilder = {\n read: (role: RoleString) => string;\n write: (role: RoleString) => string;\n create: (role: RoleString) => string;\n update: (role: RoleString) => string;\n delete: (role: RoleString) => string;\n}\n\nexport type PermissionCallback = (permission: PermissionBuilder, role: RoleBuilder) => string[];\n\nexport type QueryValue = string | number | boolean;\n\nexport type ExtractQueryValue<T> = T extends (infer U)[]\n ? U extends QueryValue ? U : never\n : T extends QueryValue | null ? NonNullable<T> : never;\n\nexport type QueryableKeys<T> = {\n [K in keyof T]: ExtractQueryValue<T[K]> extends never ? never : K;\n}[keyof T];\n\nexport type QueryBuilder<T> = {\n equal: <K extends QueryableKeys<T>>(field: K, value: ExtractQueryValue<T[K]>) => string;\n notEqual: <K extends QueryableKeys<T>>(field: K, value: ExtractQueryValue<T[K]>) => string;\n lessThan: <K extends QueryableKeys<T>>(field: K, value: ExtractQueryValue<T[K]>) => string;\n lessThanEqual: <K extends QueryableKeys<T>>(field: K, value: ExtractQueryValue<T[K]>) => string;\n greaterThan: <K extends QueryableKeys<T>>(field: K, value: ExtractQueryValue<T[K]>) => string;\n greaterThanEqual: <K extends QueryableKeys<T>>(field: K, value: ExtractQueryValue<T[K]>) => string;\n contains: <K extends QueryableKeys<T>>(field: K, value: ExtractQueryValue<T[K]>) => string;\n search: <K extends QueryableKeys<T>>(field: K, value: string) => string;\n isNull: <K extends QueryableKeys<T>>(field: K) => string;\n isNotNull: <K extends QueryableKeys<T>>(field: K) => string;\n startsWith: <K extends QueryableKeys<T>>(field: K, value: string) => string;\n endsWith: <K extends QueryableKeys<T>>(field: K, value: string) => string;\n between: <K extends QueryableKeys<T>>(field: K, start: ExtractQueryValue<T[K]>, end: ExtractQueryValue<T[K]>) => string;\n select: <K extends keyof T>(fields: K[]) => string;\n orderAsc: <K extends keyof T>(field: K) => string;\n orderDesc: <K extends keyof T>(field: K) => string;\n limit: (value: number) => string;\n offset: (value: number) => string;\n cursorAfter: (documentId: string) => string;\n cursorBefore: (documentId: string) => string;\n or: (...queries: string[]) => string;\n and: (...queries: string[]) => string;\n}\n\nexport type DatabaseId = {{{databaseIdType}}};\n\n{{{DATABASE_TABLES_TYPE}}}\n";
142182
142177
 
142183
142178
  // lib/commands/generators/typescript/templates/databases.ts.hbs
142184
- var databases_ts_default = 'import { Client, TablesDB, ID, Query, type Models, Permission } from \'{{appwriteDep}}\';\nimport type { DatabaseHandle, DatabaseId, DatabaseTableMap, DatabaseTables, QueryBuilder } from \'./types.js\';\n{{#if supportsServerSide}}\nimport { PROJECT_ID, ENDPOINT, API_KEY } from \'./constants.js\';\n{{else}}\nimport { PROJECT_ID, ENDPOINT } from \'./constants.js\';\n{{/if}}\n\nconst createQueryBuilder = <T>(): QueryBuilder<T> => ({\n equal: (field, value) => Query.equal(String(field), value as any),\n notEqual: (field, value) => Query.notEqual(String(field), value as any),\n lessThan: (field, value) => Query.lessThan(String(field), value as any),\n lessThanEqual: (field, value) => Query.lessThanEqual(String(field), value as any),\n greaterThan: (field, value) => Query.greaterThan(String(field), value as any),\n greaterThanEqual: (field, value) => Query.greaterThanEqual(String(field), value as any),\n contains: (field, value) => Query.contains(String(field), value as any),\n search: (field, value) => Query.search(String(field), value),\n isNull: (field) => Query.isNull(String(field)),\n isNotNull: (field) => Query.isNotNull(String(field)),\n startsWith: (field, value) => Query.startsWith(String(field), value),\n endsWith: (field, value) => Query.endsWith(String(field), value),\n between: (field, start, end) => Query.between(String(field), start as any, end as any),\n select: (fields) => Query.select(fields.map(String)),\n orderAsc: (field) => Query.orderAsc(String(field)),\n orderDesc: (field) => Query.orderDesc(String(field)),\n limit: (value) => Query.limit(value),\n offset: (value) => Query.offset(value),\n cursorAfter: (documentId) => Query.cursorAfter(documentId),\n cursorBefore: (documentId) => Query.cursorBefore(documentId),\n or: (...queries) => Query.or(queries),\n and: (...queries) => Query.and(queries),\n});\n\n{{{TABLE_ID_MAP}}}\n\n{{{TABLES_WITH_RELATIONSHIPS}}}\n\nconst serializePermissions = (permissions?: Permission[]): string[] | undefined =>\n permissions?.map((permission) => permission.toString());\n\nfunction createTableApi<T extends Models.Row>(\n tablesDB: TablesDB,\n databaseId: string,\n tableId: string,\n) {\n return {\n create: (data: any, options?: { rowId?: string; permissions?: Permission[]; transactionId?: string }) =>\n tablesDB.createRow<T>({\n databaseId,\n tableId,\n rowId: options?.rowId ?? ID.unique(),\n data,\n permissions: serializePermissions(options?.permissions),\n transactionId: options?.transactionId,\n }),\n get: (id: string) =>\n tablesDB.getRow<T>({\n databaseId,\n tableId,\n rowId: id,\n }),\n update: (id: string, data: any, options?: { permissions?: Permission[]; transactionId?: string }) =>\n tablesDB.updateRow<T>({\n databaseId,\n tableId,\n rowId: id,\n data,\n ...(options?.permissions ? { permissions: serializePermissions(options.permissions) } : {}),\n transactionId: options?.transactionId,\n }),\n delete: async (id: string, options?: { transactionId?: string }) => {\n await tablesDB.deleteRow({\n databaseId,\n tableId,\n rowId: id,\n transactionId: options?.transactionId,\n });\n },\n list: (options?: { queries?: (q: any) => string[] }) =>\n tablesDB.listRows<T>({\n databaseId,\n tableId,\n queries: options?.queries?.(createQueryBuilder<T>()),\n }),{{{BULK_METHODS}}}\n };\n}\n\n{{{BULK_CHECK}}}\nconst hasOwn = (obj: unknown, key: string): boolean =>\n obj != null && Object.prototype.hasOwnProperty.call(obj, key);\n\nfunction createDatabaseHandle<D extends DatabaseId>(\n tablesDB: TablesDB,\n databaseId: D,\n): DatabaseHandle<D> {\n const tableApiCache = new Map<string, unknown>();\n const dbMap = tableIdMap[databaseId];\n\n return {\n use: <T extends keyof DatabaseTableMap[D] & string>(tableName: T): DatabaseTableMap[D][T] => {\n if (!hasOwn(dbMap, tableName)) {\n throw new Error(`Unknown table "${tableName}" in database "${databaseId}"`);\n }\n\n if (!tableApiCache.has(tableName)) {\n const tableId = dbMap[tableName];\n const api = createTableApi(tablesDB, databaseId, tableId);\n {{{BULK_REMOVAL}}}\n tableApiCache.set(tableName, api);\n }\n return tableApiCache.get(tableName) as DatabaseTableMap[D][T];\n },\n{{#if supportsServerSide}}\n create: (tableId: string, name: string, options?: { permissions?: Permission[]; rowSecurity?: boolean; enabled?: boolean; columns?: any[]; indexes?: any[] }) =>\n tablesDB.createTable({\n databaseId,\n tableId,\n name,\n permissions: serializePermissions(options?.permissions),\n rowSecurity: options?.rowSecurity,\n enabled: options?.enabled,\n columns: options?.columns,\n indexes: options?.indexes,\n }),\n update: (tableName: string, name: string, options?: { permissions?: Permission[]; rowSecurity?: boolean; enabled?: boolean }) => {\n if (!hasOwn(dbMap, tableName)) {\n throw new Error(`Unknown table "${tableName}" in database "${databaseId}"`);\n }\n const tableId = dbMap[tableName];\n return tablesDB.updateTable({\n databaseId,\n tableId,\n name,\n permissions: serializePermissions(options?.permissions),\n rowSecurity: options?.rowSecurity,\n enabled: options?.enabled,\n });\n },\n delete: async (tableName: string) => {\n if (!hasOwn(dbMap, tableName)) {\n throw new Error(`Unknown table "${tableName}" in database "${databaseId}"`);\n }\n const tableId = dbMap[tableName];\n await tablesDB.deleteTable({\n databaseId,\n tableId,\n });\n },\n{{/if}}\n };\n}\n\nfunction createDatabasesApi(tablesDB: TablesDB): DatabaseTables {\n const dbCache = new Map<DatabaseId, ReturnType<typeof createDatabaseHandle>>();\n\n return {\n use: (databaseId: DatabaseId) => {\n if (!hasOwn(tableIdMap, databaseId)) {\n throw new Error(`Unknown database "${databaseId}"`);\n }\n\n if (!dbCache.has(databaseId)) {\n dbCache.set(databaseId, createDatabaseHandle(tablesDB, databaseId));\n }\n return dbCache.get(databaseId);\n },\n{{#if supportsServerSide}}\n create: (databaseId: string, name: string, options?: { enabled?: boolean }) =>\n tablesDB.create({\n databaseId,\n name,\n enabled: options?.enabled,\n }),\n update: (databaseId: DatabaseId, name: string, options?: { enabled?: boolean }) =>\n tablesDB.update({\n databaseId,\n name,\n enabled: options?.enabled,\n }),\n delete: async (databaseId: DatabaseId) => {\n await tablesDB.delete({\n databaseId,\n });\n },\n{{/if}}\n } as DatabaseTables;\n}\n\n// Initialize client\nconst client = new Client()\n .setEndpoint(ENDPOINT)\n .setProject(PROJECT_ID){{#if supportsServerSide}}\n .setKey(API_KEY){{/if}};\n\nconst tablesDB = new TablesDB(client);\n\nexport const databases: DatabaseTables = createDatabasesApi(tablesDB);\n';
142179
+ var databases_ts_default = 'import { Client, TablesDB, ID, Query, type Models, Permission, Role } from \'{{appwriteDep}}\';\nimport type { DatabaseHandle, DatabaseId, DatabaseTableMap, DatabaseTables, QueryBuilder, PermissionBuilder, RoleBuilder, RoleString } from \'./types.js\';\n{{#if supportsServerSide}}\nimport { PROJECT_ID, ENDPOINT, API_KEY } from \'./constants.js\';\n{{else}}\nimport { PROJECT_ID, ENDPOINT } from \'./constants.js\';\n{{/if}}\n\nconst createQueryBuilder = <T>(): QueryBuilder<T> => ({\n equal: (field, value) => Query.equal(String(field), value as any),\n notEqual: (field, value) => Query.notEqual(String(field), value as any),\n lessThan: (field, value) => Query.lessThan(String(field), value as any),\n lessThanEqual: (field, value) => Query.lessThanEqual(String(field), value as any),\n greaterThan: (field, value) => Query.greaterThan(String(field), value as any),\n greaterThanEqual: (field, value) => Query.greaterThanEqual(String(field), value as any),\n contains: (field, value) => Query.contains(String(field), value as any),\n search: (field, value) => Query.search(String(field), value),\n isNull: (field) => Query.isNull(String(field)),\n isNotNull: (field) => Query.isNotNull(String(field)),\n startsWith: (field, value) => Query.startsWith(String(field), value),\n endsWith: (field, value) => Query.endsWith(String(field), value),\n between: (field, start, end) => Query.between(String(field), start as any, end as any),\n select: (fields) => Query.select(fields.map(String)),\n orderAsc: (field) => Query.orderAsc(String(field)),\n orderDesc: (field) => Query.orderDesc(String(field)),\n limit: (value) => Query.limit(value),\n offset: (value) => Query.offset(value),\n cursorAfter: (documentId) => Query.cursorAfter(documentId),\n cursorBefore: (documentId) => Query.cursorBefore(documentId),\n or: (...queries) => Query.or(queries),\n and: (...queries) => Query.and(queries),\n});\n\n{{{TABLE_ID_MAP}}}\n\n{{{TABLES_WITH_RELATIONSHIPS}}}\n\nconst roleBuilder: RoleBuilder = {\n any: () => Role.any() as RoleString,\n user: (userId, status?) => Role.user(userId, status) as RoleString,\n users: (status?) => Role.users(status) as RoleString,\n guests: () => Role.guests() as RoleString,\n team: (teamId, role?) => Role.team(teamId, role) as RoleString,\n member: (memberId) => Role.member(memberId) as RoleString,\n label: (label) => Role.label(label) as RoleString,\n};\n\nconst permissionBuilder: PermissionBuilder = {\n read: (role) => Permission.read(role),\n write: (role) => Permission.write(role),\n create: (role) => Permission.create(role),\n update: (role) => Permission.update(role),\n delete: (role) => Permission.delete(role),\n};\n\nconst resolvePermissions = (callback?: (permission: { read: (role: RoleString) => string; write: (role: RoleString) => string; create: (role: RoleString) => string; update: (role: RoleString) => string; delete: (role: RoleString) => string }, role: { any: () => RoleString; user: (userId: string, status?: string) => RoleString; users: (status?: string) => RoleString; guests: () => RoleString; team: (teamId: string, role?: string) => RoleString; member: (memberId: string) => RoleString; label: (label: string) => RoleString }) => string[]): string[] | undefined =>\n callback?.(permissionBuilder, roleBuilder);\n\nfunction createTableApi<T extends Models.Row>(\n tablesDB: TablesDB,\n databaseId: string,\n tableId: string,\n) {\n return {\n create: (data: any, options?: { rowId?: string; permissions?: (permission: { read: (role: RoleString) => string; write: (role: RoleString) => string; create: (role: RoleString) => string; update: (role: RoleString) => string; delete: (role: RoleString) => string }, role: { any: () => RoleString; user: (userId: string, status?: string) => RoleString; users: (status?: string) => RoleString; guests: () => RoleString; team: (teamId: string, role?: string) => RoleString; member: (memberId: string) => RoleString; label: (label: string) => RoleString }) => string[]; transactionId?: string }) =>\n tablesDB.createRow<T>({\n databaseId,\n tableId,\n rowId: options?.rowId ?? ID.unique(),\n data,\n permissions: resolvePermissions(options?.permissions),\n transactionId: options?.transactionId,\n }),\n get: (id: string) =>\n tablesDB.getRow<T>({\n databaseId,\n tableId,\n rowId: id,\n }),\n update: (id: string, data: any, options?: { permissions?: (permission: { read: (role: RoleString) => string; write: (role: RoleString) => string; create: (role: RoleString) => string; update: (role: RoleString) => string; delete: (role: RoleString) => string }, role: { any: () => RoleString; user: (userId: string, status?: string) => RoleString; users: (status?: string) => RoleString; guests: () => RoleString; team: (teamId: string, role?: string) => RoleString; member: (memberId: string) => RoleString; label: (label: string) => RoleString }) => string[]; transactionId?: string }) =>\n tablesDB.updateRow<T>({\n databaseId,\n tableId,\n rowId: id,\n data,\n ...(options?.permissions ? { permissions: resolvePermissions(options.permissions) } : {}),\n transactionId: options?.transactionId,\n }),\n delete: async (id: string, options?: { transactionId?: string }) => {\n await tablesDB.deleteRow({\n databaseId,\n tableId,\n rowId: id,\n transactionId: options?.transactionId,\n });\n },\n list: (options?: { queries?: (q: any) => string[] }) =>\n tablesDB.listRows<T>({\n databaseId,\n tableId,\n queries: options?.queries?.(createQueryBuilder<T>()),\n }),{{{BULK_METHODS}}}\n };\n}\n\n{{{BULK_CHECK}}}\nconst hasOwn = (obj: unknown, key: string): boolean =>\n obj != null && Object.prototype.hasOwnProperty.call(obj, key);\n\nfunction createDatabaseHandle<D extends DatabaseId>(\n tablesDB: TablesDB,\n databaseId: D,\n): DatabaseHandle<D> {\n const tableApiCache = new Map<string, unknown>();\n const dbMap = tableIdMap[databaseId];\n\n return {\n use: <T extends keyof DatabaseTableMap[D] & string>(tableId: T): DatabaseTableMap[D][T] => {\n if (!hasOwn(dbMap, tableId)) {\n throw new Error(`Unknown table "${tableId}" in database "${databaseId}"`);\n }\n\n if (!tableApiCache.has(tableId)) {\n const resolvedTableId = dbMap[tableId];\n const api = createTableApi(tablesDB, databaseId, resolvedTableId);\n {{{BULK_REMOVAL}}}\n tableApiCache.set(tableId, api);\n }\n return tableApiCache.get(tableId) as DatabaseTableMap[D][T];\n },\n{{#if supportsServerSide}}\n create: (tableId: string, name: string, options?: { permissions?: (permission: { read: (role: RoleString) => string; write: (role: RoleString) => string; create: (role: RoleString) => string; update: (role: RoleString) => string; delete: (role: RoleString) => string }, role: { any: () => RoleString; user: (userId: string, status?: string) => RoleString; users: (status?: string) => RoleString; guests: () => RoleString; team: (teamId: string, role?: string) => RoleString; member: (memberId: string) => RoleString; label: (label: string) => RoleString }) => string[]; rowSecurity?: boolean; enabled?: boolean; columns?: any[]; indexes?: any[] }) =>\n tablesDB.createTable({\n databaseId,\n tableId,\n name,\n permissions: resolvePermissions(options?.permissions),\n rowSecurity: options?.rowSecurity,\n enabled: options?.enabled,\n columns: options?.columns,\n indexes: options?.indexes,\n }),\n update: (tableId: string, options?: { name?: string; permissions?: (permission: { read: (role: RoleString) => string; write: (role: RoleString) => string; create: (role: RoleString) => string; update: (role: RoleString) => string; delete: (role: RoleString) => string }, role: { any: () => RoleString; user: (userId: string, status?: string) => RoleString; users: (status?: string) => RoleString; guests: () => RoleString; team: (teamId: string, role?: string) => RoleString; member: (memberId: string) => RoleString; label: (label: string) => RoleString }) => string[]; rowSecurity?: boolean; enabled?: boolean }) => {\n if (!hasOwn(dbMap, tableId)) {\n throw new Error(`Unknown table "${tableId}" in database "${databaseId}"`);\n }\n const resolvedTableId = dbMap[tableId];\n return tablesDB.updateTable({\n databaseId,\n tableId: resolvedTableId,\n name: options?.name ?? tableId, // TODO: remove this fallback once fixed in other SDKs\n permissions: resolvePermissions(options?.permissions),\n rowSecurity: options?.rowSecurity,\n enabled: options?.enabled,\n });\n },\n delete: async (tableId: string) => {\n if (!hasOwn(dbMap, tableId)) {\n throw new Error(`Unknown table "${tableId}" in database "${databaseId}"`);\n }\n const resolvedTableId = dbMap[tableId];\n await tablesDB.deleteTable({\n databaseId,\n tableId: resolvedTableId,\n });\n },\n{{/if}}\n };\n}\n\nfunction createDatabasesApi(tablesDB: TablesDB): DatabaseTables {\n const dbCache = new Map<DatabaseId, ReturnType<typeof createDatabaseHandle>>();\n\n return {\n use: (databaseId: DatabaseId) => {\n if (!hasOwn(tableIdMap, databaseId)) {\n throw new Error(`Unknown database "${databaseId}"`);\n }\n\n if (!dbCache.has(databaseId)) {\n dbCache.set(databaseId, createDatabaseHandle(tablesDB, databaseId));\n }\n return dbCache.get(databaseId);\n },\n{{#if supportsServerSide}}\n create: (databaseId: string, name: string, options?: { enabled?: boolean }) =>\n tablesDB.create({\n databaseId,\n name,\n enabled: options?.enabled,\n }),\n update: (databaseId: DatabaseId, options?: { name?: string; enabled?: boolean }) => {\n return tablesDB.update({\n databaseId,\n name: options?.name ?? databaseId,\n enabled: options?.enabled,\n });\n },\n delete: async (databaseId: DatabaseId) => {\n await tablesDB.delete({\n databaseId,\n });\n },\n{{/if}}\n } as DatabaseTables;\n}\n\n// Initialize client\nconst client = new Client()\n .setEndpoint(ENDPOINT)\n .setProject(PROJECT_ID){{#if supportsServerSide}}\n .setKey(API_KEY){{/if}};\n\nconst tablesDB = new TablesDB(client);\n\nexport const databases: DatabaseTables = createDatabasesApi(tablesDB);\n';
142185
142180
 
142186
142181
  // lib/commands/generators/typescript/templates/index.ts.hbs
142187
142182
  var index_ts_default = '/**\n * {{sdkTitle}} Generated SDK\n *\n * This file is auto-generated. Do not edit manually.\n * Re-run `{{executableName}} generate` to regenerate.\n */\n\nexport { databases } from "./databases.js";\nexport * from "./types.js";\n';
@@ -142194,6 +142189,8 @@ var typesTemplate = import_handlebars.default.compile(String(types_ts_default));
142194
142189
  var databasesTemplate = import_handlebars.default.compile(String(databases_ts_default));
142195
142190
  var indexTemplate = import_handlebars.default.compile(String(index_ts_default));
142196
142191
  var constantsTemplate = import_handlebars.default.compile(String(constants_ts_default));
142192
+ var PERMISSION_CALLBACK_INLINE = `(permission: { read: (role: RoleString) => string; write: (role: RoleString) => string; create: (role: RoleString) => string; update: (role: RoleString) => string; delete: (role: RoleString) => string }, role: { any: () => RoleString; user: (userId: string, status?: string) => RoleString; users: (status?: string) => RoleString; guests: () => RoleString; team: (teamId: string, role?: string) => RoleString; member: (memberId: string) => RoleString; label: (label: string) => RoleString }) => string[]`;
142193
+ var getQueryCallbackInline = (typeName) => `(q: { equal: <K extends QueryableKeys<${typeName}>>(field: K, value: ExtractQueryValue<${typeName}[K]>) => string; notEqual: <K extends QueryableKeys<${typeName}>>(field: K, value: ExtractQueryValue<${typeName}[K]>) => string; lessThan: <K extends QueryableKeys<${typeName}>>(field: K, value: ExtractQueryValue<${typeName}[K]>) => string; lessThanEqual: <K extends QueryableKeys<${typeName}>>(field: K, value: ExtractQueryValue<${typeName}[K]>) => string; greaterThan: <K extends QueryableKeys<${typeName}>>(field: K, value: ExtractQueryValue<${typeName}[K]>) => string; greaterThanEqual: <K extends QueryableKeys<${typeName}>>(field: K, value: ExtractQueryValue<${typeName}[K]>) => string; contains: <K extends QueryableKeys<${typeName}>>(field: K, value: ExtractQueryValue<${typeName}[K]>) => string; search: <K extends QueryableKeys<${typeName}>>(field: K, value: string) => string; isNull: <K extends QueryableKeys<${typeName}>>(field: K) => string; isNotNull: <K extends QueryableKeys<${typeName}>>(field: K) => string; startsWith: <K extends QueryableKeys<${typeName}>>(field: K, value: string) => string; endsWith: <K extends QueryableKeys<${typeName}>>(field: K, value: string) => string; between: <K extends QueryableKeys<${typeName}>>(field: K, start: ExtractQueryValue<${typeName}[K]>, end: ExtractQueryValue<${typeName}[K]>) => string; select: <K extends keyof ${typeName}>(fields: K[]) => string; orderAsc: <K extends keyof ${typeName}>(field: K) => string; orderDesc: <K extends keyof ${typeName}>(field: K) => string; limit: (value: number) => string; offset: (value: number) => string; cursorAfter: (documentId: string) => string; cursorBefore: (documentId: string) => string; or: (...queries: string[]) => string; and: (...queries: string[]) => string }) => string[]`;
142197
142194
  var TypeScriptDatabasesGenerator = class extends BaseDatabasesGenerator {
142198
142195
  language = "typescript";
142199
142196
  fileExtension = "ts";
@@ -142222,16 +142219,19 @@ var TypeScriptDatabasesGenerator = class extends BaseDatabasesGenerator {
142222
142219
  $id: e.$id,
142223
142220
  name: e.name
142224
142221
  }));
142225
- const attributes = this.buildAttributes(entity, typeEntities, " ");
142226
- const createType = attributes.trim().length === 0 ? `export type ${typeName}Create = Record<string, never>` : `export type ${typeName}Create = {
142227
- ${attributes}
142222
+ const createAttributes = this.buildAttributes(entity, typeEntities, " ", true);
142223
+ const rowAttributes = this.buildAttributes(entity, typeEntities, " ", false);
142224
+ const createType = createAttributes.trim().length === 0 ? `export type ${typeName}Create = Record<string, never>` : `export type ${typeName}Create = {
142225
+ ${createAttributes}
142226
+ }`;
142227
+ const rowType = rowAttributes.trim().length === 0 ? `export type ${typeName} = Models.Row` : `export type ${typeName} = Models.Row & {
142228
+ ${rowAttributes}
142228
142229
  }`;
142229
- const rowType = `export type ${typeName} = Models.Row & ${typeName}Create`;
142230
142230
  return `${createType}
142231
142231
 
142232
142232
  ${rowType}`;
142233
142233
  }
142234
- buildAttributes(entity, typeEntities, indent) {
142234
+ buildAttributes(entity, typeEntities, indent, forCreate = false) {
142235
142235
  const fields = this.getFields(entity);
142236
142236
  if (!fields) return "";
142237
142237
  return fields.map((attr) => {
@@ -142248,7 +142248,7 @@ ${rowType}`;
142248
142248
  relationType: attr.relationType,
142249
142249
  side: attr.side
142250
142250
  };
142251
- return `${indent}${JSON.stringify(attr.key)}${attr.required ? "" : "?"}: ${getTypeScriptType(typeAttr, typeEntities, entity.name)};`;
142251
+ return `${indent}${JSON.stringify(attr.key)}${attr.required ? "" : "?"}: ${getTypeScriptType(typeAttr, typeEntities, entity.name, forCreate)};`;
142252
142252
  }).join("\n");
142253
142253
  }
142254
142254
  generateEnums(entities) {
@@ -142301,21 +142301,24 @@ ${enumValues}
142301
142301
  const createFields = this.buildAttributes(
142302
142302
  entity,
142303
142303
  typeEntities,
142304
- " "
142304
+ " ",
142305
+ true
142306
+ // forCreate - relationships use Create suffix
142305
142307
  );
142306
142308
  const createInline = createFields.trim().length === 0 ? "Record<string, never>" : `{
142307
142309
  ${createFields}
142308
142310
  }`;
142309
- const baseMethods = ` create: (data: ${createInline}, options?: { rowId?: string; permissions?: Permission[]; transactionId?: string }) => Promise<${typeName}>;
142311
+ const queryCallback = getQueryCallbackInline(typeName);
142312
+ const baseMethods = ` create: (data: ${createInline}, options?: { rowId?: string; permissions?: ${PERMISSION_CALLBACK_INLINE}; transactionId?: string }) => Promise<${typeName}>;
142310
142313
  get: (id: string) => Promise<${typeName}>;
142311
- update: (id: string, data: Partial<${createInline}>, options?: { permissions?: Permission[]; transactionId?: string }) => Promise<${typeName}>;
142314
+ update: (id: string, data: Partial<${createInline}>, options?: { permissions?: ${PERMISSION_CALLBACK_INLINE}; transactionId?: string }) => Promise<${typeName}>;
142312
142315
  delete: (id: string, options?: { transactionId?: string }) => Promise<void>;
142313
- list: (options?: { queries?: (q: QueryBuilder<${typeName}>) => string[] }) => Promise<{ total: number; rows: ${typeName}[] }>;`;
142316
+ list: (options?: { queries?: ${queryCallback} }) => Promise<{ total: number; rows: ${typeName}[] }>;`;
142314
142317
  const canUseBulkMethods = supportsServerSide && !this.hasRelationshipColumns(entity);
142315
142318
  const bulkMethods = canUseBulkMethods ? `
142316
142319
  createMany: (rows: Array<${createInline} & { $id?: string; $permissions?: string[] }>, options?: { transactionId?: string }) => Promise<{ total: number; rows: ${typeName}[] }>;
142317
- updateMany: (data: Partial<${createInline}>, options?: { queries?: (q: QueryBuilder<${typeName}>) => string[]; transactionId?: string }) => Promise<{ total: number; rows: ${typeName}[] }>;
142318
- deleteMany: (options?: { queries?: (q: QueryBuilder<${typeName}>) => string[]; transactionId?: string }) => Promise<{ total: number; rows: ${typeName}[] }>;` : "";
142320
+ updateMany: (data: Partial<${createInline}>, options?: { queries?: ${queryCallback}; transactionId?: string }) => Promise<{ total: number; rows: ${typeName}[] }>;
142321
+ deleteMany: (options?: { queries?: ${queryCallback}; transactionId?: string }) => Promise<{ total: number; rows: ${typeName}[] }>;` : "";
142319
142322
  return ` ${JSON.stringify(entity.name)}: {
142320
142323
  ${baseMethods}${bulkMethods}
142321
142324
  }`;
@@ -142328,40 +142331,18 @@ ${tableTypes}
142328
142331
  ${dbReturnTypes}
142329
142332
  };
142330
142333
 
142331
- export type DatabaseCreateOptions = {
142332
- enabled?: boolean;
142333
- };
142334
-
142335
- export type DatabaseUpdateOptions = {
142336
- enabled?: boolean;
142337
- };
142338
-
142339
- export type TableCreateOptions = {
142340
- permissions?: Permission[];
142341
- rowSecurity?: boolean;
142342
- enabled?: boolean;
142343
- columns?: any[];
142344
- indexes?: any[];
142345
- };
142346
-
142347
- export type TableUpdateOptions = {
142348
- permissions?: Permission[];
142349
- rowSecurity?: boolean;
142350
- enabled?: boolean;
142351
- };
142352
-
142353
142334
  export type DatabaseHandle<D extends DatabaseId> = {
142354
- use: <T extends keyof DatabaseTableMap[D] & string>(tableName: T) => DatabaseTableMap[D][T];
142355
- ${supportsServerSide ? ` create: (tableId: string, name: string, options?: TableCreateOptions) => Promise<Models.Table>;
142356
- update: <T extends keyof DatabaseTableMap[D] & string>(tableName: T, name: string, options?: TableUpdateOptions) => Promise<Models.Table>;
142357
- delete: <T extends keyof DatabaseTableMap[D] & string>(tableName: T) => Promise<void>;` : ""}
142335
+ use: <T extends keyof DatabaseTableMap[D] & string>(tableId: T) => DatabaseTableMap[D][T];
142336
+ ${supportsServerSide ? ` create: (tableId: string, name: string, options?: { permissions?: ${PERMISSION_CALLBACK_INLINE}; rowSecurity?: boolean; enabled?: boolean; columns?: any[]; indexes?: any[] }) => Promise<Models.Table>;
142337
+ update: <T extends keyof DatabaseTableMap[D] & string>(tableId: T, options?: { name?: string; permissions?: ${PERMISSION_CALLBACK_INLINE}; rowSecurity?: boolean; enabled?: boolean }) => Promise<Models.Table>;
142338
+ delete: <T extends keyof DatabaseTableMap[D] & string>(tableId: T) => Promise<void>;` : ""}
142358
142339
  };
142359
142340
 
142360
142341
  export type DatabaseTables = {
142361
142342
  use: <D extends DatabaseId>(databaseId: D) => DatabaseHandle<D>;
142362
- ${supportsServerSide ? ` create: (databaseId: string, name: string, options?: DatabaseCreateOptions) => Promise<Models.Database>;
142363
- update: (databaseId: DatabaseId, name: string, options?: DatabaseUpdateOptions) => Promise<Models.Database>;
142364
- delete: (databaseId: DatabaseId) => Promise<void>;` : ""}
142343
+ ${supportsServerSide ? ` create: (databaseId: string, name: string, options?: { enabled?: boolean }) => Promise<Models.Database>;
142344
+ update: <D extends DatabaseId>(databaseId: D, options?: { name?: string; enabled?: boolean }) => Promise<Models.Database>;
142345
+ delete: <D extends DatabaseId>(databaseId: D) => Promise<void>;` : ""}
142365
142346
  };`;
142366
142347
  }
142367
142348
  generateTypesFile(config2) {
@@ -142444,14 +142425,14 @@ ${supportsServerSide ? ` create: (databaseId: string, name: string, options?: D
142444
142425
  }
142445
142426
  generateBulkCheck(supportsBulk) {
142446
142427
  if (!supportsBulk) return "";
142447
- return `const hasBulkMethods = (dbId: string, tableName: string) => !tablesWithRelationships.has(\`\${dbId}:\${tableName}\`);
142428
+ return `const hasBulkMethods = (dbId: string, tableId: string) => !tablesWithRelationships.has(\`\${dbId}:\${tableId}\`);
142448
142429
  `;
142449
142430
  }
142450
142431
  generateBulkRemoval(supportsBulk) {
142451
142432
  if (!supportsBulk) return "";
142452
142433
  return `
142453
142434
  // Remove bulk methods for tables with relationships
142454
- if (!hasBulkMethods(databaseId, tableName)) {
142435
+ if (!hasBulkMethods(databaseId, tableId)) {
142455
142436
  delete (api as any).createMany;
142456
142437
  delete (api as any).updateMany;
142457
142438
  delete (api as any).deleteMany;
@@ -142575,7 +142556,7 @@ var generateAction = async (options) => {
142575
142556
  let detectedLanguage;
142576
142557
  const serverSideOverride = options.server ?? "auto";
142577
142558
  if (!["auto", "true", "false"].includes(serverSideOverride)) {
142578
- error48(`Invalid --server-side value: ${serverSideOverride}`);
142559
+ error48(`Invalid --server value: ${serverSideOverride}`);
142579
142560
  process.exit(1);
142580
142561
  }
142581
142562
  if (options.language) {
@@ -142640,9 +142621,6 @@ Use --language to specify the target language. Supported: ${supported}`
142640
142621
  const firstEntity = entities?.[0];
142641
142622
  const dbId = firstEntity?.databaseId ?? "databaseId";
142642
142623
  const tableName = firstEntity?.name ?? "tableName";
142643
- const formatAccessor = (value) => /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(value) ? `.${value}` : `[${JSON.stringify(value)}]`;
142644
- const dbAccessor = formatAccessor(dbId);
142645
- const tableAccessor = formatAccessor(tableName);
142646
142624
  console.log("");
142647
142625
  log(`Import the generated SDK in your project:`);
142648
142626
  console.log(
@@ -142669,7 +142647,7 @@ var generate = new Command("generate").description(
142669
142647
  `Generate a type-safe SDK from your ${SDK_TITLE} project configuration`
142670
142648
  ).option(
142671
142649
  "-o, --output <directory>",
142672
- "Output directory for generated files (default: generated)",
142650
+ "Output directory for generated files",
142673
142651
  "generated"
142674
142652
  ).option(
142675
142653
  "-l, --language <language>",
@@ -142678,6 +142656,19 @@ var generate = new Command("generate").description(
142678
142656
  "--server <mode>",
142679
142657
  "Override server-side generation (auto|true|false)",
142680
142658
  "auto"
142659
+ ).addHelpText(
142660
+ "after",
142661
+ `
142662
+ Example:
142663
+ Import the generated SDK in your project:
142664
+ import { databases } from "./generated/${SDK_TITLE_LOWER}/index.js";
142665
+
142666
+ Configure your SDK constants:
142667
+ set values in ./generated/${SDK_TITLE_LOWER}/constants.ts
142668
+
142669
+ Usage:
142670
+ const mydb = databases.use("databaseId");
142671
+ await mydb.use("tableName").create({ ... });`
142681
142672
  ).action(actionRunner(generateAction));
142682
142673
 
142683
142674
  // lib/commands/services/account.ts