UNPKG

@datastax/astra-db-ts

Version:
229 lines (228 loc) 9.25 kB
"use strict"; // Copyright Datastax, Inc // SPDX-License-Identifier: Apache-2.0 Object.defineProperty(exports, "__esModule", { value: true }); exports.TableSerDes = void 0; const ser_des_js_1 = require("../../../lib/api/ser-des/ser-des.js"); const codecs_js_1 = require("../../../documents/tables/ser-des/codecs.js"); const ctx_js_1 = require("../../../lib/api/ser-des/ctx.js"); const constants_js_1 = require("../../../documents/tables/ser-des/constants.js"); const utils_js_1 = require("../../../lib/utils.js"); const index_js_1 = require("../../../client/index.js"); const cfg_handler_js_1 = require("../../../documents/tables/ser-des/cfg-handler.js"); const utils_js_2 = require("../../../lib/api/ser-des/utils.js"); class TableSerDes extends ser_des_js_1.SerDes { constructor(cfg) { super(TableSerDes.cfg.concat([codecs, cfg]), serialize, deserialize); } adaptSerCtx(ctx) { ctx.bigNumsPresent = false; return ctx; } adaptDesCtx(ctx) { const rawDataApiResp = ctx.rawDataApiResp; const status = index_js_1.UnexpectedDataAPIResponseError.require(rawDataApiResp.status, 'No `status` found in response.', rawDataApiResp); if (ctx.target === ctx_js_1.SerDesTarget.InsertedId) { ctx.tableSchema = index_js_1.UnexpectedDataAPIResponseError.require(status.primaryKeySchema, 'No `status.primaryKeySchema` found in response.\n\n**Did you accidentally use a `Table` object on a Collection?** If so, your document was successfully inserted, but the client cannot properly deserialize the response. Please use a `Collection` object instead.', rawDataApiResp); } else { ctx.tableSchema = index_js_1.UnexpectedDataAPIResponseError.require(status.projectionSchema, 'No `status.projectionSchema` found in response.\n\n**Did you accidentally use a `Table` object on a Collection?** If so, documents may\'ve been found, but the client cannot properly deserialize the response. Please use a `Collection` object instead.', rawDataApiResp); } if (ctx.target === ctx_js_1.SerDesTarget.InsertedId) { ctx.rootObj = Object.fromEntries(Object.keys(ctx.tableSchema).map((key, i) => { return [key, ctx.rootObj[i]]; })); } if (this._cfg.sparseData !== true) { populateSparseData(ctx); } return ctx; } bigNumsPresent(ctx) { return ctx.bigNumsPresent; } } exports.TableSerDes = TableSerDes; Object.defineProperty(TableSerDes, "cfg", { enumerable: true, configurable: true, writable: true, value: cfg_handler_js_1.TableSerDesCfgHandler }); const serialize = (value, ctx) => { let resp = null; // Path-based serializers for (const pathSer of ctx.serializers.forPath[ctx.path.length] ?? []) { if ((0, utils_js_2.pathMatches)(pathSer.path, ctx.path) && pathSer.fns.find((fns) => (resp = fns(value, ctx))[0] !== ctx_js_1.NEVERMIND)) { return resp; } } // Name-based serializers const key = ctx.path[ctx.path.length - 1] ?? ''; const nameSer = ctx.serializers.forName[key]; if (nameSer?.find((fns) => (resp = fns(value, ctx))[0] !== ctx_js_1.NEVERMIND)) { return resp; } // Type-based & custom serializers for (const guardSer of ctx.serializers.forGuard) { if (guardSer.guard(value, ctx) && (resp = guardSer.fn(value, ctx))[0] !== ctx_js_1.NEVERMIND) { return resp; } } if (typeof value === 'number') { if (!isFinite(value)) { return ctx.done(value.toString()); } } else if (typeof value === 'object' && value !== null) { // Delegate serializer if (value[constants_js_1.$SerializeForTable] && (resp = value[constants_js_1.$SerializeForTable](ctx))[0] !== ctx_js_1.NEVERMIND) { return resp; } // Class-based serializers const classSer = ctx.serializers.forClass.find((c) => value instanceof c.class); if (classSer?.fns.find((fns) => (resp = fns(value, ctx))[0] !== ctx_js_1.NEVERMIND)) { return resp; } // Enable using json-bigint if ((0, utils_js_1.isBigNumber)(value)) { ctx.bigNumsPresent = true; return ctx.done(); } } else if (typeof value === 'bigint') { ctx.bigNumsPresent = true; } return ctx.recurse(); }; const deserialize = (value, ctx) => { let resp = null; // Path-based deserializers for (const pathDes of ctx.deserializers.forPath[ctx.path.length] ?? []) { if ((0, utils_js_2.pathMatches)(pathDes.path, ctx.path) && pathDes.fns.find((fns) => (resp = fns(value, ctx))[0] !== ctx_js_1.NEVERMIND)) { return resp; } } // Name-based deserializers const key = ctx.path[ctx.path.length - 1] ?? ''; const nameDes = ctx.deserializers.forName[key]; if (nameDes?.find((fns) => (resp = fns(value, ctx))[0] !== ctx_js_1.NEVERMIND)) { return resp; } // Custom deserializers for (const guardDes of ctx.deserializers.forGuard) { if (guardDes.guard(value, ctx) && (resp = guardDes.fn(value, ctx))[0] !== ctx_js_1.NEVERMIND) { return resp; } } if (ctx.path.length === 0 || value === null) { return ctx.recurse(value); } // Type-based deserializers const type = resolveAbsType(value, ctx); const typeDes = type && ctx.deserializers.forType[type]; if (typeDes && typeDes.find((fns) => (resp = fns(value, ctx))[0] !== ctx_js_1.NEVERMIND)) { return resp; } return ctx.recurse(value); }; const codecs = TableSerDes.cfg.parse({ codecs: Object.values(codecs_js_1.TableCodecs.Defaults) }); function populateSparseData(ctx) { var _a; for (const col in ctx.tableSchema) { const colIsPresent = Object.prototype.hasOwnProperty.call(ctx.rootObj, col); const typeDef = ctx.tableSchema[col]; // typeDef and type are linked, but we can't represent that in the type system :/ const type = resolveType(typeDef); switch (type) { case 'map': if (!colIsPresent) { ctx.rootObj[col] = {}; } else if (typeof typeDef === 'object' && typeDef.valueType.type === 'userDefined') { const value = ctx.rootObj[col]; if (Array.isArray(value)) { for (const kv of value) { populateSparseUdt(kv[1], typeDef.valueType.definition); } } else { for (const v of Object.values(value)) { populateSparseUdt(v, typeDef.valueType.definition); } } } break; case 'set': case 'list': if (!colIsPresent) { ctx.rootObj[col] = []; } else if (typeof typeDef === 'object' && typeDef.valueType.type === 'userDefined') { ctx.rootObj[col].forEach((obj) => populateSparseUdt(obj, typeDef.valueType.definition)); } break; case 'userDefined': (_a = ctx.rootObj)[col] ?? (_a[col] = {}); populateSparseUdt(ctx.rootObj[col], typeDef.definition); break; default: if (!colIsPresent) { ctx.rootObj[col] = null; } } } } function populateSparseUdt(obj, def) { for (const col in def.fields) { if (!Object.prototype.hasOwnProperty.call(obj, col)) { obj[col] = null; } } } function resolveAbsType(value, { path, tableSchema }) { let typeDef = tableSchema[path[0]]; if (!typeDef) return undefined; let type = resolveType(typeDef); let depth = 1; while (depth < path.length && typeDef) { switch (type) { case 'map': if (path[depth + 1] === undefined) { return (!Array.isArray(value)) ? typeDef.valueType : undefined; } typeDef = (path[depth + 1] === 0) ? typeDef.keyType : typeDef.valueType; type = resolveType(typeDef); depth += 2; break; case 'list': case 'set': typeDef = typeDef.valueType; type = resolveType(typeDef); depth++; break; case 'userDefined': typeDef = typeDef.definition.fields[path[depth]]; if (!typeDef) return undefined; type = resolveType(typeDef); depth++; break; default: return type; } } return type; } function resolveType(column) { if (typeof column === 'string') { return column; } return (column.type === 'UNSUPPORTED') ? column.apiSupport.cqlDefinition : column.type; }