@statezero/core 0.2.12 → 0.2.14

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.
@@ -636,7 +636,8 @@ async function main() {
636
636
  console.log("Fetching action schemas from backends...");
637
637
  const fetchPromises = Object.values(backendConfigs).map(async (backend) => {
638
638
  try {
639
- const response = await axios.get(`${backend.API_URL}/actions-schema/`);
639
+ const headers = backend.SYNC_TOKEN ? { "X-Sync-Token": backend.SYNC_TOKEN } : {};
640
+ const response = await axios.get(`${backend.API_URL}/actions-schema/`, { headers });
640
641
  return { backend, actions: response.data.actions || {} };
641
642
  }
642
643
  catch (error) {
@@ -508,7 +508,8 @@ const dtsTemplate = Handlebars.compile(TS_DECLARATION_TEMPLATE);
508
508
  */
509
509
  async function generateSchemaForModel(backend, model) {
510
510
  const schemaUrl = `${backend.API_URL}/${model}/get-schema/`;
511
- const schemaResponse = await axios.get(schemaUrl);
511
+ const headers = backend.SYNC_TOKEN ? { "X-Sync-Token": backend.SYNC_TOKEN } : {};
512
+ const schemaResponse = await axios.get(schemaUrl, { headers });
512
513
  /** @type {SchemaDefinition} */
513
514
  let schema;
514
515
  if (schemaResponse.data.components?.schemas?.[model]) {
@@ -1038,7 +1039,8 @@ async function main() {
1038
1039
  const backend = backendConfigs[key];
1039
1040
  backend.NAME = key;
1040
1041
  try {
1041
- const response = await axios.get(`${backend.API_URL}/models/`);
1042
+ const headers = backend.SYNC_TOKEN ? { "X-Sync-Token": backend.SYNC_TOKEN } : {};
1043
+ const response = await axios.get(`${backend.API_URL}/models/`, { headers });
1042
1044
  return { backend, models: response.data };
1043
1045
  }
1044
1046
  catch (error) {
package/dist/config.js CHANGED
@@ -50,6 +50,7 @@ const backendSchema = z.object({
50
50
  }),
51
51
  GENERATED_ACTIONS_DIR: z.string().optional(),
52
52
  BACKEND_TZ: z.string().optional(),
53
+ SYNC_TOKEN: z.string().optional(),
53
54
  fileRootURL: z.string().url("fileRootURL must be a valid URL").optional(),
54
55
  fileUploadMode: z.enum(["server", "s3"]).default("server"),
55
56
  getAuthHeaders: z
@@ -96,6 +96,7 @@ function processFieldPath(fieldPath, value, ModelClass, options = {}) {
96
96
  // This is a relationship field
97
97
  const relationship = currentModel.relationshipFields.get(part);
98
98
  const relatedModel = relationship.ModelClass();
99
+ const relationshipType = relationship.relationshipType;
99
100
  // Add this relationship field to the path
100
101
  processedPath.push(part);
101
102
  // If this is not the last part, update the current model to the related model
@@ -104,13 +105,21 @@ function processFieldPath(fieldPath, value, ModelClass, options = {}) {
104
105
  }
105
106
  else {
106
107
  // This is the last part and it's a relationship
107
- // We need to add the primary key field of the related model
108
108
  isRelationship = true;
109
- // For foreign key relationships, we need to append the primary key field
110
- // to properly match Django's behavior
111
- const pkField = relatedModel.primaryKeyField || 'id';
112
- processedPath.push(pkField);
113
- finalFieldName = pkField;
109
+ // For many-to-many relationships, don't append the primary key field
110
+ // M2M fields store an array of PKs directly, not objects
111
+ if (relationshipType === 'many-to-many') {
112
+ // Keep path as-is (e.g., 'comprehensive_models')
113
+ // Sift will handle array membership check
114
+ finalFieldName = part;
115
+ }
116
+ else {
117
+ // For foreign key relationships, we need to append the primary key field
118
+ // to properly match Django's behavior
119
+ const pkField = relatedModel.primaryKeyField || 'id';
120
+ processedPath.push(pkField);
121
+ finalFieldName = pkField;
122
+ }
114
123
  currentModel = relatedModel;
115
124
  }
116
125
  }
@@ -905,6 +914,12 @@ export function pickRequiredFields(requiredPaths, instance) {
905
914
  // skip missing
906
915
  return;
907
916
  }
917
+ // Convert M2M arrays from Model instances to PKs for comparison
918
+ // This handles the case where the live representation returns [Model1, Model2]
919
+ // but we need [pk1, pk2] for sift filtering
920
+ if (Array.isArray(value) && value.length > 0 && value[0]?.pk !== undefined) {
921
+ value = value.map(item => item.pk);
922
+ }
908
923
  // Build nested structure in the result
909
924
  let cursor = result;
910
925
  parts.forEach((key, idx) => {
@@ -64,7 +64,7 @@ ComprehensiveModel.configKey = 'backend1';
64
64
  ComprehensiveModel.modelName = 'django_app.comprehensivemodel';
65
65
  ComprehensiveModel.primaryKeyField = 'id';
66
66
  ComprehensiveModel.objects = new ComprehensiveModelManager(ComprehensiveModel);
67
- ComprehensiveModel.fields = ['id', 'char_field', 'text_field', 'int_field', 'bool_field', 'datetime_field', 'decimal_field', 'json_field', 'money_field_currency', 'money_field', 'related'];
67
+ ComprehensiveModel.fields = ['id', 'char_field', 'text_field', 'int_field', 'bool_field', 'datetime_field', 'decimal_field', 'json_field', 'money_field_currency', 'money_field', 'nullable_money_field_currency', 'nullable_money_field', 'related'];
68
68
  ComprehensiveModel.schema = schemaData;
69
69
  ComprehensiveModel.relationshipFields = new Map([
70
70
  ['related', { 'ModelClass': () => getModelClass('django_app.deepmodellevel1', 'backend1'), 'relationshipType': 'foreign-key' }]
@@ -31,7 +31,10 @@ export class Order extends Model {
31
31
  static objects: OrderManager;
32
32
  static fields: string[];
33
33
  static schema: any;
34
- static relationshipFields: Map<any, any>;
34
+ static relationshipFields: Map<string, {
35
+ ModelClass: () => Function | null;
36
+ relationshipType: string;
37
+ }>;
35
38
  constructor(data: any);
36
39
  /**
37
40
  * Define property getters and setters for all model fields
@@ -64,6 +64,8 @@ Order.configKey = 'backend1';
64
64
  Order.modelName = 'django_app.order';
65
65
  Order.primaryKeyField = 'id';
66
66
  Order.objects = new OrderManager(Order);
67
- Order.fields = ['id', 'order_number', 'customer_name', 'customer_email', 'total', 'status', 'created_at', 'last_updated'];
67
+ Order.fields = ['id', 'order_number', 'customer_name', 'customer_email', 'total', 'status', 'created_at', 'last_updated', 'items'];
68
68
  Order.schema = schemaData;
69
- Order.relationshipFields = new Map([]);
69
+ Order.relationshipFields = new Map([
70
+ ['items', { 'ModelClass': () => getModelClass('django_app.orderitem', 'backend1'), 'relationshipType': 'many-to-many' }]
71
+ ]);
@@ -64,7 +64,7 @@ ComprehensiveModel.configKey = 'default';
64
64
  ComprehensiveModel.modelName = 'django_app.comprehensivemodel';
65
65
  ComprehensiveModel.primaryKeyField = 'id';
66
66
  ComprehensiveModel.objects = new ComprehensiveModelManager(ComprehensiveModel);
67
- ComprehensiveModel.fields = ['id', 'char_field', 'text_field', 'int_field', 'bool_field', 'datetime_field', 'decimal_field', 'json_field', 'money_field_currency', 'money_field', 'related'];
67
+ ComprehensiveModel.fields = ['id', 'char_field', 'text_field', 'int_field', 'bool_field', 'datetime_field', 'decimal_field', 'json_field', 'money_field_currency', 'money_field', 'nullable_money_field_currency', 'nullable_money_field', 'related'];
68
68
  ComprehensiveModel.schema = schemaData;
69
69
  ComprehensiveModel.relationshipFields = new Map([
70
70
  ['related', { 'ModelClass': () => getModelClass('django_app.deepmodellevel1', 'default'), 'relationshipType': 'foreign-key' }]
@@ -31,7 +31,10 @@ export class Order extends Model {
31
31
  static objects: OrderManager;
32
32
  static fields: string[];
33
33
  static schema: any;
34
- static relationshipFields: Map<any, any>;
34
+ static relationshipFields: Map<string, {
35
+ ModelClass: () => Function | null;
36
+ relationshipType: string;
37
+ }>;
35
38
  constructor(data: any);
36
39
  /**
37
40
  * Define property getters and setters for all model fields
@@ -64,6 +64,8 @@ Order.configKey = 'default';
64
64
  Order.modelName = 'django_app.order';
65
65
  Order.primaryKeyField = 'id';
66
66
  Order.objects = new OrderManager(Order);
67
- Order.fields = ['id', 'order_number', 'customer_name', 'customer_email', 'total', 'status', 'created_at', 'last_updated'];
67
+ Order.fields = ['id', 'order_number', 'customer_name', 'customer_email', 'total', 'status', 'created_at', 'last_updated', 'items'];
68
68
  Order.schema = schemaData;
69
- Order.relationshipFields = new Map([]);
69
+ Order.relationshipFields = new Map([
70
+ ['items', { 'ModelClass': () => getModelClass('django_app.orderitem', 'default'), 'relationshipType': 'many-to-many' }]
71
+ ]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@statezero/core",
3
- "version": "0.2.12",
3
+ "version": "0.2.14",
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",