@basictech/schema 0.1.0 → 0.3.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,17 @@
1
1
  # @basictech/schema
2
2
 
3
+ ## 0.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - f9ad8d1: add compare func
8
+
9
+ ## 0.2.0
10
+
11
+ ### Minor Changes
12
+
13
+ - add compare schemas
14
+
3
15
  ## 0.1.0
4
16
 
5
17
  ### Minor Changes
package/README.md CHANGED
@@ -73,6 +73,19 @@ const result = validateUpdateSchema(oldSchema, newSchema)
73
73
  // Returns: { valid: boolean, errors?: any[], changes?: SchemaChange[], message?: string }
74
74
  ```
75
75
 
76
+ ### `compareSchemas(oldSchema: any, newSchema: any)`
77
+
78
+ Compares two schemas and returns the changes between them.
79
+
80
+ **Parameters:**
81
+ - `oldSchema` (required): The original schema
82
+ - `newSchema` (required): The updated schema to compare against
83
+
84
+ ```typescript
85
+ const result = compareSchemas(oldSchema, newSchema)
86
+ // Returns: { valid: boolean, changes?: SchemaChange[] }
87
+ ```
88
+
76
89
  ## Schema Structure
77
90
 
78
91
  A valid Basic schema follows this structure:
package/dist/index.d.mts CHANGED
@@ -1,26 +1,57 @@
1
- import { ErrorObject } from 'ajv';
2
-
3
1
  declare function generateEmptySchema(project_id?: string, version?: number): {
4
2
  project_id: string;
5
3
  version: number;
6
4
  tables: {
7
- fields: {
8
- example: {
9
- type: string;
5
+ foo: {
6
+ name: string;
7
+ type: string;
8
+ fields: {
9
+ bar: {
10
+ type: string;
11
+ required: boolean;
12
+ };
10
13
  };
11
14
  };
12
15
  };
13
16
  };
17
+ type Schema = {
18
+ project_id: string;
19
+ version: number;
20
+ tables: any;
21
+ };
22
+ /**
23
+ * Compare two schemas and detect any differences between them
24
+ * @param oldSchema - The original schema to compare against
25
+ * @param newSchema - The new schema to compare with the original
26
+ * @returns {Object} Comparison result containing:
27
+ * - valid: boolean indicating if schemas are identical
28
+ * - changes: Array of detected changes between schemas
29
+ */
30
+ declare function compareSchemas(oldSchema: any, newSchema: any): {
31
+ valid: boolean;
32
+ changes: SchemaChange[];
33
+ };
14
34
  /**
15
35
  * Validate a schema
16
36
  * only checks if the schema is formatted correctly, not if can be published
17
37
  * @param schema - The schema to validate
18
38
  * @returns {valid: boolean, errors: any[]} - The validation result
19
39
  */
20
- declare function validateSchema(schema: any): {
40
+ declare function validateSchema(schema: Schema): {
21
41
  valid: boolean;
22
42
  errors: ErrorObject[];
23
43
  };
44
+ type ErrorObject = {
45
+ keyword?: string;
46
+ instancePath?: string;
47
+ schemaPath?: string;
48
+ params?: Record<string, any>;
49
+ propertyName?: string;
50
+ message?: string;
51
+ schema?: any;
52
+ parentSchema?: any;
53
+ data?: any;
54
+ };
24
55
  /**
25
56
  * Validate data against a schema's table definition. Only checks against provided schema.
26
57
  * @param schema - The schema to validate against
@@ -32,20 +63,10 @@ declare function validateSchema(schema: any): {
32
63
  * - errors: Array of validation error objects
33
64
  * - message: Error message if validation failed
34
65
  */
35
- declare function validateData(schema: any, table: string, data: Record<string, any>, checkRequired?: boolean): {
36
- valid: boolean;
37
- errors: ErrorObject<string, Record<string, any>, unknown>[];
38
- message: string;
39
- } | {
40
- valid: boolean;
41
- errors: {
42
- message: string;
43
- }[];
44
- message: string;
45
- } | {
66
+ declare function validateData(schema: Schema, table: string, data: Record<string, any>, checkRequired?: boolean): {
46
67
  valid: boolean;
47
- errors: never[];
48
- message?: undefined;
68
+ errors?: ErrorObject[];
69
+ message?: string;
49
70
  };
50
71
  type SchemaChangeType = "property_changed" | "property_removed" | "table_added" | "table_removed" | "field_added" | "field_removed" | "field_type_changed" | "field_required_changed" | "field_property_added" | "field_property_changed" | "field_property_removed";
51
72
  type SchemaChange = {
@@ -58,15 +79,7 @@ type SchemaChange = {
58
79
  };
59
80
  declare function validateUpdateSchema(oldSchema: any, newSchema: any): {
60
81
  valid: boolean;
61
- errors: ErrorObject<string, Record<string, any>, unknown>[];
62
- message: string;
63
- changes?: undefined;
64
- } | {
65
- valid: boolean;
66
- errors: {
67
- change: SchemaChange;
68
- message: string;
69
- }[];
82
+ errors: ErrorObject[];
70
83
  message: string;
71
84
  changes?: undefined;
72
85
  } | {
@@ -76,11 +89,4 @@ declare function validateUpdateSchema(oldSchema: any, newSchema: any): {
76
89
  message?: undefined;
77
90
  };
78
91
 
79
- declare const schema: {
80
- validateSchema: typeof validateSchema;
81
- validateData: typeof validateData;
82
- generateEmptySchema: typeof generateEmptySchema;
83
- validateUpdateSchema: typeof validateUpdateSchema;
84
- };
85
-
86
- export { schema as default, generateEmptySchema, validateData, validateSchema, validateUpdateSchema };
92
+ export { compareSchemas, generateEmptySchema, validateData, validateSchema, validateUpdateSchema };
package/dist/index.d.ts CHANGED
@@ -1,26 +1,57 @@
1
- import { ErrorObject } from 'ajv';
2
-
3
1
  declare function generateEmptySchema(project_id?: string, version?: number): {
4
2
  project_id: string;
5
3
  version: number;
6
4
  tables: {
7
- fields: {
8
- example: {
9
- type: string;
5
+ foo: {
6
+ name: string;
7
+ type: string;
8
+ fields: {
9
+ bar: {
10
+ type: string;
11
+ required: boolean;
12
+ };
10
13
  };
11
14
  };
12
15
  };
13
16
  };
17
+ type Schema = {
18
+ project_id: string;
19
+ version: number;
20
+ tables: any;
21
+ };
22
+ /**
23
+ * Compare two schemas and detect any differences between them
24
+ * @param oldSchema - The original schema to compare against
25
+ * @param newSchema - The new schema to compare with the original
26
+ * @returns {Object} Comparison result containing:
27
+ * - valid: boolean indicating if schemas are identical
28
+ * - changes: Array of detected changes between schemas
29
+ */
30
+ declare function compareSchemas(oldSchema: any, newSchema: any): {
31
+ valid: boolean;
32
+ changes: SchemaChange[];
33
+ };
14
34
  /**
15
35
  * Validate a schema
16
36
  * only checks if the schema is formatted correctly, not if can be published
17
37
  * @param schema - The schema to validate
18
38
  * @returns {valid: boolean, errors: any[]} - The validation result
19
39
  */
20
- declare function validateSchema(schema: any): {
40
+ declare function validateSchema(schema: Schema): {
21
41
  valid: boolean;
22
42
  errors: ErrorObject[];
23
43
  };
44
+ type ErrorObject = {
45
+ keyword?: string;
46
+ instancePath?: string;
47
+ schemaPath?: string;
48
+ params?: Record<string, any>;
49
+ propertyName?: string;
50
+ message?: string;
51
+ schema?: any;
52
+ parentSchema?: any;
53
+ data?: any;
54
+ };
24
55
  /**
25
56
  * Validate data against a schema's table definition. Only checks against provided schema.
26
57
  * @param schema - The schema to validate against
@@ -32,20 +63,10 @@ declare function validateSchema(schema: any): {
32
63
  * - errors: Array of validation error objects
33
64
  * - message: Error message if validation failed
34
65
  */
35
- declare function validateData(schema: any, table: string, data: Record<string, any>, checkRequired?: boolean): {
36
- valid: boolean;
37
- errors: ErrorObject<string, Record<string, any>, unknown>[];
38
- message: string;
39
- } | {
40
- valid: boolean;
41
- errors: {
42
- message: string;
43
- }[];
44
- message: string;
45
- } | {
66
+ declare function validateData(schema: Schema, table: string, data: Record<string, any>, checkRequired?: boolean): {
46
67
  valid: boolean;
47
- errors: never[];
48
- message?: undefined;
68
+ errors?: ErrorObject[];
69
+ message?: string;
49
70
  };
50
71
  type SchemaChangeType = "property_changed" | "property_removed" | "table_added" | "table_removed" | "field_added" | "field_removed" | "field_type_changed" | "field_required_changed" | "field_property_added" | "field_property_changed" | "field_property_removed";
51
72
  type SchemaChange = {
@@ -58,15 +79,7 @@ type SchemaChange = {
58
79
  };
59
80
  declare function validateUpdateSchema(oldSchema: any, newSchema: any): {
60
81
  valid: boolean;
61
- errors: ErrorObject<string, Record<string, any>, unknown>[];
62
- message: string;
63
- changes?: undefined;
64
- } | {
65
- valid: boolean;
66
- errors: {
67
- change: SchemaChange;
68
- message: string;
69
- }[];
82
+ errors: ErrorObject[];
70
83
  message: string;
71
84
  changes?: undefined;
72
85
  } | {
@@ -76,11 +89,4 @@ declare function validateUpdateSchema(oldSchema: any, newSchema: any): {
76
89
  message?: undefined;
77
90
  };
78
91
 
79
- declare const schema: {
80
- validateSchema: typeof validateSchema;
81
- validateData: typeof validateData;
82
- generateEmptySchema: typeof generateEmptySchema;
83
- validateUpdateSchema: typeof validateUpdateSchema;
84
- };
85
-
86
- export { schema as default, generateEmptySchema, validateData, validateSchema, validateUpdateSchema };
92
+ export { compareSchemas, generateEmptySchema, validateData, validateSchema, validateUpdateSchema };
package/dist/index.js CHANGED
@@ -30,7 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // index.ts
31
31
  var schema_exports = {};
32
32
  __export(schema_exports, {
33
- default: () => schema_default,
33
+ compareSchemas: () => compareSchemas,
34
34
  generateEmptySchema: () => generateEmptySchema,
35
35
  validateData: () => validateData,
36
36
  validateSchema: () => validateSchema,
@@ -54,9 +54,21 @@ var basicJsonSchema = {
54
54
  },
55
55
  "tables": {
56
56
  "type": "object",
57
+ "propertyNames": {
58
+ "pattern": "^[a-zA-Z0-9_]+$",
59
+ "minLength": 1,
60
+ "maxLength": 50,
61
+ "type": "string"
62
+ },
57
63
  "patternProperties": {
58
64
  "^[a-zA-Z0-9_]+$": {
59
65
  "type": "object",
66
+ "propertyNames": {
67
+ "pattern": "^[a-zA-Z0-9_]+$",
68
+ "minLength": 1,
69
+ "maxLength": 50,
70
+ "type": "string"
71
+ },
60
72
  "properties": {
61
73
  "name": {
62
74
  "type": "string"
@@ -67,6 +79,12 @@ var basicJsonSchema = {
67
79
  },
68
80
  "fields": {
69
81
  "type": "object",
82
+ "propertyNames": {
83
+ "pattern": "^[a-zA-Z0-9_]+$",
84
+ "minLength": 1,
85
+ "maxLength": 50,
86
+ "type": "string"
87
+ },
70
88
  "patternProperties": {
71
89
  "^[a-zA-Z0-9_]+$": {
72
90
  "type": "object",
@@ -103,27 +121,37 @@ function generateEmptySchema(project_id = "", version = 0) {
103
121
  project_id,
104
122
  version,
105
123
  tables: {
106
- fields: {
107
- example: {
108
- type: "string"
124
+ foo: {
125
+ name: "foo",
126
+ type: "collection",
127
+ fields: {
128
+ bar: {
129
+ type: "string",
130
+ required: true
131
+ }
109
132
  }
110
133
  }
111
134
  }
112
135
  };
113
136
  }
114
- function validateSchema(schema2) {
115
- const v = validator(schema2);
137
+ function compareSchemas(oldSchema, newSchema) {
138
+ const changes = _getSchemaChanges(oldSchema, newSchema);
139
+ const valid = changes.length === 0 ? true : false;
140
+ return { valid, changes };
141
+ }
142
+ function validateSchema(schema) {
143
+ const v = validator(schema);
116
144
  return {
117
145
  valid: v,
118
146
  errors: validator.errors || []
119
147
  };
120
148
  }
121
- function validateData(schema2, table, data, checkRequired = true) {
122
- const valid = validateSchema(schema2);
149
+ function validateData(schema, table, data, checkRequired = true) {
150
+ const valid = validateSchema(schema);
123
151
  if (!valid.valid) {
124
152
  return { valid: false, errors: valid.errors, message: "Schema is invalid" };
125
153
  }
126
- const tableSchema = schema2.tables[table];
154
+ const tableSchema = schema.tables[table];
127
155
  if (!tableSchema) {
128
156
  return { valid: false, errors: [{ message: `Table ${table} not found in schema` }], message: "Table not found" };
129
157
  }
@@ -324,15 +352,9 @@ function validateUpdateSchema(oldSchema, newSchema) {
324
352
  }
325
353
  return { valid: true, changes };
326
354
  }
327
- var schema = {
328
- validateSchema,
329
- validateData,
330
- generateEmptySchema,
331
- validateUpdateSchema
332
- };
333
- var schema_default = schema;
334
355
  // Annotate the CommonJS export names for ESM import in node:
335
356
  0 && (module.exports = {
357
+ compareSchemas,
336
358
  generateEmptySchema,
337
359
  validateData,
338
360
  validateSchema,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../index.ts"],"sourcesContent":["// Basic Schema Library\n// utils for validating and interacting with Basic schemas\nimport Ajv, { ErrorObject } from 'ajv'\n\nconst basicJsonSchema = {\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"type\": \"object\",\n \"properties\": {\n \"project_id\": {\n \"type\": \"string\"\n },\n \"namespace\": {\n \"type\": \"string\",\n },\n \"version\": {\n \"type\": \"integer\",\n \"minimum\": 0\n },\n \"tables\": {\n \"type\": \"object\",\n \"patternProperties\": {\n \"^[a-zA-Z0-9_]+$\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"type\": {\n \"type\": \"string\",\n \"enum\": [\"collection\"]\n },\n \"fields\": {\n \"type\": \"object\",\n \"patternProperties\": {\n \"^[a-zA-Z0-9_]+$\": {\n \"type\": \"object\",\n \"properties\": {\n \"type\": {\n \"type\": \"string\",\n \"enum\": [\"string\", \"boolean\", \"number\", \"json\"]\n },\n \"indexed\": {\n \"type\": \"boolean\"\n }, \n \"required\": {\n \"type\": \"boolean\"\n }\n },\n \"required\": [\"type\"]\n }\n },\n \"additionalProperties\": true\n }\n },\n \"required\": [\"fields\"]\n }\n },\n \"additionalProperties\": true\n }\n },\n \"required\": [\"project_id\", \"version\", \"tables\"]\n }\n\nconst ajv = new Ajv()\nconst validator = ajv.compile(basicJsonSchema)\n\n\nfunction generateEmptySchema(project_id: string = \"\", version: number = 0) {\n return {\n project_id: project_id,\n version: version,\n tables: {\n fields: {\n example: { \n type: \"string\",\n }\n }\n }\n }\n}\n\ntype Schema = { \n project_id : string,\n version : number,\n tables : any\n}\n\n\n/**\n * Validate a schema\n * only checks if the schema is formatted correctly, not if can be published\n * @param schema - The schema to validate\n * @returns {valid: boolean, errors: any[]} - The validation result\n */\nfunction validateSchema(schema: any) : {valid: boolean, errors: ErrorObject[]} {\n const v = validator(schema)\n return { \n valid: v,\n errors: validator.errors || []\n }\n}\n\n// type ErrorObject = {\n// keyword: string;\n// instancePath: string; \n// schemaPath: string;\n// params: Record<string, any>;\n// propertyName?: string;\n// message?: string;\n// schema?: any;\n// parentSchema?: any;\n// data?: any;\n// }\n\n\n/**\n * Validate data against a schema's table definition. Only checks against provided schema.\n * @param schema - The schema to validate against\n * @param table - The table name in the schema to validate against\n * @param data - The data object to validate\n * @param checkRequired - Whether to check if required fields are present (default: true)\n * @returns {Object} Validation result containing:\n * - valid: boolean indicating if validation passed\n * - errors: Array of validation error objects\n * - message: Error message if validation failed\n */\n\nfunction validateData(schema: any, table: string, data: Record<string, any>, checkRequired: boolean = true) {\n const valid = validateSchema(schema)\n if (!valid.valid) {\n return { valid: false, errors: valid.errors, message: \"Schema is invalid\" }\n }\n\n const tableSchema = schema.tables[table]\n\n if (!tableSchema) {\n return { valid: false, errors: [{ message: `Table ${table} not found in schema` }], message: \"Table not found\" }\n }\n\n for (const [fieldName, fieldValue] of Object.entries(data)) {\n const fieldSchema = tableSchema.fields[fieldName]\n \n if (!fieldSchema) {\n return { \n valid: false, \n errors: [{ message: `Field ${fieldName} not found in schema` }],\n message: \"Invalid field\"\n }\n }\n\n const schemaType = fieldSchema.type\n const valueType = typeof fieldValue\n\n if ( \n (schemaType === 'string' && valueType !== 'string') ||\n (schemaType === 'number' && valueType !== 'number') ||\n (schemaType === 'boolean' && valueType !== 'boolean') ||\n (schemaType === 'json' && valueType !== 'object')\n ) {\n return {\n valid: false,\n errors: [{ \n message: `Field ${fieldName} should be type ${schemaType}, got ${valueType}` \n }],\n message: \"invalid type\"\n }\n }\n }\n\n if (checkRequired) {\n for (const [fieldName, fieldSchema] of Object.entries(tableSchema.fields)) {\n if ((fieldSchema as { required?: boolean }).required && !data[fieldName]) {\n return { valid: false, errors: [{ message: `Field ${fieldName} is required` }], message: \"Required field missing\" }\n }\n }\n }\n\n return { valid: true, errors: [] }\n}\n\ntype SchemaChangeType = \"property_changed\" | \"property_removed\" | \"table_added\" | \"table_removed\" | \"field_added\" | \"field_removed\" | \"field_type_changed\" | \"field_required_changed\" | \"field_property_added\" | \"field_property_changed\" | \"field_property_removed\"\n\n\ntype SchemaChange = {\n type: SchemaChangeType,\n property?: string,\n table?: string,\n field?: string,\n old?: any,\n new?: any\n}\n\nfunction _getSchemaChanges(oldSchema: any, newSchema: any) : SchemaChange[] {\n // Compare tables between schemas\n const changes : SchemaChange[] = []\n\n // Check for top level property changes\n for (const key in newSchema) {\n if (key !== 'tables' && newSchema[key] !== oldSchema[key]) {\n changes.push({\n type: 'property_changed',\n property: key,\n old: oldSchema[key],\n new: newSchema[key]\n })\n }\n }\n\n for (const key in oldSchema) {\n if (key !== 'tables' && !newSchema.hasOwnProperty(key)) {\n changes.push({\n type: 'property_removed',\n property: key,\n old: oldSchema[key]\n })\n }\n }\n\n // Check for removed tables\n for (const tableName in oldSchema.tables) {\n if (!newSchema.tables[tableName]) {\n changes.push({\n type: 'table_removed',\n table: tableName\n })\n }\n }\n\n // Check for added tables and field changes\n for (const tableName in newSchema.tables) {\n const newTable = newSchema.tables[tableName]\n const oldTable = oldSchema.tables[tableName]\n\n if (!oldTable) {\n changes.push({\n type: 'table_added', \n table: tableName\n })\n continue\n }\n\n // Compare fields\n for (const fieldName in newTable.fields) {\n const newField = newTable.fields[fieldName]\n const oldField = oldTable.fields[fieldName]\n\n if (!oldField) {\n changes.push({\n type: 'field_added',\n table: tableName,\n field: fieldName\n })\n continue\n }\n\n // Check for field type changes\n if (newField.type !== oldField.type) {\n changes.push({\n type: 'field_type_changed',\n table: tableName,\n field: fieldName,\n old: oldField.type,\n new: newField.type\n })\n }\n\n // Check for required flag changes\n if (newField.required !== oldField.required) {\n changes.push({\n type: 'field_required_changed',\n table: tableName,\n field: fieldName,\n old: oldField.required,\n new: newField.required\n })\n }\n }\n\n // Check for removed fields\n for (const fieldName in oldTable.fields) {\n if (!newTable.fields[fieldName]) {\n changes.push({\n type: 'field_removed',\n table: tableName,\n field: fieldName\n })\n }\n }\n }\n\n // Check for field property changes (excluding type which is already checked)\n for (const tableName in newSchema.tables) {\n const newTable = newSchema.tables[tableName]\n const oldTable = oldSchema.tables[tableName]\n\n if (!oldTable) continue\n\n for (const fieldName in newTable.fields) {\n const newField = newTable.fields[fieldName]\n const oldField = oldTable.fields[fieldName]\n\n if (!oldField) continue\n\n // Compare all properties except type\n for (const prop in newField) {\n if (prop === 'type') continue\n \n if (!(prop in oldField)) {\n changes.push({\n type: 'field_property_added',\n table: tableName,\n field: fieldName,\n property: prop,\n new: newField[prop]\n })\n } else if (JSON.stringify(newField[prop]) !== JSON.stringify(oldField[prop])) {\n changes.push({\n type: 'field_property_changed',\n table: tableName,\n field: fieldName,\n property: prop,\n old: oldField[prop],\n new: newField[prop]\n })\n }\n }\n\n // Check for removed properties\n for (const prop in oldField) {\n if (prop === 'type') continue\n if (!(prop in newField)) {\n changes.push({\n type: 'field_property_removed',\n table: tableName,\n field: fieldName,\n property: prop,\n old: oldField[prop]\n })\n }\n }\n }\n }\n\n return changes\n}\n\n\n// function verifyScehma(schema : any ) { \n// const valid = validateSchema(schema)\n// if (!valid.valid) {\n// return { valid: false, errors: valid.errors, message: \"Schema is invalid\" }\n// }\n\n\n\n\n// return { valid: true, errors: [] }\n// }\n\n\nfunction validateUpdateSchema(oldSchema: any, newSchema: any) {\n const oldValid = validateSchema(oldSchema)\n const newValid = validateSchema(newSchema)\n\n if (!oldValid.valid || !newValid.valid) {\n return { valid: false, errors: oldValid.errors.concat(newValid.errors), message: \"schemas are is invalid\" }\n }\n\n \n const changes = _getSchemaChanges(oldSchema, newSchema)\n\n const changeErrors = []\n for (const change of changes) {\n if (change.type === 'property_changed' && change.property === 'project_id') {\n changeErrors.push({ \n change: change,\n message: \"Cannot modify project_id property\"\n })\n }\n\n if (change.type === 'property_changed' && change.property === 'version') {\n if (change.new !== change.old + 1) {\n changeErrors.push({\n change: change,\n message: `Version must be incremented by 1. Expected version:${change.old + 1}, got version:${change.new}`\n })\n }\n }\n\n if (change.type === 'field_type_changed') {\n changeErrors.push({\n change: change,\n message: `Cannot change type of field \"${change.field}\" from \"${change.old}\" to \"${change.new}\"`\n })\n }\n }\n\n if (changeErrors.length > 0) {\n return {\n valid: false,\n errors: changeErrors,\n message: \"Invalid schema changes detected\"\n }\n }\n\n return { valid: true, changes: changes }\n}\n\nexport {\n validateSchema,\n validateData,\n generateEmptySchema,\n validateUpdateSchema\n}\n\nconst schema = {\n validateSchema,\n validateData,\n generateEmptySchema,\n validateUpdateSchema\n}\n\nexport default schema"],"mappings":"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","names":["Ajv","schema"]}
1
+ {"version":3,"sources":["../index.ts"],"sourcesContent":["// Basic Schema Library\n// utils for validating and interacting with Basic schemas\nimport Ajv from 'ajv'\n\nconst basicJsonSchema = {\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"type\": \"object\",\n \"properties\": {\n \"project_id\": {\n \"type\": \"string\"\n },\n \"namespace\": {\n \"type\": \"string\",\n },\n \"version\": {\n \"type\": \"integer\",\n \"minimum\": 0\n },\n \"tables\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"pattern\": \"^[a-zA-Z0-9_]+$\",\n \"minLength\": 1,\n \"maxLength\": 50, \n \"type\": \"string\"\n },\n \"patternProperties\": {\n \"^[a-zA-Z0-9_]+$\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"pattern\": \"^[a-zA-Z0-9_]+$\",\n \"minLength\": 1,\n \"maxLength\": 50, \n \"type\": \"string\"\n },\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"type\": {\n \"type\": \"string\",\n \"enum\": [\"collection\"]\n },\n \"fields\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"pattern\": \"^[a-zA-Z0-9_]+$\",\n \"minLength\": 1,\n \"maxLength\": 50, \n \"type\": \"string\"\n },\n \"patternProperties\": {\n \"^[a-zA-Z0-9_]+$\": {\n \"type\": \"object\",\n \"properties\": {\n \"type\": {\n \"type\": \"string\",\n \"enum\": [\"string\", \"boolean\", \"number\", \"json\"]\n },\n \"indexed\": {\n \"type\": \"boolean\"\n },\n \"required\": {\n \"type\": \"boolean\"\n }\n },\n \"required\": [\"type\"]\n }\n },\n \"additionalProperties\": true\n }\n },\n \"required\": [\"fields\"]\n }\n },\n \"additionalProperties\": true\n }\n },\n \"required\": [\"project_id\", \"version\", \"tables\"]\n}\n\nconst ajv = new Ajv()\nconst validator = ajv.compile(basicJsonSchema)\n\n\nfunction generateEmptySchema(project_id: string = \"\", version: number = 0) {\n return {\n project_id: project_id,\n version: version,\n tables: {\n foo: { \n name: \"foo\",\n type: \"collection\",\n fields: {\n bar: {\n type: \"string\",\n required: true,\n }\n }\n }\n }\n }\n}\n\ntype Schema = {\n project_id: string,\n version: number,\n tables: any\n}\n\n\n/**\n * Compare two schemas and detect any differences between them\n * @param oldSchema - The original schema to compare against\n * @param newSchema - The new schema to compare with the original\n * @returns {Object} Comparison result containing:\n * - valid: boolean indicating if schemas are identical\n * - changes: Array of detected changes between schemas\n */\nfunction compareSchemas(oldSchema: any, newSchema: any) {\n const changes = _getSchemaChanges(oldSchema, newSchema)\n const valid = changes.length === 0 ? true : false\n return { valid, changes }\n}\n\n/**\n * Validate a schema\n * only checks if the schema is formatted correctly, not if can be published\n * @param schema - The schema to validate\n * @returns {valid: boolean, errors: any[]} - The validation result\n */\nfunction validateSchema(schema: Schema): { valid: boolean, errors: ErrorObject[] } {\n const v = validator(schema)\n return {\n valid: v,\n errors: validator.errors || []\n }\n}\n\ntype ErrorObject = {\n keyword?: string;\n instancePath?: string; \n schemaPath?: string;\n params?: Record<string, any>;\n propertyName?: string;\n message?: string;\n schema?: any;\n parentSchema?: any;\n data?: any;\n}\n\n\n/**\n * Validate data against a schema's table definition. Only checks against provided schema.\n * @param schema - The schema to validate against\n * @param table - The table name in the schema to validate against\n * @param data - The data object to validate\n * @param checkRequired - Whether to check if required fields are present (default: true)\n * @returns {Object} Validation result containing:\n * - valid: boolean indicating if validation passed\n * - errors: Array of validation error objects\n * - message: Error message if validation failed\n */\n\nfunction validateData(schema: Schema, table: string, data: Record<string, any>, checkRequired: boolean = true) : { valid: boolean, errors?: ErrorObject[], message?: string } {\n const valid = validateSchema(schema)\n if (!valid.valid) {\n return { valid: false, errors: valid.errors, message: \"Schema is invalid\" }\n }\n\n const tableSchema = schema.tables[table]\n\n if (!tableSchema) {\n return { valid: false, errors: [{ message: `Table ${table} not found in schema` }], message: \"Table not found\" }\n }\n\n for (const [fieldName, fieldValue] of Object.entries(data)) {\n const fieldSchema = tableSchema.fields[fieldName]\n\n if (!fieldSchema) {\n return {\n valid: false,\n errors: [{ message: `Field ${fieldName} not found in schema` }],\n message: \"Invalid field\"\n }\n }\n\n const schemaType = fieldSchema.type\n const valueType = typeof fieldValue\n\n if (\n (schemaType === 'string' && valueType !== 'string') ||\n (schemaType === 'number' && valueType !== 'number') ||\n (schemaType === 'boolean' && valueType !== 'boolean') ||\n (schemaType === 'json' && valueType !== 'object')\n ) {\n return {\n valid: false,\n errors: [{\n message: `Field ${fieldName} should be type ${schemaType}, got ${valueType}`\n }],\n message: \"invalid type\"\n }\n }\n }\n\n if (checkRequired) {\n for (const [fieldName, fieldSchema] of Object.entries(tableSchema.fields)) {\n if ((fieldSchema as { required?: boolean }).required && !data[fieldName]) {\n return { valid: false, errors: [{ message: `Field ${fieldName} is required` }], message: \"Required field missing\" }\n }\n }\n }\n\n return { valid: true, errors: [] }\n}\n\ntype SchemaChangeType = \"property_changed\" | \"property_removed\" | \"table_added\" | \"table_removed\" | \"field_added\" | \"field_removed\" | \"field_type_changed\" | \"field_required_changed\" | \"field_property_added\" | \"field_property_changed\" | \"field_property_removed\"\n\ntype SchemaChange = {\n type: SchemaChangeType,\n property?: string,\n table?: string,\n field?: string,\n old?: any,\n new?: any\n}\n\nfunction _getSchemaChanges(oldSchema: any, newSchema: any): SchemaChange[] {\n // Compare tables between schemas\n const changes: SchemaChange[] = []\n\n // Check for top level property changes\n for (const key in newSchema) {\n if (key !== 'tables' && newSchema[key] !== oldSchema[key]) {\n changes.push({\n type: 'property_changed',\n property: key,\n old: oldSchema[key],\n new: newSchema[key]\n })\n }\n }\n\n for (const key in oldSchema) {\n if (key !== 'tables' && !newSchema.hasOwnProperty(key)) {\n changes.push({\n type: 'property_removed',\n property: key,\n old: oldSchema[key]\n })\n }\n }\n\n // Check for removed tables\n for (const tableName in oldSchema.tables) {\n if (!newSchema.tables[tableName]) {\n changes.push({\n type: 'table_removed',\n table: tableName\n })\n }\n }\n\n // Check for added tables and field changes\n for (const tableName in newSchema.tables) {\n const newTable = newSchema.tables[tableName]\n const oldTable = oldSchema.tables[tableName]\n\n if (!oldTable) {\n changes.push({\n type: 'table_added',\n table: tableName\n })\n continue\n }\n\n // Compare fields\n for (const fieldName in newTable.fields) {\n const newField = newTable.fields[fieldName]\n const oldField = oldTable.fields[fieldName]\n\n if (!oldField) {\n changes.push({\n type: 'field_added',\n table: tableName,\n field: fieldName\n })\n continue\n }\n\n // Check for field type changes\n if (newField.type !== oldField.type) {\n changes.push({\n type: 'field_type_changed',\n table: tableName,\n field: fieldName,\n old: oldField.type,\n new: newField.type\n })\n }\n\n // Check for required flag changes\n if (newField.required !== oldField.required) {\n changes.push({\n type: 'field_required_changed',\n table: tableName,\n field: fieldName,\n old: oldField.required,\n new: newField.required\n })\n }\n }\n\n // Check for removed fields\n for (const fieldName in oldTable.fields) {\n if (!newTable.fields[fieldName]) {\n changes.push({\n type: 'field_removed',\n table: tableName,\n field: fieldName\n })\n }\n }\n }\n\n // Check for field property changes (excluding type which is already checked)\n for (const tableName in newSchema.tables) {\n const newTable = newSchema.tables[tableName]\n const oldTable = oldSchema.tables[tableName]\n\n if (!oldTable) continue\n\n for (const fieldName in newTable.fields) {\n const newField = newTable.fields[fieldName]\n const oldField = oldTable.fields[fieldName]\n\n if (!oldField) continue\n\n // Compare all properties except type\n for (const prop in newField) {\n if (prop === 'type') continue\n\n if (!(prop in oldField)) {\n changes.push({\n type: 'field_property_added',\n table: tableName,\n field: fieldName,\n property: prop,\n new: newField[prop]\n })\n } else if (JSON.stringify(newField[prop]) !== JSON.stringify(oldField[prop])) {\n changes.push({\n type: 'field_property_changed',\n table: tableName,\n field: fieldName,\n property: prop,\n old: oldField[prop],\n new: newField[prop]\n })\n }\n }\n\n // Check for removed properties\n for (const prop in oldField) {\n if (prop === 'type') continue\n if (!(prop in newField)) {\n changes.push({\n type: 'field_property_removed',\n table: tableName,\n field: fieldName,\n property: prop,\n old: oldField[prop]\n })\n }\n }\n }\n }\n\n return changes\n}\n\n\nfunction validateUpdateSchema(oldSchema: any, newSchema: any) {\n const oldValid = validateSchema(oldSchema)\n const newValid = validateSchema(newSchema)\n\n if (!oldValid.valid || !newValid.valid) {\n return { valid: false, errors: oldValid.errors.concat(newValid.errors), message: \"schemas are is invalid\" }\n }\n\n\n const changes = _getSchemaChanges(oldSchema, newSchema)\n\n const changeErrors = []\n for (const change of changes) {\n if (change.type === 'property_changed' && change.property === 'project_id') {\n changeErrors.push({\n change: change,\n message: \"Cannot modify project_id property\"\n })\n }\n\n if (change.type === 'property_changed' && change.property === 'version') {\n if (change.new !== change.old + 1) {\n changeErrors.push({\n change: change,\n message: `Version must be incremented by 1. Expected version:${change.old + 1}, got version:${change.new}`\n })\n }\n }\n\n if (change.type === 'field_type_changed') {\n changeErrors.push({\n change: change,\n message: `Cannot change type of field \"${change.field}\" from \"${change.old}\" to \"${change.new}\"`\n })\n }\n }\n\n if (changeErrors.length > 0) {\n return {\n valid: false,\n errors: changeErrors,\n message: \"Invalid schema changes detected\"\n }\n }\n\n return { valid: true, changes: changes }\n}\n\nexport {\n validateSchema,\n validateData,\n generateEmptySchema,\n validateUpdateSchema,\n compareSchemas,\n}\n"],"mappings":"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","names":["Ajv"]}
package/dist/index.mjs CHANGED
@@ -16,9 +16,21 @@ var basicJsonSchema = {
16
16
  },
17
17
  "tables": {
18
18
  "type": "object",
19
+ "propertyNames": {
20
+ "pattern": "^[a-zA-Z0-9_]+$",
21
+ "minLength": 1,
22
+ "maxLength": 50,
23
+ "type": "string"
24
+ },
19
25
  "patternProperties": {
20
26
  "^[a-zA-Z0-9_]+$": {
21
27
  "type": "object",
28
+ "propertyNames": {
29
+ "pattern": "^[a-zA-Z0-9_]+$",
30
+ "minLength": 1,
31
+ "maxLength": 50,
32
+ "type": "string"
33
+ },
22
34
  "properties": {
23
35
  "name": {
24
36
  "type": "string"
@@ -29,6 +41,12 @@ var basicJsonSchema = {
29
41
  },
30
42
  "fields": {
31
43
  "type": "object",
44
+ "propertyNames": {
45
+ "pattern": "^[a-zA-Z0-9_]+$",
46
+ "minLength": 1,
47
+ "maxLength": 50,
48
+ "type": "string"
49
+ },
32
50
  "patternProperties": {
33
51
  "^[a-zA-Z0-9_]+$": {
34
52
  "type": "object",
@@ -65,27 +83,37 @@ function generateEmptySchema(project_id = "", version = 0) {
65
83
  project_id,
66
84
  version,
67
85
  tables: {
68
- fields: {
69
- example: {
70
- type: "string"
86
+ foo: {
87
+ name: "foo",
88
+ type: "collection",
89
+ fields: {
90
+ bar: {
91
+ type: "string",
92
+ required: true
93
+ }
71
94
  }
72
95
  }
73
96
  }
74
97
  };
75
98
  }
76
- function validateSchema(schema2) {
77
- const v = validator(schema2);
99
+ function compareSchemas(oldSchema, newSchema) {
100
+ const changes = _getSchemaChanges(oldSchema, newSchema);
101
+ const valid = changes.length === 0 ? true : false;
102
+ return { valid, changes };
103
+ }
104
+ function validateSchema(schema) {
105
+ const v = validator(schema);
78
106
  return {
79
107
  valid: v,
80
108
  errors: validator.errors || []
81
109
  };
82
110
  }
83
- function validateData(schema2, table, data, checkRequired = true) {
84
- const valid = validateSchema(schema2);
111
+ function validateData(schema, table, data, checkRequired = true) {
112
+ const valid = validateSchema(schema);
85
113
  if (!valid.valid) {
86
114
  return { valid: false, errors: valid.errors, message: "Schema is invalid" };
87
115
  }
88
- const tableSchema = schema2.tables[table];
116
+ const tableSchema = schema.tables[table];
89
117
  if (!tableSchema) {
90
118
  return { valid: false, errors: [{ message: `Table ${table} not found in schema` }], message: "Table not found" };
91
119
  }
@@ -286,15 +314,8 @@ function validateUpdateSchema(oldSchema, newSchema) {
286
314
  }
287
315
  return { valid: true, changes };
288
316
  }
289
- var schema = {
290
- validateSchema,
291
- validateData,
292
- generateEmptySchema,
293
- validateUpdateSchema
294
- };
295
- var schema_default = schema;
296
317
  export {
297
- schema_default as default,
318
+ compareSchemas,
298
319
  generateEmptySchema,
299
320
  validateData,
300
321
  validateSchema,
@@ -1 +1 @@
1
- {"version":3,"sources":["../index.ts"],"sourcesContent":["// Basic Schema Library\n// utils for validating and interacting with Basic schemas\nimport Ajv, { ErrorObject } from 'ajv'\n\nconst basicJsonSchema = {\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"type\": \"object\",\n \"properties\": {\n \"project_id\": {\n \"type\": \"string\"\n },\n \"namespace\": {\n \"type\": \"string\",\n },\n \"version\": {\n \"type\": \"integer\",\n \"minimum\": 0\n },\n \"tables\": {\n \"type\": \"object\",\n \"patternProperties\": {\n \"^[a-zA-Z0-9_]+$\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"type\": {\n \"type\": \"string\",\n \"enum\": [\"collection\"]\n },\n \"fields\": {\n \"type\": \"object\",\n \"patternProperties\": {\n \"^[a-zA-Z0-9_]+$\": {\n \"type\": \"object\",\n \"properties\": {\n \"type\": {\n \"type\": \"string\",\n \"enum\": [\"string\", \"boolean\", \"number\", \"json\"]\n },\n \"indexed\": {\n \"type\": \"boolean\"\n }, \n \"required\": {\n \"type\": \"boolean\"\n }\n },\n \"required\": [\"type\"]\n }\n },\n \"additionalProperties\": true\n }\n },\n \"required\": [\"fields\"]\n }\n },\n \"additionalProperties\": true\n }\n },\n \"required\": [\"project_id\", \"version\", \"tables\"]\n }\n\nconst ajv = new Ajv()\nconst validator = ajv.compile(basicJsonSchema)\n\n\nfunction generateEmptySchema(project_id: string = \"\", version: number = 0) {\n return {\n project_id: project_id,\n version: version,\n tables: {\n fields: {\n example: { \n type: \"string\",\n }\n }\n }\n }\n}\n\ntype Schema = { \n project_id : string,\n version : number,\n tables : any\n}\n\n\n/**\n * Validate a schema\n * only checks if the schema is formatted correctly, not if can be published\n * @param schema - The schema to validate\n * @returns {valid: boolean, errors: any[]} - The validation result\n */\nfunction validateSchema(schema: any) : {valid: boolean, errors: ErrorObject[]} {\n const v = validator(schema)\n return { \n valid: v,\n errors: validator.errors || []\n }\n}\n\n// type ErrorObject = {\n// keyword: string;\n// instancePath: string; \n// schemaPath: string;\n// params: Record<string, any>;\n// propertyName?: string;\n// message?: string;\n// schema?: any;\n// parentSchema?: any;\n// data?: any;\n// }\n\n\n/**\n * Validate data against a schema's table definition. Only checks against provided schema.\n * @param schema - The schema to validate against\n * @param table - The table name in the schema to validate against\n * @param data - The data object to validate\n * @param checkRequired - Whether to check if required fields are present (default: true)\n * @returns {Object} Validation result containing:\n * - valid: boolean indicating if validation passed\n * - errors: Array of validation error objects\n * - message: Error message if validation failed\n */\n\nfunction validateData(schema: any, table: string, data: Record<string, any>, checkRequired: boolean = true) {\n const valid = validateSchema(schema)\n if (!valid.valid) {\n return { valid: false, errors: valid.errors, message: \"Schema is invalid\" }\n }\n\n const tableSchema = schema.tables[table]\n\n if (!tableSchema) {\n return { valid: false, errors: [{ message: `Table ${table} not found in schema` }], message: \"Table not found\" }\n }\n\n for (const [fieldName, fieldValue] of Object.entries(data)) {\n const fieldSchema = tableSchema.fields[fieldName]\n \n if (!fieldSchema) {\n return { \n valid: false, \n errors: [{ message: `Field ${fieldName} not found in schema` }],\n message: \"Invalid field\"\n }\n }\n\n const schemaType = fieldSchema.type\n const valueType = typeof fieldValue\n\n if ( \n (schemaType === 'string' && valueType !== 'string') ||\n (schemaType === 'number' && valueType !== 'number') ||\n (schemaType === 'boolean' && valueType !== 'boolean') ||\n (schemaType === 'json' && valueType !== 'object')\n ) {\n return {\n valid: false,\n errors: [{ \n message: `Field ${fieldName} should be type ${schemaType}, got ${valueType}` \n }],\n message: \"invalid type\"\n }\n }\n }\n\n if (checkRequired) {\n for (const [fieldName, fieldSchema] of Object.entries(tableSchema.fields)) {\n if ((fieldSchema as { required?: boolean }).required && !data[fieldName]) {\n return { valid: false, errors: [{ message: `Field ${fieldName} is required` }], message: \"Required field missing\" }\n }\n }\n }\n\n return { valid: true, errors: [] }\n}\n\ntype SchemaChangeType = \"property_changed\" | \"property_removed\" | \"table_added\" | \"table_removed\" | \"field_added\" | \"field_removed\" | \"field_type_changed\" | \"field_required_changed\" | \"field_property_added\" | \"field_property_changed\" | \"field_property_removed\"\n\n\ntype SchemaChange = {\n type: SchemaChangeType,\n property?: string,\n table?: string,\n field?: string,\n old?: any,\n new?: any\n}\n\nfunction _getSchemaChanges(oldSchema: any, newSchema: any) : SchemaChange[] {\n // Compare tables between schemas\n const changes : SchemaChange[] = []\n\n // Check for top level property changes\n for (const key in newSchema) {\n if (key !== 'tables' && newSchema[key] !== oldSchema[key]) {\n changes.push({\n type: 'property_changed',\n property: key,\n old: oldSchema[key],\n new: newSchema[key]\n })\n }\n }\n\n for (const key in oldSchema) {\n if (key !== 'tables' && !newSchema.hasOwnProperty(key)) {\n changes.push({\n type: 'property_removed',\n property: key,\n old: oldSchema[key]\n })\n }\n }\n\n // Check for removed tables\n for (const tableName in oldSchema.tables) {\n if (!newSchema.tables[tableName]) {\n changes.push({\n type: 'table_removed',\n table: tableName\n })\n }\n }\n\n // Check for added tables and field changes\n for (const tableName in newSchema.tables) {\n const newTable = newSchema.tables[tableName]\n const oldTable = oldSchema.tables[tableName]\n\n if (!oldTable) {\n changes.push({\n type: 'table_added', \n table: tableName\n })\n continue\n }\n\n // Compare fields\n for (const fieldName in newTable.fields) {\n const newField = newTable.fields[fieldName]\n const oldField = oldTable.fields[fieldName]\n\n if (!oldField) {\n changes.push({\n type: 'field_added',\n table: tableName,\n field: fieldName\n })\n continue\n }\n\n // Check for field type changes\n if (newField.type !== oldField.type) {\n changes.push({\n type: 'field_type_changed',\n table: tableName,\n field: fieldName,\n old: oldField.type,\n new: newField.type\n })\n }\n\n // Check for required flag changes\n if (newField.required !== oldField.required) {\n changes.push({\n type: 'field_required_changed',\n table: tableName,\n field: fieldName,\n old: oldField.required,\n new: newField.required\n })\n }\n }\n\n // Check for removed fields\n for (const fieldName in oldTable.fields) {\n if (!newTable.fields[fieldName]) {\n changes.push({\n type: 'field_removed',\n table: tableName,\n field: fieldName\n })\n }\n }\n }\n\n // Check for field property changes (excluding type which is already checked)\n for (const tableName in newSchema.tables) {\n const newTable = newSchema.tables[tableName]\n const oldTable = oldSchema.tables[tableName]\n\n if (!oldTable) continue\n\n for (const fieldName in newTable.fields) {\n const newField = newTable.fields[fieldName]\n const oldField = oldTable.fields[fieldName]\n\n if (!oldField) continue\n\n // Compare all properties except type\n for (const prop in newField) {\n if (prop === 'type') continue\n \n if (!(prop in oldField)) {\n changes.push({\n type: 'field_property_added',\n table: tableName,\n field: fieldName,\n property: prop,\n new: newField[prop]\n })\n } else if (JSON.stringify(newField[prop]) !== JSON.stringify(oldField[prop])) {\n changes.push({\n type: 'field_property_changed',\n table: tableName,\n field: fieldName,\n property: prop,\n old: oldField[prop],\n new: newField[prop]\n })\n }\n }\n\n // Check for removed properties\n for (const prop in oldField) {\n if (prop === 'type') continue\n if (!(prop in newField)) {\n changes.push({\n type: 'field_property_removed',\n table: tableName,\n field: fieldName,\n property: prop,\n old: oldField[prop]\n })\n }\n }\n }\n }\n\n return changes\n}\n\n\n// function verifyScehma(schema : any ) { \n// const valid = validateSchema(schema)\n// if (!valid.valid) {\n// return { valid: false, errors: valid.errors, message: \"Schema is invalid\" }\n// }\n\n\n\n\n// return { valid: true, errors: [] }\n// }\n\n\nfunction validateUpdateSchema(oldSchema: any, newSchema: any) {\n const oldValid = validateSchema(oldSchema)\n const newValid = validateSchema(newSchema)\n\n if (!oldValid.valid || !newValid.valid) {\n return { valid: false, errors: oldValid.errors.concat(newValid.errors), message: \"schemas are is invalid\" }\n }\n\n \n const changes = _getSchemaChanges(oldSchema, newSchema)\n\n const changeErrors = []\n for (const change of changes) {\n if (change.type === 'property_changed' && change.property === 'project_id') {\n changeErrors.push({ \n change: change,\n message: \"Cannot modify project_id property\"\n })\n }\n\n if (change.type === 'property_changed' && change.property === 'version') {\n if (change.new !== change.old + 1) {\n changeErrors.push({\n change: change,\n message: `Version must be incremented by 1. Expected version:${change.old + 1}, got version:${change.new}`\n })\n }\n }\n\n if (change.type === 'field_type_changed') {\n changeErrors.push({\n change: change,\n message: `Cannot change type of field \"${change.field}\" from \"${change.old}\" to \"${change.new}\"`\n })\n }\n }\n\n if (changeErrors.length > 0) {\n return {\n valid: false,\n errors: changeErrors,\n message: \"Invalid schema changes detected\"\n }\n }\n\n return { valid: true, changes: changes }\n}\n\nexport {\n validateSchema,\n validateData,\n generateEmptySchema,\n validateUpdateSchema\n}\n\nconst schema = {\n validateSchema,\n validateData,\n generateEmptySchema,\n validateUpdateSchema\n}\n\nexport default schema"],"mappings":"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","names":["schema"]}
1
+ {"version":3,"sources":["../index.ts"],"sourcesContent":["// Basic Schema Library\n// utils for validating and interacting with Basic schemas\nimport Ajv from 'ajv'\n\nconst basicJsonSchema = {\n \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n \"type\": \"object\",\n \"properties\": {\n \"project_id\": {\n \"type\": \"string\"\n },\n \"namespace\": {\n \"type\": \"string\",\n },\n \"version\": {\n \"type\": \"integer\",\n \"minimum\": 0\n },\n \"tables\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"pattern\": \"^[a-zA-Z0-9_]+$\",\n \"minLength\": 1,\n \"maxLength\": 50, \n \"type\": \"string\"\n },\n \"patternProperties\": {\n \"^[a-zA-Z0-9_]+$\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"pattern\": \"^[a-zA-Z0-9_]+$\",\n \"minLength\": 1,\n \"maxLength\": 50, \n \"type\": \"string\"\n },\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"type\": {\n \"type\": \"string\",\n \"enum\": [\"collection\"]\n },\n \"fields\": {\n \"type\": \"object\",\n \"propertyNames\": {\n \"pattern\": \"^[a-zA-Z0-9_]+$\",\n \"minLength\": 1,\n \"maxLength\": 50, \n \"type\": \"string\"\n },\n \"patternProperties\": {\n \"^[a-zA-Z0-9_]+$\": {\n \"type\": \"object\",\n \"properties\": {\n \"type\": {\n \"type\": \"string\",\n \"enum\": [\"string\", \"boolean\", \"number\", \"json\"]\n },\n \"indexed\": {\n \"type\": \"boolean\"\n },\n \"required\": {\n \"type\": \"boolean\"\n }\n },\n \"required\": [\"type\"]\n }\n },\n \"additionalProperties\": true\n }\n },\n \"required\": [\"fields\"]\n }\n },\n \"additionalProperties\": true\n }\n },\n \"required\": [\"project_id\", \"version\", \"tables\"]\n}\n\nconst ajv = new Ajv()\nconst validator = ajv.compile(basicJsonSchema)\n\n\nfunction generateEmptySchema(project_id: string = \"\", version: number = 0) {\n return {\n project_id: project_id,\n version: version,\n tables: {\n foo: { \n name: \"foo\",\n type: \"collection\",\n fields: {\n bar: {\n type: \"string\",\n required: true,\n }\n }\n }\n }\n }\n}\n\ntype Schema = {\n project_id: string,\n version: number,\n tables: any\n}\n\n\n/**\n * Compare two schemas and detect any differences between them\n * @param oldSchema - The original schema to compare against\n * @param newSchema - The new schema to compare with the original\n * @returns {Object} Comparison result containing:\n * - valid: boolean indicating if schemas are identical\n * - changes: Array of detected changes between schemas\n */\nfunction compareSchemas(oldSchema: any, newSchema: any) {\n const changes = _getSchemaChanges(oldSchema, newSchema)\n const valid = changes.length === 0 ? true : false\n return { valid, changes }\n}\n\n/**\n * Validate a schema\n * only checks if the schema is formatted correctly, not if can be published\n * @param schema - The schema to validate\n * @returns {valid: boolean, errors: any[]} - The validation result\n */\nfunction validateSchema(schema: Schema): { valid: boolean, errors: ErrorObject[] } {\n const v = validator(schema)\n return {\n valid: v,\n errors: validator.errors || []\n }\n}\n\ntype ErrorObject = {\n keyword?: string;\n instancePath?: string; \n schemaPath?: string;\n params?: Record<string, any>;\n propertyName?: string;\n message?: string;\n schema?: any;\n parentSchema?: any;\n data?: any;\n}\n\n\n/**\n * Validate data against a schema's table definition. Only checks against provided schema.\n * @param schema - The schema to validate against\n * @param table - The table name in the schema to validate against\n * @param data - The data object to validate\n * @param checkRequired - Whether to check if required fields are present (default: true)\n * @returns {Object} Validation result containing:\n * - valid: boolean indicating if validation passed\n * - errors: Array of validation error objects\n * - message: Error message if validation failed\n */\n\nfunction validateData(schema: Schema, table: string, data: Record<string, any>, checkRequired: boolean = true) : { valid: boolean, errors?: ErrorObject[], message?: string } {\n const valid = validateSchema(schema)\n if (!valid.valid) {\n return { valid: false, errors: valid.errors, message: \"Schema is invalid\" }\n }\n\n const tableSchema = schema.tables[table]\n\n if (!tableSchema) {\n return { valid: false, errors: [{ message: `Table ${table} not found in schema` }], message: \"Table not found\" }\n }\n\n for (const [fieldName, fieldValue] of Object.entries(data)) {\n const fieldSchema = tableSchema.fields[fieldName]\n\n if (!fieldSchema) {\n return {\n valid: false,\n errors: [{ message: `Field ${fieldName} not found in schema` }],\n message: \"Invalid field\"\n }\n }\n\n const schemaType = fieldSchema.type\n const valueType = typeof fieldValue\n\n if (\n (schemaType === 'string' && valueType !== 'string') ||\n (schemaType === 'number' && valueType !== 'number') ||\n (schemaType === 'boolean' && valueType !== 'boolean') ||\n (schemaType === 'json' && valueType !== 'object')\n ) {\n return {\n valid: false,\n errors: [{\n message: `Field ${fieldName} should be type ${schemaType}, got ${valueType}`\n }],\n message: \"invalid type\"\n }\n }\n }\n\n if (checkRequired) {\n for (const [fieldName, fieldSchema] of Object.entries(tableSchema.fields)) {\n if ((fieldSchema as { required?: boolean }).required && !data[fieldName]) {\n return { valid: false, errors: [{ message: `Field ${fieldName} is required` }], message: \"Required field missing\" }\n }\n }\n }\n\n return { valid: true, errors: [] }\n}\n\ntype SchemaChangeType = \"property_changed\" | \"property_removed\" | \"table_added\" | \"table_removed\" | \"field_added\" | \"field_removed\" | \"field_type_changed\" | \"field_required_changed\" | \"field_property_added\" | \"field_property_changed\" | \"field_property_removed\"\n\ntype SchemaChange = {\n type: SchemaChangeType,\n property?: string,\n table?: string,\n field?: string,\n old?: any,\n new?: any\n}\n\nfunction _getSchemaChanges(oldSchema: any, newSchema: any): SchemaChange[] {\n // Compare tables between schemas\n const changes: SchemaChange[] = []\n\n // Check for top level property changes\n for (const key in newSchema) {\n if (key !== 'tables' && newSchema[key] !== oldSchema[key]) {\n changes.push({\n type: 'property_changed',\n property: key,\n old: oldSchema[key],\n new: newSchema[key]\n })\n }\n }\n\n for (const key in oldSchema) {\n if (key !== 'tables' && !newSchema.hasOwnProperty(key)) {\n changes.push({\n type: 'property_removed',\n property: key,\n old: oldSchema[key]\n })\n }\n }\n\n // Check for removed tables\n for (const tableName in oldSchema.tables) {\n if (!newSchema.tables[tableName]) {\n changes.push({\n type: 'table_removed',\n table: tableName\n })\n }\n }\n\n // Check for added tables and field changes\n for (const tableName in newSchema.tables) {\n const newTable = newSchema.tables[tableName]\n const oldTable = oldSchema.tables[tableName]\n\n if (!oldTable) {\n changes.push({\n type: 'table_added',\n table: tableName\n })\n continue\n }\n\n // Compare fields\n for (const fieldName in newTable.fields) {\n const newField = newTable.fields[fieldName]\n const oldField = oldTable.fields[fieldName]\n\n if (!oldField) {\n changes.push({\n type: 'field_added',\n table: tableName,\n field: fieldName\n })\n continue\n }\n\n // Check for field type changes\n if (newField.type !== oldField.type) {\n changes.push({\n type: 'field_type_changed',\n table: tableName,\n field: fieldName,\n old: oldField.type,\n new: newField.type\n })\n }\n\n // Check for required flag changes\n if (newField.required !== oldField.required) {\n changes.push({\n type: 'field_required_changed',\n table: tableName,\n field: fieldName,\n old: oldField.required,\n new: newField.required\n })\n }\n }\n\n // Check for removed fields\n for (const fieldName in oldTable.fields) {\n if (!newTable.fields[fieldName]) {\n changes.push({\n type: 'field_removed',\n table: tableName,\n field: fieldName\n })\n }\n }\n }\n\n // Check for field property changes (excluding type which is already checked)\n for (const tableName in newSchema.tables) {\n const newTable = newSchema.tables[tableName]\n const oldTable = oldSchema.tables[tableName]\n\n if (!oldTable) continue\n\n for (const fieldName in newTable.fields) {\n const newField = newTable.fields[fieldName]\n const oldField = oldTable.fields[fieldName]\n\n if (!oldField) continue\n\n // Compare all properties except type\n for (const prop in newField) {\n if (prop === 'type') continue\n\n if (!(prop in oldField)) {\n changes.push({\n type: 'field_property_added',\n table: tableName,\n field: fieldName,\n property: prop,\n new: newField[prop]\n })\n } else if (JSON.stringify(newField[prop]) !== JSON.stringify(oldField[prop])) {\n changes.push({\n type: 'field_property_changed',\n table: tableName,\n field: fieldName,\n property: prop,\n old: oldField[prop],\n new: newField[prop]\n })\n }\n }\n\n // Check for removed properties\n for (const prop in oldField) {\n if (prop === 'type') continue\n if (!(prop in newField)) {\n changes.push({\n type: 'field_property_removed',\n table: tableName,\n field: fieldName,\n property: prop,\n old: oldField[prop]\n })\n }\n }\n }\n }\n\n return changes\n}\n\n\nfunction validateUpdateSchema(oldSchema: any, newSchema: any) {\n const oldValid = validateSchema(oldSchema)\n const newValid = validateSchema(newSchema)\n\n if (!oldValid.valid || !newValid.valid) {\n return { valid: false, errors: oldValid.errors.concat(newValid.errors), message: \"schemas are is invalid\" }\n }\n\n\n const changes = _getSchemaChanges(oldSchema, newSchema)\n\n const changeErrors = []\n for (const change of changes) {\n if (change.type === 'property_changed' && change.property === 'project_id') {\n changeErrors.push({\n change: change,\n message: \"Cannot modify project_id property\"\n })\n }\n\n if (change.type === 'property_changed' && change.property === 'version') {\n if (change.new !== change.old + 1) {\n changeErrors.push({\n change: change,\n message: `Version must be incremented by 1. Expected version:${change.old + 1}, got version:${change.new}`\n })\n }\n }\n\n if (change.type === 'field_type_changed') {\n changeErrors.push({\n change: change,\n message: `Cannot change type of field \"${change.field}\" from \"${change.old}\" to \"${change.new}\"`\n })\n }\n }\n\n if (changeErrors.length > 0) {\n return {\n valid: false,\n errors: changeErrors,\n message: \"Invalid schema changes detected\"\n }\n }\n\n return { valid: true, changes: changes }\n}\n\nexport {\n validateSchema,\n validateData,\n generateEmptySchema,\n validateUpdateSchema,\n compareSchemas,\n}\n"],"mappings":"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","names":[]}
package/index.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  // Basic Schema Library
2
2
  // utils for validating and interacting with Basic schemas
3
- import Ajv, { ErrorObject } from 'ajv'
3
+ import Ajv from 'ajv'
4
4
 
5
5
  const basicJsonSchema = {
6
6
  "$schema": "http://json-schema.org/draft-07/schema#",
@@ -18,9 +18,21 @@ const basicJsonSchema = {
18
18
  },
19
19
  "tables": {
20
20
  "type": "object",
21
+ "propertyNames": {
22
+ "pattern": "^[a-zA-Z0-9_]+$",
23
+ "minLength": 1,
24
+ "maxLength": 50,
25
+ "type": "string"
26
+ },
21
27
  "patternProperties": {
22
28
  "^[a-zA-Z0-9_]+$": {
23
29
  "type": "object",
30
+ "propertyNames": {
31
+ "pattern": "^[a-zA-Z0-9_]+$",
32
+ "minLength": 1,
33
+ "maxLength": 50,
34
+ "type": "string"
35
+ },
24
36
  "properties": {
25
37
  "name": {
26
38
  "type": "string"
@@ -31,6 +43,12 @@ const basicJsonSchema = {
31
43
  },
32
44
  "fields": {
33
45
  "type": "object",
46
+ "propertyNames": {
47
+ "pattern": "^[a-zA-Z0-9_]+$",
48
+ "minLength": 1,
49
+ "maxLength": 50,
50
+ "type": "string"
51
+ },
34
52
  "patternProperties": {
35
53
  "^[a-zA-Z0-9_]+$": {
36
54
  "type": "object",
@@ -41,7 +59,7 @@ const basicJsonSchema = {
41
59
  },
42
60
  "indexed": {
43
61
  "type": "boolean"
44
- },
62
+ },
45
63
  "required": {
46
64
  "type": "boolean"
47
65
  }
@@ -59,58 +77,77 @@ const basicJsonSchema = {
59
77
  }
60
78
  },
61
79
  "required": ["project_id", "version", "tables"]
62
- }
80
+ }
63
81
 
64
82
  const ajv = new Ajv()
65
83
  const validator = ajv.compile(basicJsonSchema)
66
84
 
67
85
 
68
- function generateEmptySchema(project_id: string = "", version: number = 0) {
86
+ function generateEmptySchema(project_id: string = "", version: number = 0) {
69
87
  return {
70
88
  project_id: project_id,
71
89
  version: version,
72
90
  tables: {
73
- fields: {
74
- example: {
75
- type: "string",
91
+ foo: {
92
+ name: "foo",
93
+ type: "collection",
94
+ fields: {
95
+ bar: {
96
+ type: "string",
97
+ required: true,
98
+ }
76
99
  }
77
100
  }
78
101
  }
79
102
  }
80
103
  }
81
104
 
82
- type Schema = {
83
- project_id : string,
84
- version : number,
85
- tables : any
105
+ type Schema = {
106
+ project_id: string,
107
+ version: number,
108
+ tables: any
86
109
  }
87
110
 
88
111
 
112
+ /**
113
+ * Compare two schemas and detect any differences between them
114
+ * @param oldSchema - The original schema to compare against
115
+ * @param newSchema - The new schema to compare with the original
116
+ * @returns {Object} Comparison result containing:
117
+ * - valid: boolean indicating if schemas are identical
118
+ * - changes: Array of detected changes between schemas
119
+ */
120
+ function compareSchemas(oldSchema: any, newSchema: any) {
121
+ const changes = _getSchemaChanges(oldSchema, newSchema)
122
+ const valid = changes.length === 0 ? true : false
123
+ return { valid, changes }
124
+ }
125
+
89
126
  /**
90
127
  * Validate a schema
91
128
  * only checks if the schema is formatted correctly, not if can be published
92
129
  * @param schema - The schema to validate
93
130
  * @returns {valid: boolean, errors: any[]} - The validation result
94
131
  */
95
- function validateSchema(schema: any) : {valid: boolean, errors: ErrorObject[]} {
132
+ function validateSchema(schema: Schema): { valid: boolean, errors: ErrorObject[] } {
96
133
  const v = validator(schema)
97
- return {
134
+ return {
98
135
  valid: v,
99
136
  errors: validator.errors || []
100
137
  }
101
138
  }
102
139
 
103
- // type ErrorObject = {
104
- // keyword: string;
105
- // instancePath: string;
106
- // schemaPath: string;
107
- // params: Record<string, any>;
108
- // propertyName?: string;
109
- // message?: string;
110
- // schema?: any;
111
- // parentSchema?: any;
112
- // data?: any;
113
- // }
140
+ type ErrorObject = {
141
+ keyword?: string;
142
+ instancePath?: string;
143
+ schemaPath?: string;
144
+ params?: Record<string, any>;
145
+ propertyName?: string;
146
+ message?: string;
147
+ schema?: any;
148
+ parentSchema?: any;
149
+ data?: any;
150
+ }
114
151
 
115
152
 
116
153
  /**
@@ -125,7 +162,7 @@ function validateSchema(schema: any) : {valid: boolean, errors: ErrorObject[]} {
125
162
  * - message: Error message if validation failed
126
163
  */
127
164
 
128
- function validateData(schema: any, table: string, data: Record<string, any>, checkRequired: boolean = true) {
165
+ function validateData(schema: Schema, table: string, data: Record<string, any>, checkRequired: boolean = true) : { valid: boolean, errors?: ErrorObject[], message?: string } {
129
166
  const valid = validateSchema(schema)
130
167
  if (!valid.valid) {
131
168
  return { valid: false, errors: valid.errors, message: "Schema is invalid" }
@@ -139,10 +176,10 @@ function validateData(schema: any, table: string, data: Record<string, any>, che
139
176
 
140
177
  for (const [fieldName, fieldValue] of Object.entries(data)) {
141
178
  const fieldSchema = tableSchema.fields[fieldName]
142
-
179
+
143
180
  if (!fieldSchema) {
144
- return {
145
- valid: false,
181
+ return {
182
+ valid: false,
146
183
  errors: [{ message: `Field ${fieldName} not found in schema` }],
147
184
  message: "Invalid field"
148
185
  }
@@ -151,7 +188,7 @@ function validateData(schema: any, table: string, data: Record<string, any>, che
151
188
  const schemaType = fieldSchema.type
152
189
  const valueType = typeof fieldValue
153
190
 
154
- if (
191
+ if (
155
192
  (schemaType === 'string' && valueType !== 'string') ||
156
193
  (schemaType === 'number' && valueType !== 'number') ||
157
194
  (schemaType === 'boolean' && valueType !== 'boolean') ||
@@ -159,8 +196,8 @@ function validateData(schema: any, table: string, data: Record<string, any>, che
159
196
  ) {
160
197
  return {
161
198
  valid: false,
162
- errors: [{
163
- message: `Field ${fieldName} should be type ${schemaType}, got ${valueType}`
199
+ errors: [{
200
+ message: `Field ${fieldName} should be type ${schemaType}, got ${valueType}`
164
201
  }],
165
202
  message: "invalid type"
166
203
  }
@@ -180,7 +217,6 @@ function validateData(schema: any, table: string, data: Record<string, any>, che
180
217
 
181
218
  type SchemaChangeType = "property_changed" | "property_removed" | "table_added" | "table_removed" | "field_added" | "field_removed" | "field_type_changed" | "field_required_changed" | "field_property_added" | "field_property_changed" | "field_property_removed"
182
219
 
183
-
184
220
  type SchemaChange = {
185
221
  type: SchemaChangeType,
186
222
  property?: string,
@@ -190,9 +226,9 @@ type SchemaChange = {
190
226
  new?: any
191
227
  }
192
228
 
193
- function _getSchemaChanges(oldSchema: any, newSchema: any) : SchemaChange[] {
229
+ function _getSchemaChanges(oldSchema: any, newSchema: any): SchemaChange[] {
194
230
  // Compare tables between schemas
195
- const changes : SchemaChange[] = []
231
+ const changes: SchemaChange[] = []
196
232
 
197
233
  // Check for top level property changes
198
234
  for (const key in newSchema) {
@@ -233,7 +269,7 @@ function _getSchemaChanges(oldSchema: any, newSchema: any) : SchemaChange[] {
233
269
 
234
270
  if (!oldTable) {
235
271
  changes.push({
236
- type: 'table_added',
272
+ type: 'table_added',
237
273
  table: tableName
238
274
  })
239
275
  continue
@@ -304,7 +340,7 @@ function _getSchemaChanges(oldSchema: any, newSchema: any) : SchemaChange[] {
304
340
  // Compare all properties except type
305
341
  for (const prop in newField) {
306
342
  if (prop === 'type') continue
307
-
343
+
308
344
  if (!(prop in oldField)) {
309
345
  changes.push({
310
346
  type: 'field_property_added',
@@ -345,20 +381,7 @@ function _getSchemaChanges(oldSchema: any, newSchema: any) : SchemaChange[] {
345
381
  }
346
382
 
347
383
 
348
- // function verifyScehma(schema : any ) {
349
- // const valid = validateSchema(schema)
350
- // if (!valid.valid) {
351
- // return { valid: false, errors: valid.errors, message: "Schema is invalid" }
352
- // }
353
-
354
-
355
-
356
-
357
- // return { valid: true, errors: [] }
358
- // }
359
-
360
-
361
- function validateUpdateSchema(oldSchema: any, newSchema: any) {
384
+ function validateUpdateSchema(oldSchema: any, newSchema: any) {
362
385
  const oldValid = validateSchema(oldSchema)
363
386
  const newValid = validateSchema(newSchema)
364
387
 
@@ -366,13 +389,13 @@ function validateUpdateSchema(oldSchema: any, newSchema: any) {
366
389
  return { valid: false, errors: oldValid.errors.concat(newValid.errors), message: "schemas are is invalid" }
367
390
  }
368
391
 
369
-
392
+
370
393
  const changes = _getSchemaChanges(oldSchema, newSchema)
371
394
 
372
395
  const changeErrors = []
373
396
  for (const change of changes) {
374
397
  if (change.type === 'property_changed' && change.property === 'project_id') {
375
- changeErrors.push({
398
+ changeErrors.push({
376
399
  change: change,
377
400
  message: "Cannot modify project_id property"
378
401
  })
@@ -410,14 +433,6 @@ export {
410
433
  validateSchema,
411
434
  validateData,
412
435
  generateEmptySchema,
413
- validateUpdateSchema
436
+ validateUpdateSchema,
437
+ compareSchemas,
414
438
  }
415
-
416
- const schema = {
417
- validateSchema,
418
- validateData,
419
- generateEmptySchema,
420
- validateUpdateSchema
421
- }
422
-
423
- export default schema
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@basictech/schema",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "utils for Basic Schema",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",