@basictech/react 0.2.0-beta.4 → 0.2.0-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog.md +6 -0
- package/dist/index.js +1 -30
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -30
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/AuthContext.tsx +21 -31
package/changelog.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -362,34 +362,6 @@ async function deleteRecord({ projectId, accountId, tableName, id, token }) {
|
|
|
362
362
|
|
|
363
363
|
// src/AuthContext.tsx
|
|
364
364
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
365
|
-
var example = {
|
|
366
|
-
project_id: "123",
|
|
367
|
-
version: 0,
|
|
368
|
-
tables: {
|
|
369
|
-
example: {
|
|
370
|
-
name: "example",
|
|
371
|
-
type: "collection",
|
|
372
|
-
fields: {
|
|
373
|
-
id: {
|
|
374
|
-
type: "uuid",
|
|
375
|
-
primary: true
|
|
376
|
-
},
|
|
377
|
-
value: {
|
|
378
|
-
type: "string",
|
|
379
|
-
indexed: true
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
},
|
|
383
|
-
example2: {
|
|
384
|
-
name: "example2",
|
|
385
|
-
type: "collection",
|
|
386
|
-
fields: {
|
|
387
|
-
id: { type: "string", primary: true },
|
|
388
|
-
id: { type: "string", primary: true }
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
};
|
|
393
365
|
var BasicContext = (0, import_react.createContext)({
|
|
394
366
|
unicorn: "\u{1F984}",
|
|
395
367
|
isLoaded: false,
|
|
@@ -434,12 +406,11 @@ function BasicProvider({ children, project_id, schema }) {
|
|
|
434
406
|
const [error, setError] = (0, import_react.useState)(null);
|
|
435
407
|
(0, import_react.useEffect)(() => {
|
|
436
408
|
function initDb() {
|
|
437
|
-
if (!validator(
|
|
409
|
+
if (!validator(schema)) {
|
|
438
410
|
console.error("Basic Schema is invalid!", validator.errors);
|
|
439
411
|
console.group("Schema Errors");
|
|
440
412
|
let errorMessage = "";
|
|
441
413
|
validator.errors.forEach((error2, index) => {
|
|
442
|
-
console.log("error", error2);
|
|
443
414
|
console.log(`${index + 1}:`, error2.message, ` - at ${error2.instancePath}`);
|
|
444
415
|
errorMessage += `${index + 1}: ${error2.message} - at ${error2.instancePath}
|
|
445
416
|
`;
|
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/db.ts"],"sourcesContent":["import { useBasic, BasicProvider } from \"./AuthContext\";\nimport { useLiveQuery as useQuery } from \"dexie-react-hooks\";\n\nexport {\n useBasic, BasicProvider, useQuery\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'\n\nimport { validator, log } from './config'\n\n/*\nschema todo:\n field types\n array types\n relations\n*/\n\n\nconst 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 example2: {\n name: 'example2',\n type: 'collection',\n fields: {\n id: { type: 'string', primary: true },\n id: { type: 'string', primary: true },\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 isLoaded: 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 isLoaded: false,\n isSignedIn: false,\n user: null,\n signout: () => { },\n signin: () => { },\n getToken: () => new Promise(() => { }),\n getSignInLink: () => \"\",\n db: {},\n dbStatus: DBStatus.OFFLINE\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 }: { children: React.ReactNode, project_id: string, schema: any }) {\n const [isLoaded, setIsLoaded] = useState(false)\n const [isSignedIn, setIsSignedIn] = useState(false)\n const [token, setToken] = useState<Token | null>(null)\n const [authCode, setAuthCode] = useState<string | null>(null)\n const [user, setUser] = useState<User>({})\n\n const [dbStatus, setDbStatus] = useState<DBStatus>(DBStatus.LOADING)\n\n const syncRef = useRef<BasicSync | null>(null);\n\n const [error, setError] = useState<ErrorObject | null>(null)\n\n useEffect(() => {\n function initDb() {\n // console.log('S', validator(example))\n if (!validator(example)) {\n console.error('Basic Schema is invalid!', validator.errors)\n console.group('Schema Errors')\n let errorMessage = ''\n validator.errors.forEach((error, index) => {\n console.log('error', error)\n console.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\n if (!syncRef.current) {\n syncRef.current = new BasicSync('basicdb', { schema: schema });\n\n // console.log('db is open', syncRef.current.isOpen())\n // syncRef.current.open()\n // .then(() => {\n // console.log(\"is open now:\", syncRef.current.isOpen())\n // })\n\n syncRef.current.handleStatusChange((status: number, url: string) => {\n setDbStatus(getSyncStatus(status))\n })\n\n syncRef.current.syncable.getStatus().then((status) => {\n console.log('sync status', getSyncStatus(status))\n })\n }\n\n }\n\n initDb()\n }, []);\n\n\n //todo: \n //add random state to signin link & verify random state\n\n const connectToDb = async () => {\n\n const tok = await getToken()\n\n console.log('connecting to db...', tok.substring(0, 10))\n\n syncRef.current.connect({ access_token: tok })\n .catch((e) => {\n console.log('error connecting to db', e)\n })\n }\n\n useEffect(() => {\n if (token && syncRef.current) {\n connectToDb()\n }\n }, [token])\n\n const getSignInLink = () => {\n console.log('getting sign in link...')\n\n const randomState = Math.random().toString(36).substring(7);\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=1234zyx`\n\n return baseUrl;\n }\n\n const signin = () => {\n console.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 console.log('signing out!')\n setUser({})\n setIsSignedIn(false)\n setToken(null)\n setAuthCode(null)\n document.cookie = `basic_token=; Secure; SameSite=Strict`;\n }\n\n const getToken = async (): Promise<string> => {\n console.log('getting token...')\n\n if (!token) {\n console.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 console.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 => console.error('Error:', error))\n\n if (token.error) {\n console.log('error fetching token', token.error)\n return\n } else {\n // console.log('token', token)\n setToken(token)\n }\n return token\n }\n\n useEffect(() => {\n try {\n let cookie_token = getCookie('basic_token')\n if (cookie_token !== '') {\n setToken(JSON.parse(cookie_token))\n }\n\n if (window.location.search.includes('code')) {\n let code = window.location?.search?.split('code=')[1].split('&')[0]\n // console.log('code found', code)\n\n // todo: check state is valid\n setAuthCode(code) // remove this? dont need to store code?\n fetchToken(code)\n\n window.history.pushState({}, document.title, \"/\");\n\n } else {\n setIsLoaded(true)\n }\n } catch (e) {\n console.log('error getting cookie', e)\n }\n }, [])\n\n useEffect(() => {\n async function fetchUser(acc_token: string) {\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 => console.error('Error:', error))\n\n if (user.error) {\n console.log('error fetching user', user.error)\n // refreshToken()\n return\n } else {\n // console.log('user', user)\n document.cookie = `basic_token=${JSON.stringify(token)}; Secure; SameSite=Strict`;\n setUser(user)\n setIsSignedIn(true)\n setIsLoaded(true)\n }\n }\n\n async function checkToken() {\n if (!token) {\n console.log('error: no user token found')\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 console.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 setIsLoaded(true)\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 isLoaded,\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}","\"use client\"\n\nimport { v7 as uuidv7 } from 'uuid';\nimport { Dexie, PromiseExtended } from 'dexie';\n// if (typeof window !== 'undefined') {\n// import('dexie-observable');\n// }\nimport 'dexie-syncable';\nimport 'dexie-observable';\n\nimport { syncProtocol } from './syncProtocol'\nimport { SERVER_URL } from '../config'\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 console.log('Starting connection...')\n return this.syncable.connect(\"websocket\", WS_URL, { authToken: access_token });\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 console.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 console.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 console.log('Largest node id:', largestNodeId);\n console.error('HEISENBUG: More than one local sync node found.')\n\n for (const node of localSyncNodes) {\n console.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 console.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 console.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\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 console.log(\"Adding data to\", name, data)\n return this.table(name).add({\n id: uuidv7(),\n ...data\n })\n },\n\n put: (data: any) => {\n return this.table(name).put({\n id: uuidv7(),\n ...data\n })\n },\n\n update: (id: string, data: any) => {\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: (id: string) => {\n return this.table(name).get(id)\n },\n\n getAll: () => {\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","\"use client\"\nimport { Dexie } from \"dexie\";\n\nexport const syncProtocol = function () {\n console.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 console.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 console.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 console.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 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 console.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 == \"error\") {\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 console.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","import Ajv from 'ajv'\n\nexport const SERVER_URL = \"https://api.basic.tech\"\n// export const WS_URL = `${SERVER_URL}/ws`\n\nexport const log = (...args: any[]) => {\n if (process.env.NODE_ENV === 'development') {\n console.log(...args)\n }\n}\n\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 },\n \"primary\": {\n \"type\": \"boolean\"\n },\n \"indexed\": {\n \"type\": \"boolean\"\n }\n },\n \"required\": [\"type\"]\n }\n },\n \"additionalProperties\": true\n }\n },\n \"required\": [\"fields\"]\n }\n },\n \"additionalProperties\": true\n }\n },\n \"required\": [\"project_id\", \"version\", \"tables\"]\n}\n\n\nconst ajv = new Ajv()\nexport const validator = ajv.compile(basicJsonSchema)\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","error","baseUrl","token","user"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/AuthContext.tsx","../src/sync/index.ts","../src/sync/syncProtocol.js","../src/config.ts","../src/db.ts"],"sourcesContent":["import { useBasic, BasicProvider } from \"./AuthContext\";\nimport { useLiveQuery as useQuery } from \"dexie-react-hooks\";\n\nexport {\n useBasic, BasicProvider, useQuery\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'\n\nimport { validator, 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 isLoaded: 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 isLoaded: false,\n isSignedIn: false,\n user: null,\n signout: () => { },\n signin: () => { },\n getToken: () => new Promise(() => { }),\n getSignInLink: () => \"\",\n db: {},\n dbStatus: DBStatus.OFFLINE\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 }: { children: React.ReactNode, project_id: string, schema: any }) {\n const [isLoaded, setIsLoaded] = useState(false)\n const [isSignedIn, setIsSignedIn] = useState(false)\n const [token, setToken] = useState<Token | null>(null)\n const [authCode, setAuthCode] = useState<string | null>(null)\n const [user, setUser] = useState<User>({})\n\n const [dbStatus, setDbStatus] = useState<DBStatus>(DBStatus.LOADING)\n\n const syncRef = useRef<BasicSync | null>(null);\n\n const [error, setError] = useState<ErrorObject | null>(null)\n\n useEffect(() => {\n function initDb() {\n if (!validator(schema)) {\n console.error('Basic Schema is invalid!', validator.errors)\n console.group('Schema Errors')\n let errorMessage = ''\n validator.errors.forEach((error, index) => {\n console.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\n if (!syncRef.current) {\n syncRef.current = new BasicSync('basicdb', { schema: schema });\n\n // console.log('db is open', syncRef.current.isOpen())\n // syncRef.current.open()\n // .then(() => {\n // console.log(\"is open now:\", syncRef.current.isOpen())\n // })\n\n syncRef.current.handleStatusChange((status: number, url: string) => {\n setDbStatus(getSyncStatus(status))\n })\n\n syncRef.current.syncable.getStatus().then((status) => {\n console.log('sync status', getSyncStatus(status))\n })\n }\n\n }\n\n initDb()\n }, []);\n\n\n //todo: \n //add random state to signin link & verify random state\n\n const connectToDb = async () => {\n\n const tok = await getToken()\n\n console.log('connecting to db...', tok.substring(0, 10))\n\n syncRef.current.connect({ access_token: tok })\n .catch((e) => {\n console.log('error connecting to db', e)\n })\n }\n\n useEffect(() => {\n if (token && syncRef.current) {\n connectToDb()\n }\n }, [token])\n\n const getSignInLink = () => {\n console.log('getting sign in link...')\n\n const randomState = Math.random().toString(36).substring(7);\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=1234zyx`\n\n return baseUrl;\n }\n\n const signin = () => {\n console.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 console.log('signing out!')\n setUser({})\n setIsSignedIn(false)\n setToken(null)\n setAuthCode(null)\n document.cookie = `basic_token=; Secure; SameSite=Strict`;\n }\n\n const getToken = async (): Promise<string> => {\n console.log('getting token...')\n\n if (!token) {\n console.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 console.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 => console.error('Error:', error))\n\n if (token.error) {\n console.log('error fetching token', token.error)\n return\n } else {\n // console.log('token', token)\n setToken(token)\n }\n return token\n }\n\n useEffect(() => {\n try {\n let cookie_token = getCookie('basic_token')\n if (cookie_token !== '') {\n setToken(JSON.parse(cookie_token))\n }\n\n if (window.location.search.includes('code')) {\n let code = window.location?.search?.split('code=')[1].split('&')[0]\n // console.log('code found', code)\n\n // todo: check state is valid\n setAuthCode(code) // remove this? dont need to store code?\n fetchToken(code)\n\n window.history.pushState({}, document.title, \"/\");\n\n } else {\n setIsLoaded(true)\n }\n } catch (e) {\n console.log('error getting cookie', e)\n }\n }, [])\n\n useEffect(() => {\n async function fetchUser(acc_token: string) {\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 => console.error('Error:', error))\n\n if (user.error) {\n console.log('error fetching user', user.error)\n // refreshToken()\n return\n } else {\n // console.log('user', user)\n document.cookie = `basic_token=${JSON.stringify(token)}; Secure; SameSite=Strict`;\n setUser(user)\n setIsSignedIn(true)\n setIsLoaded(true)\n }\n }\n\n async function checkToken() {\n if (!token) {\n console.log('error: no user token found')\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 console.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 setIsLoaded(true)\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 isLoaded,\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}","\"use client\"\n\nimport { v7 as uuidv7 } from 'uuid';\nimport { Dexie, PromiseExtended } from 'dexie';\n// if (typeof window !== 'undefined') {\n// import('dexie-observable');\n// }\nimport 'dexie-syncable';\nimport 'dexie-observable';\n\nimport { syncProtocol } from './syncProtocol'\nimport { SERVER_URL } from '../config'\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 console.log('Starting connection...')\n return this.syncable.connect(\"websocket\", WS_URL, { authToken: access_token });\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 console.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 console.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 console.log('Largest node id:', largestNodeId);\n console.error('HEISENBUG: More than one local sync node found.')\n\n for (const node of localSyncNodes) {\n console.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 console.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 console.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\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 console.log(\"Adding data to\", name, data)\n return this.table(name).add({\n id: uuidv7(),\n ...data\n })\n },\n\n put: (data: any) => {\n return this.table(name).put({\n id: uuidv7(),\n ...data\n })\n },\n\n update: (id: string, data: any) => {\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: (id: string) => {\n return this.table(name).get(id)\n },\n\n getAll: () => {\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","\"use client\"\nimport { Dexie } from \"dexie\";\n\nexport const syncProtocol = function () {\n console.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 console.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 console.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 console.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 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 console.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 == \"error\") {\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 console.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","import Ajv from 'ajv'\n\nexport const SERVER_URL = \"https://api.basic.tech\"\n// export const WS_URL = `${SERVER_URL}/ws`\n\nexport const log = (...args: any[]) => {\n if (process.env.NODE_ENV === 'development') {\n console.log(...args)\n }\n}\n\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 },\n \"primary\": {\n \"type\": \"boolean\"\n },\n \"indexed\": {\n \"type\": \"boolean\"\n }\n },\n \"required\": [\"type\"]\n }\n },\n \"additionalProperties\": true\n }\n },\n \"required\": [\"fields\"]\n }\n },\n \"additionalProperties\": true\n }\n },\n \"required\": [\"project_id\", \"version\", \"tables\"]\n}\n\n\nconst ajv = new Ajv()\nexport const validator = ajv.compile(basicJsonSchema)\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","error","baseUrl","token","user"]}
|
package/dist/index.mjs
CHANGED
|
@@ -324,34 +324,6 @@ async function deleteRecord({ projectId, accountId, tableName, id, token }) {
|
|
|
324
324
|
|
|
325
325
|
// src/AuthContext.tsx
|
|
326
326
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
327
|
-
var example = {
|
|
328
|
-
project_id: "123",
|
|
329
|
-
version: 0,
|
|
330
|
-
tables: {
|
|
331
|
-
example: {
|
|
332
|
-
name: "example",
|
|
333
|
-
type: "collection",
|
|
334
|
-
fields: {
|
|
335
|
-
id: {
|
|
336
|
-
type: "uuid",
|
|
337
|
-
primary: true
|
|
338
|
-
},
|
|
339
|
-
value: {
|
|
340
|
-
type: "string",
|
|
341
|
-
indexed: true
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
},
|
|
345
|
-
example2: {
|
|
346
|
-
name: "example2",
|
|
347
|
-
type: "collection",
|
|
348
|
-
fields: {
|
|
349
|
-
id: { type: "string", primary: true },
|
|
350
|
-
id: { type: "string", primary: true }
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
};
|
|
355
327
|
var BasicContext = createContext({
|
|
356
328
|
unicorn: "\u{1F984}",
|
|
357
329
|
isLoaded: false,
|
|
@@ -396,12 +368,11 @@ function BasicProvider({ children, project_id, schema }) {
|
|
|
396
368
|
const [error, setError] = useState(null);
|
|
397
369
|
useEffect(() => {
|
|
398
370
|
function initDb() {
|
|
399
|
-
if (!validator(
|
|
371
|
+
if (!validator(schema)) {
|
|
400
372
|
console.error("Basic Schema is invalid!", validator.errors);
|
|
401
373
|
console.group("Schema Errors");
|
|
402
374
|
let errorMessage = "";
|
|
403
375
|
validator.errors.forEach((error2, index) => {
|
|
404
|
-
console.log("error", error2);
|
|
405
376
|
console.log(`${index + 1}:`, error2.message, ` - at ${error2.instancePath}`);
|
|
406
377
|
errorMessage += `${index + 1}: ${error2.message} - at ${error2.instancePath}
|
|
407
378
|
`;
|
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/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'\n\nimport { validator, log } from './config'\n\n/*\nschema todo:\n field types\n array types\n relations\n*/\n\n\nconst 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 example2: {\n name: 'example2',\n type: 'collection',\n fields: {\n id: { type: 'string', primary: true },\n id: { type: 'string', primary: true },\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 isLoaded: 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 isLoaded: false,\n isSignedIn: false,\n user: null,\n signout: () => { },\n signin: () => { },\n getToken: () => new Promise(() => { }),\n getSignInLink: () => \"\",\n db: {},\n dbStatus: DBStatus.OFFLINE\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 }: { children: React.ReactNode, project_id: string, schema: any }) {\n const [isLoaded, setIsLoaded] = useState(false)\n const [isSignedIn, setIsSignedIn] = useState(false)\n const [token, setToken] = useState<Token | null>(null)\n const [authCode, setAuthCode] = useState<string | null>(null)\n const [user, setUser] = useState<User>({})\n\n const [dbStatus, setDbStatus] = useState<DBStatus>(DBStatus.LOADING)\n\n const syncRef = useRef<BasicSync | null>(null);\n\n const [error, setError] = useState<ErrorObject | null>(null)\n\n useEffect(() => {\n function initDb() {\n // console.log('S', validator(example))\n if (!validator(example)) {\n console.error('Basic Schema is invalid!', validator.errors)\n console.group('Schema Errors')\n let errorMessage = ''\n validator.errors.forEach((error, index) => {\n console.log('error', error)\n console.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\n if (!syncRef.current) {\n syncRef.current = new BasicSync('basicdb', { schema: schema });\n\n // console.log('db is open', syncRef.current.isOpen())\n // syncRef.current.open()\n // .then(() => {\n // console.log(\"is open now:\", syncRef.current.isOpen())\n // })\n\n syncRef.current.handleStatusChange((status: number, url: string) => {\n setDbStatus(getSyncStatus(status))\n })\n\n syncRef.current.syncable.getStatus().then((status) => {\n console.log('sync status', getSyncStatus(status))\n })\n }\n\n }\n\n initDb()\n }, []);\n\n\n //todo: \n //add random state to signin link & verify random state\n\n const connectToDb = async () => {\n\n const tok = await getToken()\n\n console.log('connecting to db...', tok.substring(0, 10))\n\n syncRef.current.connect({ access_token: tok })\n .catch((e) => {\n console.log('error connecting to db', e)\n })\n }\n\n useEffect(() => {\n if (token && syncRef.current) {\n connectToDb()\n }\n }, [token])\n\n const getSignInLink = () => {\n console.log('getting sign in link...')\n\n const randomState = Math.random().toString(36).substring(7);\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=1234zyx`\n\n return baseUrl;\n }\n\n const signin = () => {\n console.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 console.log('signing out!')\n setUser({})\n setIsSignedIn(false)\n setToken(null)\n setAuthCode(null)\n document.cookie = `basic_token=; Secure; SameSite=Strict`;\n }\n\n const getToken = async (): Promise<string> => {\n console.log('getting token...')\n\n if (!token) {\n console.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 console.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 => console.error('Error:', error))\n\n if (token.error) {\n console.log('error fetching token', token.error)\n return\n } else {\n // console.log('token', token)\n setToken(token)\n }\n return token\n }\n\n useEffect(() => {\n try {\n let cookie_token = getCookie('basic_token')\n if (cookie_token !== '') {\n setToken(JSON.parse(cookie_token))\n }\n\n if (window.location.search.includes('code')) {\n let code = window.location?.search?.split('code=')[1].split('&')[0]\n // console.log('code found', code)\n\n // todo: check state is valid\n setAuthCode(code) // remove this? dont need to store code?\n fetchToken(code)\n\n window.history.pushState({}, document.title, \"/\");\n\n } else {\n setIsLoaded(true)\n }\n } catch (e) {\n console.log('error getting cookie', e)\n }\n }, [])\n\n useEffect(() => {\n async function fetchUser(acc_token: string) {\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 => console.error('Error:', error))\n\n if (user.error) {\n console.log('error fetching user', user.error)\n // refreshToken()\n return\n } else {\n // console.log('user', user)\n document.cookie = `basic_token=${JSON.stringify(token)}; Secure; SameSite=Strict`;\n setUser(user)\n setIsSignedIn(true)\n setIsLoaded(true)\n }\n }\n\n async function checkToken() {\n if (!token) {\n console.log('error: no user token found')\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 console.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 setIsLoaded(true)\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 isLoaded,\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}","\"use client\"\n\nimport { v7 as uuidv7 } from 'uuid';\nimport { Dexie, PromiseExtended } from 'dexie';\n// if (typeof window !== 'undefined') {\n// import('dexie-observable');\n// }\nimport 'dexie-syncable';\nimport 'dexie-observable';\n\nimport { syncProtocol } from './syncProtocol'\nimport { SERVER_URL } from '../config'\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 console.log('Starting connection...')\n return this.syncable.connect(\"websocket\", WS_URL, { authToken: access_token });\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 console.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 console.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 console.log('Largest node id:', largestNodeId);\n console.error('HEISENBUG: More than one local sync node found.')\n\n for (const node of localSyncNodes) {\n console.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 console.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 console.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\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 console.log(\"Adding data to\", name, data)\n return this.table(name).add({\n id: uuidv7(),\n ...data\n })\n },\n\n put: (data: any) => {\n return this.table(name).put({\n id: uuidv7(),\n ...data\n })\n },\n\n update: (id: string, data: any) => {\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: (id: string) => {\n return this.table(name).get(id)\n },\n\n getAll: () => {\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","\"use client\"\nimport { Dexie } from \"dexie\";\n\nexport const syncProtocol = function () {\n console.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 console.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 console.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 console.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 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 console.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 == \"error\") {\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 console.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","import Ajv from 'ajv'\n\nexport const SERVER_URL = \"https://api.basic.tech\"\n// export const WS_URL = `${SERVER_URL}/ws`\n\nexport const log = (...args: any[]) => {\n if (process.env.NODE_ENV === 'development') {\n console.log(...args)\n }\n}\n\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 },\n \"primary\": {\n \"type\": \"boolean\"\n },\n \"indexed\": {\n \"type\": \"boolean\"\n }\n },\n \"required\": [\"type\"]\n }\n },\n \"additionalProperties\": true\n }\n },\n \"required\": [\"fields\"]\n }\n },\n \"additionalProperties\": true\n }\n },\n \"required\": [\"project_id\", \"version\", \"tables\"]\n}\n\n\nconst ajv = new Ajv()\nexport const validator = ajv.compile(basicJsonSchema)\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 as useQuery } from \"dexie-react-hooks\";\n\nexport {\n useBasic, BasicProvider, useQuery\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/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'\n\nimport { validator, 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 isLoaded: 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 isLoaded: false,\n isSignedIn: false,\n user: null,\n signout: () => { },\n signin: () => { },\n getToken: () => new Promise(() => { }),\n getSignInLink: () => \"\",\n db: {},\n dbStatus: DBStatus.OFFLINE\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 }: { children: React.ReactNode, project_id: string, schema: any }) {\n const [isLoaded, setIsLoaded] = useState(false)\n const [isSignedIn, setIsSignedIn] = useState(false)\n const [token, setToken] = useState<Token | null>(null)\n const [authCode, setAuthCode] = useState<string | null>(null)\n const [user, setUser] = useState<User>({})\n\n const [dbStatus, setDbStatus] = useState<DBStatus>(DBStatus.LOADING)\n\n const syncRef = useRef<BasicSync | null>(null);\n\n const [error, setError] = useState<ErrorObject | null>(null)\n\n useEffect(() => {\n function initDb() {\n if (!validator(schema)) {\n console.error('Basic Schema is invalid!', validator.errors)\n console.group('Schema Errors')\n let errorMessage = ''\n validator.errors.forEach((error, index) => {\n console.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\n if (!syncRef.current) {\n syncRef.current = new BasicSync('basicdb', { schema: schema });\n\n // console.log('db is open', syncRef.current.isOpen())\n // syncRef.current.open()\n // .then(() => {\n // console.log(\"is open now:\", syncRef.current.isOpen())\n // })\n\n syncRef.current.handleStatusChange((status: number, url: string) => {\n setDbStatus(getSyncStatus(status))\n })\n\n syncRef.current.syncable.getStatus().then((status) => {\n console.log('sync status', getSyncStatus(status))\n })\n }\n\n }\n\n initDb()\n }, []);\n\n\n //todo: \n //add random state to signin link & verify random state\n\n const connectToDb = async () => {\n\n const tok = await getToken()\n\n console.log('connecting to db...', tok.substring(0, 10))\n\n syncRef.current.connect({ access_token: tok })\n .catch((e) => {\n console.log('error connecting to db', e)\n })\n }\n\n useEffect(() => {\n if (token && syncRef.current) {\n connectToDb()\n }\n }, [token])\n\n const getSignInLink = () => {\n console.log('getting sign in link...')\n\n const randomState = Math.random().toString(36).substring(7);\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=1234zyx`\n\n return baseUrl;\n }\n\n const signin = () => {\n console.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 console.log('signing out!')\n setUser({})\n setIsSignedIn(false)\n setToken(null)\n setAuthCode(null)\n document.cookie = `basic_token=; Secure; SameSite=Strict`;\n }\n\n const getToken = async (): Promise<string> => {\n console.log('getting token...')\n\n if (!token) {\n console.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 console.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 => console.error('Error:', error))\n\n if (token.error) {\n console.log('error fetching token', token.error)\n return\n } else {\n // console.log('token', token)\n setToken(token)\n }\n return token\n }\n\n useEffect(() => {\n try {\n let cookie_token = getCookie('basic_token')\n if (cookie_token !== '') {\n setToken(JSON.parse(cookie_token))\n }\n\n if (window.location.search.includes('code')) {\n let code = window.location?.search?.split('code=')[1].split('&')[0]\n // console.log('code found', code)\n\n // todo: check state is valid\n setAuthCode(code) // remove this? dont need to store code?\n fetchToken(code)\n\n window.history.pushState({}, document.title, \"/\");\n\n } else {\n setIsLoaded(true)\n }\n } catch (e) {\n console.log('error getting cookie', e)\n }\n }, [])\n\n useEffect(() => {\n async function fetchUser(acc_token: string) {\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 => console.error('Error:', error))\n\n if (user.error) {\n console.log('error fetching user', user.error)\n // refreshToken()\n return\n } else {\n // console.log('user', user)\n document.cookie = `basic_token=${JSON.stringify(token)}; Secure; SameSite=Strict`;\n setUser(user)\n setIsSignedIn(true)\n setIsLoaded(true)\n }\n }\n\n async function checkToken() {\n if (!token) {\n console.log('error: no user token found')\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 console.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 setIsLoaded(true)\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 isLoaded,\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}","\"use client\"\n\nimport { v7 as uuidv7 } from 'uuid';\nimport { Dexie, PromiseExtended } from 'dexie';\n// if (typeof window !== 'undefined') {\n// import('dexie-observable');\n// }\nimport 'dexie-syncable';\nimport 'dexie-observable';\n\nimport { syncProtocol } from './syncProtocol'\nimport { SERVER_URL } from '../config'\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 console.log('Starting connection...')\n return this.syncable.connect(\"websocket\", WS_URL, { authToken: access_token });\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 console.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 console.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 console.log('Largest node id:', largestNodeId);\n console.error('HEISENBUG: More than one local sync node found.')\n\n for (const node of localSyncNodes) {\n console.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 console.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 console.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\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 console.log(\"Adding data to\", name, data)\n return this.table(name).add({\n id: uuidv7(),\n ...data\n })\n },\n\n put: (data: any) => {\n return this.table(name).put({\n id: uuidv7(),\n ...data\n })\n },\n\n update: (id: string, data: any) => {\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: (id: string) => {\n return this.table(name).get(id)\n },\n\n getAll: () => {\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","\"use client\"\nimport { Dexie } from \"dexie\";\n\nexport const syncProtocol = function () {\n console.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 console.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 console.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 console.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 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 console.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 == \"error\") {\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 console.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","import Ajv from 'ajv'\n\nexport const SERVER_URL = \"https://api.basic.tech\"\n// export const WS_URL = `${SERVER_URL}/ws`\n\nexport const log = (...args: any[]) => {\n if (process.env.NODE_ENV === 'development') {\n console.log(...args)\n }\n}\n\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 },\n \"primary\": {\n \"type\": \"boolean\"\n },\n \"indexed\": {\n \"type\": \"boolean\"\n }\n },\n \"required\": [\"type\"]\n }\n },\n \"additionalProperties\": true\n }\n },\n \"required\": [\"fields\"]\n }\n },\n \"additionalProperties\": true\n }\n },\n \"required\": [\"project_id\", \"version\", \"tables\"]\n}\n\n\nconst ajv = new Ajv()\nexport const validator = ajv.compile(basicJsonSchema)\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 as useQuery } from \"dexie-react-hooks\";\n\nexport {\n useBasic, BasicProvider, useQuery\n}"],"mappings":"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","names":["Dexie","changes","baseRevision","partial","onChangesAccepted","requestId","Dexie","key","error","baseUrl","token","user"]}
|
package/package.json
CHANGED
package/src/AuthContext.tsx
CHANGED
|
@@ -16,34 +16,26 @@ schema todo:
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
const example = {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
type: 'collection',
|
|
40
|
-
fields: {
|
|
41
|
-
id: { type: 'string', primary: true },
|
|
42
|
-
id: { type: 'string', primary: true },
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
19
|
+
// const example = {
|
|
20
|
+
// project_id: '123',
|
|
21
|
+
// version: 0,
|
|
22
|
+
// tables: {
|
|
23
|
+
// example: {
|
|
24
|
+
// name: 'example',
|
|
25
|
+
// type: 'collection',
|
|
26
|
+
// fields: {
|
|
27
|
+
// id: {
|
|
28
|
+
// type: 'uuid',
|
|
29
|
+
// primary: true,
|
|
30
|
+
// },
|
|
31
|
+
// value: {
|
|
32
|
+
// type: 'string',
|
|
33
|
+
// indexed: true,
|
|
34
|
+
// },
|
|
35
|
+
// }
|
|
36
|
+
// }
|
|
37
|
+
// }
|
|
38
|
+
// }
|
|
47
39
|
|
|
48
40
|
|
|
49
41
|
type BasicSyncType = {
|
|
@@ -162,13 +154,11 @@ export function BasicProvider({ children, project_id, schema }: { children: Reac
|
|
|
162
154
|
|
|
163
155
|
useEffect(() => {
|
|
164
156
|
function initDb() {
|
|
165
|
-
|
|
166
|
-
if (!validator(example)) {
|
|
157
|
+
if (!validator(schema)) {
|
|
167
158
|
console.error('Basic Schema is invalid!', validator.errors)
|
|
168
159
|
console.group('Schema Errors')
|
|
169
160
|
let errorMessage = ''
|
|
170
161
|
validator.errors.forEach((error, index) => {
|
|
171
|
-
console.log('error', error)
|
|
172
162
|
console.log(`${index + 1}:`, error.message, ` - at ${error.instancePath}`)
|
|
173
163
|
errorMessage += `${index + 1}: ${error.message} - at ${error.instancePath}\n`
|
|
174
164
|
})
|