@basictech/react 0.2.0-beta.10 → 0.2.0-beta.11
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/.turbo/turbo-build.log +10 -10
- package/changelog.md +11 -0
- package/dist/index.d.mts +2 -96
- package/dist/index.d.ts +2 -96
- package/dist/index.js +4 -23
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4 -21
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/AuthContext.tsx +1 -1
- package/src/index.ts +30 -17
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
|
-
> @basictech/react@0.2.0-beta.
|
|
3
|
+
> @basictech/react@0.2.0-beta.10 build
|
|
4
4
|
> tsup
|
|
5
5
|
|
|
6
6
|
[34mCLI[39m Building entry: src/index.ts
|
|
@@ -11,13 +11,13 @@
|
|
|
11
11
|
[34mCLI[39m Cleaning output folder
|
|
12
12
|
[34mCJS[39m Build start
|
|
13
13
|
[34mESM[39m Build start
|
|
14
|
-
[32mESM[39m [1mdist/index.mjs [22m[32m22.
|
|
15
|
-
[32mESM[39m [1mdist/index.mjs.map [22m[32m51.
|
|
16
|
-
[32mESM[39m ⚡️ Build success in
|
|
17
|
-
[32mCJS[39m [1mdist/index.js [22m[32m24.
|
|
18
|
-
[32mCJS[39m [1mdist/index.js.map [22m[32m51.
|
|
19
|
-
[32mCJS[39m ⚡️ Build success in
|
|
14
|
+
[32mESM[39m [1mdist/index.mjs [22m[32m22.39 KB[39m
|
|
15
|
+
[32mESM[39m [1mdist/index.mjs.map [22m[32m51.69 KB[39m
|
|
16
|
+
[32mESM[39m ⚡️ Build success in 31ms
|
|
17
|
+
[32mCJS[39m [1mdist/index.js [22m[32m24.60 KB[39m
|
|
18
|
+
[32mCJS[39m [1mdist/index.js.map [22m[32m51.73 KB[39m
|
|
19
|
+
[32mCJS[39m ⚡️ Build success in 31ms
|
|
20
20
|
[34mDTS[39m Build start
|
|
21
|
-
[32mDTS[39m ⚡️ Build success in
|
|
22
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[
|
|
23
|
-
[32mDTS[39m [1mdist/index.d.mts [22m[
|
|
21
|
+
[32mDTS[39m ⚡️ Build success in 1194ms
|
|
22
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m1006.00 B[39m
|
|
23
|
+
[32mDTS[39m [1mdist/index.d.mts [22m[32m1006.00 B[39m
|
package/changelog.md
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
|
|
4
|
-
export { default as hello } from '@basictech/schema';
|
|
3
|
+
export { useLiveQuery as useQuery } from 'dexie-react-hooks';
|
|
5
4
|
|
|
6
5
|
declare enum DBStatus {
|
|
7
6
|
LOADING = "LOADING",
|
|
@@ -39,97 +38,4 @@ declare function useBasic(): {
|
|
|
39
38
|
dbStatus: DBStatus;
|
|
40
39
|
};
|
|
41
40
|
|
|
42
|
-
|
|
43
|
-
$schema: string;
|
|
44
|
-
type: string;
|
|
45
|
-
properties: {
|
|
46
|
-
project_id: {
|
|
47
|
-
type: string;
|
|
48
|
-
};
|
|
49
|
-
namespace: {
|
|
50
|
-
type: string;
|
|
51
|
-
};
|
|
52
|
-
version: {
|
|
53
|
-
type: string;
|
|
54
|
-
minimum: number;
|
|
55
|
-
};
|
|
56
|
-
tables: {
|
|
57
|
-
type: string;
|
|
58
|
-
patternProperties: {
|
|
59
|
-
"^[a-zA-Z0-9_]+$": {
|
|
60
|
-
type: string;
|
|
61
|
-
properties: {
|
|
62
|
-
name: {
|
|
63
|
-
type: string;
|
|
64
|
-
};
|
|
65
|
-
type: {
|
|
66
|
-
type: string;
|
|
67
|
-
enum: string[];
|
|
68
|
-
};
|
|
69
|
-
fields: {
|
|
70
|
-
type: string;
|
|
71
|
-
patternProperties: {
|
|
72
|
-
"^[a-zA-Z0-9_]+$": {
|
|
73
|
-
type: string;
|
|
74
|
-
properties: {
|
|
75
|
-
type: {
|
|
76
|
-
type: string;
|
|
77
|
-
enum: string[];
|
|
78
|
-
};
|
|
79
|
-
indexed: {
|
|
80
|
-
type: string;
|
|
81
|
-
};
|
|
82
|
-
required: {
|
|
83
|
-
type: string;
|
|
84
|
-
};
|
|
85
|
-
};
|
|
86
|
-
required: string[];
|
|
87
|
-
};
|
|
88
|
-
};
|
|
89
|
-
additionalProperties: boolean;
|
|
90
|
-
};
|
|
91
|
-
};
|
|
92
|
-
required: string[];
|
|
93
|
-
};
|
|
94
|
-
};
|
|
95
|
-
additionalProperties: boolean;
|
|
96
|
-
};
|
|
97
|
-
};
|
|
98
|
-
required: string[];
|
|
99
|
-
};
|
|
100
|
-
type Schema = typeof basicJsonSchema;
|
|
101
|
-
declare function generateEmptySchema(): void;
|
|
102
|
-
/**
|
|
103
|
-
* Validate a schema
|
|
104
|
-
* only checks if the schema is formatted correctly, not if can be published
|
|
105
|
-
* @param schema - The schema to validate
|
|
106
|
-
* @returns {valid: boolean, errors: any[]} - The validation result
|
|
107
|
-
*/
|
|
108
|
-
declare function validateSchema(schema: Schema): {
|
|
109
|
-
valid: boolean;
|
|
110
|
-
errors: ErrorObject[];
|
|
111
|
-
};
|
|
112
|
-
declare function validateData(schema: any, table: string, data: Record<string, any>, checkRequired?: boolean): {
|
|
113
|
-
valid: boolean;
|
|
114
|
-
errors: ErrorObject<string, Record<string, any>, unknown>[];
|
|
115
|
-
message: string;
|
|
116
|
-
} | {
|
|
117
|
-
valid: boolean;
|
|
118
|
-
errors: {
|
|
119
|
-
message: string;
|
|
120
|
-
}[];
|
|
121
|
-
message: string;
|
|
122
|
-
} | {
|
|
123
|
-
valid: boolean;
|
|
124
|
-
errors: never[];
|
|
125
|
-
message?: undefined;
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
declare function useQuery(queryable: any): any;
|
|
129
|
-
declare const sc: {
|
|
130
|
-
validateSchema: typeof validateSchema;
|
|
131
|
-
validateData: typeof validateData;
|
|
132
|
-
generateEmptySchema: typeof generateEmptySchema;
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
export { BasicProvider, sc, useBasic, useQuery };
|
|
41
|
+
export { BasicProvider, useBasic };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
|
|
4
|
-
export { default as hello } from '@basictech/schema';
|
|
3
|
+
export { useLiveQuery as useQuery } from 'dexie-react-hooks';
|
|
5
4
|
|
|
6
5
|
declare enum DBStatus {
|
|
7
6
|
LOADING = "LOADING",
|
|
@@ -39,97 +38,4 @@ declare function useBasic(): {
|
|
|
39
38
|
dbStatus: DBStatus;
|
|
40
39
|
};
|
|
41
40
|
|
|
42
|
-
|
|
43
|
-
$schema: string;
|
|
44
|
-
type: string;
|
|
45
|
-
properties: {
|
|
46
|
-
project_id: {
|
|
47
|
-
type: string;
|
|
48
|
-
};
|
|
49
|
-
namespace: {
|
|
50
|
-
type: string;
|
|
51
|
-
};
|
|
52
|
-
version: {
|
|
53
|
-
type: string;
|
|
54
|
-
minimum: number;
|
|
55
|
-
};
|
|
56
|
-
tables: {
|
|
57
|
-
type: string;
|
|
58
|
-
patternProperties: {
|
|
59
|
-
"^[a-zA-Z0-9_]+$": {
|
|
60
|
-
type: string;
|
|
61
|
-
properties: {
|
|
62
|
-
name: {
|
|
63
|
-
type: string;
|
|
64
|
-
};
|
|
65
|
-
type: {
|
|
66
|
-
type: string;
|
|
67
|
-
enum: string[];
|
|
68
|
-
};
|
|
69
|
-
fields: {
|
|
70
|
-
type: string;
|
|
71
|
-
patternProperties: {
|
|
72
|
-
"^[a-zA-Z0-9_]+$": {
|
|
73
|
-
type: string;
|
|
74
|
-
properties: {
|
|
75
|
-
type: {
|
|
76
|
-
type: string;
|
|
77
|
-
enum: string[];
|
|
78
|
-
};
|
|
79
|
-
indexed: {
|
|
80
|
-
type: string;
|
|
81
|
-
};
|
|
82
|
-
required: {
|
|
83
|
-
type: string;
|
|
84
|
-
};
|
|
85
|
-
};
|
|
86
|
-
required: string[];
|
|
87
|
-
};
|
|
88
|
-
};
|
|
89
|
-
additionalProperties: boolean;
|
|
90
|
-
};
|
|
91
|
-
};
|
|
92
|
-
required: string[];
|
|
93
|
-
};
|
|
94
|
-
};
|
|
95
|
-
additionalProperties: boolean;
|
|
96
|
-
};
|
|
97
|
-
};
|
|
98
|
-
required: string[];
|
|
99
|
-
};
|
|
100
|
-
type Schema = typeof basicJsonSchema;
|
|
101
|
-
declare function generateEmptySchema(): void;
|
|
102
|
-
/**
|
|
103
|
-
* Validate a schema
|
|
104
|
-
* only checks if the schema is formatted correctly, not if can be published
|
|
105
|
-
* @param schema - The schema to validate
|
|
106
|
-
* @returns {valid: boolean, errors: any[]} - The validation result
|
|
107
|
-
*/
|
|
108
|
-
declare function validateSchema(schema: Schema): {
|
|
109
|
-
valid: boolean;
|
|
110
|
-
errors: ErrorObject[];
|
|
111
|
-
};
|
|
112
|
-
declare function validateData(schema: any, table: string, data: Record<string, any>, checkRequired?: boolean): {
|
|
113
|
-
valid: boolean;
|
|
114
|
-
errors: ErrorObject<string, Record<string, any>, unknown>[];
|
|
115
|
-
message: string;
|
|
116
|
-
} | {
|
|
117
|
-
valid: boolean;
|
|
118
|
-
errors: {
|
|
119
|
-
message: string;
|
|
120
|
-
}[];
|
|
121
|
-
message: string;
|
|
122
|
-
} | {
|
|
123
|
-
valid: boolean;
|
|
124
|
-
errors: never[];
|
|
125
|
-
message?: undefined;
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
declare function useQuery(queryable: any): any;
|
|
129
|
-
declare const sc: {
|
|
130
|
-
validateSchema: typeof validateSchema;
|
|
131
|
-
validateData: typeof validateData;
|
|
132
|
-
generateEmptySchema: typeof generateEmptySchema;
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
export { BasicProvider, sc, useBasic, useQuery };
|
|
41
|
+
export { BasicProvider, useBasic };
|
package/dist/index.js
CHANGED
|
@@ -31,10 +31,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var src_exports = {};
|
|
32
32
|
__export(src_exports, {
|
|
33
33
|
BasicProvider: () => BasicProvider,
|
|
34
|
-
hello: () => import_schema4.default,
|
|
35
|
-
sc: () => sc,
|
|
36
34
|
useBasic: () => useBasic,
|
|
37
|
-
useQuery: () =>
|
|
35
|
+
useQuery: () => import_dexie_react_hooks.useLiveQuery
|
|
38
36
|
});
|
|
39
37
|
module.exports = __toCommonJS(src_exports);
|
|
40
38
|
|
|
@@ -52,7 +50,7 @@ var import_dexie_observable = require("dexie-observable");
|
|
|
52
50
|
var import_dexie = require("dexie");
|
|
53
51
|
|
|
54
52
|
// src/config.ts
|
|
55
|
-
var SERVER_URL = "
|
|
53
|
+
var SERVER_URL = "https://api.basic.tech";
|
|
56
54
|
var log = (...args) => {
|
|
57
55
|
try {
|
|
58
56
|
if (localStorage.getItem("basic_debug") === "true") {
|
|
@@ -227,8 +225,6 @@ var basicJsonSchema = {
|
|
|
227
225
|
};
|
|
228
226
|
var ajv = new import_ajv.default();
|
|
229
227
|
var validator = ajv.compile(basicJsonSchema);
|
|
230
|
-
function generateEmptySchema() {
|
|
231
|
-
}
|
|
232
228
|
function validateSchema(schema) {
|
|
233
229
|
const v = validator(schema);
|
|
234
230
|
return {
|
|
@@ -441,6 +437,7 @@ async function deleteRecord({ projectId, accountId, tableName, id, token }) {
|
|
|
441
437
|
}
|
|
442
438
|
|
|
443
439
|
// src/AuthContext.tsx
|
|
440
|
+
var import_schema2 = require("@basictech/schema");
|
|
444
441
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
445
442
|
var BasicContext = (0, import_react.createContext)({
|
|
446
443
|
unicorn: "\u{1F984}",
|
|
@@ -485,7 +482,7 @@ function BasicProvider({ children, project_id, schema, debug = false }) {
|
|
|
485
482
|
const syncRef = (0, import_react.useRef)(null);
|
|
486
483
|
(0, import_react.useEffect)(() => {
|
|
487
484
|
function initDb() {
|
|
488
|
-
const valid = validateSchema(schema);
|
|
485
|
+
const valid = (0, import_schema2.validateSchema)(schema);
|
|
489
486
|
if (!valid.valid) {
|
|
490
487
|
log("Basic Schema is invalid!", valid.errors);
|
|
491
488
|
console.group("Schema Errors");
|
|
@@ -753,25 +750,9 @@ function useBasic() {
|
|
|
753
750
|
|
|
754
751
|
// src/index.ts
|
|
755
752
|
var import_dexie_react_hooks = require("dexie-react-hooks");
|
|
756
|
-
var import_schema4 = __toESM(require("@basictech/schema"));
|
|
757
|
-
function useQuery(queryable) {
|
|
758
|
-
return (0, import_dexie_react_hooks.useLiveQuery)(() => {
|
|
759
|
-
if (typeof queryable === "function") {
|
|
760
|
-
return queryable();
|
|
761
|
-
}
|
|
762
|
-
return queryable;
|
|
763
|
-
}, [queryable], []);
|
|
764
|
-
}
|
|
765
|
-
var sc = {
|
|
766
|
-
validateSchema,
|
|
767
|
-
validateData,
|
|
768
|
-
generateEmptySchema
|
|
769
|
-
};
|
|
770
753
|
// Annotate the CommonJS export names for ESM import in node:
|
|
771
754
|
0 && (module.exports = {
|
|
772
755
|
BasicProvider,
|
|
773
|
-
hello,
|
|
774
|
-
sc,
|
|
775
756
|
useBasic,
|
|
776
757
|
useQuery
|
|
777
758
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/AuthContext.tsx","../src/sync/index.ts","../src/sync/syncProtocol.js","../src/config.ts","../src/schema.ts","../src/db.ts"],"sourcesContent":["import { useBasic, BasicProvider } from \"./AuthContext\";\nimport { useLiveQuery } from \"dexie-react-hooks\";\nimport { validateSchema, validateData, generateEmptySchema } from \"./schema\";\nimport hello from \"@basictech/schema\"\n\n\nfunction useQuery(queryable: any) {\n return useLiveQuery(() => {\n if (typeof queryable === 'function') {\n return queryable();\n }\n return queryable;\n }, [queryable], []);\n}\n\n\nconst sc = { \n validateSchema: validateSchema,\n validateData: validateData,\n generateEmptySchema: generateEmptySchema\n}\n\nexport {\n useBasic, BasicProvider, useQuery, sc, hello\n}\n","// @ts-nocheck\n\nimport React, { createContext, useContext, useEffect, useState, useRef } from 'react'\nimport { jwtDecode } from 'jwt-decode'\n\nimport { BasicSync } from './sync'\nimport { get, add, update, deleteRecord } from './db'\nimport { validateSchema } from './schema'\n\nimport { log } from './config'\n\n/*\nschema todo:\n field types\n array types\n relations\n*/\n\n\n// const example = {\n// project_id: '123',\n// version: 0,\n// tables: {\n// example: {\n// name: 'example',\n// type: 'collection',\n// fields: {\n// id: {\n// type: 'uuid',\n// primary: true,\n// },\n// value: {\n// type: 'string',\n// indexed: true,\n// },\n// }\n// }\n// }\n// }\n\n\ntype BasicSyncType = {\n basic_schema: any;\n connect: (options: { access_token: string }) => void;\n debugeroo: () => void;\n collection: (name: string) => {\n ref: {\n toArray: () => Promise<any[]>;\n count: () => Promise<number>;\n };\n };\n [key: string]: any; // For other potential methods and properties\n};\n\n\nenum DBStatus {\n LOADING = \"LOADING\",\n OFFLINE = \"OFFLINE\",\n CONNECTING = \"CONNECTING\",\n ONLINE = \"ONLINE\",\n SYNCING = \"SYNCING\",\n ERROR = \"ERROR\"\n}\n\ntype User = {\n name?: string,\n email?: string,\n id?: string,\n primaryEmailAddress?: {\n emailAddress: string\n },\n fullName?: string\n}\ntype Token = {\n access_token: string,\n token_type: string,\n expires_in: number,\n refresh: string,\n}\n\nexport const BasicContext = createContext<{\n unicorn: string,\n isAuthReady: boolean,\n isSignedIn: boolean,\n user: User | null,\n signout: () => void,\n signin: () => void,\n getToken: () => Promise<string>,\n getSignInLink: () => string,\n db: any,\n dbStatus: DBStatus\n}>({\n unicorn: \"🦄\",\n isAuthReady: false,\n isSignedIn: false,\n user: null,\n signout: () => { },\n signin: () => { },\n getToken: () => new Promise(() => { }),\n getSignInLink: () => \"\",\n db: {},\n dbStatus: DBStatus.LOADING\n});\n\nconst EmptyDB: BasicSyncType = {\n isOpen: false,\n collection: () => {\n return {\n ref: {\n toArray: () => [],\n count: () => 0\n }\n }\n }\n}\n\n\nfunction getSyncStatus(statusCode: number): string {\n switch (statusCode) {\n case -1:\n return \"ERROR\";\n case 0:\n return \"OFFLINE\";\n case 1:\n return \"CONNECTING\";\n case 2:\n return \"ONLINE\";\n case 3:\n return \"SYNCING\";\n case 4:\n return \"ERROR_WILL_RETRY\";\n default:\n return \"UNKNOWN\";\n }\n}\n\ntype ErrorObject = {\n code: string;\n title: string;\n message: string;\n}\n\nexport function BasicProvider({ children, project_id, schema, debug = false }: { children: React.ReactNode, project_id: string, schema: any, debug?: boolean }) {\n const [isAuthReady, setIsAuthReady] = useState(false)\n const [isSignedIn, setIsSignedIn] = useState<boolean>(false)\n const [token, setToken] = useState<Token | null>(null)\n const [user, setUser] = useState<User>({})\n\n const [dbStatus, setDbStatus] = useState<DBStatus>(DBStatus.LOADING)\n const [error, setError] = useState<ErrorObject | null>(null)\n\n const syncRef = useRef<BasicSync | null>(null);\n\n\n useEffect(() => {\n function initDb() {\n const valid = validateSchema(schema)\n if (!valid.valid) {\n log('Basic Schema is invalid!', valid.errors)\n console.group('Schema Errors')\n let errorMessage = ''\n valid.errors.forEach((error, index) => {\n log(`${index + 1}:`, error.message, ` - at ${error.instancePath}`)\n errorMessage += `${index + 1}: ${error.message} - at ${error.instancePath}\\n`\n })\n console.groupEnd('Schema Errors')\n setError({\n code: 'schema_invalid',\n title: 'Basic Schema is invalid!',\n message: errorMessage\n })\n return null\n }\n\n if (!syncRef.current) {\n log('Initializing BasicDB')\n syncRef.current = new BasicSync('basicdb', { schema: schema });\n\n // log('db is open', syncRef.current.isOpen())\n // syncRef.current.open()\n // .then(() => {\n // log(\"is open now:\", syncRef.current.isOpen())\n // })\n }\n }\n\n initDb()\n }, []);\n\n useEffect(() => {\n if (!syncRef.current) {\n return\n }\n\n // syncRef.current.handleStatusChange((status: number, url: string) => {\n // setDbStatus(getSyncStatus(status))\n // })\n\n syncRef.current.syncable.on('statusChanged', (status: number, url: string) => {\n setDbStatus(getSyncStatus(status))\n })\n\n syncRef.current.syncable.getStatus().then((status) => {\n setDbStatus(getSyncStatus(status))\n })\n }, [syncRef.current])\n\n\n const connectToDb = async () => {\n const tok = await getToken()\n if (!tok) {\n log('no token found')\n return\n }\n\n log('connecting to db...')\n\n // TODO: handle if signed out after connect() is already called\n\n syncRef.current.connect({ access_token: tok })\n .catch((e) => {\n log('error connecting to db', e)\n })\n }\n\n useEffect(() => {\n if (token && syncRef.current && isSignedIn && isSignedIn) {\n connectToDb()\n }\n }, [isSignedIn])\n\n const getSignInLink = () => {\n log('getting sign in link...')\n\n const randomState = Math.random().toString(36).substring(6);\n localStorage.setItem('basic_auth_state', randomState)\n\n let baseUrl = \"https://api.basic.tech/auth/authorize\"\n baseUrl += `?client_id=${project_id}`\n baseUrl += `&redirect_uri=${encodeURIComponent(window.location.href)}`\n baseUrl += `&response_type=code`\n baseUrl += `&scope=openid`\n baseUrl += `&state=${randomState}`\n\n return baseUrl;\n }\n\n const signin = () => {\n log('signing in: ', getSignInLink())\n const signInLink = getSignInLink()\n //todo: change to the other thing?\n window.location.href = signInLink;\n }\n\n const signout = () => {\n log('signing out!')\n setUser({})\n setIsSignedIn(false)\n setToken(null)\n document.cookie = `basic_token=; Secure; SameSite=Strict`;\n localStorage.removeItem('basic_auth_state')\n\n if (syncRef.current) {\n // WIP - BUG - sometimes connects even after signout\n syncRef.current.disconnect()\n }\n }\n\n const getToken = async (): Promise<string> => {\n log('getting token...')\n\n if (!token) {\n log('no token found')\n throw new Error('no token found')\n }\n\n const decoded = jwtDecode(token?.access_token)\n const isExpired = decoded.exp && decoded.exp < Date.now() / 1000\n\n if (isExpired) {\n log('token is expired - refreshing ...')\n const newToken = await fetchToken(token?.refresh)\n return newToken?.access_token || ''\n }\n\n return token?.access_token || ''\n }\n\n function getCookie(name: string) {\n let cookieValue = '';\n if (document.cookie && document.cookie !== '') {\n const cookies = document.cookie.split(';');\n for (let i = 0; i < cookies.length; i++) {\n const cookie = cookies[i].trim();\n if (cookie.substring(0, name.length + 1) === (name + '=')) {\n cookieValue = decodeURIComponent(cookie.substring(name.length + 1));\n break;\n }\n }\n }\n return cookieValue;\n }\n\n const fetchToken = async (code: string) => {\n const token = await fetch('https://api.basic.tech/auth/token', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({ code: code })\n })\n .then(response => response.json())\n .catch(error => log('Error:', error))\n\n if (token.error) {\n log('error fetching token', token.error)\n return\n } else {\n // log('token', token)\n setToken(token)\n }\n return token\n }\n\n useEffect(() => {\n localStorage.setItem('basic_debug', debug ? 'true' : 'false')\n\n try {\n if (window.location.search.includes('code')) {\n let code = window.location?.search?.split('code=')[1].split('&')[0]\n\n const state = localStorage.getItem('basic_auth_state')\n if (!state || state !== window.location.search.split('state=')[1].split('&')[0]) {\n log('error: auth state does not match')\n setIsAuthReady(true)\n\n localStorage.removeItem('basic_auth_state')\n window.history.pushState({}, document.title, \"/\");\n return\n }\n\n localStorage.removeItem('basic_auth_state')\n\n fetchToken(code) \n } else { \n let cookie_token = getCookie('basic_token')\n if (cookie_token !== '') {\n setToken(JSON.parse(cookie_token))\n } else { \n setIsAuthReady(true)\n }\n }\n\n\n } catch (e) {\n log('error getting cookie', e)\n }\n }, [])\n\n useEffect(() => {\n async function fetchUser(acc_token: string) {\n console.info('fetching user')\n const user = await fetch('https://api.basic.tech/auth/userInfo', {\n method: 'GET',\n headers: {\n 'Authorization': `Bearer ${acc_token}`\n }\n })\n .then(response => response.json())\n .catch(error => log('Error:', error))\n\n if (user.error) {\n log('error fetching user', user.error)\n // refreshToken()\n return\n } else {\n // log('user', user)\n document.cookie = `basic_token=${JSON.stringify(token)}; Secure; SameSite=Strict`;\n \n if (window.location.search.includes('code')) {\n window.history.pushState({}, document.title, \"/\");\n }\n \n setUser(user)\n setIsSignedIn(true)\n\n setIsAuthReady(true)\n }\n }\n\n async function checkToken() {\n if (!token) {\n log('error: no user token found')\n\n setIsAuthReady(true)\n return\n }\n\n const decoded = jwtDecode(token?.access_token)\n const isExpired = decoded.exp && decoded.exp < Date.now() / 1000\n\n if (isExpired) {\n log('token is expired - refreshing ...')\n const newToken = await fetchToken(token?.refresh)\n fetchUser(newToken.access_token)\n } else {\n fetchUser(token.access_token)\n }\n }\n\n if (token) {\n checkToken()\n } \n }, [token])\n\n\n const db_ = (tableName: string) => {\n const checkSignIn = () => {\n if (!isSignedIn) {\n throw new Error('cannot use db. user not logged in.')\n }\n }\n\n return {\n get: async () => {\n checkSignIn()\n const tok = await getToken()\n return get({ projectId: project_id, accountId: user.id, tableName: tableName, token: tok })\n },\n add: async (value: any) => {\n checkSignIn()\n const tok = await getToken()\n return add({ projectId: project_id, accountId: user.id, tableName: tableName, value: value, token: tok })\n },\n update: async (id: string, value: any) => {\n checkSignIn()\n const tok = await getToken()\n return update({ projectId: project_id, accountId: user.id, tableName: tableName, id: id, value: value, token: tok })\n },\n delete: async (id: string) => {\n checkSignIn()\n const tok = await getToken()\n return deleteRecord({ projectId: project_id, accountId: user.id, tableName: tableName, id: id, token: tok })\n }\n\n }\n\n }\n\n return (\n <BasicContext.Provider value={{\n unicorn: \"🦄\",\n isAuthReady,\n isSignedIn,\n user,\n signout,\n signin,\n getToken,\n getSignInLink,\n db: syncRef.current,\n dbStatus\n }}>\n {error && <ErrorDisplay error={error} />}\n {syncRef.current ? children : null}\n </BasicContext.Provider>\n )\n}\n\nfunction ErrorDisplay({ error }: { error: ErrorObject }) {\n return <div style={{ \n position: 'absolute',\n top: 20, \n left: 20,\n color: 'black',\n backgroundColor: '#f8d7da',\n border: '1px solid #f5c6cb',\n borderRadius: '4px',\n padding: '20px',\n maxWidth: '400px',\n margin: '20px auto',\n boxShadow: '0 2px 4px rgba(0, 0, 0, 0.1)',\n fontFamily: 'monospace', \n }}>\n <h3 style={{fontSize: '0.8rem', opacity: 0.8}}>code: {error.code}</h3>\n <h1 style={{fontSize: '1.2rem', lineHeight: '1.5'}}>{error.title}</h1>\n <p>{error.message}</p>\n </div>\n}\n\n/*\npossible errors: \n- projectid missing / invalid\n- schema missing / invalid\n*/\n\nexport function useBasic() {\n return useContext(BasicContext);\n}\n","\"use client\"\n\nimport { v7 as uuidv7 } from 'uuid';\nimport { Dexie, PromiseExtended } from 'dexie';\nimport 'dexie-syncable';\nimport 'dexie-observable';\n\nimport { syncProtocol } from './syncProtocol'\nimport { SERVER_URL, log } from '../config'\n\nimport { validateSchema, validateData } from '../schema'\nsyncProtocol()\n\n\n// const DexieSyncStatus = {\n// \"-1\": \"ERROR\",\n// \"0\": \"OFFLINE\",\n// \"1\": \"CONNECTING\",\n// \"2\": \"ONLINE\",\n// \"3\": \"SYNCING\",\n// \"4\": \"ERROR_WILL_RETRY\"\n// }\n\n\n\n\n\nexport class BasicSync extends Dexie {\n basic_schema: any\n\n constructor(name: string, options: any) {\n super(name, options);\n\n // --- INIT SCHEMA --- // \n\n //todo: handle versions?\n\n // TODO: validate schema\n this.basic_schema = options.schema\n this.version(1).stores(this._convertSchemaToDxSchema(this.basic_schema))\n\n this.version(2).stores({})\n // this.verssion\n\n\n // create an alias for toArray\n // @ts-ignore\n this.Collection.prototype.get = this.Collection.prototype.toArray\n\n\n // --- SYNC --- // \n\n // this.syncable.on(\"statusChanged\", (status, url) => { \n // console.log(\"statusChanged\", status, url)\n // })\n\n }\n\n async connect({ access_token }: { access_token: string }) {\n // const WS_URL = \"ws://localhost:3003/ws\"\n const WS_URL = `${SERVER_URL}/ws`\n\n \n // Update sync nodes\n await this.updateSyncNodes();\n \n // Proceed with the WebSocket connection\n \n log('Starting connection...')\n return this.syncable.connect(\"websocket\", WS_URL, { authToken: access_token });\n }\n\n async disconnect() {\n const WS_URL = `${SERVER_URL}/ws`\n\n return this.syncable.disconnect(WS_URL) \n }\n\n private async updateSyncNodes() {\n try {\n const syncNodes = await this.table('_syncNodes').toArray();\n const localSyncNodes = syncNodes.filter(node => node.type === 'local');\n log('Local sync nodes:', localSyncNodes);\n\n if (localSyncNodes.length > 1) {\n\n \n const largestNodeId = Math.max(...localSyncNodes.map(node => node.id));\n // Check if the largest node is already the master\n const largestNode = localSyncNodes.find(node => node.id === largestNodeId);\n if (largestNode && largestNode.isMaster === 1) {\n log('Largest node is already the master. No changes needed.');\n return; // Exit the function early as no changes are needed\n }\n\n\n log('Largest node id:', largestNodeId);\n log('HEISENBUG: More than one local sync node found.')\n\n for (const node of localSyncNodes) {\n log(`Local sync node keys:`, node.id, node.isMaster);\n await this.table('_syncNodes').update(node.id, { isMaster: node.id === largestNodeId ? 1 : 0 });\n\n log(`HEISENBUG: Setting ${node.id} to ${node.id === largestNodeId ? 'master' : '0'}`);\n }\n\n // Add a 1 second delay before returning // i dont think this helps?\n await new Promise(resolve => setTimeout(resolve, 2000));\n\n }\n\n log('Sync nodes updated');\n } catch (error) {\n console.error('Error updating _syncNodes table:', error);\n }\n }\n\n handleStatusChange(fn: any) {\n this.syncable.on(\"statusChanged\", fn)\n }\n\n\n _convertSchemaToDxSchema(schema: any) {\n const stores = Object.entries(schema.tables).map(([key, table]: any) => {\n\n const indexedFields = Object.entries(table.fields).filter(([key, field]: any) => field.indexed).map(([key, field]: any) => `,${key}`).join('')\n return {\n [key]: 'id' + indexedFields\n }\n })\n\n return Object.assign({}, ...stores)\n }\n\n debugeroo() {\n // console.log(\"debugeroo\", this.syncable)\n\n // this.syncable.list().then(x => console.log(x))\n\n // this.syncable\n return this.syncable\n }\n\n collection(name: string) {\n // TODO: check against schema\n\n return {\n\n /**\n * Returns the underlying Dexie table\n * @type {Dexie.Table}\n */\n ref: this.table(name),\n\n // --- WRITE ---- // \n add: (data: any) => {\n // log(\"Adding data to\", name, data)\n\n const valid = validateData(this.basic_schema, name, data)\n if (!valid.valid) {\n log('Invalid data', valid)\n return Promise.reject({ ... valid })\n }\n\n return this.table(name).add({\n id: uuidv7(),\n ...data\n })\n\n },\n\n put: (data: any) => {\n const valid = validateData(this.basic_schema, name, data)\n if (!valid.valid) {\n log('Invalid data', valid)\n return Promise.reject({ ... valid })\n }\n\n return this.table(name).put({\n id: uuidv7(),\n ...data\n })\n },\n\n update: (id: string, data: any) => {\n const valid = validateData(this.basic_schema, name, data, false)\n if (!valid.valid) {\n log('Invalid data', valid)\n return Promise.reject({ ... valid })\n }\n\n return this.table(name).update(id, data)\n },\n\n delete: (id: string) => {\n return this.table(name).delete(id)\n },\n\n\n // --- READ ---- // \n\n get: async (id: string) => {\n return this.table(name).get(id) \n },\n\n getAll: async () => {\n return this.table(name).toArray();\n },\n\n // --- QUERY ---- // \n // TODO: lots to do here. simplifing creating querie, filtering/ordering/limit, and execute\n\n query: () => this.table(name),\n\n filter: (fn: any) => this.table(name).filter(fn).toArray(),\n\n }\n }\n}\n\nclass QueryMethod { \n\n}\n","\"use client\"\nimport { Dexie } from \"dexie\";\nimport { log } from \"../config\";\n\nexport const syncProtocol = function () {\n log(\"Initializing syncProtocol\");\n // Constants:\n var RECONNECT_DELAY = 5000; // Reconnect delay in case of errors such as network down.\n\n Dexie.Syncable.registerSyncProtocol(\"websocket\", {\n sync: function (\n context,\n url,\n options,\n baseRevision,\n syncedRevision,\n changes,\n partial,\n applyRemoteChanges,\n onChangesAccepted,\n onSuccess,\n onError,\n ) {\n // The following vars are needed because we must know which callback to ack when server sends it's ack to us.\n var requestId = 0;\n var acceptCallbacks = {};\n\n // Connect the WebSocket to given url:\n var ws = new WebSocket(url);\n\n // console.log(\"ws OPTIONS\", options);\n\n // sendChanges() method:\n function sendChanges(changes, baseRevision, partial, onChangesAccepted) {\n log(\"sendChanges\", changes.length, baseRevision);\n ++requestId;\n acceptCallbacks[requestId.toString()] = onChangesAccepted;\n\n // In this example, the server expects the following JSON format of the request:\n // {\n // type: \"changes\"\n // baseRevision: baseRevision,\n // changes: changes,\n // partial: partial,\n // requestId: id\n // }\n // To make the sample simplified, we assume the server has the exact same specification of how changes are structured.\n // In real world, you would have to pre-process the changes array to fit the server specification.\n // However, this example shows how to deal with the WebSocket to fullfill the API.\n\n ws.send(\n JSON.stringify({\n type: \"changes\",\n changes: changes,\n partial: partial,\n baseRevision: baseRevision,\n requestId: requestId,\n }),\n );\n }\n\n\n\n // When WebSocket opens, send our changes to the server.\n ws.onopen = function (event) {\n // Initiate this socket connection by sending our clientIdentity. If we dont have a clientIdentity yet,\n // server will call back with a new client identity that we should use in future WebSocket connections.\n \n log(\"Opening socket - sending clientIdentity\", context.clientIdentity);\n ws.send(\n JSON.stringify({\n type: \"clientIdentity\",\n clientIdentity: context.clientIdentity || null,\n authToken: options.authToken\n }),\n );\n\n };\n\n // If network down or other error, tell the framework to reconnect again in some time:\n ws.onerror = function (event) {\n ws.close();\n log(\"ws.onerror\", event);\n onError(event?.message, RECONNECT_DELAY);\n };\n\n // If socket is closed (network disconnected), inform framework and make it reconnect\n ws.onclose = function (event) {\n // console.log('🙅 ws.onclose', event)\n onError(\"Socket closed: \" + event.reason, RECONNECT_DELAY);\n };\n\n // isFirstRound: Will need to call onSuccess() only when we are in sync the first time.\n // onSuccess() will unblock Dexie to be used by application code.\n // If for example app code writes: db.friends.where('shoeSize').above(40).toArray(callback), the execution of that query\n // will not run until we have called onSuccess(). This is because we want application code to get results that are as\n // accurate as possible. Specifically when connected the first time and the entire DB is being synced down to the browser,\n // it is important that queries starts running first when db is in sync.\n var isFirstRound = true;\n // When message arrive from the server, deal with the message accordingly:\n ws.onmessage = function (event) {\n try {\n // Assume we have a server that should send JSON messages of the following format:\n // {\n // type: \"clientIdentity\", \"changes\", \"ack\" or \"error\"\n // clientIdentity: unique value for our database client node to persist in the context. (Only applicable if type=\"clientIdentity\")\n // message: Error message (Only applicable if type=\"error\")\n // requestId: ID of change request that is acked by the server (Only applicable if type=\"ack\" or \"error\")\n // changes: changes from server (Only applicable if type=\"changes\")\n // lastRevision: last revision of changes sent (applicable if type=\"changes\")\n // partial: true if server has additionalChanges to send. False if these changes were the last known. (applicable if type=\"changes\")\n // }\n var requestFromServer = JSON.parse(event.data);\n log(\"requestFromServer\", requestFromServer, { acceptCallback, isFirstRound });\n\n if (requestFromServer.type == \"clientIdentity\") {\n context.clientIdentity = requestFromServer.clientIdentity;\n context.save();\n\n sendChanges(changes, baseRevision, partial, onChangesAccepted);\n\n ws.send(\n JSON.stringify({\n type: \"subscribe\",\n syncedRevision: syncedRevision,\n }),\n );\n } else if (requestFromServer.type == \"changes\") {\n applyRemoteChanges(\n requestFromServer.changes,\n requestFromServer.currentRevision,\n requestFromServer.partial,\n );\n if (isFirstRound && !requestFromServer.partial) {\n // Since this is the first sync round and server sais we've got all changes - now is the time to call onsuccess()\n onSuccess({\n // Specify a react function that will react on additional client changes\n react: function (\n changes,\n baseRevision,\n partial,\n onChangesAccepted,\n ) {\n sendChanges(\n changes,\n baseRevision,\n partial,\n onChangesAccepted,\n );\n },\n // Specify a disconnect function that will close our socket so that we dont continue to monitor changes.\n disconnect: function () {\n ws.close();\n },\n });\n isFirstRound = false;\n }\n } else if (requestFromServer.type == \"ack\") {\n var requestId = requestFromServer.requestId;\n var acceptCallback = acceptCallbacks[requestId.toString()];\n acceptCallback(); // Tell framework that server has acknowledged the changes sent.\n delete acceptCallbacks[requestId.toString()];\n } else if (requestFromServer.type == \"error\") {\n var requestId = requestFromServer.requestId;\n ws.close();\n onError(requestFromServer.message, Infinity); // Don't reconnect - an error in application level means we have done something wrong.\n } else {\n log(\"unknown message\", requestFromServer);\n ws.close();\n onError(\"unknown message\", Infinity);\n }\n } catch (e) {\n ws.close();\n onError(e, Infinity); // Something went crazy. Server sends invalid format or our code is buggy. Dont reconnect - it would continue failing.\n }\n };\n },\n });\n};\n","\n//export const SERVER_URL = \"https://api.basic.tech\"\n export const SERVER_URL = \"http://localhost:3000\"\n\n\nexport const log = (...args: any[]) => {\n try { \n if (localStorage.getItem('basic_debug') === 'true') {\n console.log('[basic]', ...args)\n }\n } catch (e) {\n // console.log('error logging', e)\n }\n}\n\n// export const log = (message: string, ...args: any[]) => {\n// try {\n// if (process.env.NODE_ENV === 'development') {\n// const stack = new Error().stack;\n// const caller = stack?.split('\\n')[2]?.trim();\n// console.log(`[basic] ${message}`, ...args);\n// // console.log(`[stack] ${caller}`);\n// }\n// } catch (e) {\n// console.error('Error in logWithStack:', e);\n// }\n// }\n","// 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 }\nconst ajv = new Ajv()\nconst validator = ajv.compile(basicJsonSchema)\n\ntype Schema = typeof basicJsonSchema\n\nfunction generateEmptySchema() {\n \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: Schema) : {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\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\n\nexport {\n validateSchema,\n validateData,\n generateEmptySchema\n}\n\n","//@ts-nocheck\n\nconst baseUrl = 'https://api.basic.tech';\n// const baseUrl = 'http://localhost:3000';\n\n\nasync function get({ projectId, accountId, tableName, token }) {\n const url = `${baseUrl}/project/${projectId}/db/${accountId}/${tableName}`;\n const response = await fetch(url, {\n headers: {\n 'Authorization': `Bearer ${token}`\n }\n });\n return response.json();\n}\n\nasync function add({ projectId, accountId, tableName, value, token }) {\n const url = `${baseUrl}/project/${projectId}/db/${accountId}/${tableName}`;\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${token}`\n },\n body: JSON.stringify({\"value\": value})\n });\n return response.json();\n}\n\nasync function update({ projectId, accountId, tableName, id, value, token }) {\n const url = `${baseUrl}/project/${projectId}/db/${accountId}/${tableName}/${id}`;\n const response = await fetch(url, {\n method: 'PATCH',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${token}`\n },\n body: JSON.stringify({id: id, value: value})\n });\n return response.json();\n}\n\nasync function deleteRecord({ projectId, accountId, tableName, id, token }) {\n const url = `${baseUrl}/project/${projectId}/db/${accountId}/${tableName}/${id}`;\n const response = await fetch(url, {\n method: 'DELETE',\n headers: {\n 'Authorization': `Bearer ${token}`\n }\n });\n return response.json();\n}\n\nexport { get, add, update, deleteRecord };\n\n"],"mappings":"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","names":["hello","import_dexie","changes","baseRevision","partial","onChangesAccepted","requestId","Ajv","key","uuidv7","error","baseUrl","token","user","import_schema"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/AuthContext.tsx","../src/sync/index.ts","../src/sync/syncProtocol.js","../src/config.ts","../src/schema.ts","../src/db.ts"],"sourcesContent":["import { useState } from \"react\";\nimport { useBasic, BasicProvider } from \"./AuthContext\";\nimport { useLiveQuery as useQuery } from \"dexie-react-hooks\";\n\n// const useQuery = (queryable: any) => {\n// const [loading, setLoading] = useState(true)\n// const [error, setError] = useState<Error | null>(null)\n\n// const result = useLiveQuery(async () => {\n// try {\n// setLoading(true)\n// setError(null)\n \n// // if (typeof queryable === 'function') {\n// // return await queryable()\n// // }\n// return queryable\n \n// } catch (err) {\n// setError(err instanceof Error ? err : new Error('Unknown error'))\n// return undefined\n// } finally {\n// setLoading(false)\n// }\n// }, [queryable])\n\n// return {\n// data: result,\n// loading,\n// error\n// }\n// }\n\n\n\nexport {\n useBasic, BasicProvider, useQuery\n}\n","// @ts-nocheck\n\nimport React, { createContext, useContext, useEffect, useState, useRef } from 'react'\nimport { jwtDecode } from 'jwt-decode'\n\nimport { BasicSync } from './sync'\nimport { get, add, update, deleteRecord } from './db'\nimport { validateSchema } from '@basictech/schema'\n\nimport { log } from './config'\n\n/*\nschema todo:\n field types\n array types\n relations\n*/\n\n\n// const example = {\n// project_id: '123',\n// version: 0,\n// tables: {\n// example: {\n// name: 'example',\n// type: 'collection',\n// fields: {\n// id: {\n// type: 'uuid',\n// primary: true,\n// },\n// value: {\n// type: 'string',\n// indexed: true,\n// },\n// }\n// }\n// }\n// }\n\n\ntype BasicSyncType = {\n basic_schema: any;\n connect: (options: { access_token: string }) => void;\n debugeroo: () => void;\n collection: (name: string) => {\n ref: {\n toArray: () => Promise<any[]>;\n count: () => Promise<number>;\n };\n };\n [key: string]: any; // For other potential methods and properties\n};\n\n\nenum DBStatus {\n LOADING = \"LOADING\",\n OFFLINE = \"OFFLINE\",\n CONNECTING = \"CONNECTING\",\n ONLINE = \"ONLINE\",\n SYNCING = \"SYNCING\",\n ERROR = \"ERROR\"\n}\n\ntype User = {\n name?: string,\n email?: string,\n id?: string,\n primaryEmailAddress?: {\n emailAddress: string\n },\n fullName?: string\n}\ntype Token = {\n access_token: string,\n token_type: string,\n expires_in: number,\n refresh: string,\n}\n\nexport const BasicContext = createContext<{\n unicorn: string,\n isAuthReady: boolean,\n isSignedIn: boolean,\n user: User | null,\n signout: () => void,\n signin: () => void,\n getToken: () => Promise<string>,\n getSignInLink: () => string,\n db: any,\n dbStatus: DBStatus\n}>({\n unicorn: \"🦄\",\n isAuthReady: false,\n isSignedIn: false,\n user: null,\n signout: () => { },\n signin: () => { },\n getToken: () => new Promise(() => { }),\n getSignInLink: () => \"\",\n db: {},\n dbStatus: DBStatus.LOADING\n});\n\nconst EmptyDB: BasicSyncType = {\n isOpen: false,\n collection: () => {\n return {\n ref: {\n toArray: () => [],\n count: () => 0\n }\n }\n }\n}\n\n\nfunction getSyncStatus(statusCode: number): string {\n switch (statusCode) {\n case -1:\n return \"ERROR\";\n case 0:\n return \"OFFLINE\";\n case 1:\n return \"CONNECTING\";\n case 2:\n return \"ONLINE\";\n case 3:\n return \"SYNCING\";\n case 4:\n return \"ERROR_WILL_RETRY\";\n default:\n return \"UNKNOWN\";\n }\n}\n\ntype ErrorObject = {\n code: string;\n title: string;\n message: string;\n}\n\nexport function BasicProvider({ children, project_id, schema, debug = false }: { children: React.ReactNode, project_id: string, schema: any, debug?: boolean }) {\n const [isAuthReady, setIsAuthReady] = useState(false)\n const [isSignedIn, setIsSignedIn] = useState<boolean>(false)\n const [token, setToken] = useState<Token | null>(null)\n const [user, setUser] = useState<User>({})\n\n const [dbStatus, setDbStatus] = useState<DBStatus>(DBStatus.LOADING)\n const [error, setError] = useState<ErrorObject | null>(null)\n\n const syncRef = useRef<BasicSync | null>(null);\n\n\n useEffect(() => {\n function initDb() {\n const valid = validateSchema(schema)\n if (!valid.valid) {\n log('Basic Schema is invalid!', valid.errors)\n console.group('Schema Errors')\n let errorMessage = ''\n valid.errors.forEach((error, index) => {\n log(`${index + 1}:`, error.message, ` - at ${error.instancePath}`)\n errorMessage += `${index + 1}: ${error.message} - at ${error.instancePath}\\n`\n })\n console.groupEnd('Schema Errors')\n setError({\n code: 'schema_invalid',\n title: 'Basic Schema is invalid!',\n message: errorMessage\n })\n return null\n }\n\n if (!syncRef.current) {\n log('Initializing BasicDB')\n syncRef.current = new BasicSync('basicdb', { schema: schema });\n\n // log('db is open', syncRef.current.isOpen())\n // syncRef.current.open()\n // .then(() => {\n // log(\"is open now:\", syncRef.current.isOpen())\n // })\n }\n }\n\n initDb()\n }, []);\n\n useEffect(() => {\n if (!syncRef.current) {\n return\n }\n\n // syncRef.current.handleStatusChange((status: number, url: string) => {\n // setDbStatus(getSyncStatus(status))\n // })\n\n syncRef.current.syncable.on('statusChanged', (status: number, url: string) => {\n setDbStatus(getSyncStatus(status))\n })\n\n syncRef.current.syncable.getStatus().then((status) => {\n setDbStatus(getSyncStatus(status))\n })\n }, [syncRef.current])\n\n\n const connectToDb = async () => {\n const tok = await getToken()\n if (!tok) {\n log('no token found')\n return\n }\n\n log('connecting to db...')\n\n // TODO: handle if signed out after connect() is already called\n\n syncRef.current.connect({ access_token: tok })\n .catch((e) => {\n log('error connecting to db', e)\n })\n }\n\n useEffect(() => {\n if (token && syncRef.current && isSignedIn && isSignedIn) {\n connectToDb()\n }\n }, [isSignedIn])\n\n const getSignInLink = () => {\n log('getting sign in link...')\n\n const randomState = Math.random().toString(36).substring(6);\n localStorage.setItem('basic_auth_state', randomState)\n\n let baseUrl = \"https://api.basic.tech/auth/authorize\"\n baseUrl += `?client_id=${project_id}`\n baseUrl += `&redirect_uri=${encodeURIComponent(window.location.href)}`\n baseUrl += `&response_type=code`\n baseUrl += `&scope=openid`\n baseUrl += `&state=${randomState}`\n\n return baseUrl;\n }\n\n const signin = () => {\n log('signing in: ', getSignInLink())\n const signInLink = getSignInLink()\n //todo: change to the other thing?\n window.location.href = signInLink;\n }\n\n const signout = () => {\n log('signing out!')\n setUser({})\n setIsSignedIn(false)\n setToken(null)\n document.cookie = `basic_token=; Secure; SameSite=Strict`;\n localStorage.removeItem('basic_auth_state')\n\n if (syncRef.current) {\n // WIP - BUG - sometimes connects even after signout\n syncRef.current.disconnect()\n }\n }\n\n const getToken = async (): Promise<string> => {\n log('getting token...')\n\n if (!token) {\n log('no token found')\n throw new Error('no token found')\n }\n\n const decoded = jwtDecode(token?.access_token)\n const isExpired = decoded.exp && decoded.exp < Date.now() / 1000\n\n if (isExpired) {\n log('token is expired - refreshing ...')\n const newToken = await fetchToken(token?.refresh)\n return newToken?.access_token || ''\n }\n\n return token?.access_token || ''\n }\n\n function getCookie(name: string) {\n let cookieValue = '';\n if (document.cookie && document.cookie !== '') {\n const cookies = document.cookie.split(';');\n for (let i = 0; i < cookies.length; i++) {\n const cookie = cookies[i].trim();\n if (cookie.substring(0, name.length + 1) === (name + '=')) {\n cookieValue = decodeURIComponent(cookie.substring(name.length + 1));\n break;\n }\n }\n }\n return cookieValue;\n }\n\n const fetchToken = async (code: string) => {\n const token = await fetch('https://api.basic.tech/auth/token', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({ code: code })\n })\n .then(response => response.json())\n .catch(error => log('Error:', error))\n\n if (token.error) {\n log('error fetching token', token.error)\n return\n } else {\n // log('token', token)\n setToken(token)\n }\n return token\n }\n\n useEffect(() => {\n localStorage.setItem('basic_debug', debug ? 'true' : 'false')\n\n try {\n if (window.location.search.includes('code')) {\n let code = window.location?.search?.split('code=')[1].split('&')[0]\n\n const state = localStorage.getItem('basic_auth_state')\n if (!state || state !== window.location.search.split('state=')[1].split('&')[0]) {\n log('error: auth state does not match')\n setIsAuthReady(true)\n\n localStorage.removeItem('basic_auth_state')\n window.history.pushState({}, document.title, \"/\");\n return\n }\n\n localStorage.removeItem('basic_auth_state')\n\n fetchToken(code) \n } else { \n let cookie_token = getCookie('basic_token')\n if (cookie_token !== '') {\n setToken(JSON.parse(cookie_token))\n } else { \n setIsAuthReady(true)\n }\n }\n\n\n } catch (e) {\n log('error getting cookie', e)\n }\n }, [])\n\n useEffect(() => {\n async function fetchUser(acc_token: string) {\n console.info('fetching user')\n const user = await fetch('https://api.basic.tech/auth/userInfo', {\n method: 'GET',\n headers: {\n 'Authorization': `Bearer ${acc_token}`\n }\n })\n .then(response => response.json())\n .catch(error => log('Error:', error))\n\n if (user.error) {\n log('error fetching user', user.error)\n // refreshToken()\n return\n } else {\n // log('user', user)\n document.cookie = `basic_token=${JSON.stringify(token)}; Secure; SameSite=Strict`;\n \n if (window.location.search.includes('code')) {\n window.history.pushState({}, document.title, \"/\");\n }\n \n setUser(user)\n setIsSignedIn(true)\n\n setIsAuthReady(true)\n }\n }\n\n async function checkToken() {\n if (!token) {\n log('error: no user token found')\n\n setIsAuthReady(true)\n return\n }\n\n const decoded = jwtDecode(token?.access_token)\n const isExpired = decoded.exp && decoded.exp < Date.now() / 1000\n\n if (isExpired) {\n log('token is expired - refreshing ...')\n const newToken = await fetchToken(token?.refresh)\n fetchUser(newToken.access_token)\n } else {\n fetchUser(token.access_token)\n }\n }\n\n if (token) {\n checkToken()\n } \n }, [token])\n\n\n const db_ = (tableName: string) => {\n const checkSignIn = () => {\n if (!isSignedIn) {\n throw new Error('cannot use db. user not logged in.')\n }\n }\n\n return {\n get: async () => {\n checkSignIn()\n const tok = await getToken()\n return get({ projectId: project_id, accountId: user.id, tableName: tableName, token: tok })\n },\n add: async (value: any) => {\n checkSignIn()\n const tok = await getToken()\n return add({ projectId: project_id, accountId: user.id, tableName: tableName, value: value, token: tok })\n },\n update: async (id: string, value: any) => {\n checkSignIn()\n const tok = await getToken()\n return update({ projectId: project_id, accountId: user.id, tableName: tableName, id: id, value: value, token: tok })\n },\n delete: async (id: string) => {\n checkSignIn()\n const tok = await getToken()\n return deleteRecord({ projectId: project_id, accountId: user.id, tableName: tableName, id: id, token: tok })\n }\n\n }\n\n }\n\n return (\n <BasicContext.Provider value={{\n unicorn: \"🦄\",\n isAuthReady,\n isSignedIn,\n user,\n signout,\n signin,\n getToken,\n getSignInLink,\n db: syncRef.current,\n dbStatus\n }}>\n {error && <ErrorDisplay error={error} />}\n {syncRef.current ? children : null}\n </BasicContext.Provider>\n )\n}\n\nfunction ErrorDisplay({ error }: { error: ErrorObject }) {\n return <div style={{ \n position: 'absolute',\n top: 20, \n left: 20,\n color: 'black',\n backgroundColor: '#f8d7da',\n border: '1px solid #f5c6cb',\n borderRadius: '4px',\n padding: '20px',\n maxWidth: '400px',\n margin: '20px auto',\n boxShadow: '0 2px 4px rgba(0, 0, 0, 0.1)',\n fontFamily: 'monospace', \n }}>\n <h3 style={{fontSize: '0.8rem', opacity: 0.8}}>code: {error.code}</h3>\n <h1 style={{fontSize: '1.2rem', lineHeight: '1.5'}}>{error.title}</h1>\n <p>{error.message}</p>\n </div>\n}\n\n/*\npossible errors: \n- projectid missing / invalid\n- schema missing / invalid\n*/\n\nexport function useBasic() {\n return useContext(BasicContext);\n}\n","\"use client\"\n\nimport { v7 as uuidv7 } from 'uuid';\nimport { Dexie, PromiseExtended } from 'dexie';\nimport 'dexie-syncable';\nimport 'dexie-observable';\n\nimport { syncProtocol } from './syncProtocol'\nimport { SERVER_URL, log } from '../config'\n\nimport { validateSchema, validateData } from '../schema'\nsyncProtocol()\n\n\n// const DexieSyncStatus = {\n// \"-1\": \"ERROR\",\n// \"0\": \"OFFLINE\",\n// \"1\": \"CONNECTING\",\n// \"2\": \"ONLINE\",\n// \"3\": \"SYNCING\",\n// \"4\": \"ERROR_WILL_RETRY\"\n// }\n\n\n\n\n\nexport class BasicSync extends Dexie {\n basic_schema: any\n\n constructor(name: string, options: any) {\n super(name, options);\n\n // --- INIT SCHEMA --- // \n\n //todo: handle versions?\n\n // TODO: validate schema\n this.basic_schema = options.schema\n this.version(1).stores(this._convertSchemaToDxSchema(this.basic_schema))\n\n this.version(2).stores({})\n // this.verssion\n\n\n // create an alias for toArray\n // @ts-ignore\n this.Collection.prototype.get = this.Collection.prototype.toArray\n\n\n // --- SYNC --- // \n\n // this.syncable.on(\"statusChanged\", (status, url) => { \n // console.log(\"statusChanged\", status, url)\n // })\n\n }\n\n async connect({ access_token }: { access_token: string }) {\n // const WS_URL = \"ws://localhost:3003/ws\"\n const WS_URL = `${SERVER_URL}/ws`\n\n \n // Update sync nodes\n await this.updateSyncNodes();\n \n // Proceed with the WebSocket connection\n \n log('Starting connection...')\n return this.syncable.connect(\"websocket\", WS_URL, { authToken: access_token });\n }\n\n async disconnect() {\n const WS_URL = `${SERVER_URL}/ws`\n\n return this.syncable.disconnect(WS_URL) \n }\n\n private async updateSyncNodes() {\n try {\n const syncNodes = await this.table('_syncNodes').toArray();\n const localSyncNodes = syncNodes.filter(node => node.type === 'local');\n log('Local sync nodes:', localSyncNodes);\n\n if (localSyncNodes.length > 1) {\n\n \n const largestNodeId = Math.max(...localSyncNodes.map(node => node.id));\n // Check if the largest node is already the master\n const largestNode = localSyncNodes.find(node => node.id === largestNodeId);\n if (largestNode && largestNode.isMaster === 1) {\n log('Largest node is already the master. No changes needed.');\n return; // Exit the function early as no changes are needed\n }\n\n\n log('Largest node id:', largestNodeId);\n log('HEISENBUG: More than one local sync node found.')\n\n for (const node of localSyncNodes) {\n log(`Local sync node keys:`, node.id, node.isMaster);\n await this.table('_syncNodes').update(node.id, { isMaster: node.id === largestNodeId ? 1 : 0 });\n\n log(`HEISENBUG: Setting ${node.id} to ${node.id === largestNodeId ? 'master' : '0'}`);\n }\n\n // Add a 1 second delay before returning // i dont think this helps?\n await new Promise(resolve => setTimeout(resolve, 2000));\n\n }\n\n log('Sync nodes updated');\n } catch (error) {\n console.error('Error updating _syncNodes table:', error);\n }\n }\n\n handleStatusChange(fn: any) {\n this.syncable.on(\"statusChanged\", fn)\n }\n\n\n _convertSchemaToDxSchema(schema: any) {\n const stores = Object.entries(schema.tables).map(([key, table]: any) => {\n\n const indexedFields = Object.entries(table.fields).filter(([key, field]: any) => field.indexed).map(([key, field]: any) => `,${key}`).join('')\n return {\n [key]: 'id' + indexedFields\n }\n })\n\n return Object.assign({}, ...stores)\n }\n\n debugeroo() {\n // console.log(\"debugeroo\", this.syncable)\n\n // this.syncable.list().then(x => console.log(x))\n\n // this.syncable\n return this.syncable\n }\n\n collection(name: string) {\n // TODO: check against schema\n\n return {\n\n /**\n * Returns the underlying Dexie table\n * @type {Dexie.Table}\n */\n ref: this.table(name),\n\n // --- WRITE ---- // \n add: (data: any) => {\n // log(\"Adding data to\", name, data)\n\n const valid = validateData(this.basic_schema, name, data)\n if (!valid.valid) {\n log('Invalid data', valid)\n return Promise.reject({ ... valid })\n }\n\n return this.table(name).add({\n id: uuidv7(),\n ...data\n })\n\n },\n\n put: (data: any) => {\n const valid = validateData(this.basic_schema, name, data)\n if (!valid.valid) {\n log('Invalid data', valid)\n return Promise.reject({ ... valid })\n }\n\n return this.table(name).put({\n id: uuidv7(),\n ...data\n })\n },\n\n update: (id: string, data: any) => {\n const valid = validateData(this.basic_schema, name, data, false)\n if (!valid.valid) {\n log('Invalid data', valid)\n return Promise.reject({ ... valid })\n }\n\n return this.table(name).update(id, data)\n },\n\n delete: (id: string) => {\n return this.table(name).delete(id)\n },\n\n\n // --- READ ---- // \n\n get: async (id: string) => {\n return this.table(name).get(id) \n },\n\n getAll: async () => {\n return this.table(name).toArray();\n },\n\n // --- QUERY ---- // \n // TODO: lots to do here. simplifing creating querie, filtering/ordering/limit, and execute\n\n query: () => this.table(name),\n\n filter: (fn: any) => this.table(name).filter(fn).toArray(),\n\n }\n }\n}\n\nclass QueryMethod { \n\n}\n","\"use client\"\nimport { Dexie } from \"dexie\";\nimport { log } from \"../config\";\n\nexport const syncProtocol = function () {\n log(\"Initializing syncProtocol\");\n // Constants:\n var RECONNECT_DELAY = 5000; // Reconnect delay in case of errors such as network down.\n\n Dexie.Syncable.registerSyncProtocol(\"websocket\", {\n sync: function (\n context,\n url,\n options,\n baseRevision,\n syncedRevision,\n changes,\n partial,\n applyRemoteChanges,\n onChangesAccepted,\n onSuccess,\n onError,\n ) {\n // The following vars are needed because we must know which callback to ack when server sends it's ack to us.\n var requestId = 0;\n var acceptCallbacks = {};\n\n // Connect the WebSocket to given url:\n var ws = new WebSocket(url);\n\n // console.log(\"ws OPTIONS\", options);\n\n // sendChanges() method:\n function sendChanges(changes, baseRevision, partial, onChangesAccepted) {\n log(\"sendChanges\", changes.length, baseRevision);\n ++requestId;\n acceptCallbacks[requestId.toString()] = onChangesAccepted;\n\n // In this example, the server expects the following JSON format of the request:\n // {\n // type: \"changes\"\n // baseRevision: baseRevision,\n // changes: changes,\n // partial: partial,\n // requestId: id\n // }\n // To make the sample simplified, we assume the server has the exact same specification of how changes are structured.\n // In real world, you would have to pre-process the changes array to fit the server specification.\n // However, this example shows how to deal with the WebSocket to fullfill the API.\n\n ws.send(\n JSON.stringify({\n type: \"changes\",\n changes: changes,\n partial: partial,\n baseRevision: baseRevision,\n requestId: requestId,\n }),\n );\n }\n\n\n\n // When WebSocket opens, send our changes to the server.\n ws.onopen = function (event) {\n // Initiate this socket connection by sending our clientIdentity. If we dont have a clientIdentity yet,\n // server will call back with a new client identity that we should use in future WebSocket connections.\n \n log(\"Opening socket - sending clientIdentity\", context.clientIdentity);\n ws.send(\n JSON.stringify({\n type: \"clientIdentity\",\n clientIdentity: context.clientIdentity || null,\n authToken: options.authToken\n }),\n );\n\n };\n\n // If network down or other error, tell the framework to reconnect again in some time:\n ws.onerror = function (event) {\n ws.close();\n log(\"ws.onerror\", event);\n onError(event?.message, RECONNECT_DELAY);\n };\n\n // If socket is closed (network disconnected), inform framework and make it reconnect\n ws.onclose = function (event) {\n // console.log('🙅 ws.onclose', event)\n onError(\"Socket closed: \" + event.reason, RECONNECT_DELAY);\n };\n\n // isFirstRound: Will need to call onSuccess() only when we are in sync the first time.\n // onSuccess() will unblock Dexie to be used by application code.\n // If for example app code writes: db.friends.where('shoeSize').above(40).toArray(callback), the execution of that query\n // will not run until we have called onSuccess(). This is because we want application code to get results that are as\n // accurate as possible. Specifically when connected the first time and the entire DB is being synced down to the browser,\n // it is important that queries starts running first when db is in sync.\n var isFirstRound = true;\n // When message arrive from the server, deal with the message accordingly:\n ws.onmessage = function (event) {\n try {\n // Assume we have a server that should send JSON messages of the following format:\n // {\n // type: \"clientIdentity\", \"changes\", \"ack\" or \"error\"\n // clientIdentity: unique value for our database client node to persist in the context. (Only applicable if type=\"clientIdentity\")\n // message: Error message (Only applicable if type=\"error\")\n // requestId: ID of change request that is acked by the server (Only applicable if type=\"ack\" or \"error\")\n // changes: changes from server (Only applicable if type=\"changes\")\n // lastRevision: last revision of changes sent (applicable if type=\"changes\")\n // partial: true if server has additionalChanges to send. False if these changes were the last known. (applicable if type=\"changes\")\n // }\n var requestFromServer = JSON.parse(event.data);\n log(\"requestFromServer\", requestFromServer, { acceptCallback, isFirstRound });\n\n if (requestFromServer.type == \"clientIdentity\") {\n context.clientIdentity = requestFromServer.clientIdentity;\n context.save();\n\n sendChanges(changes, baseRevision, partial, onChangesAccepted);\n\n ws.send(\n JSON.stringify({\n type: \"subscribe\",\n syncedRevision: syncedRevision,\n }),\n );\n } else if (requestFromServer.type == \"changes\") {\n applyRemoteChanges(\n requestFromServer.changes,\n requestFromServer.currentRevision,\n requestFromServer.partial,\n );\n if (isFirstRound && !requestFromServer.partial) {\n // Since this is the first sync round and server sais we've got all changes - now is the time to call onsuccess()\n onSuccess({\n // Specify a react function that will react on additional client changes\n react: function (\n changes,\n baseRevision,\n partial,\n onChangesAccepted,\n ) {\n sendChanges(\n changes,\n baseRevision,\n partial,\n onChangesAccepted,\n );\n },\n // Specify a disconnect function that will close our socket so that we dont continue to monitor changes.\n disconnect: function () {\n ws.close();\n },\n });\n isFirstRound = false;\n }\n } else if (requestFromServer.type == \"ack\") {\n var requestId = requestFromServer.requestId;\n var acceptCallback = acceptCallbacks[requestId.toString()];\n acceptCallback(); // Tell framework that server has acknowledged the changes sent.\n delete acceptCallbacks[requestId.toString()];\n } else if (requestFromServer.type == \"error\") {\n var requestId = requestFromServer.requestId;\n ws.close();\n onError(requestFromServer.message, Infinity); // Don't reconnect - an error in application level means we have done something wrong.\n } else {\n log(\"unknown message\", requestFromServer);\n ws.close();\n onError(\"unknown message\", Infinity);\n }\n } catch (e) {\n ws.close();\n onError(e, Infinity); // Something went crazy. Server sends invalid format or our code is buggy. Dont reconnect - it would continue failing.\n }\n };\n },\n });\n};\n","\nexport const SERVER_URL = \"https://api.basic.tech\"\n// export const SERVER_URL = \"http://localhost:3000\"\n\n\nexport const log = (...args: any[]) => {\n try { \n if (localStorage.getItem('basic_debug') === 'true') {\n console.log('[basic]', ...args)\n }\n } catch (e) {\n // console.log('error logging', e)\n }\n}\n\n// export const log = (message: string, ...args: any[]) => {\n// try {\n// if (process.env.NODE_ENV === 'development') {\n// const stack = new Error().stack;\n// const caller = stack?.split('\\n')[2]?.trim();\n// console.log(`[basic] ${message}`, ...args);\n// // console.log(`[stack] ${caller}`);\n// }\n// } catch (e) {\n// console.error('Error in logWithStack:', e);\n// }\n// }\n","// 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 }\nconst ajv = new Ajv()\nconst validator = ajv.compile(basicJsonSchema)\n\ntype Schema = typeof basicJsonSchema\n\nfunction generateEmptySchema() {\n \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: Schema) : {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\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\n\nexport {\n validateSchema,\n validateData,\n generateEmptySchema\n}\n\n","//@ts-nocheck\n\nconst baseUrl = 'https://api.basic.tech';\n// const baseUrl = 'http://localhost:3000';\n\n\nasync function get({ projectId, accountId, tableName, token }) {\n const url = `${baseUrl}/project/${projectId}/db/${accountId}/${tableName}`;\n const response = await fetch(url, {\n headers: {\n 'Authorization': `Bearer ${token}`\n }\n });\n return response.json();\n}\n\nasync function add({ projectId, accountId, tableName, value, token }) {\n const url = `${baseUrl}/project/${projectId}/db/${accountId}/${tableName}`;\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${token}`\n },\n body: JSON.stringify({\"value\": value})\n });\n return response.json();\n}\n\nasync function update({ projectId, accountId, tableName, id, value, token }) {\n const url = `${baseUrl}/project/${projectId}/db/${accountId}/${tableName}/${id}`;\n const response = await fetch(url, {\n method: 'PATCH',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${token}`\n },\n body: JSON.stringify({id: id, value: value})\n });\n return response.json();\n}\n\nasync function deleteRecord({ projectId, accountId, tableName, id, token }) {\n const url = `${baseUrl}/project/${projectId}/db/${accountId}/${tableName}/${id}`;\n const response = await fetch(url, {\n method: 'DELETE',\n headers: {\n 'Authorization': `Bearer ${token}`\n }\n });\n return response.json();\n}\n\nexport { get, add, update, deleteRecord };\n\n"],"mappings":"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","names":["useQuery","import_dexie","changes","baseRevision","partial","onChangesAccepted","requestId","Ajv","key","uuidv7","import_schema","error","baseUrl","token","user"]}
|
package/dist/index.mjs
CHANGED
|
@@ -12,7 +12,7 @@ import "dexie-observable";
|
|
|
12
12
|
import { Dexie } from "dexie";
|
|
13
13
|
|
|
14
14
|
// src/config.ts
|
|
15
|
-
var SERVER_URL = "
|
|
15
|
+
var SERVER_URL = "https://api.basic.tech";
|
|
16
16
|
var log = (...args) => {
|
|
17
17
|
try {
|
|
18
18
|
if (localStorage.getItem("basic_debug") === "true") {
|
|
@@ -187,8 +187,6 @@ var basicJsonSchema = {
|
|
|
187
187
|
};
|
|
188
188
|
var ajv = new Ajv();
|
|
189
189
|
var validator = ajv.compile(basicJsonSchema);
|
|
190
|
-
function generateEmptySchema() {
|
|
191
|
-
}
|
|
192
190
|
function validateSchema(schema) {
|
|
193
191
|
const v = validator(schema);
|
|
194
192
|
return {
|
|
@@ -401,6 +399,7 @@ async function deleteRecord({ projectId, accountId, tableName, id, token }) {
|
|
|
401
399
|
}
|
|
402
400
|
|
|
403
401
|
// src/AuthContext.tsx
|
|
402
|
+
import { validateSchema as validateSchema3 } from "@basictech/schema";
|
|
404
403
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
405
404
|
var BasicContext = createContext({
|
|
406
405
|
unicorn: "\u{1F984}",
|
|
@@ -445,7 +444,7 @@ function BasicProvider({ children, project_id, schema, debug = false }) {
|
|
|
445
444
|
const syncRef = useRef(null);
|
|
446
445
|
useEffect(() => {
|
|
447
446
|
function initDb() {
|
|
448
|
-
const valid =
|
|
447
|
+
const valid = validateSchema3(schema);
|
|
449
448
|
if (!valid.valid) {
|
|
450
449
|
log("Basic Schema is invalid!", valid.errors);
|
|
451
450
|
console.group("Schema Errors");
|
|
@@ -712,25 +711,9 @@ function useBasic() {
|
|
|
712
711
|
}
|
|
713
712
|
|
|
714
713
|
// src/index.ts
|
|
715
|
-
import { useLiveQuery } from "dexie-react-hooks";
|
|
716
|
-
import hello from "@basictech/schema";
|
|
717
|
-
function useQuery(queryable) {
|
|
718
|
-
return useLiveQuery(() => {
|
|
719
|
-
if (typeof queryable === "function") {
|
|
720
|
-
return queryable();
|
|
721
|
-
}
|
|
722
|
-
return queryable;
|
|
723
|
-
}, [queryable], []);
|
|
724
|
-
}
|
|
725
|
-
var sc = {
|
|
726
|
-
validateSchema,
|
|
727
|
-
validateData,
|
|
728
|
-
generateEmptySchema
|
|
729
|
-
};
|
|
714
|
+
import { useLiveQuery as useQuery } from "dexie-react-hooks";
|
|
730
715
|
export {
|
|
731
716
|
BasicProvider,
|
|
732
|
-
hello,
|
|
733
|
-
sc,
|
|
734
717
|
useBasic,
|
|
735
718
|
useQuery
|
|
736
719
|
};
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/AuthContext.tsx","../src/sync/index.ts","../src/sync/syncProtocol.js","../src/config.ts","../src/schema.ts","../src/db.ts","../src/index.ts"],"sourcesContent":["// @ts-nocheck\n\nimport React, { createContext, useContext, useEffect, useState, useRef } from 'react'\nimport { jwtDecode } from 'jwt-decode'\n\nimport { BasicSync } from './sync'\nimport { get, add, update, deleteRecord } from './db'\nimport { validateSchema } from './schema'\n\nimport { log } from './config'\n\n/*\nschema todo:\n field types\n array types\n relations\n*/\n\n\n// const example = {\n// project_id: '123',\n// version: 0,\n// tables: {\n// example: {\n// name: 'example',\n// type: 'collection',\n// fields: {\n// id: {\n// type: 'uuid',\n// primary: true,\n// },\n// value: {\n// type: 'string',\n// indexed: true,\n// },\n// }\n// }\n// }\n// }\n\n\ntype BasicSyncType = {\n basic_schema: any;\n connect: (options: { access_token: string }) => void;\n debugeroo: () => void;\n collection: (name: string) => {\n ref: {\n toArray: () => Promise<any[]>;\n count: () => Promise<number>;\n };\n };\n [key: string]: any; // For other potential methods and properties\n};\n\n\nenum DBStatus {\n LOADING = \"LOADING\",\n OFFLINE = \"OFFLINE\",\n CONNECTING = \"CONNECTING\",\n ONLINE = \"ONLINE\",\n SYNCING = \"SYNCING\",\n ERROR = \"ERROR\"\n}\n\ntype User = {\n name?: string,\n email?: string,\n id?: string,\n primaryEmailAddress?: {\n emailAddress: string\n },\n fullName?: string\n}\ntype Token = {\n access_token: string,\n token_type: string,\n expires_in: number,\n refresh: string,\n}\n\nexport const BasicContext = createContext<{\n unicorn: string,\n isAuthReady: boolean,\n isSignedIn: boolean,\n user: User | null,\n signout: () => void,\n signin: () => void,\n getToken: () => Promise<string>,\n getSignInLink: () => string,\n db: any,\n dbStatus: DBStatus\n}>({\n unicorn: \"🦄\",\n isAuthReady: false,\n isSignedIn: false,\n user: null,\n signout: () => { },\n signin: () => { },\n getToken: () => new Promise(() => { }),\n getSignInLink: () => \"\",\n db: {},\n dbStatus: DBStatus.LOADING\n});\n\nconst EmptyDB: BasicSyncType = {\n isOpen: false,\n collection: () => {\n return {\n ref: {\n toArray: () => [],\n count: () => 0\n }\n }\n }\n}\n\n\nfunction getSyncStatus(statusCode: number): string {\n switch (statusCode) {\n case -1:\n return \"ERROR\";\n case 0:\n return \"OFFLINE\";\n case 1:\n return \"CONNECTING\";\n case 2:\n return \"ONLINE\";\n case 3:\n return \"SYNCING\";\n case 4:\n return \"ERROR_WILL_RETRY\";\n default:\n return \"UNKNOWN\";\n }\n}\n\ntype ErrorObject = {\n code: string;\n title: string;\n message: string;\n}\n\nexport function BasicProvider({ children, project_id, schema, debug = false }: { children: React.ReactNode, project_id: string, schema: any, debug?: boolean }) {\n const [isAuthReady, setIsAuthReady] = useState(false)\n const [isSignedIn, setIsSignedIn] = useState<boolean>(false)\n const [token, setToken] = useState<Token | null>(null)\n const [user, setUser] = useState<User>({})\n\n const [dbStatus, setDbStatus] = useState<DBStatus>(DBStatus.LOADING)\n const [error, setError] = useState<ErrorObject | null>(null)\n\n const syncRef = useRef<BasicSync | null>(null);\n\n\n useEffect(() => {\n function initDb() {\n const valid = validateSchema(schema)\n if (!valid.valid) {\n log('Basic Schema is invalid!', valid.errors)\n console.group('Schema Errors')\n let errorMessage = ''\n valid.errors.forEach((error, index) => {\n log(`${index + 1}:`, error.message, ` - at ${error.instancePath}`)\n errorMessage += `${index + 1}: ${error.message} - at ${error.instancePath}\\n`\n })\n console.groupEnd('Schema Errors')\n setError({\n code: 'schema_invalid',\n title: 'Basic Schema is invalid!',\n message: errorMessage\n })\n return null\n }\n\n if (!syncRef.current) {\n log('Initializing BasicDB')\n syncRef.current = new BasicSync('basicdb', { schema: schema });\n\n // log('db is open', syncRef.current.isOpen())\n // syncRef.current.open()\n // .then(() => {\n // log(\"is open now:\", syncRef.current.isOpen())\n // })\n }\n }\n\n initDb()\n }, []);\n\n useEffect(() => {\n if (!syncRef.current) {\n return\n }\n\n // syncRef.current.handleStatusChange((status: number, url: string) => {\n // setDbStatus(getSyncStatus(status))\n // })\n\n syncRef.current.syncable.on('statusChanged', (status: number, url: string) => {\n setDbStatus(getSyncStatus(status))\n })\n\n syncRef.current.syncable.getStatus().then((status) => {\n setDbStatus(getSyncStatus(status))\n })\n }, [syncRef.current])\n\n\n const connectToDb = async () => {\n const tok = await getToken()\n if (!tok) {\n log('no token found')\n return\n }\n\n log('connecting to db...')\n\n // TODO: handle if signed out after connect() is already called\n\n syncRef.current.connect({ access_token: tok })\n .catch((e) => {\n log('error connecting to db', e)\n })\n }\n\n useEffect(() => {\n if (token && syncRef.current && isSignedIn && isSignedIn) {\n connectToDb()\n }\n }, [isSignedIn])\n\n const getSignInLink = () => {\n log('getting sign in link...')\n\n const randomState = Math.random().toString(36).substring(6);\n localStorage.setItem('basic_auth_state', randomState)\n\n let baseUrl = \"https://api.basic.tech/auth/authorize\"\n baseUrl += `?client_id=${project_id}`\n baseUrl += `&redirect_uri=${encodeURIComponent(window.location.href)}`\n baseUrl += `&response_type=code`\n baseUrl += `&scope=openid`\n baseUrl += `&state=${randomState}`\n\n return baseUrl;\n }\n\n const signin = () => {\n log('signing in: ', getSignInLink())\n const signInLink = getSignInLink()\n //todo: change to the other thing?\n window.location.href = signInLink;\n }\n\n const signout = () => {\n log('signing out!')\n setUser({})\n setIsSignedIn(false)\n setToken(null)\n document.cookie = `basic_token=; Secure; SameSite=Strict`;\n localStorage.removeItem('basic_auth_state')\n\n if (syncRef.current) {\n // WIP - BUG - sometimes connects even after signout\n syncRef.current.disconnect()\n }\n }\n\n const getToken = async (): Promise<string> => {\n log('getting token...')\n\n if (!token) {\n log('no token found')\n throw new Error('no token found')\n }\n\n const decoded = jwtDecode(token?.access_token)\n const isExpired = decoded.exp && decoded.exp < Date.now() / 1000\n\n if (isExpired) {\n log('token is expired - refreshing ...')\n const newToken = await fetchToken(token?.refresh)\n return newToken?.access_token || ''\n }\n\n return token?.access_token || ''\n }\n\n function getCookie(name: string) {\n let cookieValue = '';\n if (document.cookie && document.cookie !== '') {\n const cookies = document.cookie.split(';');\n for (let i = 0; i < cookies.length; i++) {\n const cookie = cookies[i].trim();\n if (cookie.substring(0, name.length + 1) === (name + '=')) {\n cookieValue = decodeURIComponent(cookie.substring(name.length + 1));\n break;\n }\n }\n }\n return cookieValue;\n }\n\n const fetchToken = async (code: string) => {\n const token = await fetch('https://api.basic.tech/auth/token', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({ code: code })\n })\n .then(response => response.json())\n .catch(error => log('Error:', error))\n\n if (token.error) {\n log('error fetching token', token.error)\n return\n } else {\n // log('token', token)\n setToken(token)\n }\n return token\n }\n\n useEffect(() => {\n localStorage.setItem('basic_debug', debug ? 'true' : 'false')\n\n try {\n if (window.location.search.includes('code')) {\n let code = window.location?.search?.split('code=')[1].split('&')[0]\n\n const state = localStorage.getItem('basic_auth_state')\n if (!state || state !== window.location.search.split('state=')[1].split('&')[0]) {\n log('error: auth state does not match')\n setIsAuthReady(true)\n\n localStorage.removeItem('basic_auth_state')\n window.history.pushState({}, document.title, \"/\");\n return\n }\n\n localStorage.removeItem('basic_auth_state')\n\n fetchToken(code) \n } else { \n let cookie_token = getCookie('basic_token')\n if (cookie_token !== '') {\n setToken(JSON.parse(cookie_token))\n } else { \n setIsAuthReady(true)\n }\n }\n\n\n } catch (e) {\n log('error getting cookie', e)\n }\n }, [])\n\n useEffect(() => {\n async function fetchUser(acc_token: string) {\n console.info('fetching user')\n const user = await fetch('https://api.basic.tech/auth/userInfo', {\n method: 'GET',\n headers: {\n 'Authorization': `Bearer ${acc_token}`\n }\n })\n .then(response => response.json())\n .catch(error => log('Error:', error))\n\n if (user.error) {\n log('error fetching user', user.error)\n // refreshToken()\n return\n } else {\n // log('user', user)\n document.cookie = `basic_token=${JSON.stringify(token)}; Secure; SameSite=Strict`;\n \n if (window.location.search.includes('code')) {\n window.history.pushState({}, document.title, \"/\");\n }\n \n setUser(user)\n setIsSignedIn(true)\n\n setIsAuthReady(true)\n }\n }\n\n async function checkToken() {\n if (!token) {\n log('error: no user token found')\n\n setIsAuthReady(true)\n return\n }\n\n const decoded = jwtDecode(token?.access_token)\n const isExpired = decoded.exp && decoded.exp < Date.now() / 1000\n\n if (isExpired) {\n log('token is expired - refreshing ...')\n const newToken = await fetchToken(token?.refresh)\n fetchUser(newToken.access_token)\n } else {\n fetchUser(token.access_token)\n }\n }\n\n if (token) {\n checkToken()\n } \n }, [token])\n\n\n const db_ = (tableName: string) => {\n const checkSignIn = () => {\n if (!isSignedIn) {\n throw new Error('cannot use db. user not logged in.')\n }\n }\n\n return {\n get: async () => {\n checkSignIn()\n const tok = await getToken()\n return get({ projectId: project_id, accountId: user.id, tableName: tableName, token: tok })\n },\n add: async (value: any) => {\n checkSignIn()\n const tok = await getToken()\n return add({ projectId: project_id, accountId: user.id, tableName: tableName, value: value, token: tok })\n },\n update: async (id: string, value: any) => {\n checkSignIn()\n const tok = await getToken()\n return update({ projectId: project_id, accountId: user.id, tableName: tableName, id: id, value: value, token: tok })\n },\n delete: async (id: string) => {\n checkSignIn()\n const tok = await getToken()\n return deleteRecord({ projectId: project_id, accountId: user.id, tableName: tableName, id: id, token: tok })\n }\n\n }\n\n }\n\n return (\n <BasicContext.Provider value={{\n unicorn: \"🦄\",\n isAuthReady,\n isSignedIn,\n user,\n signout,\n signin,\n getToken,\n getSignInLink,\n db: syncRef.current,\n dbStatus\n }}>\n {error && <ErrorDisplay error={error} />}\n {syncRef.current ? children : null}\n </BasicContext.Provider>\n )\n}\n\nfunction ErrorDisplay({ error }: { error: ErrorObject }) {\n return <div style={{ \n position: 'absolute',\n top: 20, \n left: 20,\n color: 'black',\n backgroundColor: '#f8d7da',\n border: '1px solid #f5c6cb',\n borderRadius: '4px',\n padding: '20px',\n maxWidth: '400px',\n margin: '20px auto',\n boxShadow: '0 2px 4px rgba(0, 0, 0, 0.1)',\n fontFamily: 'monospace', \n }}>\n <h3 style={{fontSize: '0.8rem', opacity: 0.8}}>code: {error.code}</h3>\n <h1 style={{fontSize: '1.2rem', lineHeight: '1.5'}}>{error.title}</h1>\n <p>{error.message}</p>\n </div>\n}\n\n/*\npossible errors: \n- projectid missing / invalid\n- schema missing / invalid\n*/\n\nexport function useBasic() {\n return useContext(BasicContext);\n}\n","\"use client\"\n\nimport { v7 as uuidv7 } from 'uuid';\nimport { Dexie, PromiseExtended } from 'dexie';\nimport 'dexie-syncable';\nimport 'dexie-observable';\n\nimport { syncProtocol } from './syncProtocol'\nimport { SERVER_URL, log } from '../config'\n\nimport { validateSchema, validateData } from '../schema'\nsyncProtocol()\n\n\n// const DexieSyncStatus = {\n// \"-1\": \"ERROR\",\n// \"0\": \"OFFLINE\",\n// \"1\": \"CONNECTING\",\n// \"2\": \"ONLINE\",\n// \"3\": \"SYNCING\",\n// \"4\": \"ERROR_WILL_RETRY\"\n// }\n\n\n\n\n\nexport class BasicSync extends Dexie {\n basic_schema: any\n\n constructor(name: string, options: any) {\n super(name, options);\n\n // --- INIT SCHEMA --- // \n\n //todo: handle versions?\n\n // TODO: validate schema\n this.basic_schema = options.schema\n this.version(1).stores(this._convertSchemaToDxSchema(this.basic_schema))\n\n this.version(2).stores({})\n // this.verssion\n\n\n // create an alias for toArray\n // @ts-ignore\n this.Collection.prototype.get = this.Collection.prototype.toArray\n\n\n // --- SYNC --- // \n\n // this.syncable.on(\"statusChanged\", (status, url) => { \n // console.log(\"statusChanged\", status, url)\n // })\n\n }\n\n async connect({ access_token }: { access_token: string }) {\n // const WS_URL = \"ws://localhost:3003/ws\"\n const WS_URL = `${SERVER_URL}/ws`\n\n \n // Update sync nodes\n await this.updateSyncNodes();\n \n // Proceed with the WebSocket connection\n \n log('Starting connection...')\n return this.syncable.connect(\"websocket\", WS_URL, { authToken: access_token });\n }\n\n async disconnect() {\n const WS_URL = `${SERVER_URL}/ws`\n\n return this.syncable.disconnect(WS_URL) \n }\n\n private async updateSyncNodes() {\n try {\n const syncNodes = await this.table('_syncNodes').toArray();\n const localSyncNodes = syncNodes.filter(node => node.type === 'local');\n log('Local sync nodes:', localSyncNodes);\n\n if (localSyncNodes.length > 1) {\n\n \n const largestNodeId = Math.max(...localSyncNodes.map(node => node.id));\n // Check if the largest node is already the master\n const largestNode = localSyncNodes.find(node => node.id === largestNodeId);\n if (largestNode && largestNode.isMaster === 1) {\n log('Largest node is already the master. No changes needed.');\n return; // Exit the function early as no changes are needed\n }\n\n\n log('Largest node id:', largestNodeId);\n log('HEISENBUG: More than one local sync node found.')\n\n for (const node of localSyncNodes) {\n log(`Local sync node keys:`, node.id, node.isMaster);\n await this.table('_syncNodes').update(node.id, { isMaster: node.id === largestNodeId ? 1 : 0 });\n\n log(`HEISENBUG: Setting ${node.id} to ${node.id === largestNodeId ? 'master' : '0'}`);\n }\n\n // Add a 1 second delay before returning // i dont think this helps?\n await new Promise(resolve => setTimeout(resolve, 2000));\n\n }\n\n log('Sync nodes updated');\n } catch (error) {\n console.error('Error updating _syncNodes table:', error);\n }\n }\n\n handleStatusChange(fn: any) {\n this.syncable.on(\"statusChanged\", fn)\n }\n\n\n _convertSchemaToDxSchema(schema: any) {\n const stores = Object.entries(schema.tables).map(([key, table]: any) => {\n\n const indexedFields = Object.entries(table.fields).filter(([key, field]: any) => field.indexed).map(([key, field]: any) => `,${key}`).join('')\n return {\n [key]: 'id' + indexedFields\n }\n })\n\n return Object.assign({}, ...stores)\n }\n\n debugeroo() {\n // console.log(\"debugeroo\", this.syncable)\n\n // this.syncable.list().then(x => console.log(x))\n\n // this.syncable\n return this.syncable\n }\n\n collection(name: string) {\n // TODO: check against schema\n\n return {\n\n /**\n * Returns the underlying Dexie table\n * @type {Dexie.Table}\n */\n ref: this.table(name),\n\n // --- WRITE ---- // \n add: (data: any) => {\n // log(\"Adding data to\", name, data)\n\n const valid = validateData(this.basic_schema, name, data)\n if (!valid.valid) {\n log('Invalid data', valid)\n return Promise.reject({ ... valid })\n }\n\n return this.table(name).add({\n id: uuidv7(),\n ...data\n })\n\n },\n\n put: (data: any) => {\n const valid = validateData(this.basic_schema, name, data)\n if (!valid.valid) {\n log('Invalid data', valid)\n return Promise.reject({ ... valid })\n }\n\n return this.table(name).put({\n id: uuidv7(),\n ...data\n })\n },\n\n update: (id: string, data: any) => {\n const valid = validateData(this.basic_schema, name, data, false)\n if (!valid.valid) {\n log('Invalid data', valid)\n return Promise.reject({ ... valid })\n }\n\n return this.table(name).update(id, data)\n },\n\n delete: (id: string) => {\n return this.table(name).delete(id)\n },\n\n\n // --- READ ---- // \n\n get: async (id: string) => {\n return this.table(name).get(id) \n },\n\n getAll: async () => {\n return this.table(name).toArray();\n },\n\n // --- QUERY ---- // \n // TODO: lots to do here. simplifing creating querie, filtering/ordering/limit, and execute\n\n query: () => this.table(name),\n\n filter: (fn: any) => this.table(name).filter(fn).toArray(),\n\n }\n }\n}\n\nclass QueryMethod { \n\n}\n","\"use client\"\nimport { Dexie } from \"dexie\";\nimport { log } from \"../config\";\n\nexport const syncProtocol = function () {\n log(\"Initializing syncProtocol\");\n // Constants:\n var RECONNECT_DELAY = 5000; // Reconnect delay in case of errors such as network down.\n\n Dexie.Syncable.registerSyncProtocol(\"websocket\", {\n sync: function (\n context,\n url,\n options,\n baseRevision,\n syncedRevision,\n changes,\n partial,\n applyRemoteChanges,\n onChangesAccepted,\n onSuccess,\n onError,\n ) {\n // The following vars are needed because we must know which callback to ack when server sends it's ack to us.\n var requestId = 0;\n var acceptCallbacks = {};\n\n // Connect the WebSocket to given url:\n var ws = new WebSocket(url);\n\n // console.log(\"ws OPTIONS\", options);\n\n // sendChanges() method:\n function sendChanges(changes, baseRevision, partial, onChangesAccepted) {\n log(\"sendChanges\", changes.length, baseRevision);\n ++requestId;\n acceptCallbacks[requestId.toString()] = onChangesAccepted;\n\n // In this example, the server expects the following JSON format of the request:\n // {\n // type: \"changes\"\n // baseRevision: baseRevision,\n // changes: changes,\n // partial: partial,\n // requestId: id\n // }\n // To make the sample simplified, we assume the server has the exact same specification of how changes are structured.\n // In real world, you would have to pre-process the changes array to fit the server specification.\n // However, this example shows how to deal with the WebSocket to fullfill the API.\n\n ws.send(\n JSON.stringify({\n type: \"changes\",\n changes: changes,\n partial: partial,\n baseRevision: baseRevision,\n requestId: requestId,\n }),\n );\n }\n\n\n\n // When WebSocket opens, send our changes to the server.\n ws.onopen = function (event) {\n // Initiate this socket connection by sending our clientIdentity. If we dont have a clientIdentity yet,\n // server will call back with a new client identity that we should use in future WebSocket connections.\n \n log(\"Opening socket - sending clientIdentity\", context.clientIdentity);\n ws.send(\n JSON.stringify({\n type: \"clientIdentity\",\n clientIdentity: context.clientIdentity || null,\n authToken: options.authToken\n }),\n );\n\n };\n\n // If network down or other error, tell the framework to reconnect again in some time:\n ws.onerror = function (event) {\n ws.close();\n log(\"ws.onerror\", event);\n onError(event?.message, RECONNECT_DELAY);\n };\n\n // If socket is closed (network disconnected), inform framework and make it reconnect\n ws.onclose = function (event) {\n // console.log('🙅 ws.onclose', event)\n onError(\"Socket closed: \" + event.reason, RECONNECT_DELAY);\n };\n\n // isFirstRound: Will need to call onSuccess() only when we are in sync the first time.\n // onSuccess() will unblock Dexie to be used by application code.\n // If for example app code writes: db.friends.where('shoeSize').above(40).toArray(callback), the execution of that query\n // will not run until we have called onSuccess(). This is because we want application code to get results that are as\n // accurate as possible. Specifically when connected the first time and the entire DB is being synced down to the browser,\n // it is important that queries starts running first when db is in sync.\n var isFirstRound = true;\n // When message arrive from the server, deal with the message accordingly:\n ws.onmessage = function (event) {\n try {\n // Assume we have a server that should send JSON messages of the following format:\n // {\n // type: \"clientIdentity\", \"changes\", \"ack\" or \"error\"\n // clientIdentity: unique value for our database client node to persist in the context. (Only applicable if type=\"clientIdentity\")\n // message: Error message (Only applicable if type=\"error\")\n // requestId: ID of change request that is acked by the server (Only applicable if type=\"ack\" or \"error\")\n // changes: changes from server (Only applicable if type=\"changes\")\n // lastRevision: last revision of changes sent (applicable if type=\"changes\")\n // partial: true if server has additionalChanges to send. False if these changes were the last known. (applicable if type=\"changes\")\n // }\n var requestFromServer = JSON.parse(event.data);\n log(\"requestFromServer\", requestFromServer, { acceptCallback, isFirstRound });\n\n if (requestFromServer.type == \"clientIdentity\") {\n context.clientIdentity = requestFromServer.clientIdentity;\n context.save();\n\n sendChanges(changes, baseRevision, partial, onChangesAccepted);\n\n ws.send(\n JSON.stringify({\n type: \"subscribe\",\n syncedRevision: syncedRevision,\n }),\n );\n } else if (requestFromServer.type == \"changes\") {\n applyRemoteChanges(\n requestFromServer.changes,\n requestFromServer.currentRevision,\n requestFromServer.partial,\n );\n if (isFirstRound && !requestFromServer.partial) {\n // Since this is the first sync round and server sais we've got all changes - now is the time to call onsuccess()\n onSuccess({\n // Specify a react function that will react on additional client changes\n react: function (\n changes,\n baseRevision,\n partial,\n onChangesAccepted,\n ) {\n sendChanges(\n changes,\n baseRevision,\n partial,\n onChangesAccepted,\n );\n },\n // Specify a disconnect function that will close our socket so that we dont continue to monitor changes.\n disconnect: function () {\n ws.close();\n },\n });\n isFirstRound = false;\n }\n } else if (requestFromServer.type == \"ack\") {\n var requestId = requestFromServer.requestId;\n var acceptCallback = acceptCallbacks[requestId.toString()];\n acceptCallback(); // Tell framework that server has acknowledged the changes sent.\n delete acceptCallbacks[requestId.toString()];\n } else if (requestFromServer.type == \"error\") {\n var requestId = requestFromServer.requestId;\n ws.close();\n onError(requestFromServer.message, Infinity); // Don't reconnect - an error in application level means we have done something wrong.\n } else {\n log(\"unknown message\", requestFromServer);\n ws.close();\n onError(\"unknown message\", Infinity);\n }\n } catch (e) {\n ws.close();\n onError(e, Infinity); // Something went crazy. Server sends invalid format or our code is buggy. Dont reconnect - it would continue failing.\n }\n };\n },\n });\n};\n","\n//export const SERVER_URL = \"https://api.basic.tech\"\n export const SERVER_URL = \"http://localhost:3000\"\n\n\nexport const log = (...args: any[]) => {\n try { \n if (localStorage.getItem('basic_debug') === 'true') {\n console.log('[basic]', ...args)\n }\n } catch (e) {\n // console.log('error logging', e)\n }\n}\n\n// export const log = (message: string, ...args: any[]) => {\n// try {\n// if (process.env.NODE_ENV === 'development') {\n// const stack = new Error().stack;\n// const caller = stack?.split('\\n')[2]?.trim();\n// console.log(`[basic] ${message}`, ...args);\n// // console.log(`[stack] ${caller}`);\n// }\n// } catch (e) {\n// console.error('Error in logWithStack:', e);\n// }\n// }\n","// 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 }\nconst ajv = new Ajv()\nconst validator = ajv.compile(basicJsonSchema)\n\ntype Schema = typeof basicJsonSchema\n\nfunction generateEmptySchema() {\n \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: Schema) : {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\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\n\nexport {\n validateSchema,\n validateData,\n generateEmptySchema\n}\n\n","//@ts-nocheck\n\nconst baseUrl = 'https://api.basic.tech';\n// const baseUrl = 'http://localhost:3000';\n\n\nasync function get({ projectId, accountId, tableName, token }) {\n const url = `${baseUrl}/project/${projectId}/db/${accountId}/${tableName}`;\n const response = await fetch(url, {\n headers: {\n 'Authorization': `Bearer ${token}`\n }\n });\n return response.json();\n}\n\nasync function add({ projectId, accountId, tableName, value, token }) {\n const url = `${baseUrl}/project/${projectId}/db/${accountId}/${tableName}`;\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${token}`\n },\n body: JSON.stringify({\"value\": value})\n });\n return response.json();\n}\n\nasync function update({ projectId, accountId, tableName, id, value, token }) {\n const url = `${baseUrl}/project/${projectId}/db/${accountId}/${tableName}/${id}`;\n const response = await fetch(url, {\n method: 'PATCH',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${token}`\n },\n body: JSON.stringify({id: id, value: value})\n });\n return response.json();\n}\n\nasync function deleteRecord({ projectId, accountId, tableName, id, token }) {\n const url = `${baseUrl}/project/${projectId}/db/${accountId}/${tableName}/${id}`;\n const response = await fetch(url, {\n method: 'DELETE',\n headers: {\n 'Authorization': `Bearer ${token}`\n }\n });\n return response.json();\n}\n\nexport { get, add, update, deleteRecord };\n\n","import { useBasic, BasicProvider } from \"./AuthContext\";\nimport { useLiveQuery } from \"dexie-react-hooks\";\nimport { validateSchema, validateData, generateEmptySchema } from \"./schema\";\nimport hello from \"@basictech/schema\"\n\n\nfunction useQuery(queryable: any) {\n return useLiveQuery(() => {\n if (typeof queryable === 'function') {\n return queryable();\n }\n return queryable;\n }, [queryable], []);\n}\n\n\nconst sc = { \n validateSchema: validateSchema,\n validateData: validateData,\n generateEmptySchema: generateEmptySchema\n}\n\nexport {\n useBasic, BasicProvider, useQuery, sc, hello\n}\n"],"mappings":"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","names":["Dexie","changes","baseRevision","partial","onChangesAccepted","requestId","Dexie","key","error","baseUrl","token","user"]}
|
|
1
|
+
{"version":3,"sources":["../src/AuthContext.tsx","../src/sync/index.ts","../src/sync/syncProtocol.js","../src/config.ts","../src/schema.ts","../src/db.ts","../src/index.ts"],"sourcesContent":["// @ts-nocheck\n\nimport React, { createContext, useContext, useEffect, useState, useRef } from 'react'\nimport { jwtDecode } from 'jwt-decode'\n\nimport { BasicSync } from './sync'\nimport { get, add, update, deleteRecord } from './db'\nimport { validateSchema } from '@basictech/schema'\n\nimport { log } from './config'\n\n/*\nschema todo:\n field types\n array types\n relations\n*/\n\n\n// const example = {\n// project_id: '123',\n// version: 0,\n// tables: {\n// example: {\n// name: 'example',\n// type: 'collection',\n// fields: {\n// id: {\n// type: 'uuid',\n// primary: true,\n// },\n// value: {\n// type: 'string',\n// indexed: true,\n// },\n// }\n// }\n// }\n// }\n\n\ntype BasicSyncType = {\n basic_schema: any;\n connect: (options: { access_token: string }) => void;\n debugeroo: () => void;\n collection: (name: string) => {\n ref: {\n toArray: () => Promise<any[]>;\n count: () => Promise<number>;\n };\n };\n [key: string]: any; // For other potential methods and properties\n};\n\n\nenum DBStatus {\n LOADING = \"LOADING\",\n OFFLINE = \"OFFLINE\",\n CONNECTING = \"CONNECTING\",\n ONLINE = \"ONLINE\",\n SYNCING = \"SYNCING\",\n ERROR = \"ERROR\"\n}\n\ntype User = {\n name?: string,\n email?: string,\n id?: string,\n primaryEmailAddress?: {\n emailAddress: string\n },\n fullName?: string\n}\ntype Token = {\n access_token: string,\n token_type: string,\n expires_in: number,\n refresh: string,\n}\n\nexport const BasicContext = createContext<{\n unicorn: string,\n isAuthReady: boolean,\n isSignedIn: boolean,\n user: User | null,\n signout: () => void,\n signin: () => void,\n getToken: () => Promise<string>,\n getSignInLink: () => string,\n db: any,\n dbStatus: DBStatus\n}>({\n unicorn: \"🦄\",\n isAuthReady: false,\n isSignedIn: false,\n user: null,\n signout: () => { },\n signin: () => { },\n getToken: () => new Promise(() => { }),\n getSignInLink: () => \"\",\n db: {},\n dbStatus: DBStatus.LOADING\n});\n\nconst EmptyDB: BasicSyncType = {\n isOpen: false,\n collection: () => {\n return {\n ref: {\n toArray: () => [],\n count: () => 0\n }\n }\n }\n}\n\n\nfunction getSyncStatus(statusCode: number): string {\n switch (statusCode) {\n case -1:\n return \"ERROR\";\n case 0:\n return \"OFFLINE\";\n case 1:\n return \"CONNECTING\";\n case 2:\n return \"ONLINE\";\n case 3:\n return \"SYNCING\";\n case 4:\n return \"ERROR_WILL_RETRY\";\n default:\n return \"UNKNOWN\";\n }\n}\n\ntype ErrorObject = {\n code: string;\n title: string;\n message: string;\n}\n\nexport function BasicProvider({ children, project_id, schema, debug = false }: { children: React.ReactNode, project_id: string, schema: any, debug?: boolean }) {\n const [isAuthReady, setIsAuthReady] = useState(false)\n const [isSignedIn, setIsSignedIn] = useState<boolean>(false)\n const [token, setToken] = useState<Token | null>(null)\n const [user, setUser] = useState<User>({})\n\n const [dbStatus, setDbStatus] = useState<DBStatus>(DBStatus.LOADING)\n const [error, setError] = useState<ErrorObject | null>(null)\n\n const syncRef = useRef<BasicSync | null>(null);\n\n\n useEffect(() => {\n function initDb() {\n const valid = validateSchema(schema)\n if (!valid.valid) {\n log('Basic Schema is invalid!', valid.errors)\n console.group('Schema Errors')\n let errorMessage = ''\n valid.errors.forEach((error, index) => {\n log(`${index + 1}:`, error.message, ` - at ${error.instancePath}`)\n errorMessage += `${index + 1}: ${error.message} - at ${error.instancePath}\\n`\n })\n console.groupEnd('Schema Errors')\n setError({\n code: 'schema_invalid',\n title: 'Basic Schema is invalid!',\n message: errorMessage\n })\n return null\n }\n\n if (!syncRef.current) {\n log('Initializing BasicDB')\n syncRef.current = new BasicSync('basicdb', { schema: schema });\n\n // log('db is open', syncRef.current.isOpen())\n // syncRef.current.open()\n // .then(() => {\n // log(\"is open now:\", syncRef.current.isOpen())\n // })\n }\n }\n\n initDb()\n }, []);\n\n useEffect(() => {\n if (!syncRef.current) {\n return\n }\n\n // syncRef.current.handleStatusChange((status: number, url: string) => {\n // setDbStatus(getSyncStatus(status))\n // })\n\n syncRef.current.syncable.on('statusChanged', (status: number, url: string) => {\n setDbStatus(getSyncStatus(status))\n })\n\n syncRef.current.syncable.getStatus().then((status) => {\n setDbStatus(getSyncStatus(status))\n })\n }, [syncRef.current])\n\n\n const connectToDb = async () => {\n const tok = await getToken()\n if (!tok) {\n log('no token found')\n return\n }\n\n log('connecting to db...')\n\n // TODO: handle if signed out after connect() is already called\n\n syncRef.current.connect({ access_token: tok })\n .catch((e) => {\n log('error connecting to db', e)\n })\n }\n\n useEffect(() => {\n if (token && syncRef.current && isSignedIn && isSignedIn) {\n connectToDb()\n }\n }, [isSignedIn])\n\n const getSignInLink = () => {\n log('getting sign in link...')\n\n const randomState = Math.random().toString(36).substring(6);\n localStorage.setItem('basic_auth_state', randomState)\n\n let baseUrl = \"https://api.basic.tech/auth/authorize\"\n baseUrl += `?client_id=${project_id}`\n baseUrl += `&redirect_uri=${encodeURIComponent(window.location.href)}`\n baseUrl += `&response_type=code`\n baseUrl += `&scope=openid`\n baseUrl += `&state=${randomState}`\n\n return baseUrl;\n }\n\n const signin = () => {\n log('signing in: ', getSignInLink())\n const signInLink = getSignInLink()\n //todo: change to the other thing?\n window.location.href = signInLink;\n }\n\n const signout = () => {\n log('signing out!')\n setUser({})\n setIsSignedIn(false)\n setToken(null)\n document.cookie = `basic_token=; Secure; SameSite=Strict`;\n localStorage.removeItem('basic_auth_state')\n\n if (syncRef.current) {\n // WIP - BUG - sometimes connects even after signout\n syncRef.current.disconnect()\n }\n }\n\n const getToken = async (): Promise<string> => {\n log('getting token...')\n\n if (!token) {\n log('no token found')\n throw new Error('no token found')\n }\n\n const decoded = jwtDecode(token?.access_token)\n const isExpired = decoded.exp && decoded.exp < Date.now() / 1000\n\n if (isExpired) {\n log('token is expired - refreshing ...')\n const newToken = await fetchToken(token?.refresh)\n return newToken?.access_token || ''\n }\n\n return token?.access_token || ''\n }\n\n function getCookie(name: string) {\n let cookieValue = '';\n if (document.cookie && document.cookie !== '') {\n const cookies = document.cookie.split(';');\n for (let i = 0; i < cookies.length; i++) {\n const cookie = cookies[i].trim();\n if (cookie.substring(0, name.length + 1) === (name + '=')) {\n cookieValue = decodeURIComponent(cookie.substring(name.length + 1));\n break;\n }\n }\n }\n return cookieValue;\n }\n\n const fetchToken = async (code: string) => {\n const token = await fetch('https://api.basic.tech/auth/token', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify({ code: code })\n })\n .then(response => response.json())\n .catch(error => log('Error:', error))\n\n if (token.error) {\n log('error fetching token', token.error)\n return\n } else {\n // log('token', token)\n setToken(token)\n }\n return token\n }\n\n useEffect(() => {\n localStorage.setItem('basic_debug', debug ? 'true' : 'false')\n\n try {\n if (window.location.search.includes('code')) {\n let code = window.location?.search?.split('code=')[1].split('&')[0]\n\n const state = localStorage.getItem('basic_auth_state')\n if (!state || state !== window.location.search.split('state=')[1].split('&')[0]) {\n log('error: auth state does not match')\n setIsAuthReady(true)\n\n localStorage.removeItem('basic_auth_state')\n window.history.pushState({}, document.title, \"/\");\n return\n }\n\n localStorage.removeItem('basic_auth_state')\n\n fetchToken(code) \n } else { \n let cookie_token = getCookie('basic_token')\n if (cookie_token !== '') {\n setToken(JSON.parse(cookie_token))\n } else { \n setIsAuthReady(true)\n }\n }\n\n\n } catch (e) {\n log('error getting cookie', e)\n }\n }, [])\n\n useEffect(() => {\n async function fetchUser(acc_token: string) {\n console.info('fetching user')\n const user = await fetch('https://api.basic.tech/auth/userInfo', {\n method: 'GET',\n headers: {\n 'Authorization': `Bearer ${acc_token}`\n }\n })\n .then(response => response.json())\n .catch(error => log('Error:', error))\n\n if (user.error) {\n log('error fetching user', user.error)\n // refreshToken()\n return\n } else {\n // log('user', user)\n document.cookie = `basic_token=${JSON.stringify(token)}; Secure; SameSite=Strict`;\n \n if (window.location.search.includes('code')) {\n window.history.pushState({}, document.title, \"/\");\n }\n \n setUser(user)\n setIsSignedIn(true)\n\n setIsAuthReady(true)\n }\n }\n\n async function checkToken() {\n if (!token) {\n log('error: no user token found')\n\n setIsAuthReady(true)\n return\n }\n\n const decoded = jwtDecode(token?.access_token)\n const isExpired = decoded.exp && decoded.exp < Date.now() / 1000\n\n if (isExpired) {\n log('token is expired - refreshing ...')\n const newToken = await fetchToken(token?.refresh)\n fetchUser(newToken.access_token)\n } else {\n fetchUser(token.access_token)\n }\n }\n\n if (token) {\n checkToken()\n } \n }, [token])\n\n\n const db_ = (tableName: string) => {\n const checkSignIn = () => {\n if (!isSignedIn) {\n throw new Error('cannot use db. user not logged in.')\n }\n }\n\n return {\n get: async () => {\n checkSignIn()\n const tok = await getToken()\n return get({ projectId: project_id, accountId: user.id, tableName: tableName, token: tok })\n },\n add: async (value: any) => {\n checkSignIn()\n const tok = await getToken()\n return add({ projectId: project_id, accountId: user.id, tableName: tableName, value: value, token: tok })\n },\n update: async (id: string, value: any) => {\n checkSignIn()\n const tok = await getToken()\n return update({ projectId: project_id, accountId: user.id, tableName: tableName, id: id, value: value, token: tok })\n },\n delete: async (id: string) => {\n checkSignIn()\n const tok = await getToken()\n return deleteRecord({ projectId: project_id, accountId: user.id, tableName: tableName, id: id, token: tok })\n }\n\n }\n\n }\n\n return (\n <BasicContext.Provider value={{\n unicorn: \"🦄\",\n isAuthReady,\n isSignedIn,\n user,\n signout,\n signin,\n getToken,\n getSignInLink,\n db: syncRef.current,\n dbStatus\n }}>\n {error && <ErrorDisplay error={error} />}\n {syncRef.current ? children : null}\n </BasicContext.Provider>\n )\n}\n\nfunction ErrorDisplay({ error }: { error: ErrorObject }) {\n return <div style={{ \n position: 'absolute',\n top: 20, \n left: 20,\n color: 'black',\n backgroundColor: '#f8d7da',\n border: '1px solid #f5c6cb',\n borderRadius: '4px',\n padding: '20px',\n maxWidth: '400px',\n margin: '20px auto',\n boxShadow: '0 2px 4px rgba(0, 0, 0, 0.1)',\n fontFamily: 'monospace', \n }}>\n <h3 style={{fontSize: '0.8rem', opacity: 0.8}}>code: {error.code}</h3>\n <h1 style={{fontSize: '1.2rem', lineHeight: '1.5'}}>{error.title}</h1>\n <p>{error.message}</p>\n </div>\n}\n\n/*\npossible errors: \n- projectid missing / invalid\n- schema missing / invalid\n*/\n\nexport function useBasic() {\n return useContext(BasicContext);\n}\n","\"use client\"\n\nimport { v7 as uuidv7 } from 'uuid';\nimport { Dexie, PromiseExtended } from 'dexie';\nimport 'dexie-syncable';\nimport 'dexie-observable';\n\nimport { syncProtocol } from './syncProtocol'\nimport { SERVER_URL, log } from '../config'\n\nimport { validateSchema, validateData } from '../schema'\nsyncProtocol()\n\n\n// const DexieSyncStatus = {\n// \"-1\": \"ERROR\",\n// \"0\": \"OFFLINE\",\n// \"1\": \"CONNECTING\",\n// \"2\": \"ONLINE\",\n// \"3\": \"SYNCING\",\n// \"4\": \"ERROR_WILL_RETRY\"\n// }\n\n\n\n\n\nexport class BasicSync extends Dexie {\n basic_schema: any\n\n constructor(name: string, options: any) {\n super(name, options);\n\n // --- INIT SCHEMA --- // \n\n //todo: handle versions?\n\n // TODO: validate schema\n this.basic_schema = options.schema\n this.version(1).stores(this._convertSchemaToDxSchema(this.basic_schema))\n\n this.version(2).stores({})\n // this.verssion\n\n\n // create an alias for toArray\n // @ts-ignore\n this.Collection.prototype.get = this.Collection.prototype.toArray\n\n\n // --- SYNC --- // \n\n // this.syncable.on(\"statusChanged\", (status, url) => { \n // console.log(\"statusChanged\", status, url)\n // })\n\n }\n\n async connect({ access_token }: { access_token: string }) {\n // const WS_URL = \"ws://localhost:3003/ws\"\n const WS_URL = `${SERVER_URL}/ws`\n\n \n // Update sync nodes\n await this.updateSyncNodes();\n \n // Proceed with the WebSocket connection\n \n log('Starting connection...')\n return this.syncable.connect(\"websocket\", WS_URL, { authToken: access_token });\n }\n\n async disconnect() {\n const WS_URL = `${SERVER_URL}/ws`\n\n return this.syncable.disconnect(WS_URL) \n }\n\n private async updateSyncNodes() {\n try {\n const syncNodes = await this.table('_syncNodes').toArray();\n const localSyncNodes = syncNodes.filter(node => node.type === 'local');\n log('Local sync nodes:', localSyncNodes);\n\n if (localSyncNodes.length > 1) {\n\n \n const largestNodeId = Math.max(...localSyncNodes.map(node => node.id));\n // Check if the largest node is already the master\n const largestNode = localSyncNodes.find(node => node.id === largestNodeId);\n if (largestNode && largestNode.isMaster === 1) {\n log('Largest node is already the master. No changes needed.');\n return; // Exit the function early as no changes are needed\n }\n\n\n log('Largest node id:', largestNodeId);\n log('HEISENBUG: More than one local sync node found.')\n\n for (const node of localSyncNodes) {\n log(`Local sync node keys:`, node.id, node.isMaster);\n await this.table('_syncNodes').update(node.id, { isMaster: node.id === largestNodeId ? 1 : 0 });\n\n log(`HEISENBUG: Setting ${node.id} to ${node.id === largestNodeId ? 'master' : '0'}`);\n }\n\n // Add a 1 second delay before returning // i dont think this helps?\n await new Promise(resolve => setTimeout(resolve, 2000));\n\n }\n\n log('Sync nodes updated');\n } catch (error) {\n console.error('Error updating _syncNodes table:', error);\n }\n }\n\n handleStatusChange(fn: any) {\n this.syncable.on(\"statusChanged\", fn)\n }\n\n\n _convertSchemaToDxSchema(schema: any) {\n const stores = Object.entries(schema.tables).map(([key, table]: any) => {\n\n const indexedFields = Object.entries(table.fields).filter(([key, field]: any) => field.indexed).map(([key, field]: any) => `,${key}`).join('')\n return {\n [key]: 'id' + indexedFields\n }\n })\n\n return Object.assign({}, ...stores)\n }\n\n debugeroo() {\n // console.log(\"debugeroo\", this.syncable)\n\n // this.syncable.list().then(x => console.log(x))\n\n // this.syncable\n return this.syncable\n }\n\n collection(name: string) {\n // TODO: check against schema\n\n return {\n\n /**\n * Returns the underlying Dexie table\n * @type {Dexie.Table}\n */\n ref: this.table(name),\n\n // --- WRITE ---- // \n add: (data: any) => {\n // log(\"Adding data to\", name, data)\n\n const valid = validateData(this.basic_schema, name, data)\n if (!valid.valid) {\n log('Invalid data', valid)\n return Promise.reject({ ... valid })\n }\n\n return this.table(name).add({\n id: uuidv7(),\n ...data\n })\n\n },\n\n put: (data: any) => {\n const valid = validateData(this.basic_schema, name, data)\n if (!valid.valid) {\n log('Invalid data', valid)\n return Promise.reject({ ... valid })\n }\n\n return this.table(name).put({\n id: uuidv7(),\n ...data\n })\n },\n\n update: (id: string, data: any) => {\n const valid = validateData(this.basic_schema, name, data, false)\n if (!valid.valid) {\n log('Invalid data', valid)\n return Promise.reject({ ... valid })\n }\n\n return this.table(name).update(id, data)\n },\n\n delete: (id: string) => {\n return this.table(name).delete(id)\n },\n\n\n // --- READ ---- // \n\n get: async (id: string) => {\n return this.table(name).get(id) \n },\n\n getAll: async () => {\n return this.table(name).toArray();\n },\n\n // --- QUERY ---- // \n // TODO: lots to do here. simplifing creating querie, filtering/ordering/limit, and execute\n\n query: () => this.table(name),\n\n filter: (fn: any) => this.table(name).filter(fn).toArray(),\n\n }\n }\n}\n\nclass QueryMethod { \n\n}\n","\"use client\"\nimport { Dexie } from \"dexie\";\nimport { log } from \"../config\";\n\nexport const syncProtocol = function () {\n log(\"Initializing syncProtocol\");\n // Constants:\n var RECONNECT_DELAY = 5000; // Reconnect delay in case of errors such as network down.\n\n Dexie.Syncable.registerSyncProtocol(\"websocket\", {\n sync: function (\n context,\n url,\n options,\n baseRevision,\n syncedRevision,\n changes,\n partial,\n applyRemoteChanges,\n onChangesAccepted,\n onSuccess,\n onError,\n ) {\n // The following vars are needed because we must know which callback to ack when server sends it's ack to us.\n var requestId = 0;\n var acceptCallbacks = {};\n\n // Connect the WebSocket to given url:\n var ws = new WebSocket(url);\n\n // console.log(\"ws OPTIONS\", options);\n\n // sendChanges() method:\n function sendChanges(changes, baseRevision, partial, onChangesAccepted) {\n log(\"sendChanges\", changes.length, baseRevision);\n ++requestId;\n acceptCallbacks[requestId.toString()] = onChangesAccepted;\n\n // In this example, the server expects the following JSON format of the request:\n // {\n // type: \"changes\"\n // baseRevision: baseRevision,\n // changes: changes,\n // partial: partial,\n // requestId: id\n // }\n // To make the sample simplified, we assume the server has the exact same specification of how changes are structured.\n // In real world, you would have to pre-process the changes array to fit the server specification.\n // However, this example shows how to deal with the WebSocket to fullfill the API.\n\n ws.send(\n JSON.stringify({\n type: \"changes\",\n changes: changes,\n partial: partial,\n baseRevision: baseRevision,\n requestId: requestId,\n }),\n );\n }\n\n\n\n // When WebSocket opens, send our changes to the server.\n ws.onopen = function (event) {\n // Initiate this socket connection by sending our clientIdentity. If we dont have a clientIdentity yet,\n // server will call back with a new client identity that we should use in future WebSocket connections.\n \n log(\"Opening socket - sending clientIdentity\", context.clientIdentity);\n ws.send(\n JSON.stringify({\n type: \"clientIdentity\",\n clientIdentity: context.clientIdentity || null,\n authToken: options.authToken\n }),\n );\n\n };\n\n // If network down or other error, tell the framework to reconnect again in some time:\n ws.onerror = function (event) {\n ws.close();\n log(\"ws.onerror\", event);\n onError(event?.message, RECONNECT_DELAY);\n };\n\n // If socket is closed (network disconnected), inform framework and make it reconnect\n ws.onclose = function (event) {\n // console.log('🙅 ws.onclose', event)\n onError(\"Socket closed: \" + event.reason, RECONNECT_DELAY);\n };\n\n // isFirstRound: Will need to call onSuccess() only when we are in sync the first time.\n // onSuccess() will unblock Dexie to be used by application code.\n // If for example app code writes: db.friends.where('shoeSize').above(40).toArray(callback), the execution of that query\n // will not run until we have called onSuccess(). This is because we want application code to get results that are as\n // accurate as possible. Specifically when connected the first time and the entire DB is being synced down to the browser,\n // it is important that queries starts running first when db is in sync.\n var isFirstRound = true;\n // When message arrive from the server, deal with the message accordingly:\n ws.onmessage = function (event) {\n try {\n // Assume we have a server that should send JSON messages of the following format:\n // {\n // type: \"clientIdentity\", \"changes\", \"ack\" or \"error\"\n // clientIdentity: unique value for our database client node to persist in the context. (Only applicable if type=\"clientIdentity\")\n // message: Error message (Only applicable if type=\"error\")\n // requestId: ID of change request that is acked by the server (Only applicable if type=\"ack\" or \"error\")\n // changes: changes from server (Only applicable if type=\"changes\")\n // lastRevision: last revision of changes sent (applicable if type=\"changes\")\n // partial: true if server has additionalChanges to send. False if these changes were the last known. (applicable if type=\"changes\")\n // }\n var requestFromServer = JSON.parse(event.data);\n log(\"requestFromServer\", requestFromServer, { acceptCallback, isFirstRound });\n\n if (requestFromServer.type == \"clientIdentity\") {\n context.clientIdentity = requestFromServer.clientIdentity;\n context.save();\n\n sendChanges(changes, baseRevision, partial, onChangesAccepted);\n\n ws.send(\n JSON.stringify({\n type: \"subscribe\",\n syncedRevision: syncedRevision,\n }),\n );\n } else if (requestFromServer.type == \"changes\") {\n applyRemoteChanges(\n requestFromServer.changes,\n requestFromServer.currentRevision,\n requestFromServer.partial,\n );\n if (isFirstRound && !requestFromServer.partial) {\n // Since this is the first sync round and server sais we've got all changes - now is the time to call onsuccess()\n onSuccess({\n // Specify a react function that will react on additional client changes\n react: function (\n changes,\n baseRevision,\n partial,\n onChangesAccepted,\n ) {\n sendChanges(\n changes,\n baseRevision,\n partial,\n onChangesAccepted,\n );\n },\n // Specify a disconnect function that will close our socket so that we dont continue to monitor changes.\n disconnect: function () {\n ws.close();\n },\n });\n isFirstRound = false;\n }\n } else if (requestFromServer.type == \"ack\") {\n var requestId = requestFromServer.requestId;\n var acceptCallback = acceptCallbacks[requestId.toString()];\n acceptCallback(); // Tell framework that server has acknowledged the changes sent.\n delete acceptCallbacks[requestId.toString()];\n } else if (requestFromServer.type == \"error\") {\n var requestId = requestFromServer.requestId;\n ws.close();\n onError(requestFromServer.message, Infinity); // Don't reconnect - an error in application level means we have done something wrong.\n } else {\n log(\"unknown message\", requestFromServer);\n ws.close();\n onError(\"unknown message\", Infinity);\n }\n } catch (e) {\n ws.close();\n onError(e, Infinity); // Something went crazy. Server sends invalid format or our code is buggy. Dont reconnect - it would continue failing.\n }\n };\n },\n });\n};\n","\nexport const SERVER_URL = \"https://api.basic.tech\"\n// export const SERVER_URL = \"http://localhost:3000\"\n\n\nexport const log = (...args: any[]) => {\n try { \n if (localStorage.getItem('basic_debug') === 'true') {\n console.log('[basic]', ...args)\n }\n } catch (e) {\n // console.log('error logging', e)\n }\n}\n\n// export const log = (message: string, ...args: any[]) => {\n// try {\n// if (process.env.NODE_ENV === 'development') {\n// const stack = new Error().stack;\n// const caller = stack?.split('\\n')[2]?.trim();\n// console.log(`[basic] ${message}`, ...args);\n// // console.log(`[stack] ${caller}`);\n// }\n// } catch (e) {\n// console.error('Error in logWithStack:', e);\n// }\n// }\n","// 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 }\nconst ajv = new Ajv()\nconst validator = ajv.compile(basicJsonSchema)\n\ntype Schema = typeof basicJsonSchema\n\nfunction generateEmptySchema() {\n \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: Schema) : {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\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\n\nexport {\n validateSchema,\n validateData,\n generateEmptySchema\n}\n\n","//@ts-nocheck\n\nconst baseUrl = 'https://api.basic.tech';\n// const baseUrl = 'http://localhost:3000';\n\n\nasync function get({ projectId, accountId, tableName, token }) {\n const url = `${baseUrl}/project/${projectId}/db/${accountId}/${tableName}`;\n const response = await fetch(url, {\n headers: {\n 'Authorization': `Bearer ${token}`\n }\n });\n return response.json();\n}\n\nasync function add({ projectId, accountId, tableName, value, token }) {\n const url = `${baseUrl}/project/${projectId}/db/${accountId}/${tableName}`;\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${token}`\n },\n body: JSON.stringify({\"value\": value})\n });\n return response.json();\n}\n\nasync function update({ projectId, accountId, tableName, id, value, token }) {\n const url = `${baseUrl}/project/${projectId}/db/${accountId}/${tableName}/${id}`;\n const response = await fetch(url, {\n method: 'PATCH',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${token}`\n },\n body: JSON.stringify({id: id, value: value})\n });\n return response.json();\n}\n\nasync function deleteRecord({ projectId, accountId, tableName, id, token }) {\n const url = `${baseUrl}/project/${projectId}/db/${accountId}/${tableName}/${id}`;\n const response = await fetch(url, {\n method: 'DELETE',\n headers: {\n 'Authorization': `Bearer ${token}`\n }\n });\n return response.json();\n}\n\nexport { get, add, update, deleteRecord };\n\n","import { useState } from \"react\";\nimport { useBasic, BasicProvider } from \"./AuthContext\";\nimport { useLiveQuery as useQuery } from \"dexie-react-hooks\";\n\n// const useQuery = (queryable: any) => {\n// const [loading, setLoading] = useState(true)\n// const [error, setError] = useState<Error | null>(null)\n\n// const result = useLiveQuery(async () => {\n// try {\n// setLoading(true)\n// setError(null)\n \n// // if (typeof queryable === 'function') {\n// // return await queryable()\n// // }\n// return queryable\n \n// } catch (err) {\n// setError(err instanceof Error ? err : new Error('Unknown error'))\n// return undefined\n// } finally {\n// setLoading(false)\n// }\n// }, [queryable])\n\n// return {\n// data: result,\n// loading,\n// error\n// }\n// }\n\n\n\nexport {\n useBasic, BasicProvider, useQuery\n}\n"],"mappings":"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","names":["Dexie","changes","baseRevision","partial","onChangesAccepted","requestId","Dexie","key","validateSchema","validateSchema","error","baseUrl","token","user"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@basictech/react",
|
|
3
|
-
"version": "0.2.0-beta.
|
|
3
|
+
"version": "0.2.0-beta.11",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"dexie-syncable": "^4.0.1-beta.13",
|
|
25
25
|
"jwt-decode": "^4.0.0",
|
|
26
26
|
"uuid": "^10.0.0",
|
|
27
|
-
"@basictech/schema": "0.1.0-beta.
|
|
27
|
+
"@basictech/schema": "0.1.0-beta.1"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@repo/typescript-config": "*",
|
package/src/AuthContext.tsx
CHANGED
|
@@ -5,7 +5,7 @@ import { jwtDecode } from 'jwt-decode'
|
|
|
5
5
|
|
|
6
6
|
import { BasicSync } from './sync'
|
|
7
7
|
import { get, add, update, deleteRecord } from './db'
|
|
8
|
-
import { validateSchema } from '
|
|
8
|
+
import { validateSchema } from '@basictech/schema'
|
|
9
9
|
|
|
10
10
|
import { log } from './config'
|
|
11
11
|
|
package/src/index.ts
CHANGED
|
@@ -1,25 +1,38 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
1
2
|
import { useBasic, BasicProvider } from "./AuthContext";
|
|
2
|
-
import { useLiveQuery } from "dexie-react-hooks";
|
|
3
|
-
import { validateSchema, validateData, generateEmptySchema } from "./schema";
|
|
4
|
-
import hello from "@basictech/schema"
|
|
3
|
+
import { useLiveQuery as useQuery } from "dexie-react-hooks";
|
|
5
4
|
|
|
5
|
+
// const useQuery = (queryable: any) => {
|
|
6
|
+
// const [loading, setLoading] = useState(true)
|
|
7
|
+
// const [error, setError] = useState<Error | null>(null)
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
9
|
+
// const result = useLiveQuery(async () => {
|
|
10
|
+
// try {
|
|
11
|
+
// setLoading(true)
|
|
12
|
+
// setError(null)
|
|
13
|
+
|
|
14
|
+
// // if (typeof queryable === 'function') {
|
|
15
|
+
// // return await queryable()
|
|
16
|
+
// // }
|
|
17
|
+
// return queryable
|
|
18
|
+
|
|
19
|
+
// } catch (err) {
|
|
20
|
+
// setError(err instanceof Error ? err : new Error('Unknown error'))
|
|
21
|
+
// return undefined
|
|
22
|
+
// } finally {
|
|
23
|
+
// setLoading(false)
|
|
24
|
+
// }
|
|
25
|
+
// }, [queryable])
|
|
26
|
+
|
|
27
|
+
// return {
|
|
28
|
+
// data: result,
|
|
29
|
+
// loading,
|
|
30
|
+
// error
|
|
31
|
+
// }
|
|
32
|
+
// }
|
|
15
33
|
|
|
16
34
|
|
|
17
|
-
const sc = {
|
|
18
|
-
validateSchema: validateSchema,
|
|
19
|
-
validateData: validateData,
|
|
20
|
-
generateEmptySchema: generateEmptySchema
|
|
21
|
-
}
|
|
22
35
|
|
|
23
36
|
export {
|
|
24
|
-
useBasic, BasicProvider, useQuery
|
|
37
|
+
useBasic, BasicProvider, useQuery
|
|
25
38
|
}
|