@zenstackhq/sdk 3.0.0-alpha.0 → 3.0.0-alpha.10

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/dist/index.cjs CHANGED
@@ -318,9 +318,9 @@ var Model = class extends ContainerDeclaration {
318
318
  }
319
319
  name;
320
320
  isView;
321
- fields;
321
+ fields = [];
322
322
  constructor(name, isView, documentations = []) {
323
- super(documentations), this.name = name, this.isView = isView, this.fields = [];
323
+ super(documentations), this.name = name, this.isView = isView;
324
324
  }
325
325
  addField(name, type, attributes = [], documentations = [], addToFront = false) {
326
326
  const field = new ModelField(name, type, attributes, documentations);
@@ -540,9 +540,9 @@ var Enum = class extends ContainerDeclaration {
540
540
  __name(this, "Enum");
541
541
  }
542
542
  name;
543
- fields;
543
+ fields = [];
544
544
  constructor(name, documentations = []) {
545
- super(documentations), this.name = name, this.fields = [];
545
+ super(documentations), this.name = name;
546
546
  }
547
547
  addField(name, attributes = [], documentations = []) {
548
548
  const field = new EnumField(name, attributes, documentations);
@@ -591,15 +591,14 @@ var PrismaSchemaGenerator = class {
591
591
  __name(this, "PrismaSchemaGenerator");
592
592
  }
593
593
  zmodel;
594
- PRELUDE;
595
- constructor(zmodel) {
596
- this.zmodel = zmodel;
597
- this.PRELUDE = `//////////////////////////////////////////////////////////////////////////////////////////////
594
+ PRELUDE = `//////////////////////////////////////////////////////////////////////////////////////////////
598
595
  // DO NOT MODIFY THIS FILE //
599
596
  // This file is automatically generated by ZenStack CLI and should not be manually updated. //
600
597
  //////////////////////////////////////////////////////////////////////////////////////////////
601
598
 
602
599
  `;
600
+ constructor(zmodel) {
601
+ this.zmodel = zmodel;
603
602
  }
604
603
  async generate() {
605
604
  const prisma = new PrismaModel();
@@ -810,11 +809,11 @@ var PrismaSchemaGenerator = class {
810
809
  };
811
810
 
812
811
  // src/ts-schema-generator.ts
812
+ var import_common_helpers = require("@zenstackhq/common-helpers");
813
813
  var import_language = require("@zenstackhq/language");
814
814
  var import_ast3 = require("@zenstackhq/language/ast");
815
815
  var import_node_fs = __toESM(require("fs"), 1);
816
816
  var import_node_path = __toESM(require("path"), 1);
817
- var import_tiny_invariant = __toESM(require("tiny-invariant"), 1);
818
817
  var import_ts_pattern2 = require("ts-pattern");
819
818
  var ts = __toESM(require("typescript"), 1);
820
819
  var TsSchemaGenerator = class {
@@ -852,27 +851,6 @@ var TsSchemaGenerator = class {
852
851
  ts.factory.createImportSpecifier(false, void 0, ts.factory.createIdentifier("ExpressionUtils"))
853
852
  ])), ts.factory.createStringLiteral("@zenstackhq/runtime/schema"));
854
853
  statements.push(runtimeImportDecl);
855
- const { type: providerType } = this.getDataSourceProvider(model);
856
- switch (providerType) {
857
- case "sqlite": {
858
- const pathImportDecl = ts.factory.createImportDeclaration(void 0, ts.factory.createImportClause(false, ts.factory.createIdentifier("path"), void 0), ts.factory.createStringLiteral("node:path"));
859
- statements.push(pathImportDecl);
860
- const urlImportDecl = ts.factory.createImportDeclaration(void 0, ts.factory.createImportClause(false, ts.factory.createIdentifier("url"), void 0), ts.factory.createStringLiteral("node:url"));
861
- statements.push(urlImportDecl);
862
- const dialectConfigImportDecl = ts.factory.createImportDeclaration(void 0, ts.factory.createImportClause(false, void 0, ts.factory.createNamedImports([
863
- ts.factory.createImportSpecifier(false, void 0, ts.factory.createIdentifier("toDialectConfig"))
864
- ])), ts.factory.createStringLiteral("@zenstackhq/runtime/utils/sqlite-utils"));
865
- statements.push(dialectConfigImportDecl);
866
- break;
867
- }
868
- case "postgresql": {
869
- const dialectConfigImportDecl = ts.factory.createImportDeclaration(void 0, ts.factory.createImportClause(false, void 0, ts.factory.createNamedImports([
870
- ts.factory.createImportSpecifier(false, void 0, ts.factory.createIdentifier("toDialectConfig"))
871
- ])), ts.factory.createStringLiteral("@zenstackhq/runtime/utils/pg-utils"));
872
- statements.push(dialectConfigImportDecl);
873
- break;
874
- }
875
- }
876
854
  const declaration = ts.factory.createVariableStatement([
877
855
  ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)
878
856
  ], ts.factory.createVariableDeclarationList([
@@ -909,8 +887,7 @@ var TsSchemaGenerator = class {
909
887
  createProviderObject(model) {
910
888
  const dsProvider = this.getDataSourceProvider(model);
911
889
  return ts.factory.createObjectLiteralExpression([
912
- ts.factory.createPropertyAssignment("type", ts.factory.createStringLiteral(dsProvider.type)),
913
- ts.factory.createPropertyAssignment("dialectConfigProvider", this.createDialectConfigProvider(dsProvider))
890
+ ts.factory.createPropertyAssignment("type", ts.factory.createStringLiteral(dsProvider.type))
914
891
  ], true);
915
892
  }
916
893
  createModelsObject(model) {
@@ -937,19 +914,26 @@ var TsSchemaGenerator = class {
937
914
  }
938
915
  createComputedFieldsObject(fields) {
939
916
  return ts.factory.createObjectLiteralExpression(fields.map((field) => ts.factory.createMethodDeclaration(void 0, void 0, field.name, void 0, void 0, [], ts.factory.createTypeReferenceNode("OperandExpression", [
940
- ts.factory.createKeywordTypeNode(this.mapTypeToTSSyntaxKeyword(field.type.type))
917
+ ts.factory.createTypeReferenceNode(this.mapFieldTypeToTSType(field.type))
941
918
  ]), ts.factory.createBlock([
942
919
  ts.factory.createThrowStatement(ts.factory.createNewExpression(ts.factory.createIdentifier("Error"), void 0, [
943
920
  ts.factory.createStringLiteral("This is a stub for computed field")
944
921
  ]))
945
922
  ], true))), true);
946
923
  }
947
- mapTypeToTSSyntaxKeyword(type) {
948
- return (0, import_ts_pattern2.match)(type).with("String", () => ts.SyntaxKind.StringKeyword).with("Boolean", () => ts.SyntaxKind.BooleanKeyword).with("Int", () => ts.SyntaxKind.NumberKeyword).with("Float", () => ts.SyntaxKind.NumberKeyword).with("BigInt", () => ts.SyntaxKind.BigIntKeyword).with("Decimal", () => ts.SyntaxKind.NumberKeyword).otherwise(() => ts.SyntaxKind.UnknownKeyword);
924
+ mapFieldTypeToTSType(type) {
925
+ let result = (0, import_ts_pattern2.match)(type.type).with("String", () => "string").with("Boolean", () => "boolean").with("Int", () => "number").with("Float", () => "number").with("BigInt", () => "bigint").with("Decimal", () => "number").otherwise(() => "unknown");
926
+ if (type.array) {
927
+ result = `${result}[]`;
928
+ }
929
+ if (type.optional) {
930
+ result = `${result} | null`;
931
+ }
932
+ return result;
949
933
  }
950
934
  createDataModelFieldObject(field) {
951
935
  const objectFields = [
952
- ts.factory.createPropertyAssignment("type", ts.factory.createStringLiteral(field.type.type ?? field.type.reference.$refText))
936
+ ts.factory.createPropertyAssignment("type", this.generateFieldTypeLiteral(field))
953
937
  ];
954
938
  if (isIdField(field)) {
955
939
  objectFields.push(ts.factory.createPropertyAssignment("id", ts.factory.createTrue()));
@@ -969,9 +953,9 @@ var TsSchemaGenerator = class {
969
953
  if (field.attributes.length > 0) {
970
954
  objectFields.push(ts.factory.createPropertyAssignment("attributes", ts.factory.createArrayLiteralExpression(field.attributes.map((attr) => this.createAttributeObject(attr)))));
971
955
  }
972
- const defaultValue = this.getMappedDefault(field);
956
+ const defaultValue = this.getFieldMappedDefault(field);
973
957
  if (defaultValue !== void 0) {
974
- if (typeof defaultValue === "object") {
958
+ if (typeof defaultValue === "object" && !Array.isArray(defaultValue)) {
975
959
  if ("call" in defaultValue) {
976
960
  objectFields.push(ts.factory.createPropertyAssignment("default", ts.factory.createCallExpression(ts.factory.createIdentifier("ExpressionUtils.call"), void 0, [
977
961
  ts.factory.createStringLiteral(defaultValue.call),
@@ -990,7 +974,11 @@ var TsSchemaGenerator = class {
990
974
  throw new Error(`Unsupported default value type for field ${field.name}`);
991
975
  }
992
976
  } else {
993
- objectFields.push(ts.factory.createPropertyAssignment("default", typeof defaultValue === "string" ? ts.factory.createStringLiteral(defaultValue) : typeof defaultValue === "number" ? ts.factory.createNumericLiteral(defaultValue) : defaultValue === true ? ts.factory.createTrue() : ts.factory.createFalse()));
977
+ if (Array.isArray(defaultValue)) {
978
+ objectFields.push(ts.factory.createPropertyAssignment("default", ts.factory.createArrayLiteralExpression(defaultValue.map((item) => this.createLiteralNode(item)))));
979
+ } else {
980
+ objectFields.push(ts.factory.createPropertyAssignment("default", this.createLiteralNode(defaultValue)));
981
+ }
994
982
  }
995
983
  }
996
984
  if (hasAttribute(field, "@computed")) {
@@ -1007,12 +995,12 @@ var TsSchemaGenerator = class {
1007
995
  }
1008
996
  getDataSourceProvider(model) {
1009
997
  const dataSource = model.declarations.find(import_ast3.isDataSource);
1010
- (0, import_tiny_invariant.default)(dataSource, "No data source found in the model");
998
+ (0, import_common_helpers.invariant)(dataSource, "No data source found in the model");
1011
999
  const providerExpr = dataSource.fields.find((f) => f.name === "provider")?.value;
1012
- (0, import_tiny_invariant.default)((0, import_ast3.isLiteralExpr)(providerExpr), "Provider must be a literal");
1000
+ (0, import_common_helpers.invariant)((0, import_ast3.isLiteralExpr)(providerExpr), "Provider must be a literal");
1013
1001
  const type = providerExpr.value;
1014
1002
  const urlExpr = dataSource.fields.find((f) => f.name === "url")?.value;
1015
- (0, import_tiny_invariant.default)((0, import_ast3.isLiteralExpr)(urlExpr) || (0, import_ast3.isInvocationExpr)(urlExpr), "URL must be a literal or env function");
1003
+ (0, import_common_helpers.invariant)((0, import_ast3.isLiteralExpr)(urlExpr) || (0, import_ast3.isInvocationExpr)(urlExpr), "URL must be a literal or env function");
1016
1004
  if ((0, import_ast3.isLiteralExpr)(urlExpr)) {
1017
1005
  return {
1018
1006
  type,
@@ -1020,8 +1008,8 @@ var TsSchemaGenerator = class {
1020
1008
  env: void 0
1021
1009
  };
1022
1010
  } else if ((0, import_ast3.isInvocationExpr)(urlExpr)) {
1023
- (0, import_tiny_invariant.default)(urlExpr.function.$refText === "env", 'only "env" function is supported');
1024
- (0, import_tiny_invariant.default)(urlExpr.args.length === 1, "env function must have one argument");
1011
+ (0, import_common_helpers.invariant)(urlExpr.function.$refText === "env", 'only "env" function is supported');
1012
+ (0, import_common_helpers.invariant)(urlExpr.args.length === 1, "env function must have one argument");
1025
1013
  return {
1026
1014
  type,
1027
1015
  env: urlExpr.args[0].value.value,
@@ -1031,34 +1019,39 @@ var TsSchemaGenerator = class {
1031
1019
  throw new Error("Unsupported URL type");
1032
1020
  }
1033
1021
  }
1034
- getMappedDefault(field) {
1022
+ getFieldMappedDefault(field) {
1035
1023
  const defaultAttr = getAttribute(field, "@default");
1036
1024
  if (!defaultAttr) {
1037
1025
  return void 0;
1038
1026
  }
1039
1027
  const defaultValue = defaultAttr.args[0]?.value;
1040
- (0, import_tiny_invariant.default)(defaultValue, "Expected a default value");
1041
- if ((0, import_ast3.isLiteralExpr)(defaultValue)) {
1042
- const lit = defaultValue.value;
1043
- return field.type.type === "Boolean" ? lit : [
1028
+ (0, import_common_helpers.invariant)(defaultValue, "Expected a default value");
1029
+ return this.getMappedValue(defaultValue, field.type);
1030
+ }
1031
+ getMappedValue(expr, fieldType) {
1032
+ if ((0, import_ast3.isLiteralExpr)(expr)) {
1033
+ const lit = expr.value;
1034
+ return fieldType.type === "Boolean" ? lit : [
1044
1035
  "Int",
1045
1036
  "Float",
1046
1037
  "Decimal",
1047
1038
  "BigInt"
1048
- ].includes(field.type.type) ? Number(lit) : lit;
1049
- } else if ((0, import_ast3.isReferenceExpr)(defaultValue) && (0, import_ast3.isEnumField)(defaultValue.target.ref)) {
1050
- return defaultValue.target.ref.name;
1051
- } else if ((0, import_ast3.isInvocationExpr)(defaultValue)) {
1039
+ ].includes(fieldType.type) ? Number(lit) : lit;
1040
+ } else if ((0, import_ast3.isArrayExpr)(expr)) {
1041
+ return expr.items.map((item) => this.getMappedValue(item, fieldType));
1042
+ } else if ((0, import_ast3.isReferenceExpr)(expr) && (0, import_ast3.isEnumField)(expr.target.ref)) {
1043
+ return expr.target.ref.name;
1044
+ } else if ((0, import_ast3.isInvocationExpr)(expr)) {
1052
1045
  return {
1053
- call: defaultValue.function.$refText,
1054
- args: defaultValue.args.map((arg) => this.getLiteral(arg.value))
1046
+ call: expr.function.$refText,
1047
+ args: expr.args.map((arg) => this.getLiteral(arg.value))
1055
1048
  };
1056
- } else if (this.isAuthMemberAccess(defaultValue)) {
1049
+ } else if (this.isAuthMemberAccess(expr)) {
1057
1050
  return {
1058
- authMember: this.getMemberAccessChain(defaultValue)
1051
+ authMember: this.getMemberAccessChain(expr)
1059
1052
  };
1060
1053
  } else {
1061
- throw new Error(`Unsupported default value type for field ${field.name}`);
1054
+ throw new Error(`Unsupported default value type for ${expr.$type}`);
1062
1055
  }
1063
1056
  }
1064
1057
  getMemberAccessChain(expr) {
@@ -1157,7 +1150,7 @@ var TsSchemaGenerator = class {
1157
1150
  if (relation) {
1158
1151
  const nameArg = relation.args.find((arg) => arg.$resolvedParam.name === "name");
1159
1152
  if (nameArg) {
1160
- (0, import_tiny_invariant.default)((0, import_ast3.isLiteralExpr)(nameArg.value), "name must be a literal");
1153
+ (0, import_common_helpers.invariant)((0, import_ast3.isLiteralExpr)(nameArg.value), "name must be a literal");
1161
1154
  return nameArg.value.value;
1162
1155
  }
1163
1156
  }
@@ -1171,10 +1164,11 @@ var TsSchemaGenerator = class {
1171
1164
  for (const field of dm.fields) {
1172
1165
  if (hasAttribute(field, "@id") || hasAttribute(field, "@unique")) {
1173
1166
  properties.push(ts.factory.createPropertyAssignment(field.name, ts.factory.createObjectLiteralExpression([
1174
- ts.factory.createPropertyAssignment("type", ts.factory.createStringLiteral(field.type.type))
1167
+ ts.factory.createPropertyAssignment("type", this.generateFieldTypeLiteral(field))
1175
1168
  ])));
1176
1169
  }
1177
1170
  }
1171
+ const seenKeys = /* @__PURE__ */ new Set();
1178
1172
  for (const attr of dm.attributes) {
1179
1173
  if (attr.decl.$refText === "@@id" || attr.decl.$refText === "@@unique") {
1180
1174
  const fieldNames = this.getReferenceNames(attr.args[0].value);
@@ -1184,13 +1178,18 @@ var TsSchemaGenerator = class {
1184
1178
  if (fieldNames.length === 1) {
1185
1179
  const fieldDef = dm.fields.find((f) => f.name === fieldNames[0]);
1186
1180
  properties.push(ts.factory.createPropertyAssignment(fieldNames[0], ts.factory.createObjectLiteralExpression([
1187
- ts.factory.createPropertyAssignment("type", ts.factory.createStringLiteral(fieldDef.type.type))
1181
+ ts.factory.createPropertyAssignment("type", this.generateFieldTypeLiteral(fieldDef))
1188
1182
  ])));
1189
1183
  } else {
1184
+ const key = fieldNames.join("_");
1185
+ if (seenKeys.has(key)) {
1186
+ continue;
1187
+ }
1188
+ seenKeys.add(key);
1190
1189
  properties.push(ts.factory.createPropertyAssignment(fieldNames.join("_"), ts.factory.createObjectLiteralExpression(fieldNames.map((field) => {
1191
1190
  const fieldDef = dm.fields.find((f) => f.name === field);
1192
1191
  return ts.factory.createPropertyAssignment(field, ts.factory.createObjectLiteralExpression([
1193
- ts.factory.createPropertyAssignment("type", ts.factory.createStringLiteral(fieldDef.type.type))
1192
+ ts.factory.createPropertyAssignment("type", this.generateFieldTypeLiteral(fieldDef))
1194
1193
  ]));
1195
1194
  }))));
1196
1195
  }
@@ -1198,6 +1197,10 @@ var TsSchemaGenerator = class {
1198
1197
  }
1199
1198
  return ts.factory.createObjectLiteralExpression(properties, true);
1200
1199
  }
1200
+ generateFieldTypeLiteral(field) {
1201
+ (0, import_common_helpers.invariant)(field.type.type || field.type.reference || field.type.unsupported, "Field type must be a primitive, reference, or Unsupported");
1202
+ return field.type.type ? ts.factory.createStringLiteral(field.type.type) : field.type.reference ? ts.factory.createStringLiteral(field.type.reference.$refText) : ts.factory.createStringLiteral("Unsupported");
1203
+ }
1201
1204
  createEnumObject(e) {
1202
1205
  return ts.factory.createObjectLiteralExpression(e.fields.map((field) => ts.factory.createPropertyAssignment(field.name, ts.factory.createStringLiteral(field.name))), true);
1203
1206
  }
@@ -1218,44 +1221,6 @@ var TsSchemaGenerator = class {
1218
1221
  createLiteralNode(arg) {
1219
1222
  return arg === null ? ts.factory.createNull() : typeof arg === "string" ? ts.factory.createStringLiteral(arg) : typeof arg === "number" ? ts.factory.createNumericLiteral(arg) : arg === true ? ts.factory.createTrue() : arg === false ? ts.factory.createFalse() : void 0;
1220
1223
  }
1221
- createDialectConfigProvider(dsProvider) {
1222
- const type = dsProvider.type;
1223
- let urlExpr;
1224
- if (dsProvider.env !== void 0) {
1225
- urlExpr = ts.factory.createIdentifier(`process.env['${dsProvider.env}']`);
1226
- } else {
1227
- urlExpr = ts.factory.createStringLiteral(dsProvider.url);
1228
- if (type === "sqlite") {
1229
- let parsedUrl;
1230
- try {
1231
- parsedUrl = new URL(dsProvider.url);
1232
- } catch {
1233
- }
1234
- if (parsedUrl) {
1235
- if (parsedUrl.protocol !== "file:") {
1236
- throw new Error("Invalid SQLite URL: only file protocol is supported");
1237
- }
1238
- urlExpr = ts.factory.createStringLiteral(dsProvider.url.replace(/^file:/, ""));
1239
- }
1240
- }
1241
- }
1242
- return (0, import_ts_pattern2.match)(type).with("sqlite", () => {
1243
- return ts.factory.createFunctionExpression(void 0, void 0, void 0, void 0, void 0, void 0, ts.factory.createBlock([
1244
- ts.factory.createReturnStatement(ts.factory.createCallExpression(ts.factory.createIdentifier("toDialectConfig"), void 0, [
1245
- urlExpr,
1246
- ts.factory.createIdentifier(`typeof __dirname !== 'undefined' ? __dirname : path.dirname(url.fileURLToPath(import.meta.url))`)
1247
- ]))
1248
- ], true));
1249
- }).with("postgresql", () => {
1250
- return ts.factory.createFunctionExpression(void 0, void 0, void 0, void 0, void 0, void 0, ts.factory.createBlock([
1251
- ts.factory.createReturnStatement(ts.factory.createCallExpression(ts.factory.createIdentifier("toDialectConfig"), void 0, [
1252
- urlExpr
1253
- ]))
1254
- ], true));
1255
- }).otherwise(() => {
1256
- throw new Error(`Unsupported provider: ${type}`);
1257
- });
1258
- }
1259
1224
  createProceduresObject(procedures) {
1260
1225
  return ts.factory.createObjectLiteralExpression(procedures.map((proc) => ts.factory.createPropertyAssignment(proc.name, this.createProcedureObject(proc))), true);
1261
1226
  }
@@ -1290,6 +1255,8 @@ var TsSchemaGenerator = class {
1290
1255
  // This file is automatically generated by ZenStack CLI and should not be manually updated. //
1291
1256
  //////////////////////////////////////////////////////////////////////////////////////////////
1292
1257
 
1258
+ /* eslint-disable */
1259
+
1293
1260
  `;
1294
1261
  ts.addSyntheticLeadingComment(statements[0], ts.SyntaxKind.SingleLineCommentTrivia, banner);
1295
1262
  }