tina4-nodejs 3.13.103 → 3.13.105
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/CLAUDE.md +16 -2
- package/package.json +1 -1
- package/packages/cli/dist/bin.js +747 -57
- package/packages/core/dist/index.js +750 -57
- package/packages/core/src/authGate.ts +6 -0
- package/packages/core/src/index.ts +2 -0
- package/packages/core/src/queue.ts +75 -18
- package/packages/core/src/queueBackends/liteBackend.ts +17 -1
- package/packages/core/src/queueBackends/mongoBackend.ts +80 -14
- package/packages/core/src/server.ts +5 -0
- package/packages/core/src/sso.ts +285 -0
- package/packages/orm/dist/index.js +755 -62
- package/packages/orm/src/adapters/postgres.ts +2 -0
- package/packages/orm/src/baseModel.ts +63 -10
- package/packages/orm/src/index.ts +2 -0
- package/packages/orm/src/migration.ts +14 -5
- package/packages/orm/src/point.ts +105 -0
- package/packages/orm/src/queryBuilder.ts +66 -5
- package/packages/orm/src/sqlTranslator.ts +63 -0
- package/packages/orm/src/types.ts +5 -1
- package/packages/swagger/dist/index.js +11 -1
- package/packages/swagger/src/generator.ts +11 -1
- package/types/core/src/index.d.ts +2 -0
- package/types/core/src/queue.d.ts +41 -4
- package/types/core/src/queueBackends/liteBackend.d.ts +7 -1
- package/types/core/src/queueBackends/mongoBackend.d.ts +7 -2
- package/types/core/src/sso.d.ts +55 -0
- package/types/orm/src/baseModel.d.ts +13 -5
- package/types/orm/src/index.d.ts +2 -0
- package/types/orm/src/point.d.ts +24 -0
- package/types/orm/src/queryBuilder.d.ts +10 -1
- package/types/orm/src/sqlTranslator.d.ts +13 -0
- package/types/orm/src/types.d.ts +5 -1
|
@@ -74,7 +74,13 @@ export interface QueueBackendInterface {
|
|
|
74
74
|
close(): void;
|
|
75
75
|
complete?(queue: string, id: string): void;
|
|
76
76
|
fail?(queue: string, id: string, error: string, maxRetries: number, retryBackoff: number): void;
|
|
77
|
-
|
|
77
|
+
/**
|
|
78
|
+
* Explicit manual re-queue: returns true if the id was found and revived,
|
|
79
|
+
* false otherwise (parity with Python's backend.retry_job()). A backend may
|
|
80
|
+
* legacy-return void; callers coerce a void return to true so nothing that
|
|
81
|
+
* used to be reported as success silently flips to failure.
|
|
82
|
+
*/
|
|
83
|
+
retry?(queue: string, id: string, delaySeconds?: number): boolean | void;
|
|
78
84
|
deadLetters?(queue: string, maxRetries?: number): QueueJob[];
|
|
79
85
|
failed?(queue: string, maxRetries?: number): QueueJob[];
|
|
80
86
|
retryFailed?(queue: string, maxRetries?: number): number;
|
|
@@ -137,7 +143,19 @@ export declare class Queue {
|
|
|
137
143
|
*/
|
|
138
144
|
process(handler: (job: QueueJob | QueueJob[]) => Promise<void> | void, options?: ProcessOptions): void;
|
|
139
145
|
/**
|
|
140
|
-
* Count jobs
|
|
146
|
+
* Count jobs by status. Defaults to "pending".
|
|
147
|
+
*
|
|
148
|
+
* ``"pending"`` counts jobs waiting to be popped -- INCLUDES retryable-
|
|
149
|
+
* but-attempted ones, because they live in the pending queue under the
|
|
150
|
+
* auto-retry lifecycle (see failed()).
|
|
151
|
+
* ``"reserved"`` counts jobs a consumer has popped but not yet
|
|
152
|
+
* completed/failed (in-flight against the visibility timeout).
|
|
153
|
+
* ``"completed"`` counts jobs the consumer has finished successfully.
|
|
154
|
+
* ``"failed"``, ``"dead"``, ``"dead_letter"`` are ALIASES that all count
|
|
155
|
+
* the dead-letter store -- jobs whose attempts >= maxRetries and that
|
|
156
|
+
* have given up. Use deadLetters() to list them. Retryable-but-attempted
|
|
157
|
+
* jobs are NOT counted by size("failed"); use failed() to list them or
|
|
158
|
+
* size("pending") to include them in a total.
|
|
141
159
|
*/
|
|
142
160
|
size(status?: string): number;
|
|
143
161
|
/**
|
|
@@ -172,7 +190,11 @@ export declare class Queue {
|
|
|
172
190
|
/**
|
|
173
191
|
* Get jobs that failed at least once but are still being retried
|
|
174
192
|
* (0 < attempts < maxRetries). These live in the pending queue under the
|
|
175
|
-
* auto-retry lifecycle
|
|
193
|
+
* auto-retry lifecycle (fail() re-queues them with an incremented attempts
|
|
194
|
+
* count and a retryBackoff delay) so pop() picks them up again. They are
|
|
195
|
+
* NOT counted by size("failed") -- that alias counts the dead-letter store,
|
|
196
|
+
* matching deadLetters(). To include retryable-failed jobs in a total, use
|
|
197
|
+
* size("pending"). Terminal failures are returned by deadLetters().
|
|
176
198
|
*/
|
|
177
199
|
failed(): QueueJob[];
|
|
178
200
|
/**
|
|
@@ -184,7 +206,22 @@ export declare class Queue {
|
|
|
184
206
|
*/
|
|
185
207
|
retry(jobId?: string, delaySeconds?: number): boolean;
|
|
186
208
|
/**
|
|
187
|
-
* Get
|
|
209
|
+
* Get jobs that exceeded max_retries -- terminal failures.
|
|
210
|
+
*
|
|
211
|
+
* Same set counted by size("failed") / size("dead") / size("dead_letter")
|
|
212
|
+
* (three aliases for the dead-letter store). To LIST retryable-but-
|
|
213
|
+
* attempted jobs (attempts > 0 AND attempts < maxRetries) that are still
|
|
214
|
+
* being auto-retried, use failed() -- those live in the pending queue and
|
|
215
|
+
* are NOT dead letters.
|
|
216
|
+
*
|
|
217
|
+
* Returns Job objects with the failure reason on ``.error`` (not raw dicts)
|
|
218
|
+
* so callers can iterate uniformly with the rest of the queue API and, in
|
|
219
|
+
* particular, call ``.retry()`` on each to manually revive it:
|
|
220
|
+
*
|
|
221
|
+
* for (const job of queue.deadLetters()) {
|
|
222
|
+
* Log.warn(`revived ${job.id}: ${job.error}`);
|
|
223
|
+
* job.retry();
|
|
224
|
+
* }
|
|
188
225
|
*/
|
|
189
226
|
deadLetters(maxRetries?: number): QueueJob[];
|
|
190
227
|
/**
|
|
@@ -122,7 +122,13 @@ export declare class LiteBackend {
|
|
|
122
122
|
* Explicit re-queue requested by the caller (job.retry()).
|
|
123
123
|
*
|
|
124
124
|
* Always re-enqueues regardless of the retry limit — manual override,
|
|
125
|
-
* distinct from the automatic failJob() path.
|
|
125
|
+
* distinct from the automatic failJob() path. Cleans up BOTH the
|
|
126
|
+
* reservation record AND any dead-letter file for this id, so a caller
|
|
127
|
+
* that iterates deadLetters() and calls .retry() on each doesn't leave
|
|
128
|
+
* the failed/ directory carrying duplicates (PY-12-05, 3.13.105).
|
|
129
|
+
* Aligns with retry(queue, jobId) which had always unlinked the
|
|
130
|
+
* dead-letter file -- two spellings of the same intent that previously
|
|
131
|
+
* diverged.
|
|
126
132
|
*/
|
|
127
133
|
retryJob(queue: string, job: QueueJob, delaySeconds?: number): void;
|
|
128
134
|
}
|
|
@@ -87,8 +87,13 @@ export declare class MongoBackend implements QueueBackend {
|
|
|
87
87
|
* retries remain, else dead-letter. Mirrors the file/lite backend.
|
|
88
88
|
*/
|
|
89
89
|
fail(queue: string, id: string, error: string, maxRetries: number, retryBackoff?: number): void;
|
|
90
|
-
/**
|
|
91
|
-
|
|
90
|
+
/**
|
|
91
|
+
* Revive a specific dead-letter job by id. Returns true if the DL was found
|
|
92
|
+
* and revived, false otherwise (parity with LiteBackend.retry(queue, id)
|
|
93
|
+
* and Python's mongo_backend.retry_job()). Pre-3.13.105 this returned void
|
|
94
|
+
* and Queue.retry(id) reported success for every call, even for unknown ids.
|
|
95
|
+
*/
|
|
96
|
+
retry(queue: string, id: string, delaySeconds?: number): boolean;
|
|
92
97
|
/** Jobs that exceeded max retries (the `<queue>.dead_letter` collection topic). */
|
|
93
98
|
deadLetters(queue: string, maxRetries?: number): QueueJob[];
|
|
94
99
|
/** Jobs that failed but are still eligible for retry (status=failed, attempts < max). */
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { Router } from "./router.js";
|
|
2
|
+
export declare class SsoError extends Error {
|
|
3
|
+
}
|
|
4
|
+
type Json = Record<string, any>;
|
|
5
|
+
export interface SsoOptions {
|
|
6
|
+
issuer?: string;
|
|
7
|
+
clientId?: string;
|
|
8
|
+
clientSecret?: string;
|
|
9
|
+
redirectUri?: string;
|
|
10
|
+
scopes?: string[];
|
|
11
|
+
verify?: "introspection" | "jwks";
|
|
12
|
+
postLogoutRedirectUri?: string;
|
|
13
|
+
claimMap?: Record<string, string>;
|
|
14
|
+
timeout?: number;
|
|
15
|
+
}
|
|
16
|
+
export declare class Sso {
|
|
17
|
+
static readonly PENDING_KEY = "_tina4_sso_pending";
|
|
18
|
+
static readonly SESSION_KEY = "_tina4_sso";
|
|
19
|
+
readonly issuer: string;
|
|
20
|
+
readonly clientId: string;
|
|
21
|
+
readonly clientSecret?: string;
|
|
22
|
+
readonly redirectUri: string;
|
|
23
|
+
readonly scopes: string[];
|
|
24
|
+
readonly verify: "introspection" | "jwks";
|
|
25
|
+
readonly postLogoutRedirectUri?: string;
|
|
26
|
+
readonly claimMap: Record<string, string>;
|
|
27
|
+
readonly timeout: number;
|
|
28
|
+
private metadata;
|
|
29
|
+
private static mountedRouters;
|
|
30
|
+
constructor(options?: SsoOptions);
|
|
31
|
+
static fromIssuer(options?: SsoOptions): Promise<Sso>;
|
|
32
|
+
static configured(): boolean;
|
|
33
|
+
private jsonEnv;
|
|
34
|
+
private static secureUrl;
|
|
35
|
+
private validateConfig;
|
|
36
|
+
private requestJson;
|
|
37
|
+
discover(force?: boolean): Promise<Json>;
|
|
38
|
+
static safeReturn(value?: string): string;
|
|
39
|
+
private session;
|
|
40
|
+
login(requestOrSession: any, returnTo?: string): Promise<string>;
|
|
41
|
+
private static equal;
|
|
42
|
+
private static jwtPayload;
|
|
43
|
+
private introspect;
|
|
44
|
+
private claim;
|
|
45
|
+
private normalize;
|
|
46
|
+
callback(requestOrSession: any, query?: Json): Promise<{
|
|
47
|
+
identity: Json;
|
|
48
|
+
return_to: string;
|
|
49
|
+
}>;
|
|
50
|
+
identity(requestOrSession: any): Json | null;
|
|
51
|
+
refresh(requestOrSession: any): Promise<Json>;
|
|
52
|
+
logout(requestOrSession: any, returnTo?: string): Promise<string>;
|
|
53
|
+
static mountConfigured(router: Router): Promise<boolean>;
|
|
54
|
+
}
|
|
55
|
+
export { Sso as SSO };
|
|
@@ -271,6 +271,8 @@ export declare class BaseModel {
|
|
|
271
271
|
* @param case_ Key casing: 'camel' (default, keys as-is) or 'snake' (convert via fieldMapping).
|
|
272
272
|
*/
|
|
273
273
|
toDict(include?: string[], case_?: "camel" | "snake"): Record<string, unknown>;
|
|
274
|
+
toFeature(geometryField?: string, include?: string[]): Record<string, unknown>;
|
|
275
|
+
static featureCollection(models: BaseModel[], geometryField?: string, include?: string[]): Record<string, unknown>;
|
|
274
276
|
/**
|
|
275
277
|
* Convert to an associative object (alias for toDict).
|
|
276
278
|
*/
|
|
@@ -302,6 +304,7 @@ export declare class BaseModel {
|
|
|
302
304
|
* Uses the adapter's createTable method if available, otherwise builds SQL directly.
|
|
303
305
|
*/
|
|
304
306
|
static createTable(): Promise<boolean>;
|
|
307
|
+
private static createSpatialIndexes;
|
|
305
308
|
/**
|
|
306
309
|
* Find a record by primary key or throw an error if not found.
|
|
307
310
|
*/
|
|
@@ -336,11 +339,16 @@ export declare class BaseModel {
|
|
|
336
339
|
/**
|
|
337
340
|
* Invalidate every cached query that touches this model's table.
|
|
338
341
|
*
|
|
339
|
-
* Tag-scoped
|
|
340
|
-
* this table is busted too
|
|
341
|
-
* never touches this table is left intact
|
|
342
|
-
*
|
|
343
|
-
*
|
|
342
|
+
* Tag-scoped in the ORM layer (a cached JOIN on another model that reads
|
|
343
|
+
* this table is busted too because it carries this table's tag; a query
|
|
344
|
+
* that never touches this table is left intact), then cascaded to the
|
|
345
|
+
* DB layer on this model's bound connection so an out-of-band write /
|
|
346
|
+
* deliberate refresh / race-with-another-process cannot leave stale rows
|
|
347
|
+
* in db.fetch()'s persistent cache. Called after every ORM write
|
|
348
|
+
* (save/delete/forceDelete/restore) so a read-after-write never serves
|
|
349
|
+
* a stale/deleted row (CACHE-DEC-01). PY-06-22 (3.13.105) added the
|
|
350
|
+
* DB-layer cascade -- previously the two cache layers disagreed under
|
|
351
|
+
* TINA4_AUTO_CACHING=true + TINA4_DB_CACHE=true.
|
|
344
352
|
*/
|
|
345
353
|
static clearCache(): void;
|
|
346
354
|
/**
|
package/types/orm/src/index.d.ts
CHANGED
|
@@ -19,6 +19,8 @@ export type { ValidationError } from "./validation.js";
|
|
|
19
19
|
export { BaseModel, snakeToCamel, camelToSnake } from "./baseModel.js";
|
|
20
20
|
export { QueryBuilder } from "./queryBuilder.js";
|
|
21
21
|
export { SQLTranslator, QueryCache } from "./sqlTranslator.js";
|
|
22
|
+
export { Point, SpatialNotSupportedError, DEFAULT_SRID } from "./point.js";
|
|
23
|
+
export type { GeoJsonPoint } from "./point.js";
|
|
22
24
|
export { DEFAULT_DATABASE_CONNECT_TIMEOUT_SECONDS, CONNECT_TIMEOUT_TOLERANCE_MS, connectTimeoutMillis, driverConnectTimeoutMillis, connectTarget, withConnectTimeout, } from "./connectTimeout.js";
|
|
23
25
|
export { CachedDatabaseAdapter } from "./cachedDatabase.js";
|
|
24
26
|
export type { CachedAdapterOptions } from "./cachedDatabase.js";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare const DEFAULT_SRID = 4326;
|
|
2
|
+
export declare class SpatialNotSupportedError extends Error {
|
|
3
|
+
constructor(message: string);
|
|
4
|
+
}
|
|
5
|
+
export type GeoJsonPoint = {
|
|
6
|
+
type: "Point";
|
|
7
|
+
coordinates: [number, number];
|
|
8
|
+
};
|
|
9
|
+
/** Immutable SRID-aware longitude/latitude point (ADR-0057). */
|
|
10
|
+
export declare class Point {
|
|
11
|
+
readonly lon: number;
|
|
12
|
+
readonly lat: number;
|
|
13
|
+
readonly srid: number;
|
|
14
|
+
constructor(lon: unknown, lat: unknown, srid?: unknown);
|
|
15
|
+
get wkt(): string;
|
|
16
|
+
get ewkt(): string;
|
|
17
|
+
get geojson(): GeoJsonPoint;
|
|
18
|
+
toJSON(): GeoJsonPoint;
|
|
19
|
+
toArray(): [number, number];
|
|
20
|
+
static parse(value: unknown, srid?: number): Point;
|
|
21
|
+
static geometryBinding(value: unknown, srid?: number): [string, "ewkt" | "geojson"];
|
|
22
|
+
private static fromGeoJson;
|
|
23
|
+
private static fromWkb;
|
|
24
|
+
}
|
|
@@ -22,6 +22,7 @@ export declare class QueryBuilder {
|
|
|
22
22
|
private table;
|
|
23
23
|
private db;
|
|
24
24
|
private columns;
|
|
25
|
+
private selectParams;
|
|
25
26
|
private wheres;
|
|
26
27
|
private params;
|
|
27
28
|
private joinClauses;
|
|
@@ -29,6 +30,8 @@ export declare class QueryBuilder {
|
|
|
29
30
|
private havings;
|
|
30
31
|
private havingParams;
|
|
31
32
|
private orderByCols;
|
|
33
|
+
private orderByParams;
|
|
34
|
+
private primaryKey;
|
|
32
35
|
private limitVal;
|
|
33
36
|
private offsetVal;
|
|
34
37
|
/**
|
|
@@ -42,7 +45,7 @@ export declare class QueryBuilder {
|
|
|
42
45
|
* @param db - Optional database adapter.
|
|
43
46
|
* @returns A new QueryBuilder instance.
|
|
44
47
|
*/
|
|
45
|
-
static fromTable(tableName: string, db?: DatabaseAdapter): QueryBuilder;
|
|
48
|
+
static fromTable(tableName: string, db?: DatabaseAdapter, primaryKey?: string): QueryBuilder;
|
|
46
49
|
/**
|
|
47
50
|
* Set the columns to select.
|
|
48
51
|
*
|
|
@@ -104,6 +107,11 @@ export declare class QueryBuilder {
|
|
|
104
107
|
* @returns this for chaining.
|
|
105
108
|
*/
|
|
106
109
|
orderBy(expression: string): QueryBuilder;
|
|
110
|
+
withinDistance(column: string, pointValue: unknown, radiusMetres: number, srid?: number): QueryBuilder;
|
|
111
|
+
intersects(column: string, geometry: unknown, srid?: number): QueryBuilder;
|
|
112
|
+
bbox(column: string, minLon: unknown, minLat: unknown, maxLon: unknown, maxLat: unknown, srid?: number): QueryBuilder;
|
|
113
|
+
selectDistance(column: string, pointValue: unknown, alias?: string, srid?: number): QueryBuilder;
|
|
114
|
+
orderByDistance(column: string, pointValue: unknown, direction?: "ASC" | "DESC", srid?: number): QueryBuilder;
|
|
107
115
|
/**
|
|
108
116
|
* Set LIMIT and optional OFFSET.
|
|
109
117
|
*
|
|
@@ -190,4 +198,5 @@ export declare class QueryBuilder {
|
|
|
190
198
|
* Ensure a database adapter is available.
|
|
191
199
|
*/
|
|
192
200
|
private ensureDb;
|
|
201
|
+
private engine;
|
|
193
202
|
}
|
|
@@ -17,6 +17,19 @@
|
|
|
17
17
|
* Also includes a query cache with TTL support.
|
|
18
18
|
*/
|
|
19
19
|
export declare class SQLTranslator {
|
|
20
|
+
private static readonly SPATIAL_ENGINES;
|
|
21
|
+
private static readonly SPATIAL_IDENTIFIER;
|
|
22
|
+
static requireSpatial(engine: string, feature: string): string;
|
|
23
|
+
static spatialIdentifier(name: string, what?: string): string;
|
|
24
|
+
static pointColumnType(engine: string, srid?: number): string;
|
|
25
|
+
static spatialIndex(engine: string, table: string, column: string): string;
|
|
26
|
+
static pointLiteral(engine: string, srid?: number): string;
|
|
27
|
+
static withinDistance(engine: string, column: string, srid?: number): string;
|
|
28
|
+
static distance(engine: string, column: string, srid?: number): string;
|
|
29
|
+
static distanceAs(engine: string, column: string, alias: string, srid?: number): string;
|
|
30
|
+
static geometryLiteral(engine: string, form: "ewkt" | "geojson", srid?: number): string;
|
|
31
|
+
static intersects(engine: string, column: string, form?: "ewkt" | "geojson", srid?: number): string;
|
|
32
|
+
static bbox(engine: string, column: string, srid?: number): string;
|
|
20
33
|
/**
|
|
21
34
|
* Convert LIMIT/OFFSET to Firebird ROWS...TO syntax.
|
|
22
35
|
*
|
package/types/orm/src/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type FieldType = "string" | "integer" | "number" | "numeric" | "decimal" | "boolean" | "datetime" | "text" | "json" | "foreignKey";
|
|
1
|
+
export type FieldType = "string" | "integer" | "number" | "numeric" | "decimal" | "boolean" | "datetime" | "text" | "json" | "foreignKey" | "point";
|
|
2
2
|
export interface FieldDefinition {
|
|
3
3
|
type: FieldType;
|
|
4
4
|
primaryKey?: boolean;
|
|
@@ -23,6 +23,10 @@ export interface FieldDefinition {
|
|
|
23
23
|
references?: string;
|
|
24
24
|
/** For type "foreignKey": override the has-many property name on the referenced model */
|
|
25
25
|
relatedName?: string;
|
|
26
|
+
/** For type "point": spatial reference id (default WGS 84 / 4326). */
|
|
27
|
+
srid?: number;
|
|
28
|
+
/** For type "point": create the provider's spatial index (default true). */
|
|
29
|
+
spatialIndex?: boolean;
|
|
26
30
|
}
|
|
27
31
|
export interface RelationshipDefinition {
|
|
28
32
|
model: string;
|