rads-db 0.1.28 → 0.1.31

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
@@ -17,10 +17,25 @@ function generateValidators(schema) {
17
17
  }
18
18
  const result = {};
19
19
  for (const key in zodSchemas) {
20
- result[key] = (value) => zodSchemas[key].parse(value);
20
+ result[key] = (value) => {
21
+ value = zodSchemas[key].parse(value);
22
+ fillDefaultValues(schema, key, value);
23
+ return value;
24
+ };
21
25
  }
22
26
  return result;
23
27
  }
28
+ function fillDefaultValues(schema, typeName, value) {
29
+ const type = schema[typeName];
30
+ if (!type)
31
+ return;
32
+ for (const fName in type.fields) {
33
+ const field = type.fields[fName];
34
+ if (field.defaultValueCopyFrom) {
35
+ value[fName] = ___default.cloneDeep(value[field.defaultValueCopyFrom]);
36
+ }
37
+ }
38
+ }
24
39
  function getZodSchema(zodSchemas, schema, key) {
25
40
  if (zodSchemas[key])
26
41
  return zodSchemas[key];
@@ -32,7 +47,8 @@ function getZodSchema(zodSchemas, schema, key) {
32
47
  const objectSchema = {};
33
48
  for (const fieldName in type.fields) {
34
49
  const shouldBeLazy = type.fields[fieldName].type === type.name;
35
- objectSchema[fieldName] = getFieldZodSchema(zodSchemas, schema, type.fields[fieldName], shouldBeLazy);
50
+ const f = type.fields[fieldName];
51
+ objectSchema[fieldName] = getFieldZodSchema(zodSchemas, schema, f, shouldBeLazy);
36
52
  }
37
53
  return zod.z.object(objectSchema);
38
54
  }
@@ -44,6 +60,8 @@ function getFieldZodSchema(zodSchemas, schema, field, shouldBeLazy) {
44
60
  fieldSchema = fieldSchema.optional();
45
61
  if (field.defaultValue !== void 0)
46
62
  fieldSchema = fieldSchema.default(field.defaultValue);
63
+ if (field.defaultValueCopyFrom !== void 0)
64
+ fieldSchema = fieldSchema.optional();
47
65
  return fieldSchema;
48
66
  }
49
67
  function getFieldZodSchemaBase(zodSchemas, schema, field, shouldBeLazy) {
@@ -65,8 +83,9 @@ function getFieldZodSchemaBase(zodSchemas, schema, field, shouldBeLazy) {
65
83
  if (schema[field.type]) {
66
84
  const getSchema = () => {
67
85
  let zodSchema = getZodSchema(zodSchemas, schema, field.type);
68
- if (schema[field.type].decorators.entity)
86
+ if (schema[field.type].decorators.entity) {
69
87
  zodSchema = zodSchema.deepPartial().required({ id: true });
88
+ }
70
89
  return zodSchema;
71
90
  };
72
91
  return shouldBeLazy ? zod.z.lazy(getSchema) : getSchema();
package/dist/index.d.ts CHANGED
@@ -113,6 +113,7 @@ interface FieldDefinition {
113
113
  name: string;
114
114
  type: string;
115
115
  defaultValue?: any;
116
+ defaultValueCopyFrom?: string;
116
117
  isRequired?: boolean;
117
118
  isArray?: boolean;
118
119
  comment?: string;
@@ -168,7 +169,7 @@ interface RadsRequestContext {
168
169
  declare function entity(meta?: EntityDecoratorArgs): (classConstructor: Function, _ctx?: ClassDecoratorContext<any>) => void;
169
170
  declare function field(meta?: FieldDecoratorArgs): (a: any, b?: ClassFieldDecoratorContext) => void;
170
171
  declare function precomputed(meta?: ComputedDecoratorArgs): (a: any, b?: ClassFieldDecoratorContext | ClassDecoratorContext) => void;
171
- declare function computed(meta?: ComputedDecoratorArgs): (a: any, b?: ClassFieldDecoratorContext) => void;
172
+ declare function computed(meta?: ComputedDecoratorArgs): (a: any, b?: ClassFieldDecoratorContext | ClassDecoratorContext) => void;
172
173
 
173
174
  declare function createRads(args?: CreateRadsArgs): RadsDb;
174
175
  declare function getRestRoutes(db: RadsDb, prefix?: string): Record<string, Record<string, Function>>;
package/dist/index.mjs CHANGED
@@ -11,10 +11,25 @@ function generateValidators(schema) {
11
11
  }
12
12
  const result = {};
13
13
  for (const key in zodSchemas) {
14
- result[key] = (value) => zodSchemas[key].parse(value);
14
+ result[key] = (value) => {
15
+ value = zodSchemas[key].parse(value);
16
+ fillDefaultValues(schema, key, value);
17
+ return value;
18
+ };
15
19
  }
16
20
  return result;
17
21
  }
22
+ function fillDefaultValues(schema, typeName, value) {
23
+ const type = schema[typeName];
24
+ if (!type)
25
+ return;
26
+ for (const fName in type.fields) {
27
+ const field = type.fields[fName];
28
+ if (field.defaultValueCopyFrom) {
29
+ value[fName] = _.cloneDeep(value[field.defaultValueCopyFrom]);
30
+ }
31
+ }
32
+ }
18
33
  function getZodSchema(zodSchemas, schema, key) {
19
34
  if (zodSchemas[key])
20
35
  return zodSchemas[key];
@@ -26,7 +41,8 @@ function getZodSchema(zodSchemas, schema, key) {
26
41
  const objectSchema = {};
27
42
  for (const fieldName in type.fields) {
28
43
  const shouldBeLazy = type.fields[fieldName].type === type.name;
29
- objectSchema[fieldName] = getFieldZodSchema(zodSchemas, schema, type.fields[fieldName], shouldBeLazy);
44
+ const f = type.fields[fieldName];
45
+ objectSchema[fieldName] = getFieldZodSchema(zodSchemas, schema, f, shouldBeLazy);
30
46
  }
31
47
  return z.object(objectSchema);
32
48
  }
@@ -38,6 +54,8 @@ function getFieldZodSchema(zodSchemas, schema, field, shouldBeLazy) {
38
54
  fieldSchema = fieldSchema.optional();
39
55
  if (field.defaultValue !== void 0)
40
56
  fieldSchema = fieldSchema.default(field.defaultValue);
57
+ if (field.defaultValueCopyFrom !== void 0)
58
+ fieldSchema = fieldSchema.optional();
41
59
  return fieldSchema;
42
60
  }
43
61
  function getFieldZodSchemaBase(zodSchemas, schema, field, shouldBeLazy) {
@@ -59,8 +77,9 @@ function getFieldZodSchemaBase(zodSchemas, schema, field, shouldBeLazy) {
59
77
  if (schema[field.type]) {
60
78
  const getSchema = () => {
61
79
  let zodSchema = getZodSchema(zodSchemas, schema, field.type);
62
- if (schema[field.type].decorators.entity)
80
+ if (schema[field.type].decorators.entity) {
63
81
  zodSchema = zodSchema.deepPartial().required({ id: true });
82
+ }
64
83
  return zodSchema;
65
84
  };
66
85
  return shouldBeLazy ? z.lazy(getSchema) : getSchema();
@@ -8,6 +8,7 @@ var _typescript = require("typescript");
8
8
  var _lodash = _interopRequireDefault(require("lodash"));
9
9
  var _pluralize = _interopRequireDefault(require("pluralize"));
10
10
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
+ const supportedPrimitiveTypes = ["string", "number", "boolean"];
11
12
  function parseSchema(typescriptFiles) {
12
13
  const result = {};
13
14
  const typesMap = {};
@@ -60,6 +61,37 @@ function parseSchema(typescriptFiles) {
60
61
  throw new Error(`Entity "${key}" must have an id`);
61
62
  }
62
63
  }
64
+ fillComputedDefinitionsForType(result);
65
+ processThisReferenceDefaultValues(result, typesMap);
66
+ return result;
67
+ }
68
+ function processThisReferenceDefaultValues(result, typesMap) {
69
+ for (const key in result) {
70
+ const type = result[key];
71
+ const fields = type.fields;
72
+ if (!fields) continue;
73
+ for (const fName in fields) {
74
+ const field = fields[fName];
75
+ if (field.defaultValueCopyFrom) {
76
+ const sourceField = fields[field.defaultValueCopyFrom];
77
+ if (!sourceField) throw new Error(`Cannot find field ${key}.${field.defaultValueCopyFrom}"`);
78
+ if (field.type === "thisReference") {
79
+ field.type = sourceField.type;
80
+ field.isArray = sourceField.isArray;
81
+ }
82
+ verifyDefaultValueType(field.isArray || false, {
83
+ type: sourceField.type,
84
+ value: sourceField.defaultValue
85
+ }, field.type, supportedPrimitiveTypes, {
86
+ typesMap,
87
+ result,
88
+ sourceFile: typesMap[key]?.sourceFile
89
+ });
90
+ }
91
+ }
92
+ }
93
+ }
94
+ function fillComputedDefinitionsForType(result) {
63
95
  for (const key in result) {
64
96
  const type = result[key];
65
97
  const fields = type.fields;
@@ -71,7 +103,6 @@ function parseSchema(typescriptFiles) {
71
103
  if (computedFields.length) type.computedFields = computedFields;
72
104
  if (nestedTypeFields.length) type.nestedTypeFields = nestedTypeFields;
73
105
  }
74
- return result;
75
106
  }
76
107
  function getOrder(f) {
77
108
  const decorator = f.decorators.computed || f.decorators.precomputed;
@@ -160,7 +191,15 @@ function getEnumValues(node, parentNode, ctx) {
160
191
  function parseClassMember(node, parentName, ctx) {
161
192
  const name = node.name.getText(ctx.sourceFile);
162
193
  const defaultValueDescription = parseLiteralNode(node.initializer, ctx);
163
- const defaultValue = defaultValueDescription?.value;
194
+ let defaultValue;
195
+ let defaultValueCopyFrom;
196
+ if (defaultValueDescription) {
197
+ if (defaultValueDescription.type === "thisReference") {
198
+ defaultValueCopyFrom = defaultValueDescription.value;
199
+ } else {
200
+ defaultValue = defaultValueDescription.value;
201
+ }
202
+ }
164
203
  const isRequired = !node.questionToken;
165
204
  const comment = node.jsDoc?.[0]?.comment;
166
205
  const decorators = parseDecorators(node.modifiers, ctx);
@@ -171,6 +210,7 @@ function parseClassMember(node, parentName, ctx) {
171
210
  const result = {
172
211
  type,
173
212
  defaultValue,
213
+ defaultValueCopyFrom,
174
214
  name,
175
215
  isRequired,
176
216
  isArray,
@@ -180,9 +220,8 @@ function parseClassMember(node, parentName, ctx) {
180
220
  return result;
181
221
  }
182
222
  function parseFieldType(ctx, parentName, fieldName, node, defaultValueDescription) {
183
- const supportedPrimitiveTypes = ["string", "number", "boolean"];
184
223
  let isArray = false;
185
- let nodeType = node.type;
224
+ let nodeType = node?.type;
186
225
  if (nodeType?.kind === _typescript.SyntaxKind.ArrayType) {
187
226
  isArray = true;
188
227
  nodeType = nodeType.elementType;
@@ -211,11 +250,11 @@ function parseFieldType(ctx, parentName, fieldName, node, defaultValueDescriptio
211
250
  const subType = type.slice(7, -1);
212
251
  if (!ctx.typesMap[subType]) throw new Error(`Unexpected property type: '${type}'`);
213
252
  } else {
214
- if (!supportedPrimitiveTypes.includes(type) && !ctx.typesMap[type]) {
253
+ if (!supportedPrimitiveTypes.includes(type) && !ctx.typesMap[type] && type !== "thisReference") {
215
254
  throw new Error(`Unexpected property type: '${type}'`);
216
255
  }
217
256
  }
218
- if (defaultValueDescription) {
257
+ if (defaultValueDescription && defaultValueDescription.type !== "thisReference") {
219
258
  verifyDefaultValueType(isArray, defaultValueDescription, type, supportedPrimitiveTypes, ctx);
220
259
  }
221
260
  return {
@@ -223,13 +262,13 @@ function parseFieldType(ctx, parentName, fieldName, node, defaultValueDescriptio
223
262
  type
224
263
  };
225
264
  }
226
- function verifyDefaultValueType(isArray, defaultValueDescription, type, supportedPrimitiveTypes, ctx) {
265
+ function verifyDefaultValueType(isArray, defaultValueDescription, type, supportedPrimitiveTypes2, ctx) {
227
266
  if (isArray) {
228
267
  if (defaultValueDescription.type !== "array") {
229
268
  throw new Error(`Default value type is different from field type: '${type}'`);
230
269
  }
231
270
  } else {
232
- if (supportedPrimitiveTypes.includes(type) && defaultValueDescription.type !== type) {
271
+ if (supportedPrimitiveTypes2.includes(type) && defaultValueDescription.type !== type) {
233
272
  throw new Error(`Default value type is different from field type: '${type}'`);
234
273
  }
235
274
  const enumValues = ctx.result[type]?.enumValues;
@@ -291,6 +330,12 @@ function parseLiteralNode(expr, ctx) {
291
330
  type: "array",
292
331
  value: []
293
332
  };
333
+ if (expr.kind === _typescript.SyntaxKind.PropertyAccessExpression && expr.expression.kind === _typescript.SyntaxKind.ThisKeyword) {
334
+ return {
335
+ type: "thisReference",
336
+ value: expr.name?.text
337
+ };
338
+ }
294
339
  throw new Error(`Unexpected property expression: "${expr.getText(ctx.sourceFile)}"`);
295
340
  }
296
341
  function parseObjectLiteral(arg, ctx) {
@@ -1,6 +1,7 @@
1
1
  import { ScriptTarget, SyntaxKind, createSourceFile } from "typescript";
2
2
  import _ from "lodash";
3
3
  import pluralize from "pluralize";
4
+ const supportedPrimitiveTypes = ["string", "number", "boolean"];
4
5
  export function parseSchema(typescriptFiles) {
5
6
  const result = {};
6
7
  const typesMap = {};
@@ -40,6 +41,38 @@ export function parseSchema(typescriptFiles) {
40
41
  throw new Error(`Entity "${key}" must have an id`);
41
42
  }
42
43
  }
44
+ fillComputedDefinitionsForType(result);
45
+ processThisReferenceDefaultValues(result, typesMap);
46
+ return result;
47
+ }
48
+ function processThisReferenceDefaultValues(result, typesMap) {
49
+ for (const key in result) {
50
+ const type = result[key];
51
+ const fields = type.fields;
52
+ if (!fields)
53
+ continue;
54
+ for (const fName in fields) {
55
+ const field = fields[fName];
56
+ if (field.defaultValueCopyFrom) {
57
+ const sourceField = fields[field.defaultValueCopyFrom];
58
+ if (!sourceField)
59
+ throw new Error(`Cannot find field ${key}.${field.defaultValueCopyFrom}"`);
60
+ if (field.type === "thisReference") {
61
+ field.type = sourceField.type;
62
+ field.isArray = sourceField.isArray;
63
+ }
64
+ verifyDefaultValueType(
65
+ field.isArray || false,
66
+ { type: sourceField.type, value: sourceField.defaultValue },
67
+ field.type,
68
+ supportedPrimitiveTypes,
69
+ { typesMap, result, sourceFile: typesMap[key]?.sourceFile }
70
+ );
71
+ }
72
+ }
73
+ }
74
+ }
75
+ function fillComputedDefinitionsForType(result) {
43
76
  for (const key in result) {
44
77
  const type = result[key];
45
78
  const fields = type.fields;
@@ -55,7 +88,6 @@ export function parseSchema(typescriptFiles) {
55
88
  if (nestedTypeFields.length)
56
89
  type.nestedTypeFields = nestedTypeFields;
57
90
  }
58
- return result;
59
91
  }
60
92
  function getOrder(f) {
61
93
  const decorator = f.decorators.computed || f.decorators.precomputed;
@@ -137,20 +169,27 @@ function getEnumValues(node, parentNode, ctx) {
137
169
  function parseClassMember(node, parentName, ctx) {
138
170
  const name = node.name.getText(ctx.sourceFile);
139
171
  const defaultValueDescription = parseLiteralNode(node.initializer, ctx);
140
- const defaultValue = defaultValueDescription?.value;
172
+ let defaultValue;
173
+ let defaultValueCopyFrom;
174
+ if (defaultValueDescription) {
175
+ if (defaultValueDescription.type === "thisReference") {
176
+ defaultValueCopyFrom = defaultValueDescription.value;
177
+ } else {
178
+ defaultValue = defaultValueDescription.value;
179
+ }
180
+ }
141
181
  const isRequired = !node.questionToken;
142
182
  const comment = node.jsDoc?.[0]?.comment;
143
183
  const decorators = parseDecorators(node.modifiers, ctx);
144
184
  const { isArray, type } = parseFieldType(ctx, parentName, name, node, defaultValueDescription);
145
- const result = { type, defaultValue, name, isRequired, isArray, comment };
185
+ const result = { type, defaultValue, defaultValueCopyFrom, name, isRequired, isArray, comment };
146
186
  if (!_.isEmpty(decorators))
147
187
  result.decorators = decorators;
148
188
  return result;
149
189
  }
150
190
  function parseFieldType(ctx, parentName, fieldName, node, defaultValueDescription) {
151
- const supportedPrimitiveTypes = ["string", "number", "boolean"];
152
191
  let isArray = false;
153
- let nodeType = node.type;
192
+ let nodeType = node?.type;
154
193
  if (nodeType?.kind === SyntaxKind.ArrayType) {
155
194
  isArray = true;
156
195
  nodeType = nodeType.elementType;
@@ -178,22 +217,22 @@ function parseFieldType(ctx, parentName, fieldName, node, defaultValueDescriptio
178
217
  if (!ctx.typesMap[subType])
179
218
  throw new Error(`Unexpected property type: '${type}'`);
180
219
  } else {
181
- if (!supportedPrimitiveTypes.includes(type) && !ctx.typesMap[type]) {
220
+ if (!supportedPrimitiveTypes.includes(type) && !ctx.typesMap[type] && type !== "thisReference") {
182
221
  throw new Error(`Unexpected property type: '${type}'`);
183
222
  }
184
223
  }
185
- if (defaultValueDescription) {
224
+ if (defaultValueDescription && defaultValueDescription.type !== "thisReference") {
186
225
  verifyDefaultValueType(isArray, defaultValueDescription, type, supportedPrimitiveTypes, ctx);
187
226
  }
188
227
  return { isArray, type };
189
228
  }
190
- function verifyDefaultValueType(isArray, defaultValueDescription, type, supportedPrimitiveTypes, ctx) {
229
+ function verifyDefaultValueType(isArray, defaultValueDescription, type, supportedPrimitiveTypes2, ctx) {
191
230
  if (isArray) {
192
231
  if (defaultValueDescription.type !== "array") {
193
232
  throw new Error(`Default value type is different from field type: '${type}'`);
194
233
  }
195
234
  } else {
196
- if (supportedPrimitiveTypes.includes(type) && defaultValueDescription.type !== type) {
235
+ if (supportedPrimitiveTypes2.includes(type) && defaultValueDescription.type !== type) {
197
236
  throw new Error(`Default value type is different from field type: '${type}'`);
198
237
  }
199
238
  const enumValues = ctx.result[type]?.enumValues;
@@ -242,6 +281,9 @@ function parseLiteralNode(expr, ctx) {
242
281
  return { type: "object", value: parseObjectLiteral(expr, ctx) };
243
282
  if (expr.kind === SyntaxKind.ArrayLiteralExpression)
244
283
  return { type: "array", value: [] };
284
+ if (expr.kind === SyntaxKind.PropertyAccessExpression && expr.expression.kind === SyntaxKind.ThisKeyword) {
285
+ return { type: "thisReference", value: expr.name?.text };
286
+ }
245
287
  throw new Error(`Unexpected property expression: "${expr.getText(ctx.sourceFile)}"`);
246
288
  }
247
289
  function parseObjectLiteral(arg, ctx) {
package/package.json CHANGED
@@ -28,7 +28,7 @@
28
28
  "require": "./integrations/*.cjs"
29
29
  }
30
30
  },
31
- "version": "0.1.28",
31
+ "version": "0.1.31",
32
32
  "description": "Say goodbye to boilerplate code and hello to efficient and elegant syntax.",
33
33
  "keywords": [],
34
34
  "author": "",