Skip to content

Commit

Permalink
enhanced coll bignumbers support
Browse files Browse the repository at this point in the history
  • Loading branch information
toptobes committed Jan 6, 2025
1 parent d43992a commit cbcc101
Show file tree
Hide file tree
Showing 13 changed files with 248 additions and 68 deletions.
45 changes: 35 additions & 10 deletions etc/astra-db-ts.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -287,9 +287,9 @@ export interface BaseSerDesCtx<Fns extends CodecSerDesFns> {
// (undocumented)
keyTransformer?: KeyTransformer;
// (undocumented)
path: string[];
next<T>(obj?: T): readonly [1, T?];
// (undocumented)
recurse<T>(obj?: T): readonly [1, T?];
path: string[];
// (undocumented)
rootObj: SomeDoc;
}
Expand Down Expand Up @@ -381,7 +381,7 @@ export interface CollCodecSerDesFns {
// @public (undocumented)
export interface CollDesCtx extends BaseDesCtx<CollCodecSerDesFns> {
// (undocumented)
bigNumsEnabled: boolean;
getNumRepForPath?: GetCollNumRepFn;
}

// @public
Expand Down Expand Up @@ -599,7 +599,7 @@ export type CollectionReplaceOneResult<RSchema> = GenericUpdateResult<IdOf<RSche
// @public (undocumented)
export interface CollectionSerDesConfig extends BaseSerDesConfig<CollCodecSerDesFns, CollSerCtx, CollDesCtx> {
// (undocumented)
enableBigNumbers?: boolean;
enableBigNumbers?: GetCollNumRepFn;
}

// @public
Expand Down Expand Up @@ -648,6 +648,12 @@ export interface CollectionVectorOptions {
sourceModel?: string;
}

// @public (undocumented)
export type CollNumRep = 'number' | 'bigint' | 'bignumber' | 'string' | 'number_or_string';

// @public (undocumented)
export type CollNumRepCfg = Record<string, CollNumRep>;

// @public (undocumented)
export interface CollSerCtx extends BaseSerCtx<CollCodecSerDesFns> {
// (undocumented)
Expand Down Expand Up @@ -957,9 +963,7 @@ export class DataAPIResponseError extends DataAPIError {
export class DataAPITime implements TableCodec<typeof DataAPITime> {
static [$DeserializeForTable](_: unknown, value: any, ctx: TableDesCtx): readonly [0, (DataAPITime | undefined)?];
[$SerializeForTable](ctx: TableSerCtx): readonly [0, (string | undefined)?];
constructor(input?: string | Date | (DataAPITimeComponents & {
nanoseconds?: number;
}));
constructor(input?: string | Date | PartialDataAPITimeComponents);
components(): DataAPITimeComponents;
toDate(base?: Date | DataAPIDate): Date;
toString(): string;
Expand Down Expand Up @@ -1418,6 +1422,9 @@ export interface GenericUpdateOneOptions extends WithTimeout<'generalMethodTimeo
// @public
export type GenericUpdateResult<ID, N extends number> = (GuaranteedUpdateResult<N> & UpsertedUpdateResult<ID>) | (GuaranteedUpdateResult<N> & NoUpsertUpdateResult);

// @public (undocumented)
export type GetCollNumRepFn = (path: string[]) => CollNumRep;

// @public
export interface GuaranteedUpdateResult<N extends number> {
matchedCount: N;
Expand Down Expand Up @@ -1613,6 +1620,19 @@ export interface NoUpsertUpdateResult {
// @public
export type nullish = null | undefined;

// @public (undocumented)
export class NumCoercionError extends Error {
constructor(path: string[], value: number | BigNumber, from: 'number' | 'bignumber', to: CollNumRep);
// (undocumented)
readonly from: 'number' | 'bignumber';
// (undocumented)
readonly path: string[];
// (undocumented)
readonly to: CollNumRep;
// (undocumented)
readonly value: number | BigNumber;
}

// @public
export class ObjectId implements CollCodec<typeof ObjectId> {
static [$DeserializeForCollection](_: string, value: any, ctx: CollDesCtx): readonly [0, (ObjectId | undefined)?];
Expand All @@ -1634,6 +1654,11 @@ export type OneOrMany<T> = T | readonly T[];
// @public
export type OpaqueHttpClient = any;

// @public
export type PartialDataAPITimeComponents = (Omit<DataAPITimeComponents, 'nanoseconds'> & {
nanoseconds?: number;
});

// @public (undocumented)
export type PathCodec<Fns extends CodecSerDesFns> = {
serialize?: Fns['serialize'];
Expand Down Expand Up @@ -1818,9 +1843,9 @@ export interface TableDescriptor {
// @public (undocumented)
export interface TableDesCtx extends BaseDesCtx<TableCodecSerDesFns> {
// (undocumented)
populateSparseData: boolean;
next: never;
// (undocumented)
recurse: never;
populateSparseData: boolean;
// (undocumented)
tableSchema: ListTableColumnDefinitions;
}
Expand Down Expand Up @@ -1976,7 +2001,7 @@ export interface TableVectorIndexOptions {
}

// @public
export const time: (time?: string | Date | DataAPITimeComponents) => DataAPITime;
export const time: (time?: string | Date | PartialDataAPITimeComponents) => DataAPITime;

// @public
export type TimedOutCategories = OneOrMany<keyof TimeoutDescriptor> | 'provided';
Expand Down
25 changes: 2 additions & 23 deletions scripts/playground.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ create)
exit 1
fi

npm run build
npm pack
scripts/build.sh -no-report

rm -rf etc/playgrounds/"$2"
mkdir -p etc/playgrounds/"$2"
Expand All @@ -30,8 +29,7 @@ create)
npm i -D typescript tsx dotenv
cp ../../../tsconfig.json .

npm i "${tarball_dir}"/datastax-astra-db-ts-*.tgz
rm "${tarball_dir}"/datastax-astra-db-ts-*.tgz
npm i "$tarball_dir"

echo "import * as $ from '@datastax/astra-db-ts';
import dotenv from 'dotenv';
Expand All @@ -49,25 +47,6 @@ const table = db.table('test_table');
})();" > index.ts
;;
update)
if [ -z "$2" ]; then
echo "Usage: $0 update <name>"
exit 1
fi

if [ ! -d etc/playgrounds/"$2" ]; then
echo "Playground '$2' not found"
exit 1
fi

npm run build
npm pack

cd etc/playgrounds/"$2" || exit 1

npm i "${tarball_dir}"/datastax-astra-db-ts-*.tgz
rm "${tarball_dir}"/datastax-astra-db-ts-*.tgz
;;
destroy)
if [ -z "$2" ]; then
echo "Usage: $0 destroy <name>"
Expand Down
2 changes: 1 addition & 1 deletion src/documents/collections/collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ import { CollectionFindCursor } from '@/src/documents/collections/cursor';
import { withJbiNullProtoFix } from '@/src/lib/utils';
import { CollectionSerDes } from '@/src/documents/collections/ser-des/ser-des';

const jbi = JBI({ storeAsString: true });
const jbi = JBI;

/**
* #### Overview
Expand Down
8 changes: 8 additions & 0 deletions src/documents/collections/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,13 @@ export {
CollCodecs,
CollCodec,
} from './ser-des/codecs';

export {
CollNumRep,
GetCollNumRepFn,
NumCoercionError,
CollNumRepCfg,
} from './ser-des/big-nums';

export { $DeserializeForCollection } from '@/src/documents/collections/ser-des/constants';
export { $SerializeForCollection } from '@/src/documents/collections/ser-des/constants';
91 changes: 91 additions & 0 deletions src/documents/collections/ser-des/big-nums.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Copyright DataStax, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import BigNumber from 'bignumber.js';

export type CollNumRep =
| 'number'
| 'bigint'
| 'bignumber'
| 'string'
| 'number_or_string';

export type GetCollNumRepFn = (path: string[]) => CollNumRep;

export type CollNumRepCfg = Record<string, CollNumRep>;

const $NumRep = Symbol('NumRep');

interface NumRepTree {
[$NumRep]?: CollNumRep;
[key: string]: NumRepTree;
}

export const collNumRepFnFromCfg = (cfg: CollNumRepCfg): GetCollNumRepFn => {
const tree = buildNumRepTree(cfg);

return (path: string[]) => {
return findMatchingPath(path, tree) ?? 'number';
};
};

const buildNumRepTree = (cfg: CollNumRepCfg): NumRepTree => {
const result: NumRepTree = {};

Object.entries(cfg).forEach(([path, rep]) => {
const keys = path.split('.');
let current = result;

keys.forEach((key, index) => {
current[key] ??= {};

if (index === keys.length - 1) {
current[key][$NumRep] = rep;
}

current = current[key];
});
});

return result;
};

const findMatchingPath = (path: string[], tree: NumRepTree | undefined): CollNumRep | undefined => {
if (!tree) {
return undefined;
}

if (path.length === 0) {
return tree[$NumRep];
}

const [key, ...rest] = path;

return findMatchingPath(rest, tree[key]) ?? findMatchingPath(rest, tree['*']) ?? tree['*']?.[$NumRep];
};

export class NumCoercionError extends Error {
public readonly path: string[];
public readonly value: number | BigNumber;
public readonly from: 'number' | 'bignumber';
public readonly to: CollNumRep;

public constructor(path: string[], value: number | BigNumber, from: 'number' | 'bignumber', to: CollNumRep) {
super(`Failed to coerce value from ${from} to ${to} at path: ${path.join('.')}`);
this.path = path;
this.value = value;
this.from = from;
this.to = to;
}
}
Loading

0 comments on commit cbcc101

Please sign in to comment.