@tstdl/base 0.93.29 → 0.93.30

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.
@@ -112,7 +112,7 @@ export type ParadeSpecialQueryObject<T extends BaseEntity = BaseEntity> = {
112
112
  empty?: null;
113
113
  moreLikeThis?: {
114
114
  keyValue?: any;
115
- document?: Record<TargetColumnPath<T>, any>;
115
+ document?: Record<TargetColumnPath<T>>;
116
116
  fields?: readonly TargetColumnPath<T>[];
117
117
  minDocFrequency?: number;
118
118
  maxDocFrequency?: number;
@@ -1,5 +1,6 @@
1
1
  export * from './json.js';
2
2
  export * from './numeric-date.js';
3
+ export * from './numeric.js';
3
4
  export * from './timestamp.js';
4
5
  export * from './tsvector.js';
5
6
  export * from './uuid.js';
@@ -1,5 +1,6 @@
1
1
  export * from './json.js';
2
2
  export * from './numeric-date.js';
3
+ export * from './numeric.js';
3
4
  export * from './timestamp.js';
4
5
  export * from './tsvector.js';
5
6
  export * from './uuid.js';
@@ -0,0 +1,17 @@
1
+ import { NumberSchema, type NumberSchemaOptions, type SchemaDecoratorOptions, type SchemaPropertyDecorator } from '../../schema/index.js';
2
+ import type { TypedOmit } from '../../types/types.js';
3
+ export type NumericSchemaOptions = NumberSchemaOptions & {
4
+ precision?: number;
5
+ scale?: number;
6
+ mode?: 'string' | 'number' | 'bigint';
7
+ };
8
+ export declare class NumericSchema extends NumberSchema {
9
+ readonly name = "Numeric";
10
+ readonly precision: number | null;
11
+ readonly scale: number | null;
12
+ readonly mode: 'string' | 'number' | 'bigint' | null;
13
+ constructor(options?: NumericSchemaOptions);
14
+ }
15
+ export declare function numeric(precision: number, scale: number, options?: TypedOmit<NumericSchemaOptions, 'precision' | 'scale'>): NumericSchema;
16
+ export declare function numeric(options?: NumericSchemaOptions): NumericSchema;
17
+ export declare function NumericProperty(options?: NumericSchemaOptions & SchemaDecoratorOptions): SchemaPropertyDecorator;
@@ -0,0 +1,23 @@
1
+ import { NumberSchema, Property } from '../../schema/index.js';
2
+ import { isObject } from '../../utils/type-guards.js';
3
+ export class NumericSchema extends NumberSchema {
4
+ name = 'Numeric';
5
+ precision;
6
+ scale;
7
+ mode;
8
+ constructor(options) {
9
+ super(options);
10
+ this.precision = options?.precision ?? null;
11
+ this.scale = options?.scale ?? null;
12
+ this.mode = options?.mode ?? null;
13
+ }
14
+ }
15
+ export function numeric(precisionOrOptions, scale, options) {
16
+ if (isObject(precisionOrOptions)) {
17
+ return new NumericSchema(precisionOrOptions);
18
+ }
19
+ return new NumericSchema({ precision: precisionOrOptions, scale, ...options });
20
+ }
21
+ export function NumericProperty(options) {
22
+ return Property(numeric(options), options);
23
+ }
@@ -1,6 +1,6 @@
1
1
  import { sql, SQL } from 'drizzle-orm';
2
2
  import { toCamelCase, toSnakeCase } from 'drizzle-orm/casing';
3
- import { boolean, check, doublePrecision, foreignKey, index, integer, jsonb, pgSchema, primaryKey, text, unique, uniqueIndex, uuid } from 'drizzle-orm/pg-core';
3
+ import { boolean, check, doublePrecision, foreignKey, index, integer, jsonb, numeric, pgSchema, primaryKey, text, unique, uniqueIndex, uuid } from 'drizzle-orm/pg-core';
4
4
  import { match, P } from 'ts-pattern';
5
5
  import { MultiKeyMap } from '../../../data-structures/multi-key-map.js';
6
6
  import { tryGetEnumName } from '../../../enumeration/enumeration.js';
@@ -17,11 +17,7 @@ import { fromEntries, mapObjectKeysToSnakeCase, objectEntries } from '../../../u
17
17
  import { assertDefined, assertDefinedPass, isArray, isDefined, isNotNull, isNotNullOrUndefined, isNull, isString, isUndefined } from '../../../utils/type-guards.js';
18
18
  import { resolveValueOrProvider } from '../../../utils/value-or-provider.js';
19
19
  import { bytea, numericDate, timestamp, tsvector } from '../../data-types/index.js';
20
- import { JsonSchema } from '../../schemas/json.js';
21
- import { NumericDateSchema } from '../../schemas/numeric-date.js';
22
- import { TimestampSchema } from '../../schemas/timestamp.js';
23
- import { TsVectorSchema } from '../../schemas/tsvector.js';
24
- import { UuidSchema } from '../../schemas/uuid.js';
20
+ import { JsonSchema, NumericDateSchema, NumericSchema, TimestampSchema, TsVectorSchema, UuidSchema } from '../../schemas/index.js';
25
21
  import { decryptBytes, encryptBytes } from '../encryption.js';
26
22
  import { convertQuery, resolveTargetColumn, resolveTargetColumns } from '../query-converter.js';
27
23
  const getDbSchema = memoizeSingle(pgSchema);
@@ -315,6 +311,7 @@ function getPostgresBaseColumn(columnName, dbSchema, schema, reflectionData, con
315
311
  })
316
312
  .with(P.instanceOf(TimestampSchema), () => timestamp(columnName))
317
313
  .with(P.instanceOf(NumericDateSchema), () => numericDate(columnName))
314
+ .with(P.instanceOf(NumericSchema), (n) => numeric(columnName, { precision: n.precision ?? undefined, scale: n.scale ?? undefined, mode: n.mode ?? 'number' }))
318
315
  .with(P.instanceOf(NumberSchema), (s) => (s.integer ? integer(columnName) : doublePrecision(columnName)))
319
316
  .with(P.instanceOf(StringSchema), () => text(columnName))
320
317
  .with(P.instanceOf(BooleanSchema), () => boolean(columnName))
@@ -1,5 +1,4 @@
1
1
  import { and, Column, eq, gt, gte, inArray, isNotNull, isNull, isSQLWrapper, lt, lte, ne, not, notInArray, or, SQL, sql } from 'drizzle-orm';
2
- import { PgColumn } from 'drizzle-orm/pg-core';
3
2
  import { match } from 'ts-pattern';
4
3
  import { NotSupportedError } from '../../errors/not-supported.error.js';
5
4
  import { hasOwnProperty, mapObject, mapObjectKeysToSnakeCase, objectEntries } from '../../utils/object/object.js';
@@ -371,7 +370,7 @@ function convertParadeSpecialQuery(query, table, columnDefinitionsMap) {
371
370
  return jsonbBuildObject({
372
371
  ...properties,
373
372
  fields: fieldsArraySql,
374
- document: documentJson
373
+ document: documentJson,
375
374
  });
376
375
  })
377
376
  .exhaustive();
package/orm/types.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  * like primary keys and default values. It also re-exports common decorators and schemas.
6
6
  */
7
7
  import type { $Type, HasDefault as DrizzleHasDefault, IsPrimaryKey as DrizzleIsPrimaryKey } from 'drizzle-orm';
8
- import type { boolean, doublePrecision, integer, jsonb, PgColumnBuilder, PgColumnBuilderBase, PgEnumColumnBuilderInitial, text, uuid } from 'drizzle-orm/pg-core';
8
+ import type { boolean, doublePrecision, integer, jsonb, numeric, PgColumnBuilder, PgColumnBuilderBase, PgEnumColumnBuilderInitial, text, uuid } from 'drizzle-orm/pg-core';
9
9
  import type { AbstractConstructor, EnumerationObject, EnumerationValue, GetTagMetadata, HasTag, ObjectLiteral, Tagged, UnionToTuple, UnwrapTagged } from '../types/index.js';
10
10
  import type { bytea, numericDate, timestamp } from './data-types/index.js';
11
11
  /** Tag identifier for column type information. */
@@ -64,21 +64,16 @@ export type Json<T> = Tagged<T, ColumnTypeTag, $Type<ReturnType<typeof jsonb>, T
64
64
  * @template T - The enumeration object type.
65
65
  */
66
66
  export type Enum<T extends string | number> = Tagged<T, ColumnTypeTag, EnumColumn<T>>;
67
- /** Tagged type representing a `text` column. */
68
67
  export type Text<T extends string = string> = Tagged<string, ColumnTypeTag, ReturnType<typeof text<string, TextTuple<T>>>>;
69
- /** Tagged type representing a `uuid` column. Stores the UUID as a string. */
70
68
  export type Uuid = Tagged<string, ColumnTypeTag, ReturnType<typeof uuid>>;
71
- /** Tagged type representing an `integer` column. */
72
69
  export type Integer = Tagged<number, ColumnTypeTag, ReturnType<typeof integer>>;
73
- /** Tagged type representing a `double precision` column. */
74
70
  export type DoublePrecision = Tagged<number, ColumnTypeTag, ReturnType<typeof doublePrecision>>;
75
- /** Tagged type representing a `boolean` column. */
76
71
  export type Boolean = Tagged<number, ColumnTypeTag, ReturnType<typeof boolean>>;
77
- /** Tagged type representing a custom `numericDate` column (stores date as number YYYYMMDD). */
72
+ export type Numeric<T extends 'number' | 'string' | 'bigint' = 'number'> = Tagged<T extends 'number' ? number : T extends 'string' ? string : bigint, ColumnTypeTag, ReturnType<typeof numeric<T>>>;
73
+ /** Tagged type representing a custom `numericDate` column (stores date as number - days since epoch). */
78
74
  export type NumericDate = Tagged<number, ColumnTypeTag, ReturnType<typeof numericDate>>;
79
75
  /** Tagged type representing a `timestamp` column (stores timestamp as number - milliseconds since epoch). */
80
76
  export type Timestamp = Tagged<number, ColumnTypeTag, ReturnType<typeof timestamp>>;
81
- /** Tagged type representing a `bytea` (byte array) column. */
82
77
  export type Bytea = Tagged<Uint8Array, ColumnTypeTag, ReturnType<typeof bytea>>;
83
78
  /**
84
79
  * Tagged type representing an encrypted column.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tstdl/base",
3
- "version": "0.93.29",
3
+ "version": "0.93.30",
4
4
  "author": "Patrick Hein",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -38,7 +38,7 @@ __decorate([
38
38
  Test = __decorate([
39
39
  ParadeExpressionIndex('foo', () => sql `'foo'`),
40
40
  ParadeCompoundIndex('search_text', (table) => [table.title, 'content', 'tags']),
41
- ParadeIndex({ columns: ['language'], mutableSegmentRows: 12 })
41
+ ParadeIndex({ columns: ['language'] })
42
42
  ], Test);
43
43
  export { Test };
44
44
  export const testData = [
@@ -132,7 +132,6 @@ export const testData = [
132
132
  tags: ['testing', 'database', 'automation', 'best practices'],
133
133
  language: 'english',
134
134
  },
135
- // --- Cooking Posts (16-25) ---
136
135
  {
137
136
  title: 'The Perfect Weeknight Pasta Recipe',
138
137
  content: 'A quick and delicious pasta recipe that you can make in under 30 minutes. Perfect for a busy weeknight. This recipe uses fresh tomatoes and basil.',
@@ -193,7 +192,6 @@ export const testData = [
193
192
  tags: ['smoothie', 'recipe', 'breakfast', 'healthy'],
194
193
  language: 'english',
195
194
  },
196
- // --- Travel Posts (26-35) ---
197
195
  {
198
196
  title: 'A Backpacker\'s Guide to Southeast Asia',
199
197
  content: 'Explore the wonders of Southeast Asia on a budget. This guide covers top destinations, packing tips, and how to travel safely and affordably.',
@@ -254,7 +252,6 @@ export const testData = [
254
252
  tags: ['solo travel', 'travel tips', 'adventure'],
255
253
  language: 'english',
256
254
  },
257
- // --- Science & Lifestyle Posts (36-45) ---
258
255
  {
259
256
  title: 'The Mysteries of Black Holes Explained',
260
257
  content: 'What are black holes and how do they form? This article provides a simple explanation of one of the universe\'s most fascinating phenomena.',
@@ -315,7 +312,6 @@ export const testData = [
315
312
  tags: ['fitness', 'health', 'wellness', 'exercise'],
316
313
  language: 'english',
317
314
  },
318
- // --- Multi-Language Posts (46-50) ---
319
315
  {
320
316
  title: 'Einführung in die Volltextsuche mit PostgreSQL',
321
317
  content: 'Dieser Leitfaden erklärt die Grundlagen der Volltextsuche in einer PostgreSQL Datenbank. Wir behandeln Konfiguration und Abfragen.',
package/test1.js CHANGED
@@ -10,6 +10,7 @@ import { configureOrm, injectRepository } from './orm/server/index.js';
10
10
  import { configurePostgresQueue, migratePostgresQueueSchema } from './queue/postgres/index.js';
11
11
  import { migrateTestSchema } from './test/module.js';
12
12
  import { Test, testData } from './test/test.model.js';
13
+ import { timedBenchmarkAsync } from './utils/benchmark.js';
13
14
  import * as configParser from './utils/config-parser.js';
14
15
  const config = {
15
16
  database: {
@@ -53,18 +54,20 @@ async function main(_cancellationSignal) {
53
54
  if (await repository.count() == 0) {
54
55
  await repository.insertMany(testData);
55
56
  }
56
- const result = await repository.loadManyByQuery({
57
- title: { $parade: { match: { value: 'quick fox', distance: 2 } } },
57
+ let result;
58
+ const benchmarkResult = await timedBenchmarkAsync(1000, async () => {
59
+ result = await repository.search({
60
+ query: {
61
+ $parade: { fields: ['content'], query: 'vitamins' },
62
+ },
63
+ highlight: { source: 'content', includePositions: true },
64
+ score: true,
65
+ });
58
66
  });
59
- const result2 = await repository.search({
60
- query: {
61
- $parade: { fields: ['content'], query: 'vibrant city' },
62
- },
63
- highlight: { source: 'content', includePositions: true },
64
- });
65
- for (const item of result2) {
67
+ for (const item of result) {
66
68
  console.log(item);
67
69
  }
70
+ console.log('Benchmark result:', benchmarkResult);
68
71
  }
69
72
  Application.run('Test', [
70
73
  provideInitializer(bootstrap),