UNPKG

@instantdb/core

Version:
218 lines • 8.58 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.FrameworkClient = exports.isServer = void 0; // The FrameworkClient class is a mini version of a query store that allows making queries on both the frontend and backend // you can register queries, await their results and serialize them over a server/client boundary. // The class is generic so that it can be a good starting off point to make other ssr adapters. const index_ts_1 = require("./index.js"); const s = __importStar(require("./store.js")); const instaql_js_1 = __importDefault(require("./instaql.js")); const linkIndex_ts_1 = require("./utils/linkIndex.js"); exports.isServer = typeof window === 'undefined' || 'Deno' in globalThis; class FrameworkClient { params; db; // stores all of the query promises so that ssr can read them // and send the relevant results alongside the html that resulted in the query resolving resultMap = new Map(); queryResolvedCallbacks = []; constructor(params) { this.params = params; this.db = params.db; this.resultMap = new Map(); } subscribe = (callback) => { this.queryResolvedCallbacks.push(callback); }; // Runs on the client when ssr gets html script tags addQueryResult = (queryKey, value) => { this.resultMap.set(queryKey, { type: value.type, status: 'success', data: value, promise: null, error: null, }); // send the result to the client if (!exports.isServer) { // make sure the attrs are there to create stores if (!this.db._reactor.attrs) { this.db._reactor._setAttrs(value.attrs); } this.db._reactor._addQueryData(value.query, value, !!this.db._reactor.config.schema); } }; // creates an entry in the results map // and returns the same thing added to the map query = (_query, opts) => { const { hash, query } = this.hashQuery(_query, opts); if (this.db._reactor.status === 'authenticated') { const promise = this.db.queryOnce(_query, opts); let entry = { status: 'pending', type: 'session', data: undefined, error: undefined, promise: promise, }; promise.then((result) => { entry.status = 'success'; entry.data = result; entry.promise = null; }); promise.catch((error) => { entry.status = 'error'; entry.error = error; entry.promise = null; }); this.resultMap.set(hash, entry); return entry; } const promise = this.getTriplesAndAttrsForQuery(query); let entry = { status: 'pending', type: 'http', data: undefined, error: undefined, promise: promise, }; promise.then((result) => { entry.status = 'success'; entry.data = result; entry.promise = null; }); promise.catch((error) => { entry.status = 'error'; entry.error = error; entry.promise = null; }); promise.then((result) => { this.queryResolvedCallbacks.forEach((callback) => { callback({ queryHash: hash, query: query, attrs: result.attrs, triples: result.triples, pageInfo: result.pageInfo, }); }); }); this.resultMap.set(hash, entry); return entry; }; getExistingResultForQuery = (_query, opts) => { const { hash } = this.hashQuery(_query, opts); return this.resultMap.get(hash); }; // creates a query result from a set of triples, query, and attrs // can be run server side or client side completeIsomorphic = (query, triples, attrs, pageInfo) => { const attrMap = {}; attrs.forEach((attr) => { attrMap[attr.id] = attr; }); const enableCardinalityInference = Boolean(this.db?._reactor?.config?.schema) && ('cardinalityInference' in this.db?._reactor?.config ? Boolean(this.db?._reactor.config?.cardinalityInference) : true); const attrsStore = new s.AttrsStoreClass(attrs.reduce((acc, attr) => { acc[attr.id] = attr; return acc; }, {}), (0, linkIndex_ts_1.createLinkIndex)(this.db?._reactor.config.schema)); const store = s.createStore(attrsStore, triples, enableCardinalityInference, this.params.db._reactor.config.useDateObjects || false); const resp = (0, instaql_js_1.default)({ store: store, attrsStore: attrsStore, pageInfo: pageInfo, aggregate: undefined, }, query); return resp; }; hashQuery = (_query, opts) => { if (_query && opts && 'ruleParams' in opts) { _query = { $$ruleParams: opts['ruleParams'], ..._query }; } const query = _query ? (0, index_ts_1.coerceQuery)(_query) : null; return { hash: (0, index_ts_1.weakHash)(query), query: query }; }; // Run by the server to get triples and attrs getTriplesAndAttrsForQuery = async (query) => { try { const response = await fetch(`${this.db._reactor.config.apiURI}/runtime/framework/query`, { method: 'POST', headers: { 'app-id': this.params.db._reactor.config.appId, 'Content-Type': 'application/json', Authorization: this.params.token ? `Bearer ${this.params.token}` : undefined, }, body: JSON.stringify({ query: query, }), }); if (!response.ok) { throw new Error('Error getting triples from server'); } const data = await response.json(); const attrs = data?.attrs; if (!attrs) { throw new Error('No attrs'); } // TODO: make safer const triples = data.result?.[0].data?.['datalog-result']?.['join-rows'][0]; const pageInfo = data.result?.[0]?.data?.['page-info']; return { attrs, triples, type: 'http', queryHash: this.hashQuery(query).hash, query, pageInfo, }; } catch (err) { const errWithMessage = new Error('Error getting triples from framework client'); errWithMessage.cause = err; throw errWithMessage; } }; } exports.FrameworkClient = FrameworkClient; //# sourceMappingURL=framework.js.map