@basictech/react 0.2.0-beta.8 → 0.2.0-beta.9
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 +6 -0
- package/dist/index.d.mts +93 -1
- package/dist/index.d.ts +93 -1
- package/dist/index.js +138 -65
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +137 -65
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/AuthContext.tsx +6 -5
- package/src/config.ts +2 -64
- package/src/index.ts +7 -1
- package/src/schema.ts +159 -0
- package/src/sync/index.ts +23 -4
package/changelog.md
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import React from 'react';
|
|
3
|
+
import { ErrorObject } from 'ajv';
|
|
3
4
|
|
|
4
5
|
declare enum DBStatus {
|
|
5
6
|
LOADING = "LOADING",
|
|
@@ -37,6 +38,97 @@ declare function useBasic(): {
|
|
|
37
38
|
dbStatus: DBStatus;
|
|
38
39
|
};
|
|
39
40
|
|
|
41
|
+
declare const basicJsonSchema: {
|
|
42
|
+
$schema: string;
|
|
43
|
+
type: string;
|
|
44
|
+
properties: {
|
|
45
|
+
project_id: {
|
|
46
|
+
type: string;
|
|
47
|
+
};
|
|
48
|
+
namespace: {
|
|
49
|
+
type: string;
|
|
50
|
+
};
|
|
51
|
+
version: {
|
|
52
|
+
type: string;
|
|
53
|
+
minimum: number;
|
|
54
|
+
};
|
|
55
|
+
tables: {
|
|
56
|
+
type: string;
|
|
57
|
+
patternProperties: {
|
|
58
|
+
"^[a-zA-Z0-9_]+$": {
|
|
59
|
+
type: string;
|
|
60
|
+
properties: {
|
|
61
|
+
name: {
|
|
62
|
+
type: string;
|
|
63
|
+
};
|
|
64
|
+
type: {
|
|
65
|
+
type: string;
|
|
66
|
+
enum: string[];
|
|
67
|
+
};
|
|
68
|
+
fields: {
|
|
69
|
+
type: string;
|
|
70
|
+
patternProperties: {
|
|
71
|
+
"^[a-zA-Z0-9_]+$": {
|
|
72
|
+
type: string;
|
|
73
|
+
properties: {
|
|
74
|
+
type: {
|
|
75
|
+
type: string;
|
|
76
|
+
enum: string[];
|
|
77
|
+
};
|
|
78
|
+
indexed: {
|
|
79
|
+
type: string;
|
|
80
|
+
};
|
|
81
|
+
required: {
|
|
82
|
+
type: string;
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
required: string[];
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
additionalProperties: boolean;
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
required: string[];
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
additionalProperties: boolean;
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
required: string[];
|
|
98
|
+
};
|
|
99
|
+
type Schema = typeof basicJsonSchema;
|
|
100
|
+
declare function generateEmptySchema(): void;
|
|
101
|
+
/**
|
|
102
|
+
* Validate a schema
|
|
103
|
+
* only checks if the schema is formatted correctly, not if can be published
|
|
104
|
+
* @param schema - The schema to validate
|
|
105
|
+
* @returns {valid: boolean, errors: any[]} - The validation result
|
|
106
|
+
*/
|
|
107
|
+
declare function validateSchema(schema: Schema): {
|
|
108
|
+
valid: boolean;
|
|
109
|
+
errors: ErrorObject[];
|
|
110
|
+
};
|
|
111
|
+
declare function validateData(schema: any, table: string, data: Record<string, any>, checkRequired?: boolean): {
|
|
112
|
+
valid: boolean;
|
|
113
|
+
errors: ErrorObject<string, Record<string, any>, unknown>[];
|
|
114
|
+
message: string;
|
|
115
|
+
} | {
|
|
116
|
+
valid: boolean;
|
|
117
|
+
errors: {
|
|
118
|
+
message: string;
|
|
119
|
+
}[];
|
|
120
|
+
message: string;
|
|
121
|
+
} | {
|
|
122
|
+
valid: boolean;
|
|
123
|
+
errors: never[];
|
|
124
|
+
message?: undefined;
|
|
125
|
+
};
|
|
126
|
+
|
|
40
127
|
declare function useQuery(queryable: any): any;
|
|
128
|
+
declare const sc: {
|
|
129
|
+
validateSchema: typeof validateSchema;
|
|
130
|
+
validateData: typeof validateData;
|
|
131
|
+
generateEmptySchema: typeof generateEmptySchema;
|
|
132
|
+
};
|
|
41
133
|
|
|
42
|
-
export { BasicProvider, useBasic, useQuery };
|
|
134
|
+
export { BasicProvider, sc, useBasic, useQuery };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import React from 'react';
|
|
3
|
+
import { ErrorObject } from 'ajv';
|
|
3
4
|
|
|
4
5
|
declare enum DBStatus {
|
|
5
6
|
LOADING = "LOADING",
|
|
@@ -37,6 +38,97 @@ declare function useBasic(): {
|
|
|
37
38
|
dbStatus: DBStatus;
|
|
38
39
|
};
|
|
39
40
|
|
|
41
|
+
declare const basicJsonSchema: {
|
|
42
|
+
$schema: string;
|
|
43
|
+
type: string;
|
|
44
|
+
properties: {
|
|
45
|
+
project_id: {
|
|
46
|
+
type: string;
|
|
47
|
+
};
|
|
48
|
+
namespace: {
|
|
49
|
+
type: string;
|
|
50
|
+
};
|
|
51
|
+
version: {
|
|
52
|
+
type: string;
|
|
53
|
+
minimum: number;
|
|
54
|
+
};
|
|
55
|
+
tables: {
|
|
56
|
+
type: string;
|
|
57
|
+
patternProperties: {
|
|
58
|
+
"^[a-zA-Z0-9_]+$": {
|
|
59
|
+
type: string;
|
|
60
|
+
properties: {
|
|
61
|
+
name: {
|
|
62
|
+
type: string;
|
|
63
|
+
};
|
|
64
|
+
type: {
|
|
65
|
+
type: string;
|
|
66
|
+
enum: string[];
|
|
67
|
+
};
|
|
68
|
+
fields: {
|
|
69
|
+
type: string;
|
|
70
|
+
patternProperties: {
|
|
71
|
+
"^[a-zA-Z0-9_]+$": {
|
|
72
|
+
type: string;
|
|
73
|
+
properties: {
|
|
74
|
+
type: {
|
|
75
|
+
type: string;
|
|
76
|
+
enum: string[];
|
|
77
|
+
};
|
|
78
|
+
indexed: {
|
|
79
|
+
type: string;
|
|
80
|
+
};
|
|
81
|
+
required: {
|
|
82
|
+
type: string;
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
required: string[];
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
additionalProperties: boolean;
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
required: string[];
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
additionalProperties: boolean;
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
required: string[];
|
|
98
|
+
};
|
|
99
|
+
type Schema = typeof basicJsonSchema;
|
|
100
|
+
declare function generateEmptySchema(): void;
|
|
101
|
+
/**
|
|
102
|
+
* Validate a schema
|
|
103
|
+
* only checks if the schema is formatted correctly, not if can be published
|
|
104
|
+
* @param schema - The schema to validate
|
|
105
|
+
* @returns {valid: boolean, errors: any[]} - The validation result
|
|
106
|
+
*/
|
|
107
|
+
declare function validateSchema(schema: Schema): {
|
|
108
|
+
valid: boolean;
|
|
109
|
+
errors: ErrorObject[];
|
|
110
|
+
};
|
|
111
|
+
declare function validateData(schema: any, table: string, data: Record<string, any>, checkRequired?: boolean): {
|
|
112
|
+
valid: boolean;
|
|
113
|
+
errors: ErrorObject<string, Record<string, any>, unknown>[];
|
|
114
|
+
message: string;
|
|
115
|
+
} | {
|
|
116
|
+
valid: boolean;
|
|
117
|
+
errors: {
|
|
118
|
+
message: string;
|
|
119
|
+
}[];
|
|
120
|
+
message: string;
|
|
121
|
+
} | {
|
|
122
|
+
valid: boolean;
|
|
123
|
+
errors: never[];
|
|
124
|
+
message?: undefined;
|
|
125
|
+
};
|
|
126
|
+
|
|
40
127
|
declare function useQuery(queryable: any): any;
|
|
128
|
+
declare const sc: {
|
|
129
|
+
validateSchema: typeof validateSchema;
|
|
130
|
+
validateData: typeof validateData;
|
|
131
|
+
generateEmptySchema: typeof generateEmptySchema;
|
|
132
|
+
};
|
|
41
133
|
|
|
42
|
-
export { BasicProvider, useBasic, useQuery };
|
|
134
|
+
export { BasicProvider, sc, useBasic, useQuery };
|
package/dist/index.js
CHANGED
|
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var src_exports = {};
|
|
32
32
|
__export(src_exports, {
|
|
33
33
|
BasicProvider: () => BasicProvider,
|
|
34
|
+
sc: () => sc,
|
|
34
35
|
useBasic: () => useBasic,
|
|
35
36
|
useQuery: () => useQuery
|
|
36
37
|
});
|
|
@@ -50,8 +51,7 @@ var import_dexie_observable = require("dexie-observable");
|
|
|
50
51
|
var import_dexie = require("dexie");
|
|
51
52
|
|
|
52
53
|
// src/config.ts
|
|
53
|
-
var
|
|
54
|
-
var SERVER_URL = "http://localhost:3000";
|
|
54
|
+
var SERVER_URL = "https://api.basic.tech";
|
|
55
55
|
var log = (...args) => {
|
|
56
56
|
try {
|
|
57
57
|
if (localStorage.getItem("basic_debug") === "true") {
|
|
@@ -60,65 +60,6 @@ var log = (...args) => {
|
|
|
60
60
|
} catch (e) {
|
|
61
61
|
}
|
|
62
62
|
};
|
|
63
|
-
var basicJsonSchema = {
|
|
64
|
-
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
65
|
-
"type": "object",
|
|
66
|
-
"properties": {
|
|
67
|
-
"project_id": {
|
|
68
|
-
"type": "string"
|
|
69
|
-
},
|
|
70
|
-
"namespace": {
|
|
71
|
-
"type": "string"
|
|
72
|
-
},
|
|
73
|
-
"version": {
|
|
74
|
-
"type": "integer",
|
|
75
|
-
"minimum": 0
|
|
76
|
-
},
|
|
77
|
-
"tables": {
|
|
78
|
-
"type": "object",
|
|
79
|
-
"patternProperties": {
|
|
80
|
-
"^[a-zA-Z0-9_]+$": {
|
|
81
|
-
"type": "object",
|
|
82
|
-
"properties": {
|
|
83
|
-
"name": {
|
|
84
|
-
"type": "string"
|
|
85
|
-
},
|
|
86
|
-
"type": {
|
|
87
|
-
"type": "string",
|
|
88
|
-
"enum": ["collection"]
|
|
89
|
-
},
|
|
90
|
-
"fields": {
|
|
91
|
-
"type": "object",
|
|
92
|
-
"patternProperties": {
|
|
93
|
-
"^[a-zA-Z0-9_]+$": {
|
|
94
|
-
"type": "object",
|
|
95
|
-
"properties": {
|
|
96
|
-
"type": {
|
|
97
|
-
"type": "string"
|
|
98
|
-
},
|
|
99
|
-
"primary": {
|
|
100
|
-
"type": "boolean"
|
|
101
|
-
},
|
|
102
|
-
"indexed": {
|
|
103
|
-
"type": "boolean"
|
|
104
|
-
}
|
|
105
|
-
},
|
|
106
|
-
"required": ["type"]
|
|
107
|
-
}
|
|
108
|
-
},
|
|
109
|
-
"additionalProperties": true
|
|
110
|
-
}
|
|
111
|
-
},
|
|
112
|
-
"required": ["fields"]
|
|
113
|
-
}
|
|
114
|
-
},
|
|
115
|
-
"additionalProperties": true
|
|
116
|
-
}
|
|
117
|
-
},
|
|
118
|
-
"required": ["project_id", "version", "tables"]
|
|
119
|
-
};
|
|
120
|
-
var ajv = new import_ajv.default();
|
|
121
|
-
var validator = ajv.compile(basicJsonSchema);
|
|
122
63
|
|
|
123
64
|
// src/sync/syncProtocol.js
|
|
124
65
|
var syncProtocol = function() {
|
|
@@ -223,6 +164,117 @@ var syncProtocol = function() {
|
|
|
223
164
|
});
|
|
224
165
|
};
|
|
225
166
|
|
|
167
|
+
// src/schema.ts
|
|
168
|
+
var import_ajv = __toESM(require("ajv"));
|
|
169
|
+
var basicJsonSchema = {
|
|
170
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
171
|
+
"type": "object",
|
|
172
|
+
"properties": {
|
|
173
|
+
"project_id": {
|
|
174
|
+
"type": "string"
|
|
175
|
+
},
|
|
176
|
+
"namespace": {
|
|
177
|
+
"type": "string"
|
|
178
|
+
},
|
|
179
|
+
"version": {
|
|
180
|
+
"type": "integer",
|
|
181
|
+
"minimum": 0
|
|
182
|
+
},
|
|
183
|
+
"tables": {
|
|
184
|
+
"type": "object",
|
|
185
|
+
"patternProperties": {
|
|
186
|
+
"^[a-zA-Z0-9_]+$": {
|
|
187
|
+
"type": "object",
|
|
188
|
+
"properties": {
|
|
189
|
+
"name": {
|
|
190
|
+
"type": "string"
|
|
191
|
+
},
|
|
192
|
+
"type": {
|
|
193
|
+
"type": "string",
|
|
194
|
+
"enum": ["collection"]
|
|
195
|
+
},
|
|
196
|
+
"fields": {
|
|
197
|
+
"type": "object",
|
|
198
|
+
"patternProperties": {
|
|
199
|
+
"^[a-zA-Z0-9_]+$": {
|
|
200
|
+
"type": "object",
|
|
201
|
+
"properties": {
|
|
202
|
+
"type": {
|
|
203
|
+
"type": "string",
|
|
204
|
+
"enum": ["string", "boolean", "number", "json"]
|
|
205
|
+
},
|
|
206
|
+
"indexed": {
|
|
207
|
+
"type": "boolean"
|
|
208
|
+
},
|
|
209
|
+
"required": {
|
|
210
|
+
"type": "boolean"
|
|
211
|
+
}
|
|
212
|
+
},
|
|
213
|
+
"required": ["type"]
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
"additionalProperties": true
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
"required": ["fields"]
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
"additionalProperties": true
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
"required": ["project_id", "version", "tables"]
|
|
226
|
+
};
|
|
227
|
+
var ajv = new import_ajv.default();
|
|
228
|
+
var validator = ajv.compile(basicJsonSchema);
|
|
229
|
+
function generateEmptySchema() {
|
|
230
|
+
}
|
|
231
|
+
function validateSchema(schema) {
|
|
232
|
+
const v = validator(schema);
|
|
233
|
+
return {
|
|
234
|
+
valid: v,
|
|
235
|
+
errors: validator.errors || []
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
function validateData(schema, table, data, checkRequired = true) {
|
|
239
|
+
const valid = validateSchema(schema);
|
|
240
|
+
if (!valid.valid) {
|
|
241
|
+
return { valid: false, errors: valid.errors, message: "Schema is invalid" };
|
|
242
|
+
}
|
|
243
|
+
const tableSchema = schema.tables[table];
|
|
244
|
+
if (!tableSchema) {
|
|
245
|
+
return { valid: false, errors: [{ message: `Table ${table} not found in schema` }], message: "Table not found" };
|
|
246
|
+
}
|
|
247
|
+
for (const [fieldName, fieldValue] of Object.entries(data)) {
|
|
248
|
+
const fieldSchema = tableSchema.fields[fieldName];
|
|
249
|
+
if (!fieldSchema) {
|
|
250
|
+
return {
|
|
251
|
+
valid: false,
|
|
252
|
+
errors: [{ message: `Field ${fieldName} not found in schema` }],
|
|
253
|
+
message: "Invalid field"
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
const schemaType = fieldSchema.type;
|
|
257
|
+
const valueType = typeof fieldValue;
|
|
258
|
+
if (schemaType === "string" && valueType !== "string" || schemaType === "number" && valueType !== "number" || schemaType === "boolean" && valueType !== "boolean" || schemaType === "json" && valueType !== "object") {
|
|
259
|
+
return {
|
|
260
|
+
valid: false,
|
|
261
|
+
errors: [{
|
|
262
|
+
message: `Field ${fieldName} should be type ${schemaType}, got ${valueType}`
|
|
263
|
+
}],
|
|
264
|
+
message: "invalid type"
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
if (checkRequired) {
|
|
269
|
+
for (const [fieldName, fieldSchema] of Object.entries(tableSchema.fields)) {
|
|
270
|
+
if (fieldSchema.required && !data[fieldName]) {
|
|
271
|
+
return { valid: false, errors: [{ message: `Field ${fieldName} is required` }], message: "Required field missing" };
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return { valid: true, errors: [] };
|
|
276
|
+
}
|
|
277
|
+
|
|
226
278
|
// src/sync/index.ts
|
|
227
279
|
syncProtocol();
|
|
228
280
|
var BasicSync = class extends import_dexie2.Dexie {
|
|
@@ -290,19 +342,33 @@ var BasicSync = class extends import_dexie2.Dexie {
|
|
|
290
342
|
ref: this.table(name),
|
|
291
343
|
// --- WRITE ---- //
|
|
292
344
|
add: (data) => {
|
|
293
|
-
|
|
345
|
+
const valid = validateData(this.basic_schema, name, data);
|
|
346
|
+
if (!valid.valid) {
|
|
347
|
+
log("Invalid data", valid);
|
|
348
|
+
return Promise.reject({ ...valid });
|
|
349
|
+
}
|
|
294
350
|
return this.table(name).add({
|
|
295
351
|
id: (0, import_uuid.v7)(),
|
|
296
352
|
...data
|
|
297
353
|
});
|
|
298
354
|
},
|
|
299
355
|
put: (data) => {
|
|
356
|
+
const valid = validateData(this.basic_schema, name, data);
|
|
357
|
+
if (!valid.valid) {
|
|
358
|
+
log("Invalid data", valid);
|
|
359
|
+
return Promise.reject({ ...valid });
|
|
360
|
+
}
|
|
300
361
|
return this.table(name).put({
|
|
301
362
|
id: (0, import_uuid.v7)(),
|
|
302
363
|
...data
|
|
303
364
|
});
|
|
304
365
|
},
|
|
305
366
|
update: (id, data) => {
|
|
367
|
+
const valid = validateData(this.basic_schema, name, data, false);
|
|
368
|
+
if (!valid.valid) {
|
|
369
|
+
log("Invalid data", valid);
|
|
370
|
+
return Promise.reject({ ...valid });
|
|
371
|
+
}
|
|
306
372
|
return this.table(name).update(id, data);
|
|
307
373
|
},
|
|
308
374
|
delete: (id) => {
|
|
@@ -414,11 +480,12 @@ function BasicProvider({ children, project_id, schema, debug = false }) {
|
|
|
414
480
|
const syncRef = (0, import_react.useRef)(null);
|
|
415
481
|
(0, import_react.useEffect)(() => {
|
|
416
482
|
function initDb() {
|
|
417
|
-
|
|
418
|
-
|
|
483
|
+
const valid = validateSchema(schema);
|
|
484
|
+
if (!valid.valid) {
|
|
485
|
+
log("Basic Schema is invalid!", valid.errors);
|
|
419
486
|
console.group("Schema Errors");
|
|
420
487
|
let errorMessage = "";
|
|
421
|
-
|
|
488
|
+
valid.errors.forEach((error2, index) => {
|
|
422
489
|
log(`${index + 1}:`, error2.message, ` - at ${error2.instancePath}`);
|
|
423
490
|
errorMessage += `${index + 1}: ${error2.message} - at ${error2.instancePath}
|
|
424
491
|
`;
|
|
@@ -686,9 +753,15 @@ function useQuery(queryable) {
|
|
|
686
753
|
return queryable;
|
|
687
754
|
}, [queryable], []);
|
|
688
755
|
}
|
|
756
|
+
var sc = {
|
|
757
|
+
validateSchema,
|
|
758
|
+
validateData,
|
|
759
|
+
generateEmptySchema
|
|
760
|
+
};
|
|
689
761
|
// Annotate the CommonJS export names for ESM import in node:
|
|
690
762
|
0 && (module.exports = {
|
|
691
763
|
BasicProvider,
|
|
764
|
+
sc,
|
|
692
765
|
useBasic,
|
|
693
766
|
useQuery
|
|
694
767
|
});
|