@tstdl/base 0.93.69 → 0.93.71
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/audit/module.js +1 -1
- package/authentication/server/module.js +1 -1
- package/document-management/server/module.js +1 -1
- package/formats/formats.d.ts +29 -21
- package/formats/formats.js +64 -58
- package/key-value-store/postgres/module.js +1 -1
- package/lock/postgres/module.js +1 -1
- package/mail/module.js +1 -1
- package/orm/server/database.d.ts +4 -2
- package/orm/server/database.js +7 -2
- package/orm/server/transactional.d.ts +1 -1
- package/package.json +6 -6
- package/queue/postgres/module.js +1 -1
- package/rpc/endpoints/message-port.rpc-endpoint.d.ts +2 -3
- package/rpc/endpoints/message-port.rpc-endpoint.js +2 -6
- package/test/module.js +1 -1
- package/test-schema.d.ts +1 -0
- package/test-schema.js +124 -0
- package/test6.js +29 -120
package/audit/module.js
CHANGED
|
@@ -28,6 +28,6 @@ export async function migrateAuditSchema() {
|
|
|
28
28
|
await migrate(database, {
|
|
29
29
|
migrationsSchema: 'audit',
|
|
30
30
|
migrationsTable: '_migrations',
|
|
31
|
-
migrationsFolder: import.meta.resolve('./drizzle')
|
|
31
|
+
migrationsFolder: import.meta.resolve('./drizzle'),
|
|
32
32
|
});
|
|
33
33
|
}
|
|
@@ -50,6 +50,6 @@ export async function migrateAuthenticationSchema() {
|
|
|
50
50
|
await migrate(database, {
|
|
51
51
|
migrationsSchema: 'authentication',
|
|
52
52
|
migrationsTable: '_migrations',
|
|
53
|
-
migrationsFolder: import.meta.resolve('./drizzle')
|
|
53
|
+
migrationsFolder: import.meta.resolve('./drizzle'),
|
|
54
54
|
});
|
|
55
55
|
}
|
|
@@ -17,6 +17,6 @@ export async function migrateDocumentManagementSchema() {
|
|
|
17
17
|
await migrate(database, {
|
|
18
18
|
migrationsSchema: 'document_management',
|
|
19
19
|
migrationsTable: '_migrations',
|
|
20
|
-
migrationsFolder: import.meta.resolve('./drizzle')
|
|
20
|
+
migrationsFolder: import.meta.resolve('./drizzle'),
|
|
21
21
|
});
|
|
22
22
|
}
|
package/formats/formats.d.ts
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { DateTime } from 'luxon';
|
|
2
|
+
import type { ValueOrProvider } from '../utils/value-or-provider.js';
|
|
3
|
+
type LocaleOption = {
|
|
3
4
|
locale?: string;
|
|
4
|
-
}
|
|
5
|
+
};
|
|
6
|
+
export type ConfigureLocaleOptions = {
|
|
7
|
+
locale?: ValueOrProvider<string>;
|
|
8
|
+
};
|
|
9
|
+
export type FormatNumberOptions = Intl.NumberFormatOptions & LocaleOption;
|
|
10
|
+
export type FormatDateTimeOptions = Intl.DateTimeFormatOptions & LocaleOption;
|
|
11
|
+
export type FormatNumberValue = number | bigint | Intl.StringNumericLiteral;
|
|
12
|
+
export type FormatDateTimeValue = number | Date | DateTime;
|
|
13
|
+
export declare let getLocale: () => string;
|
|
14
|
+
export declare function configureFormats({ locale }: ConfigureLocaleOptions): void;
|
|
5
15
|
export declare const integerFormat: Intl.NumberFormatOptions;
|
|
6
16
|
export declare const decimalFormat: Intl.NumberFormatOptions;
|
|
7
17
|
export declare const decimal1Format: Intl.NumberFormatOptions;
|
|
8
|
-
export declare const yearFormat: Intl.NumberFormatOptions;
|
|
9
18
|
export declare const dateTimeNumeric: Intl.DateTimeFormatOptions;
|
|
10
19
|
export declare const dateTimeShort: Intl.DateTimeFormatOptions;
|
|
11
20
|
export declare const dateTimeLong: Intl.DateTimeFormatOptions;
|
|
@@ -16,19 +25,21 @@ export declare const timeShort: Intl.DateTimeFormatOptions;
|
|
|
16
25
|
export declare const currencyFormat: Intl.NumberFormatOptions;
|
|
17
26
|
export declare const currencyFormatWithoutCents: Intl.NumberFormatOptions;
|
|
18
27
|
export declare const percentFormat: Intl.NumberFormatOptions;
|
|
19
|
-
export declare function formatNumber(value:
|
|
20
|
-
export declare function
|
|
21
|
-
export declare function
|
|
22
|
-
export declare function
|
|
23
|
-
export declare function
|
|
24
|
-
export declare function
|
|
25
|
-
export declare function
|
|
26
|
-
export declare function
|
|
27
|
-
export declare function
|
|
28
|
-
export declare function
|
|
29
|
-
export declare function
|
|
30
|
-
export declare function
|
|
31
|
-
export declare function
|
|
28
|
+
export declare function formatNumber(value: FormatNumberValue, format?: FormatNumberOptions): string;
|
|
29
|
+
export declare function formatDateTime(value: number | Date | DateTime, format?: FormatDateTimeOptions): string;
|
|
30
|
+
export declare function formatInteger(value: FormatNumberValue, format?: FormatNumberOptions): string;
|
|
31
|
+
export declare function formatDecimal(value: FormatNumberValue, format?: FormatNumberOptions): string;
|
|
32
|
+
export declare function formatCurrency(value: FormatNumberValue, currency: string, format?: FormatNumberOptions): string;
|
|
33
|
+
export declare function formatCurrencyWithoutCents(value: FormatNumberValue, currency: string, format?: FormatNumberOptions): string;
|
|
34
|
+
export declare function formatEuro(value: FormatNumberValue, format?: FormatNumberOptions): string;
|
|
35
|
+
export declare function formatEuroWithoutCents(value: FormatNumberValue, format?: FormatNumberOptions): string;
|
|
36
|
+
export declare function formatPercent(value: FormatNumberValue, format?: FormatNumberOptions): string;
|
|
37
|
+
export declare function formatTimeShort(value: FormatDateTimeValue, format?: FormatDateTimeOptions): string;
|
|
38
|
+
export declare function formatDateShort(value: FormatDateTimeValue, format?: FormatDateTimeOptions): string;
|
|
39
|
+
export declare function formatDate(dateOrTimestamp: FormatDateTimeValue, format?: FormatDateTimeOptions): string;
|
|
40
|
+
export declare function formatNumericDate(numericDate: number, options?: FormatDateTimeOptions): string;
|
|
41
|
+
export declare function formatNumericDateShort(numericDate: number, options?: FormatDateTimeOptions): string;
|
|
42
|
+
export declare function formatNumericDateLong(numericDate: number, options?: FormatDateTimeOptions): string;
|
|
32
43
|
export type FormatPersonNameOptions<F = unknown> = {
|
|
33
44
|
lastNameFirst?: boolean;
|
|
34
45
|
fallback?: F;
|
|
@@ -45,7 +56,4 @@ export declare function formatPersonName(person: {
|
|
|
45
56
|
} | null | undefined, options?: FormatPersonNameOptions & {
|
|
46
57
|
fallback?: undefined;
|
|
47
58
|
}): string;
|
|
48
|
-
|
|
49
|
-
* @deprecated use {@link formatPersonName} instead
|
|
50
|
-
*/
|
|
51
|
-
export declare const formatUserName: typeof formatPersonName;
|
|
59
|
+
export {};
|
package/formats/formats.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { isNullOrUndefined,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { DateTime } from 'luxon';
|
|
2
|
+
import { numericDateToDate } from '../utils/date-time.js';
|
|
3
|
+
import { isDefined, isNullOrUndefined, isString } from '../utils/type-guards.js';
|
|
4
|
+
const numberFormatterMap = new Map();
|
|
5
|
+
const dateTimeFormatterMap = new Map();
|
|
6
|
+
export let getLocale = () => 'de-DE';
|
|
7
|
+
export function configureFormats({ locale }) {
|
|
8
|
+
getLocale = (isString(locale)
|
|
9
|
+
? () => locale
|
|
10
|
+
: locale) ?? getLocale;
|
|
7
11
|
}
|
|
8
12
|
export const integerFormat = {
|
|
9
13
|
useGrouping: true,
|
|
@@ -19,10 +23,6 @@ export const decimal1Format = {
|
|
|
19
23
|
minimumFractionDigits: 0,
|
|
20
24
|
maximumFractionDigits: 1,
|
|
21
25
|
};
|
|
22
|
-
export const yearFormat = {
|
|
23
|
-
useGrouping: false,
|
|
24
|
-
maximumFractionDigits: 0,
|
|
25
|
-
};
|
|
26
26
|
export const dateTimeNumeric = {
|
|
27
27
|
year: 'numeric',
|
|
28
28
|
month: '2-digit',
|
|
@@ -77,57 +77,54 @@ export const percentFormat = {
|
|
|
77
77
|
minimumFractionDigits: 2,
|
|
78
78
|
maximumFractionDigits: 2,
|
|
79
79
|
};
|
|
80
|
-
const getDecimalFormatter = memoize(_getDecimalFormatter);
|
|
81
|
-
const integerFormatter = memoizeSingle((loc) => Intl.NumberFormat(loc, integerFormat));
|
|
82
|
-
const decimalFormatter = memoizeSingle((loc) => Intl.NumberFormat(loc, decimalFormat));
|
|
83
|
-
const yearFormatter = memoizeSingle((loc) => Intl.NumberFormat(loc, yearFormat));
|
|
84
|
-
const percentFormatter = memoizeSingle((loc) => Intl.NumberFormat(loc, percentFormat));
|
|
85
|
-
const dateFormatter = memoizeSingle((loc) => Intl.DateTimeFormat(loc, dateShort));
|
|
86
|
-
const currencyFormatter = memoize((currency, loc) => Intl.NumberFormat(loc, { ...currencyFormat, currency }));
|
|
87
|
-
const currencyFormatterWithoutCents = memoize((currency, loc) => Intl.NumberFormat(loc, { ...currencyFormatWithoutCents, currency }));
|
|
88
|
-
const timeShortFormatter = memoizeSingle((loc) => Intl.DateTimeFormat(loc, timeShort));
|
|
89
|
-
const dateShortFormatter = memoizeSingle((loc) => Intl.DateTimeFormat(loc, dateShort));
|
|
90
80
|
export function formatNumber(value, format) {
|
|
91
|
-
|
|
81
|
+
const locale = format?.locale ?? getLocale();
|
|
82
|
+
return getNumberFormatter(locale, format).format(value);
|
|
92
83
|
}
|
|
93
|
-
export function
|
|
94
|
-
|
|
84
|
+
export function formatDateTime(value, format) {
|
|
85
|
+
const date = DateTime.isDateTime(value) ? value.toJSDate() : value;
|
|
86
|
+
const locale = format?.locale ?? getLocale();
|
|
87
|
+
return getDateTimeFormatter(locale, format).format(date);
|
|
95
88
|
}
|
|
96
|
-
export function
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
return
|
|
89
|
+
export function formatInteger(value, format) {
|
|
90
|
+
return formatNumber(value, { ...integerFormat, ...format });
|
|
91
|
+
}
|
|
92
|
+
export function formatDecimal(value, format) {
|
|
93
|
+
return formatNumber(value, { ...decimalFormat, ...format });
|
|
101
94
|
}
|
|
102
|
-
export function
|
|
103
|
-
return
|
|
95
|
+
export function formatCurrency(value, currency, format) {
|
|
96
|
+
return formatNumber(value, { ...currencyFormat, currency, ...format });
|
|
104
97
|
}
|
|
105
|
-
export function
|
|
106
|
-
return
|
|
98
|
+
export function formatCurrencyWithoutCents(value, currency, format) {
|
|
99
|
+
return formatNumber(value, { ...currencyFormatWithoutCents, currency, ...format });
|
|
107
100
|
}
|
|
108
|
-
export function
|
|
109
|
-
return
|
|
101
|
+
export function formatEuro(value, format) {
|
|
102
|
+
return formatCurrency(value, 'EUR', format);
|
|
110
103
|
}
|
|
111
|
-
export function
|
|
112
|
-
return
|
|
104
|
+
export function formatEuroWithoutCents(value, format) {
|
|
105
|
+
return formatCurrencyWithoutCents(value, 'EUR', format);
|
|
113
106
|
}
|
|
114
|
-
export function
|
|
115
|
-
return
|
|
107
|
+
export function formatPercent(value, format) {
|
|
108
|
+
return formatNumber(value, { ...percentFormat, ...format });
|
|
116
109
|
}
|
|
117
|
-
export function
|
|
118
|
-
return
|
|
110
|
+
export function formatTimeShort(value, format) {
|
|
111
|
+
return formatDateTime(value, { ...timeShort, ...format });
|
|
119
112
|
}
|
|
120
|
-
export function
|
|
121
|
-
return
|
|
113
|
+
export function formatDateShort(value, format) {
|
|
114
|
+
return formatDateTime(value, { ...dateShort, ...format });
|
|
122
115
|
}
|
|
123
|
-
export function
|
|
124
|
-
return
|
|
116
|
+
export function formatDate(dateOrTimestamp, format) {
|
|
117
|
+
return formatDateTime(dateOrTimestamp, { ...dateShort, ...format });
|
|
125
118
|
}
|
|
126
|
-
export function
|
|
127
|
-
|
|
119
|
+
export function formatNumericDate(numericDate, options) {
|
|
120
|
+
const timestamp = numericDateToDate(numericDate);
|
|
121
|
+
return formatDateTime(timestamp, { ...dateShort, ...options });
|
|
128
122
|
}
|
|
129
|
-
export function
|
|
130
|
-
return
|
|
123
|
+
export function formatNumericDateShort(numericDate, options) {
|
|
124
|
+
return formatNumericDate(numericDate, { ...dateShort, ...options });
|
|
125
|
+
}
|
|
126
|
+
export function formatNumericDateLong(numericDate, options) {
|
|
127
|
+
return formatNumericDate(numericDate, { ...dateLong, ...options });
|
|
131
128
|
}
|
|
132
129
|
export function formatPersonName(person, { lastNameFirst = false, fallback } = {}) {
|
|
133
130
|
if (isNullOrUndefined(person?.firstName) || isNullOrUndefined(person.lastName)) {
|
|
@@ -138,14 +135,23 @@ export function formatPersonName(person, { lastNameFirst = false, fallback } = {
|
|
|
138
135
|
}
|
|
139
136
|
return `${person.firstName} ${person.lastName}`;
|
|
140
137
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
138
|
+
function getNumberFormatter(locale, options) {
|
|
139
|
+
const key = JSON.stringify({ locale, options });
|
|
140
|
+
const existing = numberFormatterMap.get(key);
|
|
141
|
+
if (isDefined(existing)) {
|
|
142
|
+
return existing;
|
|
143
|
+
}
|
|
144
|
+
const formatter = new Intl.NumberFormat(locale, options);
|
|
145
|
+
numberFormatterMap.set(key, formatter);
|
|
146
|
+
return formatter;
|
|
147
|
+
}
|
|
148
|
+
function getDateTimeFormatter(locale, options) {
|
|
149
|
+
const key = JSON.stringify({ locale, options });
|
|
150
|
+
const existing = dateTimeFormatterMap.get(key);
|
|
151
|
+
if (isDefined(existing)) {
|
|
152
|
+
return existing;
|
|
153
|
+
}
|
|
154
|
+
const formatter = new Intl.DateTimeFormat(locale, options);
|
|
155
|
+
dateTimeFormatterMap.set(key, formatter);
|
|
156
|
+
return formatter;
|
|
151
157
|
}
|
|
@@ -18,6 +18,6 @@ export async function migratePostgresKeyValueStoreSchema() {
|
|
|
18
18
|
await migrate(database, {
|
|
19
19
|
migrationsSchema: 'key_value_store',
|
|
20
20
|
migrationsTable: '_migrations',
|
|
21
|
-
migrationsFolder: import.meta.resolve('./drizzle')
|
|
21
|
+
migrationsFolder: import.meta.resolve('./drizzle'),
|
|
22
22
|
});
|
|
23
23
|
}
|
package/lock/postgres/module.js
CHANGED
|
@@ -21,6 +21,6 @@ export async function migratePostgresLockSchema() {
|
|
|
21
21
|
await migrate(database, {
|
|
22
22
|
migrationsSchema: 'lock',
|
|
23
23
|
migrationsTable: '_migrations',
|
|
24
|
-
migrationsFolder: import.meta.resolve('./drizzle')
|
|
24
|
+
migrationsFolder: import.meta.resolve('./drizzle'),
|
|
25
25
|
});
|
|
26
26
|
}
|
package/mail/module.js
CHANGED
|
@@ -31,6 +31,6 @@ export async function migrateMailSchema() {
|
|
|
31
31
|
await migrate(database, {
|
|
32
32
|
migrationsSchema: 'mail',
|
|
33
33
|
migrationsTable: '_migrations',
|
|
34
|
-
migrationsFolder: import.meta.resolve('./drizzle')
|
|
34
|
+
migrationsFolder: import.meta.resolve('./drizzle'),
|
|
35
35
|
});
|
|
36
36
|
}
|
package/orm/server/database.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* It sets up the dependency injection for the database instance.
|
|
5
5
|
*/
|
|
6
6
|
import { NodePgDatabase } from 'drizzle-orm/node-postgres';
|
|
7
|
-
import { migrate } from 'drizzle-orm/node-postgres/migrator';
|
|
7
|
+
import { migrate as drizzleMigrate } from 'drizzle-orm/node-postgres/migrator';
|
|
8
8
|
import { type PoolConfig } from 'pg';
|
|
9
9
|
import type { Resolvable, resolveArgumentType } from '../../injector/interfaces.js';
|
|
10
10
|
/**
|
|
@@ -20,4 +20,6 @@ export type DatabaseArgument = PoolConfig;
|
|
|
20
20
|
export declare class Database extends NodePgDatabase<any> implements Resolvable<DatabaseArgument> {
|
|
21
21
|
readonly [resolveArgumentType]?: DatabaseArgument;
|
|
22
22
|
}
|
|
23
|
-
|
|
23
|
+
type MigrateParameters = Parameters<typeof drizzleMigrate>;
|
|
24
|
+
export declare function migrate(db: MigrateParameters[0], config: MigrateParameters[1]): Promise<void>;
|
|
25
|
+
export {};
|
package/orm/server/database.js
CHANGED
|
@@ -10,7 +10,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
10
10
|
* It sets up the dependency injection for the database instance.
|
|
11
11
|
*/
|
|
12
12
|
import { drizzle, NodePgDatabase } from 'drizzle-orm/node-postgres';
|
|
13
|
-
import { migrate } from 'drizzle-orm/node-postgres/migrator';
|
|
13
|
+
import { migrate as drizzleMigrate } from 'drizzle-orm/node-postgres/migrator';
|
|
14
14
|
import { Pool } from 'pg';
|
|
15
15
|
import { inject, Injector, ReplaceClass } from '../../injector/index.js';
|
|
16
16
|
import { isUndefined } from '../../utils/type-guards.js';
|
|
@@ -41,4 +41,9 @@ Injector.registerSingleton(Database, {
|
|
|
41
41
|
return drizzle(pool);
|
|
42
42
|
},
|
|
43
43
|
});
|
|
44
|
-
export
|
|
44
|
+
export async function migrate(db, config) {
|
|
45
|
+
const migrationsFolder = config.migrationsFolder
|
|
46
|
+
.replace('file://', '') // drizzle doesn't like it
|
|
47
|
+
.replace(/index.jsx$/, ''); // workaround for weird import.meta.resolve behavior with tsx
|
|
48
|
+
await drizzleMigrate(db, { ...config, migrationsFolder });
|
|
49
|
+
}
|
|
@@ -22,7 +22,7 @@ declare const getCurrentTransactionalContext: {
|
|
|
22
22
|
export { getCurrentTransactionalContext, isInTransactionalContext, runInTransactionalContext };
|
|
23
23
|
export declare abstract class Transactional<ContextData = unknown> {
|
|
24
24
|
#private;
|
|
25
|
-
readonly session:
|
|
25
|
+
readonly session: PgTransaction | Database;
|
|
26
26
|
readonly isInTransaction: boolean;
|
|
27
27
|
constructor();
|
|
28
28
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tstdl/base",
|
|
3
|
-
"version": "0.93.
|
|
3
|
+
"version": "0.93.71",
|
|
4
4
|
"author": "Patrick Hein",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -140,9 +140,9 @@
|
|
|
140
140
|
"type-fest": "^5.3"
|
|
141
141
|
},
|
|
142
142
|
"peerDependencies": {
|
|
143
|
-
"@genkit-ai/google-genai": "^1.
|
|
143
|
+
"@genkit-ai/google-genai": "^1.26",
|
|
144
144
|
"@google-cloud/storage": "^7.18",
|
|
145
|
-
"@google/genai": "^1.
|
|
145
|
+
"@google/genai": "^1.34",
|
|
146
146
|
"@toon-format/toon": "^2.1.0",
|
|
147
147
|
"@tstdl/angular": "^0.93",
|
|
148
148
|
"@zxcvbn-ts/core": "^3.0",
|
|
@@ -151,7 +151,7 @@
|
|
|
151
151
|
"@zxcvbn-ts/language-en": "^3.0",
|
|
152
152
|
"drizzle-orm": "^0.45",
|
|
153
153
|
"file-type": "^21.1",
|
|
154
|
-
"genkit": "^1.
|
|
154
|
+
"genkit": "^1.26",
|
|
155
155
|
"handlebars": "^4.7",
|
|
156
156
|
"minio": "^8.0",
|
|
157
157
|
"mjml": "^4.18",
|
|
@@ -175,9 +175,9 @@
|
|
|
175
175
|
"@types/koa__router": "12.0",
|
|
176
176
|
"@types/luxon": "3.7",
|
|
177
177
|
"@types/mjml": "4.7",
|
|
178
|
-
"@types/node": "
|
|
178
|
+
"@types/node": "25",
|
|
179
179
|
"@types/nodemailer": "7.0",
|
|
180
|
-
"@types/pg": "8.
|
|
180
|
+
"@types/pg": "8.16",
|
|
181
181
|
"concurrently": "9.2",
|
|
182
182
|
"drizzle-kit": "0.31",
|
|
183
183
|
"eslint": "9.39",
|
package/queue/postgres/module.js
CHANGED
|
@@ -24,6 +24,6 @@ export async function migratePostgresQueueSchema() {
|
|
|
24
24
|
await migrate(database, {
|
|
25
25
|
migrationsSchema: 'queue',
|
|
26
26
|
migrationsTable: '_migrations',
|
|
27
|
-
migrationsFolder: import.meta.resolve('./drizzle')
|
|
27
|
+
migrationsFolder: import.meta.resolve('./drizzle'),
|
|
28
28
|
});
|
|
29
29
|
}
|
|
@@ -20,7 +20,6 @@ type MessagePortDataMessage<T> = MessagePortMessageBase<'data'> & {
|
|
|
20
20
|
type MessagePortMessage<T> = MessagePortOpenChannelMessage | MessagePortCloseChannelMessage | MessagePortDataMessage<T>;
|
|
21
21
|
export declare class MessagePortRpcChannel<Data = any, Req = any, Res = any> extends RpcChannel<Data, Req, Res> {
|
|
22
22
|
#private;
|
|
23
|
-
private readonly _postMessage;
|
|
24
23
|
private transport;
|
|
25
24
|
readonly messagePortMessage$: Observable<MessagePortMessage<RpcChannelMessage<Data, Req, Res>>>;
|
|
26
25
|
channelMessages$: Observable<RpcChannelMessage<Data, Req, Res>>;
|
|
@@ -30,9 +29,9 @@ export declare class MessagePortRpcChannel<Data = any, Req = any, Res = any> ext
|
|
|
30
29
|
lastSequence: number;
|
|
31
30
|
constructor(id: string, transport: MessagePortRpcTransport | undefined, endpoint: MessagePortRpcEndpoint);
|
|
32
31
|
setTransport(transport: MessagePortRpcTransport): void;
|
|
33
|
-
postPortMessage(message: MessagePortMessage<RpcChannelMessage<Data, Req, Res>>,
|
|
32
|
+
postPortMessage(message: MessagePortMessage<RpcChannelMessage<Data, Req, Res>>, transferOrOptions?: Transferable[] | NodeWorkerThreads.Transferable[] | NodeWorkerThreads.StructuredSerializeOptions | StructuredSerializeOptions): void;
|
|
34
33
|
close(): void;
|
|
35
|
-
postMessage(message: RpcChannelMessage<Data, Req, Res>, transfer?:
|
|
34
|
+
postMessage(message: RpcChannelMessage<Data, Req, Res>, transfer?: Transferable[] | StructuredSerializeOptions): void | Promise<void>;
|
|
36
35
|
}
|
|
37
36
|
export declare class MessagePortRpcEndpoint extends RpcEndpoint {
|
|
38
37
|
#private;
|
|
@@ -6,7 +6,6 @@ import { RpcChannel, RpcEndpoint } from '../rpc.endpoint.js';
|
|
|
6
6
|
export class MessagePortRpcChannel extends RpcChannel {
|
|
7
7
|
#transportSubject = new ReplaySubject(1);
|
|
8
8
|
#closeSubject = new Subject();
|
|
9
|
-
_postMessage;
|
|
10
9
|
transport = { postMessage: deferThrow(() => new Error('Rpc transport not yet initialized.')) };
|
|
11
10
|
messagePortMessage$;
|
|
12
11
|
channelMessages$;
|
|
@@ -22,9 +21,6 @@ export class MessagePortRpcChannel extends RpcChannel {
|
|
|
22
21
|
}
|
|
23
22
|
this.messagePortMessage$ = this.#transportSubject.pipe(startWith(transport), filter(isDefined), switchMap((newTransport) => fromEvent(newTransport, 'message')), takeUntil(this.#closeSubject), map((message) => ((message instanceof MessageEvent) ? message.data : message)), shareReplay({ bufferSize: 0, refCount: true }));
|
|
24
23
|
this.channelMessages$ = this.messagePortMessage$.pipe(filter((message) => message.type == 'data'), map((message) => message.data));
|
|
25
|
-
this._postMessage = isBrowser
|
|
26
|
-
? (data, transfer) => this.transport.postMessage(data, { transfer })
|
|
27
|
-
: (data, transfer) => this.transport.postMessage(data, transfer);
|
|
28
24
|
if (transport instanceof MessagePort) {
|
|
29
25
|
transport.start();
|
|
30
26
|
}
|
|
@@ -39,8 +35,8 @@ export class MessagePortRpcChannel extends RpcChannel {
|
|
|
39
35
|
this.#transportSubject.next(transport);
|
|
40
36
|
this.#transportSubject.complete();
|
|
41
37
|
}
|
|
42
|
-
postPortMessage(message,
|
|
43
|
-
this.
|
|
38
|
+
postPortMessage(message, transferOrOptions) {
|
|
39
|
+
this.transport.postMessage(message, transferOrOptions);
|
|
44
40
|
}
|
|
45
41
|
close() {
|
|
46
42
|
this.postPortMessage({ seq: this.sequence++, type: 'close-channel' });
|
package/test/module.js
CHANGED
|
@@ -12,6 +12,6 @@ export async function migrateTestSchema() {
|
|
|
12
12
|
await migrate(database, {
|
|
13
13
|
migrationsSchema: 'test',
|
|
14
14
|
migrationsTable: '_migrations',
|
|
15
|
-
migrationsFolder: import.meta.resolve('./drizzle')
|
|
15
|
+
migrationsFolder: import.meta.resolve('./drizzle'),
|
|
16
16
|
});
|
|
17
17
|
}
|
package/test-schema.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/test-schema.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import z from 'zod';
|
|
2
|
+
import { Application } from './application/application.js';
|
|
3
|
+
import { provideModule, provideSignalHandler } from './application/providers.js';
|
|
4
|
+
import { PrettyPrintLogFormatter, provideConsoleLogTransport } from './logger/index.js';
|
|
5
|
+
import { array, boolean, literal, number, object, optional, string, union } from './schema/index.js';
|
|
6
|
+
import { benchmark } from './utils/benchmark.js';
|
|
7
|
+
function logResult(name, tstdl, zod) {
|
|
8
|
+
const faster = tstdl.millisecondsPerOperation < zod.millisecondsPerOperation ? 'TSTDL' : 'Zod';
|
|
9
|
+
const factor = tstdl.millisecondsPerOperation < zod.millisecondsPerOperation ? zod.millisecondsPerOperation / tstdl.millisecondsPerOperation : tstdl.millisecondsPerOperation / zod.millisecondsPerOperation;
|
|
10
|
+
console.log(`\n--- ${name} ---`);
|
|
11
|
+
console.log(`TSTDL: ${tstdl.operationsPerMillisecond.toFixed(2)} ops/ms`);
|
|
12
|
+
console.log(`Zod: ${zod.operationsPerMillisecond.toFixed(2)} ops/ms`);
|
|
13
|
+
console.log(`Result: ${faster} is ${factor.toFixed(2)}x faster`);
|
|
14
|
+
}
|
|
15
|
+
// --- SETUP SCHEMAS ---
|
|
16
|
+
// 1. Primitive Schema
|
|
17
|
+
const tstdlString = string();
|
|
18
|
+
const zodString = z.string();
|
|
19
|
+
// 2. Simple Object
|
|
20
|
+
const tstdlUser = object({
|
|
21
|
+
name: string(),
|
|
22
|
+
age: number(),
|
|
23
|
+
isActive: boolean(),
|
|
24
|
+
});
|
|
25
|
+
const zodUser = z.object({
|
|
26
|
+
name: z.string(),
|
|
27
|
+
age: z.number(),
|
|
28
|
+
isActive: z.boolean(),
|
|
29
|
+
});
|
|
30
|
+
// 3. Complex Nested Schema
|
|
31
|
+
const tstdlComplex = object({
|
|
32
|
+
id: number(),
|
|
33
|
+
tags: array(string()),
|
|
34
|
+
metadata: optional(object({
|
|
35
|
+
createdAt: number(),
|
|
36
|
+
source: union(literal('web'), literal('mobile')),
|
|
37
|
+
})),
|
|
38
|
+
});
|
|
39
|
+
const zodComplex = z.object({
|
|
40
|
+
id: z.number(),
|
|
41
|
+
tags: z.array(z.string()),
|
|
42
|
+
metadata: z.object({
|
|
43
|
+
createdAt: z.number(),
|
|
44
|
+
source: z.union([z.literal('web'), z.literal('mobile')]),
|
|
45
|
+
}).optional(),
|
|
46
|
+
});
|
|
47
|
+
// 4. Large Array
|
|
48
|
+
const tstdlArray = array(number());
|
|
49
|
+
const zodArray = z.array(z.number());
|
|
50
|
+
// --- DATA ---
|
|
51
|
+
const validString = 'Hello World';
|
|
52
|
+
const validUser = {
|
|
53
|
+
name: 'Alice',
|
|
54
|
+
age: 30,
|
|
55
|
+
isActive: true,
|
|
56
|
+
};
|
|
57
|
+
const validComplex = {
|
|
58
|
+
id: 101,
|
|
59
|
+
tags: ['admin', 'staff', 'verified'],
|
|
60
|
+
metadata: {
|
|
61
|
+
createdAt: 1678900000,
|
|
62
|
+
source: 'web',
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
const largeArrayData = Array.from({ length: 1000 }, (_, i) => i);
|
|
66
|
+
const invalidUser = {
|
|
67
|
+
name: 'Bob',
|
|
68
|
+
age: '30', // Invalid: string instead of number
|
|
69
|
+
isActive: true,
|
|
70
|
+
};
|
|
71
|
+
// --- RUN BENCHMARKS ---
|
|
72
|
+
console.log('Starting Benchmarks...');
|
|
73
|
+
// 1. Primitive Parsing
|
|
74
|
+
const ITERATIONS_PRIMITIVE = 1_000_000;
|
|
75
|
+
const zodPrim = benchmark(ITERATIONS_PRIMITIVE, () => zodString.parse(validString));
|
|
76
|
+
const tstdlPrim = benchmark(ITERATIONS_PRIMITIVE, () => tstdlString.parse(validString));
|
|
77
|
+
logResult(`Primitive String Parse (${ITERATIONS_PRIMITIVE} ops)`, tstdlPrim, zodPrim);
|
|
78
|
+
// 2. Simple Object Parsing
|
|
79
|
+
const ITERATIONS_OBJ = 500_000;
|
|
80
|
+
const zodObj = benchmark(ITERATIONS_OBJ, () => zodUser.parse(validUser));
|
|
81
|
+
const tstdlObj = benchmark(ITERATIONS_OBJ, () => tstdlUser.parse(validUser));
|
|
82
|
+
logResult(`Simple Object Parse (${ITERATIONS_OBJ} ops)`, tstdlObj, zodObj);
|
|
83
|
+
// 3. Complex Nested Object Parsing
|
|
84
|
+
const ITERATIONS_COMPLEX = 200_000;
|
|
85
|
+
const zodCmplx = benchmark(ITERATIONS_COMPLEX, () => zodComplex.parse(validComplex));
|
|
86
|
+
const tstdlCmplx = benchmark(ITERATIONS_COMPLEX, () => tstdlComplex.parse(validComplex));
|
|
87
|
+
logResult(`Complex Object Parse (${ITERATIONS_COMPLEX} ops)`, tstdlCmplx, zodCmplx);
|
|
88
|
+
// 4. Large Array Parsing
|
|
89
|
+
const ITERATIONS_ARRAY = 5_000;
|
|
90
|
+
const zodArr = benchmark(ITERATIONS_ARRAY, () => zodArray.parse(largeArrayData));
|
|
91
|
+
const tstdlArr = benchmark(ITERATIONS_ARRAY, () => tstdlArray.parse(largeArrayData));
|
|
92
|
+
logResult(`Large Array (1k items) Parse (${ITERATIONS_ARRAY} ops)`, tstdlArr, zodArr);
|
|
93
|
+
// 5. Error Handling (Exceptions)
|
|
94
|
+
// Note: TSTDL creates stack traces by default, Zod does not.
|
|
95
|
+
const ITERATIONS_ERROR = 100_000;
|
|
96
|
+
const tstdlErr = benchmark(ITERATIONS_ERROR, () => {
|
|
97
|
+
try {
|
|
98
|
+
tstdlUser.parse(invalidUser);
|
|
99
|
+
}
|
|
100
|
+
catch (e) { }
|
|
101
|
+
});
|
|
102
|
+
const zodErr = benchmark(ITERATIONS_ERROR, () => {
|
|
103
|
+
try {
|
|
104
|
+
zodUser.parse(invalidUser);
|
|
105
|
+
}
|
|
106
|
+
catch (e) { }
|
|
107
|
+
});
|
|
108
|
+
logResult(`Error Handling / Throwing (${ITERATIONS_ERROR} ops)`, tstdlErr, zodErr);
|
|
109
|
+
// 6. Error Handling (TSTDL Fast Errors vs Zod)
|
|
110
|
+
// TSTDL has a 'fastErrors' option which might improve performance by skipping stack traces
|
|
111
|
+
const tstdlErrFast = benchmark(ITERATIONS_ERROR, () => {
|
|
112
|
+
try {
|
|
113
|
+
tstdlUser.parse(invalidUser, { fastErrors: true });
|
|
114
|
+
}
|
|
115
|
+
catch (e) { }
|
|
116
|
+
});
|
|
117
|
+
logResult(`Error Handling (TSTDL fastErrors=true) (${ITERATIONS_ERROR} ops)`, tstdlErrFast, zodErr);
|
|
118
|
+
function main() {
|
|
119
|
+
}
|
|
120
|
+
Application.run('Test', [
|
|
121
|
+
provideModule(main),
|
|
122
|
+
provideConsoleLogTransport(PrettyPrintLogFormatter),
|
|
123
|
+
provideSignalHandler(),
|
|
124
|
+
]);
|
package/test6.js
CHANGED
|
@@ -1,124 +1,33 @@
|
|
|
1
|
-
import z from 'zod';
|
|
2
|
-
import { Application } from './application/application.js';
|
|
3
|
-
import { provideModule, provideSignalHandler } from './application/providers.js';
|
|
4
|
-
import { PrettyPrintLogFormatter, provideConsoleLogTransport } from './logger/index.js';
|
|
5
|
-
import { array, boolean, literal, number, object, optional, string, union } from './schema/index.js';
|
|
6
1
|
import { benchmark } from './utils/benchmark.js';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
// --- SETUP SCHEMAS ---
|
|
16
|
-
// 1. Primitive Schema
|
|
17
|
-
const tstdlString = string();
|
|
18
|
-
const zodString = z.string();
|
|
19
|
-
// 2. Simple Object
|
|
20
|
-
const tstdlUser = object({
|
|
21
|
-
name: string(),
|
|
22
|
-
age: number(),
|
|
23
|
-
isActive: boolean(),
|
|
24
|
-
});
|
|
25
|
-
const zodUser = z.object({
|
|
26
|
-
name: z.string(),
|
|
27
|
-
age: z.number(),
|
|
28
|
-
isActive: z.boolean(),
|
|
29
|
-
});
|
|
30
|
-
// 3. Complex Nested Schema
|
|
31
|
-
const tstdlComplex = object({
|
|
32
|
-
id: number(),
|
|
33
|
-
tags: array(string()),
|
|
34
|
-
metadata: optional(object({
|
|
35
|
-
createdAt: number(),
|
|
36
|
-
source: union(literal('web'), literal('mobile')),
|
|
37
|
-
})),
|
|
38
|
-
});
|
|
39
|
-
const zodComplex = z.object({
|
|
40
|
-
id: z.number(),
|
|
41
|
-
tags: z.array(z.string()),
|
|
42
|
-
metadata: z.object({
|
|
43
|
-
createdAt: z.number(),
|
|
44
|
-
source: z.union([z.literal('web'), z.literal('mobile')]),
|
|
45
|
-
}).optional(),
|
|
46
|
-
});
|
|
47
|
-
// 4. Large Array
|
|
48
|
-
const tstdlArray = array(number());
|
|
49
|
-
const zodArray = z.array(z.number());
|
|
50
|
-
// --- DATA ---
|
|
51
|
-
const validString = 'Hello World';
|
|
52
|
-
const validUser = {
|
|
53
|
-
name: 'Alice',
|
|
54
|
-
age: 30,
|
|
55
|
-
isActive: true,
|
|
56
|
-
};
|
|
57
|
-
const validComplex = {
|
|
58
|
-
id: 101,
|
|
59
|
-
tags: ['admin', 'staff', 'verified'],
|
|
60
|
-
metadata: {
|
|
61
|
-
createdAt: 1678900000,
|
|
62
|
-
source: 'web',
|
|
63
|
-
},
|
|
64
|
-
};
|
|
65
|
-
const largeArrayData = Array.from({ length: 1000 }, (_, i) => i);
|
|
66
|
-
const invalidUser = {
|
|
67
|
-
name: 'Bob',
|
|
68
|
-
age: '30', // Invalid: string instead of number
|
|
69
|
-
isActive: true,
|
|
70
|
-
};
|
|
71
|
-
// --- RUN BENCHMARKS ---
|
|
72
|
-
console.log('Starting Benchmarks...');
|
|
73
|
-
// 1. Primitive Parsing
|
|
74
|
-
const ITERATIONS_PRIMITIVE = 1_000_000;
|
|
75
|
-
const zodPrim = benchmark(ITERATIONS_PRIMITIVE, () => zodString.parse(validString));
|
|
76
|
-
const tstdlPrim = benchmark(ITERATIONS_PRIMITIVE, () => tstdlString.parse(validString));
|
|
77
|
-
logResult(`Primitive String Parse (${ITERATIONS_PRIMITIVE} ops)`, tstdlPrim, zodPrim);
|
|
78
|
-
// 2. Simple Object Parsing
|
|
79
|
-
const ITERATIONS_OBJ = 500_000;
|
|
80
|
-
const zodObj = benchmark(ITERATIONS_OBJ, () => zodUser.parse(validUser));
|
|
81
|
-
const tstdlObj = benchmark(ITERATIONS_OBJ, () => tstdlUser.parse(validUser));
|
|
82
|
-
logResult(`Simple Object Parse (${ITERATIONS_OBJ} ops)`, tstdlObj, zodObj);
|
|
83
|
-
// 3. Complex Nested Object Parsing
|
|
84
|
-
const ITERATIONS_COMPLEX = 200_000;
|
|
85
|
-
const zodCmplx = benchmark(ITERATIONS_COMPLEX, () => zodComplex.parse(validComplex));
|
|
86
|
-
const tstdlCmplx = benchmark(ITERATIONS_COMPLEX, () => tstdlComplex.parse(validComplex));
|
|
87
|
-
logResult(`Complex Object Parse (${ITERATIONS_COMPLEX} ops)`, tstdlCmplx, zodCmplx);
|
|
88
|
-
// 4. Large Array Parsing
|
|
89
|
-
const ITERATIONS_ARRAY = 5_000;
|
|
90
|
-
const zodArr = benchmark(ITERATIONS_ARRAY, () => zodArray.parse(largeArrayData));
|
|
91
|
-
const tstdlArr = benchmark(ITERATIONS_ARRAY, () => tstdlArray.parse(largeArrayData));
|
|
92
|
-
logResult(`Large Array (1k items) Parse (${ITERATIONS_ARRAY} ops)`, tstdlArr, zodArr);
|
|
93
|
-
// 5. Error Handling (Exceptions)
|
|
94
|
-
// Note: TSTDL creates stack traces by default, Zod does not.
|
|
95
|
-
const ITERATIONS_ERROR = 100_000;
|
|
96
|
-
const tstdlErr = benchmark(ITERATIONS_ERROR, () => {
|
|
97
|
-
try {
|
|
98
|
-
tstdlUser.parse(invalidUser);
|
|
99
|
-
}
|
|
100
|
-
catch (e) { }
|
|
101
|
-
});
|
|
102
|
-
const zodErr = benchmark(ITERATIONS_ERROR, () => {
|
|
103
|
-
try {
|
|
104
|
-
zodUser.parse(invalidUser);
|
|
2
|
+
import { isDefined } from './utils/type-guards.js';
|
|
3
|
+
const numberFormatterMap = new Map();
|
|
4
|
+
function getNumberFormatter1(locale, options) {
|
|
5
|
+
const key = JSON.stringify({ locale, ...options });
|
|
6
|
+
const existing = numberFormatterMap.get(key);
|
|
7
|
+
if (isDefined(existing)) {
|
|
8
|
+
return existing;
|
|
105
9
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
10
|
+
const formatter = new Intl.NumberFormat(locale, options);
|
|
11
|
+
numberFormatterMap.set(key, formatter);
|
|
12
|
+
return formatter;
|
|
13
|
+
}
|
|
14
|
+
function getNumberFormatter2(locale, options) {
|
|
15
|
+
const key = JSON.stringify({ locale, options });
|
|
16
|
+
const existing = numberFormatterMap.get(key);
|
|
17
|
+
if (isDefined(existing)) {
|
|
18
|
+
return existing;
|
|
114
19
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
20
|
+
const formatter = new Intl.NumberFormat(locale, options);
|
|
21
|
+
numberFormatterMap.set(key, formatter);
|
|
22
|
+
return formatter;
|
|
23
|
+
}
|
|
24
|
+
function format1(value, locale, format) {
|
|
25
|
+
return getNumberFormatter1(locale, format).format(value);
|
|
26
|
+
}
|
|
27
|
+
function format2(value, locale, format) {
|
|
28
|
+
return getNumberFormatter2(locale, format).format(value);
|
|
119
29
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
]);
|
|
30
|
+
const result1 = benchmark(200000, (run) => format1(run, 'en-US', { maximumFractionDigits: 2 }));
|
|
31
|
+
const result2 = benchmark(200000, (run) => format2(run, 'en-US', { maximumFractionDigits: 2 }));
|
|
32
|
+
console.log(`format: ${result1.operationsPerMillisecond.toFixed(2)} ops/ms`);
|
|
33
|
+
console.log(`formatCached: ${result2.operationsPerMillisecond.toFixed(2)} ops/ms`);
|