@statezero/core 0.1.4 → 0.1.6

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.
@@ -159,7 +159,7 @@ const JS_MODEL_TEMPLATE = `/**
159
159
 
160
160
  import { Model, Manager, QuerySet, getModelClass } from '{{modulePath}}';
161
161
  import { wrapReactiveModel } from '{{modulePath}}';
162
- import schemaData from './{{className}}.schema.json';
162
+ import schemaData from './{{toLowerCase className}}.schema.json';
163
163
 
164
164
  /**
165
165
  * Model-specific QuerySet implementation
@@ -499,6 +499,9 @@ Handlebars.registerHelper("ifDefaultProvided", function (defaultValue, options)
499
499
  Handlebars.registerHelper("isRequired", function (required) {
500
500
  return required ? "" : "?";
501
501
  });
502
+ Handlebars.registerHelper("toLowerCase", function (str) {
503
+ return str.toLowerCase();
504
+ });
502
505
  const jsTemplate = Handlebars.compile(JS_MODEL_TEMPLATE);
503
506
  const dtsTemplate = Handlebars.compile(TS_DECLARATION_TEMPLATE);
504
507
  // --------------------
@@ -511,9 +514,8 @@ const dtsTemplate = Handlebars.compile(TS_DECLARATION_TEMPLATE);
511
514
  * @returns {Promise<{model: string, relativePath: string}>}
512
515
  */
513
516
  async function generateSchemaForModel(backend, model) {
514
- const authHeaders = backend.getAuthHeaders ? backend.getAuthHeaders() : {};
515
517
  const schemaUrl = `${backend.API_URL}/${model}/get-schema/`;
516
- const schemaResponse = await axios.get(schemaUrl, authHeaders);
518
+ const schemaResponse = await axios.get(schemaUrl);
517
519
  /** @type {SchemaDefinition} */
518
520
  let schema;
519
521
  if (schemaResponse.data.components?.schemas?.[model]) {
@@ -1008,10 +1010,7 @@ async function main() {
1008
1010
  const backend = backendConfigs[key];
1009
1011
  backend.NAME = key;
1010
1012
  try {
1011
- const authHeaders = backend.getAuthHeaders
1012
- ? backend.getAuthHeaders()
1013
- : {};
1014
- const response = await axios.get(`${backend.API_URL}/models/`, authHeaders);
1013
+ const response = await axios.get(`${backend.API_URL}/models/`);
1015
1014
  return { backend, models: response.data };
1016
1015
  }
1017
1016
  catch (error) {
@@ -1,10 +1,10 @@
1
- import { Manager } from './manager.js';
2
- import { ValidationError } from './errors.js';
3
- import { modelStoreRegistry } from '../../syncEngine/registries/modelStoreRegistry.js';
4
- import { isNil } from 'lodash-es';
5
- import { QueryExecutor } from './queryExecutor';
6
- import { wrapReactiveModel } from '../../reactiveAdaptor.js';
7
- import { DateParsingHelpers } from './dates.js';
1
+ import { Manager } from "./manager.js";
2
+ import { ValidationError } from "./errors.js";
3
+ import { modelStoreRegistry } from "../../syncEngine/registries/modelStoreRegistry.js";
4
+ import { isNil } from "lodash-es";
5
+ import { QueryExecutor } from "./queryExecutor";
6
+ import { wrapReactiveModel } from "../../reactiveAdaptor.js";
7
+ import { DateParsingHelpers } from "./dates.js";
8
8
  /**
9
9
  * A constructor for a Model.
10
10
  *
@@ -54,7 +54,7 @@ export class Model {
54
54
  * Instantiate from pk using queryset scoped singletons
55
55
  */
56
56
  static fromPk(pk, querySet) {
57
- let qsId = querySet ? querySet.__uuid : '';
57
+ let qsId = querySet ? querySet.__uuid : "";
58
58
  let key = `${qsId}__${this.configKey}__${this.modelName}__${pk}`;
59
59
  if (!this.instanceCache.has(key)) {
60
60
  const instance = new this();
@@ -90,15 +90,15 @@ export class Model {
90
90
  // footgun - fieldInfo.ModelClass() calls the arrow function that lazily gets the model class
91
91
  let relPkField = fieldInfo.ModelClass().primaryKeyField;
92
92
  switch (fieldInfo.relationshipType) {
93
- case 'many-to-many':
93
+ case "many-to-many":
94
94
  // value is an array
95
95
  if (!Array.isArray(value) && value)
96
96
  throw new Error(`Data corruption: m2m field for ${ModelClass.modelName} stored as ${value}`);
97
97
  // set each pk to the full model object for that pk
98
- value = value.map(pk => fieldInfo.ModelClass().fromPk(pk));
98
+ value = value.map((pk) => fieldInfo.ModelClass().fromPk(pk));
99
99
  break;
100
- case 'one-to-one':
101
- case 'foreign-key':
100
+ case "one-to-one":
101
+ case "foreign-key":
102
102
  // footgun - fieldInfo.ModelClass() calls the arrow function that lazily gets the model class
103
103
  if (!isNil(value))
104
104
  value = fieldInfo.ModelClass().fromPk(value);
@@ -135,13 +135,13 @@ export class Model {
135
135
  return;
136
136
  const allowedFields = this.fields;
137
137
  for (const key of Object.keys(data)) {
138
- if (key === 'repr' || key === 'type')
138
+ if (key === "repr" || key === "type")
139
139
  continue;
140
140
  // Handle nested fields by splitting on double underscore
141
141
  // and taking just the base field name
142
- const baseField = key.split('__')[0];
142
+ const baseField = key.split("__")[0];
143
143
  if (!allowedFields.includes(baseField)) {
144
- let errorMsg = `Invalid field: ${baseField}. Allowed fields are: ${allowedFields.join(', ')}`;
144
+ let errorMsg = `Invalid field: ${baseField}. Allowed fields are: ${allowedFields.join(", ")}`;
145
145
  console.error(errorMsg);
146
146
  throw new ValidationError(errorMsg);
147
147
  }
@@ -165,6 +165,18 @@ export class Model {
165
165
  if (storedValue)
166
166
  value = storedValue[field];
167
167
  }
168
+ if (ModelClass.relationshipFields &&
169
+ ModelClass.relationshipFields.has(field) &&
170
+ value) {
171
+ let fieldInfo = ModelClass.relationshipFields.get(field);
172
+ switch (fieldInfo.relationshipType) {
173
+ case "many-to-many":
174
+ return value.map((instance) => instance.pk ? instance.pk : instance);
175
+ case "one-to-one":
176
+ case "foreign-key":
177
+ return value.pk ? value.pk : value;
178
+ }
179
+ }
168
180
  return value;
169
181
  }
170
182
  /**
@@ -192,16 +204,20 @@ export class Model {
192
204
  async save() {
193
205
  const ModelClass = this.constructor;
194
206
  const pkField = ModelClass.primaryKeyField;
195
- const querySet = !this.pk ? ModelClass.objects.newQuerySet() : ModelClass.objects.filter({ [pkField]: this.pk });
207
+ const querySet = !this.pk
208
+ ? ModelClass.objects.newQuerySet()
209
+ : ModelClass.objects.filter({ [pkField]: this.pk });
196
210
  const data = this.serialize();
197
211
  let instance;
198
212
  if (!this.pk) {
199
213
  // Create new instance
200
- instance = await QueryExecutor.execute(querySet, 'create', { data });
214
+ instance = await QueryExecutor.execute(querySet, "create", { data });
201
215
  }
202
216
  else {
203
217
  // Update existing instance
204
- instance = await QueryExecutor.execute(querySet, 'update_instance', { data });
218
+ instance = await QueryExecutor.execute(querySet, "update_instance", {
219
+ data,
220
+ });
205
221
  }
206
222
  this._pk = instance.pk;
207
223
  this._data = {};
@@ -218,14 +234,14 @@ export class Model {
218
234
  */
219
235
  async delete() {
220
236
  if (!this.pk) {
221
- throw new Error('Cannot delete unsaved instance');
237
+ throw new Error("Cannot delete unsaved instance");
222
238
  }
223
239
  const ModelClass = this.constructor;
224
240
  const pkField = ModelClass.primaryKeyField;
225
241
  const querySet = ModelClass.objects.filter({ [pkField]: this.pk });
226
242
  // Pass the instance data with primary key as the args
227
243
  const args = { [pkField]: this.pk };
228
- const result = await QueryExecutor.execute(querySet, 'delete_instance', args);
244
+ const result = await QueryExecutor.execute(querySet, "delete_instance", args);
229
245
  // result -> [deletedCount, { [modelName]: deletedCount }];
230
246
  return result;
231
247
  }
@@ -237,10 +253,12 @@ export class Model {
237
253
  */
238
254
  async refreshFromDb() {
239
255
  if (!this.pk) {
240
- throw new Error('Cannot refresh unsaved instance');
256
+ throw new Error("Cannot refresh unsaved instance");
241
257
  }
242
258
  const ModelClass = this.constructor;
243
- const fresh = await ModelClass.objects.get({ [ModelClass.primaryKeyField]: this.pk });
259
+ const fresh = await ModelClass.objects.get({
260
+ [ModelClass.primaryKeyField]: this.pk,
261
+ });
244
262
  // clear the current data and fresh data will flow
245
263
  this._data = {};
246
264
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@statezero/core",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "type": "module",
5
5
  "module": "ESNext",
6
6
  "description": "The type-safe frontend client for StateZero - connect directly to your backend models with zero boilerplate",