@atscript/db 0.1.110 → 0.1.111
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/dist/{db-view-CHprAlvK.mjs → db-view-BllUecjK.mjs} +32 -5
- package/dist/{db-view-BIbH65VE.cjs → db-view-UfGVUAol.cjs} +37 -4
- package/dist/index.cjs +2 -1
- package/dist/index.d.cts +15 -1
- package/dist/index.d.mts +15 -1
- package/dist/index.mjs +2 -2
- package/dist/plugin.cjs +37 -2
- package/dist/plugin.mjs +37 -2
- package/dist/shared.cjs +1 -1
- package/dist/shared.mjs +1 -1
- package/dist/sync.cjs +2 -1
- package/dist/sync.d.cts +6 -1
- package/dist/sync.d.mts +6 -1
- package/dist/sync.mjs +2 -1
- package/dist/{validation-utils-CR4H3_nc.cjs → validation-utils-B7SXPkm7.cjs} +1 -0
- package/dist/{validation-utils-D4R08oed.mjs → validation-utils-MWOP1Ts4.mjs} +1 -0
- package/package.json +6 -6
|
@@ -2101,6 +2101,31 @@ var NativeIntegrity = class extends IntegrityStrategy {
|
|
|
2101
2101
|
}
|
|
2102
2102
|
};
|
|
2103
2103
|
//#endregion
|
|
2104
|
+
//#region src/shared/failure-collector.ts
|
|
2105
|
+
/**
|
|
2106
|
+
* Collects failures from a batch of independent operations so one failing
|
|
2107
|
+
* operation (e.g. CREATE UNIQUE INDEX over duplicate rows) doesn't abort the
|
|
2108
|
+
* rest. Run every operation through `attempt`, then call `throwIfAny()` to
|
|
2109
|
+
* rethrow the collected failures as a single aggregate error — so the caller
|
|
2110
|
+
* (schema sync) still marks the entry errored and skips persisting the schema
|
|
2111
|
+
* hash, and the next boot retries.
|
|
2112
|
+
*/
|
|
2113
|
+
function createFailureCollector(what) {
|
|
2114
|
+
const failures = [];
|
|
2115
|
+
return {
|
|
2116
|
+
attempt: async (label, op) => {
|
|
2117
|
+
try {
|
|
2118
|
+
await op();
|
|
2119
|
+
} catch (error) {
|
|
2120
|
+
failures.push(`${label}: ${error.message}`);
|
|
2121
|
+
}
|
|
2122
|
+
},
|
|
2123
|
+
throwIfAny: () => {
|
|
2124
|
+
if (failures.length > 0) throw new Error(`${what} failed for ${failures.length} operation(s): ${failures.join("; ")}`);
|
|
2125
|
+
}
|
|
2126
|
+
};
|
|
2127
|
+
}
|
|
2128
|
+
//#endregion
|
|
2104
2129
|
//#region src/base-adapter.ts
|
|
2105
2130
|
const EMPTY_DEFAULT_FNS = /* @__PURE__ */ new Set();
|
|
2106
2131
|
const txStorage = new AsyncLocalStorage();
|
|
@@ -2387,6 +2412,7 @@ var BaseDbAdapter = class {
|
|
|
2387
2412
|
const existingNames = new Set(managed.map((i) => i.name));
|
|
2388
2413
|
const existingColumns = new Map(managed.filter((i) => i.columns).map((i) => [i.name, i.columns]));
|
|
2389
2414
|
const desiredNames = /* @__PURE__ */ new Set();
|
|
2415
|
+
const { attempt, throwIfAny } = createFailureCollector("index sync");
|
|
2390
2416
|
for (const index of this._table.indexes.values()) {
|
|
2391
2417
|
if (opts.warnUnsupportedTypes?.types.includes(index.type)) {
|
|
2392
2418
|
this.logger.warn(`[${opts.warnUnsupportedTypes.adapter}] ${index.type} index "${index.name}" declared but not supported by this adapter — skipped`);
|
|
@@ -2395,19 +2421,20 @@ var BaseDbAdapter = class {
|
|
|
2395
2421
|
if (opts.shouldSkipType?.(index.type)) continue;
|
|
2396
2422
|
desiredNames.add(index.key);
|
|
2397
2423
|
if (!existingNames.has(index.key)) {
|
|
2398
|
-
await opts.createIndex(index);
|
|
2424
|
+
await attempt(`create index "${index.key}"`, () => opts.createIndex(index));
|
|
2399
2425
|
continue;
|
|
2400
2426
|
}
|
|
2401
2427
|
if (index.type === "plain" || index.type === "unique") {
|
|
2402
2428
|
const liveColumns = existingColumns.get(index.key);
|
|
2403
2429
|
const desiredColumns = index.fields.map((f) => f.name);
|
|
2404
|
-
if (liveColumns && (liveColumns.length !== desiredColumns.length || liveColumns.some((c, i) => c !== desiredColumns[i]))) {
|
|
2430
|
+
if (liveColumns && (liveColumns.length !== desiredColumns.length || liveColumns.some((c, i) => c !== desiredColumns[i]))) await attempt(`rebuild index "${index.key}"`, async () => {
|
|
2405
2431
|
await opts.dropIndex(index.key);
|
|
2406
2432
|
await opts.createIndex(index);
|
|
2407
|
-
}
|
|
2433
|
+
});
|
|
2408
2434
|
}
|
|
2409
2435
|
}
|
|
2410
|
-
for (const name of existingNames) if (!desiredNames.has(name)) await opts.dropIndex(name);
|
|
2436
|
+
for (const name of existingNames) if (!desiredNames.has(name)) await attempt(`drop index "${name}"`, () => opts.dropIndex(name));
|
|
2437
|
+
throwIfAny();
|
|
2411
2438
|
}
|
|
2412
2439
|
/**
|
|
2413
2440
|
* Returns available search indexes for this adapter.
|
|
@@ -3678,4 +3705,4 @@ var AtscriptDbView = class extends AtscriptDbReadable {
|
|
|
3678
3705
|
}
|
|
3679
3706
|
};
|
|
3680
3707
|
//#endregion
|
|
3681
|
-
export { NoopLogger as S,
|
|
3708
|
+
export { NoopLogger as C, isGeoPointType as S, DocumentFieldMapper as _, ApplicationIntegrity as a, TableMetadata as b, IntegrityStrategy as c, resolveDesignType as d, assertGeoPoint as f, RelationalFieldMapper as g, guardQuery as h, decomposePatch as i, NativeIntegrity as l, guardFilter as m, AtscriptDbTable as n, BaseDbAdapter as o, guardAggregate as p, assertNoVersionWrites as r, createFailureCollector as s, AtscriptDbView as t, AtscriptDbReadable as u, FieldMappingStrategy as v, isGeoIndexableType as x, UniquSelect as y };
|
|
@@ -2101,6 +2101,31 @@ var NativeIntegrity = class extends IntegrityStrategy {
|
|
|
2101
2101
|
}
|
|
2102
2102
|
};
|
|
2103
2103
|
//#endregion
|
|
2104
|
+
//#region src/shared/failure-collector.ts
|
|
2105
|
+
/**
|
|
2106
|
+
* Collects failures from a batch of independent operations so one failing
|
|
2107
|
+
* operation (e.g. CREATE UNIQUE INDEX over duplicate rows) doesn't abort the
|
|
2108
|
+
* rest. Run every operation through `attempt`, then call `throwIfAny()` to
|
|
2109
|
+
* rethrow the collected failures as a single aggregate error — so the caller
|
|
2110
|
+
* (schema sync) still marks the entry errored and skips persisting the schema
|
|
2111
|
+
* hash, and the next boot retries.
|
|
2112
|
+
*/
|
|
2113
|
+
function createFailureCollector(what) {
|
|
2114
|
+
const failures = [];
|
|
2115
|
+
return {
|
|
2116
|
+
attempt: async (label, op) => {
|
|
2117
|
+
try {
|
|
2118
|
+
await op();
|
|
2119
|
+
} catch (error) {
|
|
2120
|
+
failures.push(`${label}: ${error.message}`);
|
|
2121
|
+
}
|
|
2122
|
+
},
|
|
2123
|
+
throwIfAny: () => {
|
|
2124
|
+
if (failures.length > 0) throw new Error(`${what} failed for ${failures.length} operation(s): ${failures.join("; ")}`);
|
|
2125
|
+
}
|
|
2126
|
+
};
|
|
2127
|
+
}
|
|
2128
|
+
//#endregion
|
|
2104
2129
|
//#region src/base-adapter.ts
|
|
2105
2130
|
const EMPTY_DEFAULT_FNS = /* @__PURE__ */ new Set();
|
|
2106
2131
|
const txStorage = new node_async_hooks.AsyncLocalStorage();
|
|
@@ -2387,6 +2412,7 @@ var BaseDbAdapter = class {
|
|
|
2387
2412
|
const existingNames = new Set(managed.map((i) => i.name));
|
|
2388
2413
|
const existingColumns = new Map(managed.filter((i) => i.columns).map((i) => [i.name, i.columns]));
|
|
2389
2414
|
const desiredNames = /* @__PURE__ */ new Set();
|
|
2415
|
+
const { attempt, throwIfAny } = createFailureCollector("index sync");
|
|
2390
2416
|
for (const index of this._table.indexes.values()) {
|
|
2391
2417
|
if (opts.warnUnsupportedTypes?.types.includes(index.type)) {
|
|
2392
2418
|
this.logger.warn(`[${opts.warnUnsupportedTypes.adapter}] ${index.type} index "${index.name}" declared but not supported by this adapter — skipped`);
|
|
@@ -2395,19 +2421,20 @@ var BaseDbAdapter = class {
|
|
|
2395
2421
|
if (opts.shouldSkipType?.(index.type)) continue;
|
|
2396
2422
|
desiredNames.add(index.key);
|
|
2397
2423
|
if (!existingNames.has(index.key)) {
|
|
2398
|
-
await opts.createIndex(index);
|
|
2424
|
+
await attempt(`create index "${index.key}"`, () => opts.createIndex(index));
|
|
2399
2425
|
continue;
|
|
2400
2426
|
}
|
|
2401
2427
|
if (index.type === "plain" || index.type === "unique") {
|
|
2402
2428
|
const liveColumns = existingColumns.get(index.key);
|
|
2403
2429
|
const desiredColumns = index.fields.map((f) => f.name);
|
|
2404
|
-
if (liveColumns && (liveColumns.length !== desiredColumns.length || liveColumns.some((c, i) => c !== desiredColumns[i]))) {
|
|
2430
|
+
if (liveColumns && (liveColumns.length !== desiredColumns.length || liveColumns.some((c, i) => c !== desiredColumns[i]))) await attempt(`rebuild index "${index.key}"`, async () => {
|
|
2405
2431
|
await opts.dropIndex(index.key);
|
|
2406
2432
|
await opts.createIndex(index);
|
|
2407
|
-
}
|
|
2433
|
+
});
|
|
2408
2434
|
}
|
|
2409
2435
|
}
|
|
2410
|
-
for (const name of existingNames) if (!desiredNames.has(name)) await opts.dropIndex(name);
|
|
2436
|
+
for (const name of existingNames) if (!desiredNames.has(name)) await attempt(`drop index "${name}"`, () => opts.dropIndex(name));
|
|
2437
|
+
throwIfAny();
|
|
2411
2438
|
}
|
|
2412
2439
|
/**
|
|
2413
2440
|
* Returns available search indexes for this adapter.
|
|
@@ -3768,6 +3795,12 @@ Object.defineProperty(exports, "assertNoVersionWrites", {
|
|
|
3768
3795
|
return assertNoVersionWrites;
|
|
3769
3796
|
}
|
|
3770
3797
|
});
|
|
3798
|
+
Object.defineProperty(exports, "createFailureCollector", {
|
|
3799
|
+
enumerable: true,
|
|
3800
|
+
get: function() {
|
|
3801
|
+
return createFailureCollector;
|
|
3802
|
+
}
|
|
3803
|
+
});
|
|
3771
3804
|
Object.defineProperty(exports, "decomposePatch", {
|
|
3772
3805
|
enumerable: true,
|
|
3773
3806
|
get: function() {
|
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_db_error = require("./db-error-DXwEzmYJ.cjs");
|
|
3
|
-
const require_db_view = require("./db-view-
|
|
3
|
+
const require_db_view = require("./db-view-UfGVUAol.cjs");
|
|
4
4
|
const require_ops = require("./ops.cjs");
|
|
5
5
|
const require_validator = require("./validator-BSk8lPH1.cjs");
|
|
6
6
|
let node_crypto = require("node:crypto");
|
|
@@ -377,6 +377,7 @@ Object.defineProperty(exports, "computeInsights", {
|
|
|
377
377
|
}
|
|
378
378
|
});
|
|
379
379
|
exports.createDbValidatorPlugin = require_validator.createDbValidatorPlugin;
|
|
380
|
+
exports.createFailureCollector = require_db_view.createFailureCollector;
|
|
380
381
|
exports.decomposePatch = require_db_view.decomposePatch;
|
|
381
382
|
exports.forceNavNonOptional = require_validator.forceNavNonOptional;
|
|
382
383
|
exports.getDbFieldOp = require_ops.getDbFieldOp;
|
package/dist/index.d.cts
CHANGED
|
@@ -215,4 +215,18 @@ declare function decomposePatch(payload: Record<string, unknown>, table: Atscrip
|
|
|
215
215
|
*/
|
|
216
216
|
declare function assertNoVersionWrites(data: Record<string, unknown>, versionColumn: string): void;
|
|
217
217
|
//#endregion
|
|
218
|
-
|
|
218
|
+
//#region src/shared/failure-collector.d.ts
|
|
219
|
+
/**
|
|
220
|
+
* Collects failures from a batch of independent operations so one failing
|
|
221
|
+
* operation (e.g. CREATE UNIQUE INDEX over duplicate rows) doesn't abort the
|
|
222
|
+
* rest. Run every operation through `attempt`, then call `throwIfAny()` to
|
|
223
|
+
* rethrow the collected failures as a single aggregate error — so the caller
|
|
224
|
+
* (schema sync) still marks the entry errored and skips persisting the schema
|
|
225
|
+
* hash, and the next boot retries.
|
|
226
|
+
*/
|
|
227
|
+
declare function createFailureCollector(what: string): {
|
|
228
|
+
attempt: (label: string, op: () => Promise<unknown>) => Promise<void>;
|
|
229
|
+
throwIfAny: () => void;
|
|
230
|
+
};
|
|
231
|
+
//#endregion
|
|
232
|
+
export { $cas, $dec, $inc, $insert, $mul, $remove, $replace, $update, $upsert, type AggregateControls, type AggregateExpr, type AggregateFn, type AggregateQuery, type AggregateResult, ApplicationIntegrity, AtscriptDbReadable, AtscriptDbTable, AtscriptDbView, type AtscriptDbWritable, type AtscriptQueryComparison, type AtscriptQueryFieldRef, type AtscriptQueryNode, type AtscriptRef, BaseDbAdapter, CasExhaustedError, type DbControls, DbEncryption, DbError, type DbErrorCode, type DbQuery, type DbResponse, DbSpace, type DbValidationContext, DocumentFieldMapper, FieldMappingStrategy, type FieldOpsFor, type FilterExpr, type FilterVisitor, type FlatOf, IntegrityStrategy, NativeIntegrity, type NavPropsOf, NoopLogger, type OwnPropsOf, type PrimaryKeyOf, RelationalFieldMapper, type TAdapterFactory, type TArrayPatch, type TCascadeResolver, type TCascadeTarget, type TColumnDiff, type TCrudOp, type TCrudPermissions, type TDbActionInfo, type TDbActionIntent, type TDbActionLevel, type TDbActionProcessor, type TDbCas, type TDbCollation, type TDbDefaultFn, type TDbDefaultValue, type TDbDeleteResult, type TDbEncryptionOptions, type TDbFieldMeta, type TDbFieldOp, type TDbForeignKey, type TDbIndex, type TDbIndexField, type TDbIndexType, type TDbInsertManyResult, type TDbInsertResult, type TDbPatch, type TDbReferentialAction, type TDbRelation, type TDbSpaceOptions, type TDbStorageType, type TDbUpdateResult, type TExistingColumn, type TExistingTableOption, type TFieldMeta, type TFieldOps, type TFkLookupResolver, type TFkLookupTarget, type TGenericLogger, type TIdDescriptor, type TIdentification, type TMetaResponse, type TMetadataOverrides, type TRelationInfo, type TSearchIndexInfo, type TSyncColumnResult, type TTableOptionDiff, type TTableResolver, type TValueFormatterPair, type TViewColumnMapping, type TViewJoin, type TViewPlan, type TWriteTableResolver, TableMetadata, type TypedWithRelation, UniquSelect, type Uniquery, type UniqueryControls, type ValidationContext, type ValidatorMode, type WithOptimisticRetryOptions, type WithRelation, assertGeoPoint, assertNoVersionWrites, buildDbValidator, buildValidationContext, computeInsights, createDbValidatorPlugin, createFailureCollector, decomposePatch, forceNavNonOptional, getDbFieldOp, getKeyProps, guardAggregate, guardFilter, guardQuery, isDbFieldOp, isGeoIndexableType, isGeoPointType, isNavRelation, isPrimitive, resolveDesignType, separateCas, separateFieldOps, translateQueryTree, walkFilter, withOptimisticRetry };
|
package/dist/index.d.mts
CHANGED
|
@@ -215,4 +215,18 @@ declare function decomposePatch(payload: Record<string, unknown>, table: Atscrip
|
|
|
215
215
|
*/
|
|
216
216
|
declare function assertNoVersionWrites(data: Record<string, unknown>, versionColumn: string): void;
|
|
217
217
|
//#endregion
|
|
218
|
-
|
|
218
|
+
//#region src/shared/failure-collector.d.ts
|
|
219
|
+
/**
|
|
220
|
+
* Collects failures from a batch of independent operations so one failing
|
|
221
|
+
* operation (e.g. CREATE UNIQUE INDEX over duplicate rows) doesn't abort the
|
|
222
|
+
* rest. Run every operation through `attempt`, then call `throwIfAny()` to
|
|
223
|
+
* rethrow the collected failures as a single aggregate error — so the caller
|
|
224
|
+
* (schema sync) still marks the entry errored and skips persisting the schema
|
|
225
|
+
* hash, and the next boot retries.
|
|
226
|
+
*/
|
|
227
|
+
declare function createFailureCollector(what: string): {
|
|
228
|
+
attempt: (label: string, op: () => Promise<unknown>) => Promise<void>;
|
|
229
|
+
throwIfAny: () => void;
|
|
230
|
+
};
|
|
231
|
+
//#endregion
|
|
232
|
+
export { $cas, $dec, $inc, $insert, $mul, $remove, $replace, $update, $upsert, type AggregateControls, type AggregateExpr, type AggregateFn, type AggregateQuery, type AggregateResult, ApplicationIntegrity, AtscriptDbReadable, AtscriptDbTable, AtscriptDbView, type AtscriptDbWritable, type AtscriptQueryComparison, type AtscriptQueryFieldRef, type AtscriptQueryNode, type AtscriptRef, BaseDbAdapter, CasExhaustedError, type DbControls, DbEncryption, DbError, type DbErrorCode, type DbQuery, type DbResponse, DbSpace, type DbValidationContext, DocumentFieldMapper, FieldMappingStrategy, type FieldOpsFor, type FilterExpr, type FilterVisitor, type FlatOf, IntegrityStrategy, NativeIntegrity, type NavPropsOf, NoopLogger, type OwnPropsOf, type PrimaryKeyOf, RelationalFieldMapper, type TAdapterFactory, type TArrayPatch, type TCascadeResolver, type TCascadeTarget, type TColumnDiff, type TCrudOp, type TCrudPermissions, type TDbActionInfo, type TDbActionIntent, type TDbActionLevel, type TDbActionProcessor, type TDbCas, type TDbCollation, type TDbDefaultFn, type TDbDefaultValue, type TDbDeleteResult, type TDbEncryptionOptions, type TDbFieldMeta, type TDbFieldOp, type TDbForeignKey, type TDbIndex, type TDbIndexField, type TDbIndexType, type TDbInsertManyResult, type TDbInsertResult, type TDbPatch, type TDbReferentialAction, type TDbRelation, type TDbSpaceOptions, type TDbStorageType, type TDbUpdateResult, type TExistingColumn, type TExistingTableOption, type TFieldMeta, type TFieldOps, type TFkLookupResolver, type TFkLookupTarget, type TGenericLogger, type TIdDescriptor, type TIdentification, type TMetaResponse, type TMetadataOverrides, type TRelationInfo, type TSearchIndexInfo, type TSyncColumnResult, type TTableOptionDiff, type TTableResolver, type TValueFormatterPair, type TViewColumnMapping, type TViewJoin, type TViewPlan, type TWriteTableResolver, TableMetadata, type TypedWithRelation, UniquSelect, type Uniquery, type UniqueryControls, type ValidationContext, type ValidatorMode, type WithOptimisticRetryOptions, type WithRelation, assertGeoPoint, assertNoVersionWrites, buildDbValidator, buildValidationContext, computeInsights, createDbValidatorPlugin, createFailureCollector, decomposePatch, forceNavNonOptional, getDbFieldOp, getKeyProps, guardAggregate, guardFilter, guardQuery, isDbFieldOp, isGeoIndexableType, isGeoPointType, isNavRelation, isPrimitive, resolveDesignType, separateCas, separateFieldOps, translateQueryTree, walkFilter, withOptimisticRetry };
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as DbError, t as CasExhaustedError } from "./db-error-BHPXOKzc.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { C as NoopLogger, S as isGeoPointType, _ as DocumentFieldMapper, a as ApplicationIntegrity, b as TableMetadata, c as IntegrityStrategy, d as resolveDesignType, f as assertGeoPoint, g as RelationalFieldMapper, h as guardQuery, i as decomposePatch, l as NativeIntegrity, m as guardFilter, n as AtscriptDbTable, o as BaseDbAdapter, p as guardAggregate, r as assertNoVersionWrites, s as createFailureCollector, t as AtscriptDbView, u as AtscriptDbReadable, v as FieldMappingStrategy, x as isGeoIndexableType, y as UniquSelect } from "./db-view-BllUecjK.mjs";
|
|
3
3
|
import { $cas, $dec, $inc, $insert, $mul, $remove, $replace, $update, $upsert, getDbFieldOp, isDbFieldOp, separateCas, separateFieldOps } from "./ops.mjs";
|
|
4
4
|
import { a as isNavRelation, i as forceNavNonOptional, n as buildValidationContext, o as createDbValidatorPlugin, s as getKeyProps, t as buildDbValidator } from "./validator-C7plt6Kf.mjs";
|
|
5
5
|
import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
|
|
@@ -339,4 +339,4 @@ function translateQueryTree(node, resolveField) {
|
|
|
339
339
|
return { [leftField]: { [comp.op]: comp.right } };
|
|
340
340
|
}
|
|
341
341
|
//#endregion
|
|
342
|
-
export { $cas, $dec, $inc, $insert, $mul, $remove, $replace, $update, $upsert, ApplicationIntegrity, AtscriptDbReadable, AtscriptDbTable, AtscriptDbView, BaseDbAdapter, CasExhaustedError, DbEncryption, DbError, DbSpace, DocumentFieldMapper, FieldMappingStrategy, IntegrityStrategy, NativeIntegrity, NoopLogger, RelationalFieldMapper, TableMetadata, UniquSelect, assertGeoPoint, assertNoVersionWrites, buildDbValidator, buildValidationContext, computeInsights, createDbValidatorPlugin, decomposePatch, forceNavNonOptional, getDbFieldOp, getKeyProps, guardAggregate, guardFilter, guardQuery, isDbFieldOp, isGeoIndexableType, isGeoPointType, isNavRelation, isPrimitive, resolveDesignType, separateCas, separateFieldOps, translateQueryTree, walkFilter, withOptimisticRetry };
|
|
342
|
+
export { $cas, $dec, $inc, $insert, $mul, $remove, $replace, $update, $upsert, ApplicationIntegrity, AtscriptDbReadable, AtscriptDbTable, AtscriptDbView, BaseDbAdapter, CasExhaustedError, DbEncryption, DbError, DbSpace, DocumentFieldMapper, FieldMappingStrategy, IntegrityStrategy, NativeIntegrity, NoopLogger, RelationalFieldMapper, TableMetadata, UniquSelect, assertGeoPoint, assertNoVersionWrites, buildDbValidator, buildValidationContext, computeInsights, createDbValidatorPlugin, createFailureCollector, decomposePatch, forceNavNonOptional, getDbFieldOp, getKeyProps, guardAggregate, guardFilter, guardQuery, isDbFieldOp, isGeoIndexableType, isGeoPointType, isNavRelation, isPrimitive, resolveDesignType, separateCas, separateFieldOps, translateQueryTree, walkFilter, withOptimisticRetry };
|
package/dist/plugin.cjs
CHANGED
|
@@ -2,13 +2,14 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_validation_utils = require("./validation-utils-
|
|
5
|
+
const require_validation_utils = require("./validation-utils-B7SXPkm7.cjs");
|
|
6
6
|
let _atscript_core = require("@atscript/core");
|
|
7
7
|
//#region src/plugin/annotations/agg.ts
|
|
8
8
|
const dbAggAnnotations = { agg: {
|
|
9
9
|
sum: new _atscript_core.AnnotationSpec({
|
|
10
10
|
description: "Declares a view field as SUM of a source column.",
|
|
11
11
|
nodeType: ["prop"],
|
|
12
|
+
passedWhenReferred: false,
|
|
12
13
|
argument: {
|
|
13
14
|
name: "field",
|
|
14
15
|
type: "string",
|
|
@@ -21,6 +22,7 @@ const dbAggAnnotations = { agg: {
|
|
|
21
22
|
avg: new _atscript_core.AnnotationSpec({
|
|
22
23
|
description: "Declares a view field as AVG of a source column.",
|
|
23
24
|
nodeType: ["prop"],
|
|
25
|
+
passedWhenReferred: false,
|
|
24
26
|
argument: {
|
|
25
27
|
name: "field",
|
|
26
28
|
type: "string",
|
|
@@ -33,6 +35,7 @@ const dbAggAnnotations = { agg: {
|
|
|
33
35
|
count: new _atscript_core.AnnotationSpec({
|
|
34
36
|
description: "Declares a view field as COUNT. Without argument: COUNT(*). With field name argument: COUNT(field) (non-null count).",
|
|
35
37
|
nodeType: ["prop"],
|
|
38
|
+
passedWhenReferred: false,
|
|
36
39
|
argument: {
|
|
37
40
|
name: "field",
|
|
38
41
|
type: "string",
|
|
@@ -46,6 +49,7 @@ const dbAggAnnotations = { agg: {
|
|
|
46
49
|
min: new _atscript_core.AnnotationSpec({
|
|
47
50
|
description: "Declares a view field as MIN of a source column.",
|
|
48
51
|
nodeType: ["prop"],
|
|
52
|
+
passedWhenReferred: false,
|
|
49
53
|
argument: {
|
|
50
54
|
name: "field",
|
|
51
55
|
type: "string",
|
|
@@ -55,6 +59,7 @@ const dbAggAnnotations = { agg: {
|
|
|
55
59
|
max: new _atscript_core.AnnotationSpec({
|
|
56
60
|
description: "Declares a view field as MAX of a source column.",
|
|
57
61
|
nodeType: ["prop"],
|
|
62
|
+
passedWhenReferred: false,
|
|
58
63
|
argument: {
|
|
59
64
|
name: "field",
|
|
60
65
|
type: "string",
|
|
@@ -94,6 +99,7 @@ const dbAmountAnnotations = { amount: { currency: {
|
|
|
94
99
|
ref: new _atscript_core.AnnotationSpec({
|
|
95
100
|
description: "Binds this amount to a **sibling field** that holds its currency code. Use when each row may have a different currency.\n\nThe referenced field should be of type `db.currencyCode` (or at least a `string`).\n\nOnly valid on `decimal` fields.\n\n**Example:**\n```atscript\ncurrency: db.currencyCode\n@db.amount.currency.ref 'currency'\namount: decimal\n```\n",
|
|
96
101
|
nodeType: ["prop"],
|
|
102
|
+
passedWhenReferred: false,
|
|
97
103
|
multiple: false,
|
|
98
104
|
argument: {
|
|
99
105
|
name: "fieldName",
|
|
@@ -121,6 +127,7 @@ const dbColumnAnnotations = {
|
|
|
121
127
|
patch: { strategy: new _atscript_core.AnnotationSpec({
|
|
122
128
|
description: "Defines the **patching strategy** for updating nested objects.\n\n- **\"replace\"** → The field or object will be **fully replaced**.\n- **\"merge\"** → The field or object will be **merged recursively** (applies only to objects, not arrays).\n\n**Example:**\n```atscript\n@db.patch.strategy \"merge\"\nsettings: {\n notifications: boolean\n preferences: {\n theme: string\n }\n}\n```\n",
|
|
123
129
|
nodeType: ["prop"],
|
|
130
|
+
passedWhenReferred: false,
|
|
124
131
|
multiple: false,
|
|
125
132
|
argument: {
|
|
126
133
|
name: "strategy",
|
|
@@ -150,6 +157,7 @@ const dbColumnAnnotations = {
|
|
|
150
157
|
$self: new _atscript_core.AnnotationSpec({
|
|
151
158
|
description: "Overrides the physical column name in the database. For nested (flattened) fields, the parent prefix is still prepended automatically.\n\n**Example:**\n```atscript\n@db.column \"first_name\"\nfirstName: string\n// → physical column: first_name\n\n// Nested:\naddress: {\n @db.column \"zip_code\"\n zip: string\n}\n// → physical column: address__zip_code\n```\n",
|
|
152
159
|
nodeType: ["prop"],
|
|
160
|
+
passedWhenReferred: false,
|
|
153
161
|
argument: {
|
|
154
162
|
name: "name",
|
|
155
163
|
type: "string",
|
|
@@ -159,6 +167,7 @@ const dbColumnAnnotations = {
|
|
|
159
167
|
renamed: new _atscript_core.AnnotationSpec({
|
|
160
168
|
description: "Specifies the previous local field name for column rename migration. The sync engine generates ALTER TABLE RENAME COLUMN instead of drop+add.\n\n**Example:**\n```atscript\n@db.column.renamed \"zip\"\npostalCode: string\n// Renames address__zip → address__postalCode\n```\n",
|
|
161
169
|
nodeType: ["prop"],
|
|
170
|
+
passedWhenReferred: false,
|
|
162
171
|
argument: {
|
|
163
172
|
name: "oldName",
|
|
164
173
|
type: "string",
|
|
@@ -168,6 +177,7 @@ const dbColumnAnnotations = {
|
|
|
168
177
|
collate: new _atscript_core.AnnotationSpec({
|
|
169
178
|
description: "Portable collation for string comparison and sorting. Adapters map the generic value to their native collation.\n\n- **\"binary\"** — exact byte comparison (case-sensitive)\n- **\"nocase\"** — case-insensitive comparison\n- **\"unicode\"** — full Unicode-aware sorting\n\nFor adapter-specific collations, use `@db.<engine>.collate` instead.\n\n**Example:**\n```atscript\n@db.column.collate \"nocase\"\nusername: string\n```\n",
|
|
170
179
|
nodeType: ["prop"],
|
|
180
|
+
passedWhenReferred: false,
|
|
171
181
|
argument: {
|
|
172
182
|
name: "collation",
|
|
173
183
|
type: "string",
|
|
@@ -185,6 +195,7 @@ const dbColumnAnnotations = {
|
|
|
185
195
|
precision: new _atscript_core.AnnotationSpec({
|
|
186
196
|
description: "Sets decimal precision and scale for database storage. Adapters map this to their native decimal type (e.g., `DECIMAL(10,2)` in SQL, ignored in MongoDB).\n\nFor `decimal` fields the runtime value is a string; for `number` fields this is a DB storage hint only.\n\n**Example:**\n```atscript\n@db.column.precision 10, 2\nprice: decimal\n```\n",
|
|
187
197
|
nodeType: ["prop"],
|
|
198
|
+
passedWhenReferred: false,
|
|
188
199
|
argument: [{
|
|
189
200
|
name: "precision",
|
|
190
201
|
type: "number",
|
|
@@ -200,11 +211,13 @@ const dbColumnAnnotations = {
|
|
|
200
211
|
}),
|
|
201
212
|
dimension: new _atscript_core.AnnotationSpec({
|
|
202
213
|
description: "Marks a field as a dimension — groupable in aggregate queries ($groupBy). Dimension fields automatically receive a database index during schema sync.",
|
|
203
|
-
nodeType: ["prop"]
|
|
214
|
+
nodeType: ["prop"],
|
|
215
|
+
passedWhenReferred: false
|
|
204
216
|
}),
|
|
205
217
|
measure: new _atscript_core.AnnotationSpec({
|
|
206
218
|
description: "Marks a field as a measure — aggregatable in aggregate queries (sum, avg, count, min, max). Only valid on numeric or decimal fields.",
|
|
207
219
|
nodeType: ["prop"],
|
|
220
|
+
passedWhenReferred: false,
|
|
208
221
|
validate(token, _args, doc) {
|
|
209
222
|
return require_validation_utils.validateFieldBaseType(token, doc, "@db.column.measure", ["number", "decimal"]);
|
|
210
223
|
}
|
|
@@ -214,6 +227,7 @@ const dbColumnAnnotations = {
|
|
|
214
227
|
version: new _atscript_core.AnnotationSpec({
|
|
215
228
|
description: "Marks a numeric column as the row's version for optimistic concurrency control (OCC). The adapter auto-increments this column on every UPDATE, and callers may pass `$cas: { <col>: N }` in a write payload to make the update conditional on the current version. Direct writes to the version column (as plain SET, `$inc`, or `$mul`) are rejected.\n\n**Constraints:**\n- At most one version column per table.\n- Must resolve to an integer type (`int`, `int32`, `int64`, etc.).\n- Default value on insert is `0`.\n\n**Example:**\n```atscript\n@db.column.version\nversion: int\n```\n",
|
|
216
229
|
nodeType: ["prop"],
|
|
230
|
+
passedWhenReferred: false,
|
|
217
231
|
validate(token, _args, doc) {
|
|
218
232
|
const errors = require_validation_utils.validateFieldBaseType(token, doc, "@db.column.version", "number");
|
|
219
233
|
if (token.parentNode.has("optional")) errors.push({
|
|
@@ -239,6 +253,7 @@ const dbColumnAnnotations = {
|
|
|
239
253
|
$self: new _atscript_core.AnnotationSpec({
|
|
240
254
|
description: "Sets a static DB-level default value (used in DDL DEFAULT clause). For string fields the value is used as-is; for other types it is parsed as JSON.\n\n**Example:**\n```atscript\n@db.default \"active\"\nstatus: string\n```\n",
|
|
241
255
|
nodeType: ["prop"],
|
|
256
|
+
passedWhenReferred: false,
|
|
242
257
|
argument: {
|
|
243
258
|
name: "value",
|
|
244
259
|
type: "string",
|
|
@@ -248,6 +263,7 @@ const dbColumnAnnotations = {
|
|
|
248
263
|
increment: new _atscript_core.AnnotationSpec({
|
|
249
264
|
description: "Auto-incrementing integer default. Each adapter maps this to its native mechanism (e.g., `AUTO_INCREMENT` in MySQL, `INTEGER PRIMARY KEY` in SQLite, counter collection in MongoDB).\n\n**Example:**\n```atscript\n@db.default.increment\nid: number.int\n\n// With optional start value:\n@db.default.increment 1000\nid: number.int\n```\n",
|
|
250
265
|
nodeType: ["prop"],
|
|
266
|
+
passedWhenReferred: false,
|
|
251
267
|
argument: {
|
|
252
268
|
optional: true,
|
|
253
269
|
name: "start",
|
|
@@ -261,6 +277,7 @@ const dbColumnAnnotations = {
|
|
|
261
277
|
uuid: new _atscript_core.AnnotationSpec({
|
|
262
278
|
description: "UUID generation default. Each adapter maps this to its native mechanism (e.g., `DEFAULT (UUID())` in MySQL, `gen_random_uuid()` in PostgreSQL, app-level in SQLite).\n\n**Example:**\n```atscript\n@db.default.uuid\nid: string.uuid\n```\n",
|
|
263
279
|
nodeType: ["prop"],
|
|
280
|
+
passedWhenReferred: false,
|
|
264
281
|
validate(token, args, doc) {
|
|
265
282
|
return require_validation_utils.validateFieldBaseType(token, doc, "db.default.uuid", "string");
|
|
266
283
|
}
|
|
@@ -268,6 +285,7 @@ const dbColumnAnnotations = {
|
|
|
268
285
|
now: new _atscript_core.AnnotationSpec({
|
|
269
286
|
description: "Current timestamp default. Each adapter maps this to its native mechanism (e.g., `DEFAULT CURRENT_TIMESTAMP` in MySQL, `DEFAULT now()` in PostgreSQL).\n\n**Example:**\n```atscript\n@db.default.now\ncreatedAt: number.timestamp\n```\n",
|
|
270
287
|
nodeType: ["prop"],
|
|
288
|
+
passedWhenReferred: false,
|
|
271
289
|
validate(token, args, doc) {
|
|
272
290
|
return require_validation_utils.validateFieldBaseType(token, doc, "db.default.now", ["number", "string"]);
|
|
273
291
|
}
|
|
@@ -276,6 +294,7 @@ const dbColumnAnnotations = {
|
|
|
276
294
|
json: new _atscript_core.AnnotationSpec({
|
|
277
295
|
description: "Forces a field to be stored as a single JSON column instead of being flattened into separate columns. Use on nested object fields that should remain as JSON in the database.\n\n**Example:**\n```atscript\n@db.json\nmetadata: { key: string, value: string }\n```\n",
|
|
278
296
|
nodeType: ["prop"],
|
|
297
|
+
passedWhenReferred: false,
|
|
279
298
|
validate(token, _args, doc) {
|
|
280
299
|
const errors = [];
|
|
281
300
|
const definition = token.parentNode.getDefinition();
|
|
@@ -293,6 +312,7 @@ const dbColumnAnnotations = {
|
|
|
293
312
|
ignore: new _atscript_core.AnnotationSpec({
|
|
294
313
|
description: "Excludes a field from the database schema. The field exists in the Atscript type but has no column in the DB.\n\n**Example:**\n```atscript\n@db.ignore\ndisplayName: string\n```\n",
|
|
295
314
|
nodeType: ["prop"],
|
|
315
|
+
passedWhenReferred: false,
|
|
296
316
|
validate(token, _args, _doc) {
|
|
297
317
|
const errors = [];
|
|
298
318
|
if (token.parentNode.countAnnotations("meta.id") > 0) errors.push({
|
|
@@ -306,6 +326,7 @@ const dbColumnAnnotations = {
|
|
|
306
326
|
encrypted: new _atscript_core.AnnotationSpec({
|
|
307
327
|
description: "Encrypts this field at rest. Values are AES-256-GCM encrypted by the core layer before reaching the database and decrypted on read — transparent to application code.\n\nConstraints: the field cannot be filtered, sorted, indexed, used as PK/FK, patched with arithmetic ops, or referenced by search/vector/geo features.\n\n**Example:**\n```atscript\n@db.encrypted\napiToken?: string\n```\n",
|
|
308
328
|
nodeType: ["prop"],
|
|
329
|
+
passedWhenReferred: false,
|
|
309
330
|
multiple: false,
|
|
310
331
|
validate(token, _args, _doc) {
|
|
311
332
|
const errors = [];
|
|
@@ -344,6 +365,7 @@ function columnCapability(capability, verb) {
|
|
|
344
365
|
@db.table.${capability} "manual"\nexport interface User {
|
|
345
366
|
` + example + "}\n```\n",
|
|
346
367
|
nodeType: ["prop"],
|
|
368
|
+
passedWhenReferred: false,
|
|
347
369
|
multiple: false,
|
|
348
370
|
validate(token, _args, _doc) {
|
|
349
371
|
const errors = [];
|
|
@@ -363,6 +385,7 @@ const dbIndexAnnotations = { index: {
|
|
|
363
385
|
plain: new _atscript_core.AnnotationSpec({
|
|
364
386
|
description: "Standard (non-unique) index for query performance. Fields sharing the same index name form a composite index.\n\n**Example:**\n```atscript\n@db.index.plain \"idx_timeline\", \"desc\"\ncreatedAt: number.timestamp\n```\n",
|
|
365
387
|
nodeType: ["prop"],
|
|
388
|
+
passedWhenReferred: false,
|
|
366
389
|
multiple: true,
|
|
367
390
|
mergeStrategy: "append",
|
|
368
391
|
argument: [{
|
|
@@ -381,6 +404,7 @@ const dbIndexAnnotations = { index: {
|
|
|
381
404
|
unique: new _atscript_core.AnnotationSpec({
|
|
382
405
|
description: "Unique index — ensures no two rows/documents have the same value(s). Fields sharing the same index name form a composite unique constraint.\n\n**Example:**\n```atscript\n@db.index.unique \"tenant_email\"\nemail: string.email\n```\n",
|
|
383
406
|
nodeType: ["prop"],
|
|
407
|
+
passedWhenReferred: false,
|
|
384
408
|
multiple: true,
|
|
385
409
|
mergeStrategy: "append",
|
|
386
410
|
argument: {
|
|
@@ -393,6 +417,7 @@ const dbIndexAnnotations = { index: {
|
|
|
393
417
|
fulltext: new _atscript_core.AnnotationSpec({
|
|
394
418
|
description: "Full-text search index. Fields sharing the same index name form a composite full-text index.\n\n**Example:**\n```atscript\n@db.index.fulltext \"ft_content\"\ntitle: string\n\n@db.index.fulltext \"ft_content\", 5\nbio: string\n```\n",
|
|
395
419
|
nodeType: ["prop"],
|
|
420
|
+
passedWhenReferred: false,
|
|
396
421
|
multiple: true,
|
|
397
422
|
mergeStrategy: "append",
|
|
398
423
|
argument: [{
|
|
@@ -410,6 +435,7 @@ const dbIndexAnnotations = { index: {
|
|
|
410
435
|
geo: new _atscript_core.AnnotationSpec({
|
|
411
436
|
description: "Geospatial index on a `db.geoPoint` field. Enables `geoSearch()` (distance-ranked) and accelerates `$geoWithin` filters.\n\n**Example:**\n```atscript\n@db.index.geo\ngeo: db.geoPoint\n```\n",
|
|
412
437
|
nodeType: ["prop"],
|
|
438
|
+
passedWhenReferred: false,
|
|
413
439
|
multiple: false,
|
|
414
440
|
argument: {
|
|
415
441
|
optional: true,
|
|
@@ -425,6 +451,7 @@ const dbRelAnnotations = { rel: {
|
|
|
425
451
|
FK: new _atscript_core.AnnotationSpec({
|
|
426
452
|
description: "Declares a foreign key reference on this field. The field must use a chain reference type (e.g., `User.id`) whose target is a primary key (`@meta.id`) or unique (`@db.index.unique`) field.\n\n**Dual role:**\n- On a `@db.table` interface, `@db.rel.FK` additionally drives DB-relation semantics — relation loading with `@db.rel.to` / `@db.rel.from`, junction pairing with `@db.rel.via`, etc.\n- On any other interface (value-help sources, WF forms, plain interfaces), `@db.rel.FK` acts purely as the value-help indicator: the client-side picker resolver uses it to decide which fields render a value-help picker. The target's `@db.http.path` (stamped by its readable controller) supplies the picker URL.\n\n**Example:**\n```atscript\n@db.rel.FK\nauthorId: User.id\n\n// With alias (required when multiple FKs point to the same type)\n@db.rel.FK \"author\"\nauthorId: User.id\n```\n",
|
|
427
453
|
nodeType: ["prop"],
|
|
454
|
+
passedWhenReferred: false,
|
|
428
455
|
argument: {
|
|
429
456
|
optional: true,
|
|
430
457
|
name: "alias",
|
|
@@ -509,6 +536,7 @@ const dbRelAnnotations = { rel: {
|
|
|
509
536
|
to: new _atscript_core.AnnotationSpec({
|
|
510
537
|
description: "Forward navigational property — the FK is on **this** interface. The compiler resolves the matching @db.rel.FK by target type or alias.\n\n**Example:**\n```atscript\n@db.rel.to\nauthor?: User\n\n// With alias\n@db.rel.to \"author\"\nauthor?: User\n```\n",
|
|
511
538
|
nodeType: ["prop"],
|
|
539
|
+
passedWhenReferred: false,
|
|
512
540
|
argument: {
|
|
513
541
|
optional: true,
|
|
514
542
|
name: "alias",
|
|
@@ -592,6 +620,7 @@ const dbRelAnnotations = { rel: {
|
|
|
592
620
|
from: new _atscript_core.AnnotationSpec({
|
|
593
621
|
description: "Inverse navigational property — the FK is on the **target** interface, pointing back to this one.\n\n**Example:**\n```atscript\n@db.rel.from\nposts: Post[]\n\n// With alias\n@db.rel.from \"original\"\ncomments: Comment[]\n```\n",
|
|
594
622
|
nodeType: ["prop"],
|
|
623
|
+
passedWhenReferred: false,
|
|
595
624
|
argument: {
|
|
596
625
|
optional: true,
|
|
597
626
|
name: "alias",
|
|
@@ -680,6 +709,7 @@ const dbRelAnnotations = { rel: {
|
|
|
680
709
|
via: new _atscript_core.AnnotationSpec({
|
|
681
710
|
description: "Declares a many-to-many navigational property through an explicit junction table. `@db.rel.via` is self-sufficient — no `@db.rel.from` pairing is needed.\n\n**Example:**\n```atscript\n@db.rel.via PostTag\ntags: Tag[]\n```\n",
|
|
682
711
|
nodeType: ["prop"],
|
|
712
|
+
passedWhenReferred: false,
|
|
683
713
|
argument: {
|
|
684
714
|
name: "junction",
|
|
685
715
|
type: "ref",
|
|
@@ -739,6 +769,7 @@ const dbRelAnnotations = { rel: {
|
|
|
739
769
|
filter: new _atscript_core.AnnotationSpec({
|
|
740
770
|
description: "Applies a filter to a navigational property, restricting which related records are loaded.\n\n**Example:**\n```atscript\n@db.rel.from\n@db.rel.filter `Post.published = true`\npublishedPosts: Post[]\n```\n",
|
|
741
771
|
nodeType: ["prop"],
|
|
772
|
+
passedWhenReferred: false,
|
|
742
773
|
argument: {
|
|
743
774
|
name: "condition",
|
|
744
775
|
type: "query",
|
|
@@ -778,6 +809,7 @@ const dbSearchAnnotations = { search: {
|
|
|
778
809
|
$self: new _atscript_core.AnnotationSpec({
|
|
779
810
|
description: "Marks a field as a **vector embedding** for **similarity search**.\n\n- Each adapter maps this to its native vector type and index:\n - **MongoDB** → Atlas `$vectorSearch` index\n - **MySQL 9+** → `VECTOR(N)` column + `VEC_DISTANCE_*` functions\n - **PostgreSQL** → pgvector `vector(N)` column + distance operators\n - **SQLite** → `BLOB` column + `vec0` virtual index (requires the `sqlite-vec` extension; falls back to JSON `TEXT` when unavailable)\n\n**Example:**\n```atscript\n@db.search.vector 1536, \"cosine\"\nembedding: db.vector\n```\n",
|
|
780
811
|
nodeType: ["prop"],
|
|
812
|
+
passedWhenReferred: false,
|
|
781
813
|
multiple: false,
|
|
782
814
|
argument: [
|
|
783
815
|
{
|
|
@@ -822,6 +854,7 @@ const dbSearchAnnotations = { search: {
|
|
|
822
854
|
threshold: new _atscript_core.AnnotationSpec({
|
|
823
855
|
description: "Sets a **default minimum similarity threshold** for vector search queries on this field.\n\n- Results with a similarity score below this threshold are excluded.\n- Query-time `$threshold` control overrides this default.\n- Value range: `0` to `1` (where `1` means exact match).\n\n**Example:**\n```atscript\n@db.search.vector 1536, \"cosine\"\n@db.search.vector.threshold 0.7\nembedding: db.vector\n```\n",
|
|
824
856
|
nodeType: ["prop"],
|
|
857
|
+
passedWhenReferred: false,
|
|
825
858
|
multiple: false,
|
|
826
859
|
argument: {
|
|
827
860
|
optional: false,
|
|
@@ -834,6 +867,7 @@ const dbSearchAnnotations = { search: {
|
|
|
834
867
|
filter: new _atscript_core.AnnotationSpec({
|
|
835
868
|
description: "Assigns a field as a **pre-filter** for a **vector search index**.\n\n- Filters allow vector search queries to return results only within a specific subset.\n- The referenced index must be defined using `@db.search.vector`.\n\n**Example:**\n```atscript\n@db.search.vector 1536, \"cosine\"\nembedding: db.vector\n\n@db.search.filter \"embedding\"\ncategory: string\n```\n",
|
|
836
869
|
nodeType: ["prop"],
|
|
870
|
+
passedWhenReferred: false,
|
|
837
871
|
multiple: true,
|
|
838
872
|
argument: {
|
|
839
873
|
optional: false,
|
|
@@ -1074,6 +1108,7 @@ const dbUnitAnnotations = { unit: {
|
|
|
1074
1108
|
ref: new _atscript_core.AnnotationSpec({
|
|
1075
1109
|
description: "Binds this quantity to a **sibling field** that holds its unit. Use when different rows may carry different units (e.g. mixed kg/lb measurements).\n\nThe referenced field must be a `string`.\n\nValid on `decimal` and `number` fields. Aggregating this field forces the referenced unit field into `$groupBy` at runtime — summing rows with different units is rejected.\n\n**Example:**\n```atscript\nunit: string\n@db.unit.ref 'unit'\nweight: decimal\n```\n",
|
|
1076
1110
|
nodeType: ["prop"],
|
|
1111
|
+
passedWhenReferred: false,
|
|
1077
1112
|
multiple: false,
|
|
1078
1113
|
argument: {
|
|
1079
1114
|
name: "fieldName",
|
package/dist/plugin.mjs
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { a as getAnnotationAlias, c as getParentStruct, d as validateExclusiveWith, f as validateFieldBaseType, i as validateRefArgument, l as getParentTypeName, n as hasAnyViewAnnotation, o as getDbTableOwner, p as validateSiblingStringField, r as validateQueryScope, s as getNavTargetTypeName, t as findFKFieldsPointingTo, u as refActionAnnotation } from "./validation-utils-
|
|
1
|
+
import { a as getAnnotationAlias, c as getParentStruct, d as validateExclusiveWith, f as validateFieldBaseType, i as validateRefArgument, l as getParentTypeName, n as hasAnyViewAnnotation, o as getDbTableOwner, p as validateSiblingStringField, r as validateQueryScope, s as getNavTargetTypeName, t as findFKFieldsPointingTo, u as refActionAnnotation } from "./validation-utils-MWOP1Ts4.mjs";
|
|
2
2
|
import { AnnotationSpec, isArray, isInterface, isPrimitive, isRef, isStructure } from "@atscript/core";
|
|
3
3
|
//#region src/plugin/annotations/agg.ts
|
|
4
4
|
const dbAggAnnotations = { agg: {
|
|
5
5
|
sum: new AnnotationSpec({
|
|
6
6
|
description: "Declares a view field as SUM of a source column.",
|
|
7
7
|
nodeType: ["prop"],
|
|
8
|
+
passedWhenReferred: false,
|
|
8
9
|
argument: {
|
|
9
10
|
name: "field",
|
|
10
11
|
type: "string",
|
|
@@ -17,6 +18,7 @@ const dbAggAnnotations = { agg: {
|
|
|
17
18
|
avg: new AnnotationSpec({
|
|
18
19
|
description: "Declares a view field as AVG of a source column.",
|
|
19
20
|
nodeType: ["prop"],
|
|
21
|
+
passedWhenReferred: false,
|
|
20
22
|
argument: {
|
|
21
23
|
name: "field",
|
|
22
24
|
type: "string",
|
|
@@ -29,6 +31,7 @@ const dbAggAnnotations = { agg: {
|
|
|
29
31
|
count: new AnnotationSpec({
|
|
30
32
|
description: "Declares a view field as COUNT. Without argument: COUNT(*). With field name argument: COUNT(field) (non-null count).",
|
|
31
33
|
nodeType: ["prop"],
|
|
34
|
+
passedWhenReferred: false,
|
|
32
35
|
argument: {
|
|
33
36
|
name: "field",
|
|
34
37
|
type: "string",
|
|
@@ -42,6 +45,7 @@ const dbAggAnnotations = { agg: {
|
|
|
42
45
|
min: new AnnotationSpec({
|
|
43
46
|
description: "Declares a view field as MIN of a source column.",
|
|
44
47
|
nodeType: ["prop"],
|
|
48
|
+
passedWhenReferred: false,
|
|
45
49
|
argument: {
|
|
46
50
|
name: "field",
|
|
47
51
|
type: "string",
|
|
@@ -51,6 +55,7 @@ const dbAggAnnotations = { agg: {
|
|
|
51
55
|
max: new AnnotationSpec({
|
|
52
56
|
description: "Declares a view field as MAX of a source column.",
|
|
53
57
|
nodeType: ["prop"],
|
|
58
|
+
passedWhenReferred: false,
|
|
54
59
|
argument: {
|
|
55
60
|
name: "field",
|
|
56
61
|
type: "string",
|
|
@@ -90,6 +95,7 @@ const dbAmountAnnotations = { amount: { currency: {
|
|
|
90
95
|
ref: new AnnotationSpec({
|
|
91
96
|
description: "Binds this amount to a **sibling field** that holds its currency code. Use when each row may have a different currency.\n\nThe referenced field should be of type `db.currencyCode` (or at least a `string`).\n\nOnly valid on `decimal` fields.\n\n**Example:**\n```atscript\ncurrency: db.currencyCode\n@db.amount.currency.ref 'currency'\namount: decimal\n```\n",
|
|
92
97
|
nodeType: ["prop"],
|
|
98
|
+
passedWhenReferred: false,
|
|
93
99
|
multiple: false,
|
|
94
100
|
argument: {
|
|
95
101
|
name: "fieldName",
|
|
@@ -117,6 +123,7 @@ const dbColumnAnnotations = {
|
|
|
117
123
|
patch: { strategy: new AnnotationSpec({
|
|
118
124
|
description: "Defines the **patching strategy** for updating nested objects.\n\n- **\"replace\"** → The field or object will be **fully replaced**.\n- **\"merge\"** → The field or object will be **merged recursively** (applies only to objects, not arrays).\n\n**Example:**\n```atscript\n@db.patch.strategy \"merge\"\nsettings: {\n notifications: boolean\n preferences: {\n theme: string\n }\n}\n```\n",
|
|
119
125
|
nodeType: ["prop"],
|
|
126
|
+
passedWhenReferred: false,
|
|
120
127
|
multiple: false,
|
|
121
128
|
argument: {
|
|
122
129
|
name: "strategy",
|
|
@@ -146,6 +153,7 @@ const dbColumnAnnotations = {
|
|
|
146
153
|
$self: new AnnotationSpec({
|
|
147
154
|
description: "Overrides the physical column name in the database. For nested (flattened) fields, the parent prefix is still prepended automatically.\n\n**Example:**\n```atscript\n@db.column \"first_name\"\nfirstName: string\n// → physical column: first_name\n\n// Nested:\naddress: {\n @db.column \"zip_code\"\n zip: string\n}\n// → physical column: address__zip_code\n```\n",
|
|
148
155
|
nodeType: ["prop"],
|
|
156
|
+
passedWhenReferred: false,
|
|
149
157
|
argument: {
|
|
150
158
|
name: "name",
|
|
151
159
|
type: "string",
|
|
@@ -155,6 +163,7 @@ const dbColumnAnnotations = {
|
|
|
155
163
|
renamed: new AnnotationSpec({
|
|
156
164
|
description: "Specifies the previous local field name for column rename migration. The sync engine generates ALTER TABLE RENAME COLUMN instead of drop+add.\n\n**Example:**\n```atscript\n@db.column.renamed \"zip\"\npostalCode: string\n// Renames address__zip → address__postalCode\n```\n",
|
|
157
165
|
nodeType: ["prop"],
|
|
166
|
+
passedWhenReferred: false,
|
|
158
167
|
argument: {
|
|
159
168
|
name: "oldName",
|
|
160
169
|
type: "string",
|
|
@@ -164,6 +173,7 @@ const dbColumnAnnotations = {
|
|
|
164
173
|
collate: new AnnotationSpec({
|
|
165
174
|
description: "Portable collation for string comparison and sorting. Adapters map the generic value to their native collation.\n\n- **\"binary\"** — exact byte comparison (case-sensitive)\n- **\"nocase\"** — case-insensitive comparison\n- **\"unicode\"** — full Unicode-aware sorting\n\nFor adapter-specific collations, use `@db.<engine>.collate` instead.\n\n**Example:**\n```atscript\n@db.column.collate \"nocase\"\nusername: string\n```\n",
|
|
166
175
|
nodeType: ["prop"],
|
|
176
|
+
passedWhenReferred: false,
|
|
167
177
|
argument: {
|
|
168
178
|
name: "collation",
|
|
169
179
|
type: "string",
|
|
@@ -181,6 +191,7 @@ const dbColumnAnnotations = {
|
|
|
181
191
|
precision: new AnnotationSpec({
|
|
182
192
|
description: "Sets decimal precision and scale for database storage. Adapters map this to their native decimal type (e.g., `DECIMAL(10,2)` in SQL, ignored in MongoDB).\n\nFor `decimal` fields the runtime value is a string; for `number` fields this is a DB storage hint only.\n\n**Example:**\n```atscript\n@db.column.precision 10, 2\nprice: decimal\n```\n",
|
|
183
193
|
nodeType: ["prop"],
|
|
194
|
+
passedWhenReferred: false,
|
|
184
195
|
argument: [{
|
|
185
196
|
name: "precision",
|
|
186
197
|
type: "number",
|
|
@@ -196,11 +207,13 @@ const dbColumnAnnotations = {
|
|
|
196
207
|
}),
|
|
197
208
|
dimension: new AnnotationSpec({
|
|
198
209
|
description: "Marks a field as a dimension — groupable in aggregate queries ($groupBy). Dimension fields automatically receive a database index during schema sync.",
|
|
199
|
-
nodeType: ["prop"]
|
|
210
|
+
nodeType: ["prop"],
|
|
211
|
+
passedWhenReferred: false
|
|
200
212
|
}),
|
|
201
213
|
measure: new AnnotationSpec({
|
|
202
214
|
description: "Marks a field as a measure — aggregatable in aggregate queries (sum, avg, count, min, max). Only valid on numeric or decimal fields.",
|
|
203
215
|
nodeType: ["prop"],
|
|
216
|
+
passedWhenReferred: false,
|
|
204
217
|
validate(token, _args, doc) {
|
|
205
218
|
return validateFieldBaseType(token, doc, "@db.column.measure", ["number", "decimal"]);
|
|
206
219
|
}
|
|
@@ -210,6 +223,7 @@ const dbColumnAnnotations = {
|
|
|
210
223
|
version: new AnnotationSpec({
|
|
211
224
|
description: "Marks a numeric column as the row's version for optimistic concurrency control (OCC). The adapter auto-increments this column on every UPDATE, and callers may pass `$cas: { <col>: N }` in a write payload to make the update conditional on the current version. Direct writes to the version column (as plain SET, `$inc`, or `$mul`) are rejected.\n\n**Constraints:**\n- At most one version column per table.\n- Must resolve to an integer type (`int`, `int32`, `int64`, etc.).\n- Default value on insert is `0`.\n\n**Example:**\n```atscript\n@db.column.version\nversion: int\n```\n",
|
|
212
225
|
nodeType: ["prop"],
|
|
226
|
+
passedWhenReferred: false,
|
|
213
227
|
validate(token, _args, doc) {
|
|
214
228
|
const errors = validateFieldBaseType(token, doc, "@db.column.version", "number");
|
|
215
229
|
if (token.parentNode.has("optional")) errors.push({
|
|
@@ -235,6 +249,7 @@ const dbColumnAnnotations = {
|
|
|
235
249
|
$self: new AnnotationSpec({
|
|
236
250
|
description: "Sets a static DB-level default value (used in DDL DEFAULT clause). For string fields the value is used as-is; for other types it is parsed as JSON.\n\n**Example:**\n```atscript\n@db.default \"active\"\nstatus: string\n```\n",
|
|
237
251
|
nodeType: ["prop"],
|
|
252
|
+
passedWhenReferred: false,
|
|
238
253
|
argument: {
|
|
239
254
|
name: "value",
|
|
240
255
|
type: "string",
|
|
@@ -244,6 +259,7 @@ const dbColumnAnnotations = {
|
|
|
244
259
|
increment: new AnnotationSpec({
|
|
245
260
|
description: "Auto-incrementing integer default. Each adapter maps this to its native mechanism (e.g., `AUTO_INCREMENT` in MySQL, `INTEGER PRIMARY KEY` in SQLite, counter collection in MongoDB).\n\n**Example:**\n```atscript\n@db.default.increment\nid: number.int\n\n// With optional start value:\n@db.default.increment 1000\nid: number.int\n```\n",
|
|
246
261
|
nodeType: ["prop"],
|
|
262
|
+
passedWhenReferred: false,
|
|
247
263
|
argument: {
|
|
248
264
|
optional: true,
|
|
249
265
|
name: "start",
|
|
@@ -257,6 +273,7 @@ const dbColumnAnnotations = {
|
|
|
257
273
|
uuid: new AnnotationSpec({
|
|
258
274
|
description: "UUID generation default. Each adapter maps this to its native mechanism (e.g., `DEFAULT (UUID())` in MySQL, `gen_random_uuid()` in PostgreSQL, app-level in SQLite).\n\n**Example:**\n```atscript\n@db.default.uuid\nid: string.uuid\n```\n",
|
|
259
275
|
nodeType: ["prop"],
|
|
276
|
+
passedWhenReferred: false,
|
|
260
277
|
validate(token, args, doc) {
|
|
261
278
|
return validateFieldBaseType(token, doc, "db.default.uuid", "string");
|
|
262
279
|
}
|
|
@@ -264,6 +281,7 @@ const dbColumnAnnotations = {
|
|
|
264
281
|
now: new AnnotationSpec({
|
|
265
282
|
description: "Current timestamp default. Each adapter maps this to its native mechanism (e.g., `DEFAULT CURRENT_TIMESTAMP` in MySQL, `DEFAULT now()` in PostgreSQL).\n\n**Example:**\n```atscript\n@db.default.now\ncreatedAt: number.timestamp\n```\n",
|
|
266
283
|
nodeType: ["prop"],
|
|
284
|
+
passedWhenReferred: false,
|
|
267
285
|
validate(token, args, doc) {
|
|
268
286
|
return validateFieldBaseType(token, doc, "db.default.now", ["number", "string"]);
|
|
269
287
|
}
|
|
@@ -272,6 +290,7 @@ const dbColumnAnnotations = {
|
|
|
272
290
|
json: new AnnotationSpec({
|
|
273
291
|
description: "Forces a field to be stored as a single JSON column instead of being flattened into separate columns. Use on nested object fields that should remain as JSON in the database.\n\n**Example:**\n```atscript\n@db.json\nmetadata: { key: string, value: string }\n```\n",
|
|
274
292
|
nodeType: ["prop"],
|
|
293
|
+
passedWhenReferred: false,
|
|
275
294
|
validate(token, _args, doc) {
|
|
276
295
|
const errors = [];
|
|
277
296
|
const definition = token.parentNode.getDefinition();
|
|
@@ -289,6 +308,7 @@ const dbColumnAnnotations = {
|
|
|
289
308
|
ignore: new AnnotationSpec({
|
|
290
309
|
description: "Excludes a field from the database schema. The field exists in the Atscript type but has no column in the DB.\n\n**Example:**\n```atscript\n@db.ignore\ndisplayName: string\n```\n",
|
|
291
310
|
nodeType: ["prop"],
|
|
311
|
+
passedWhenReferred: false,
|
|
292
312
|
validate(token, _args, _doc) {
|
|
293
313
|
const errors = [];
|
|
294
314
|
if (token.parentNode.countAnnotations("meta.id") > 0) errors.push({
|
|
@@ -302,6 +322,7 @@ const dbColumnAnnotations = {
|
|
|
302
322
|
encrypted: new AnnotationSpec({
|
|
303
323
|
description: "Encrypts this field at rest. Values are AES-256-GCM encrypted by the core layer before reaching the database and decrypted on read — transparent to application code.\n\nConstraints: the field cannot be filtered, sorted, indexed, used as PK/FK, patched with arithmetic ops, or referenced by search/vector/geo features.\n\n**Example:**\n```atscript\n@db.encrypted\napiToken?: string\n```\n",
|
|
304
324
|
nodeType: ["prop"],
|
|
325
|
+
passedWhenReferred: false,
|
|
305
326
|
multiple: false,
|
|
306
327
|
validate(token, _args, _doc) {
|
|
307
328
|
const errors = [];
|
|
@@ -340,6 +361,7 @@ function columnCapability(capability, verb) {
|
|
|
340
361
|
@db.table.${capability} "manual"\nexport interface User {
|
|
341
362
|
` + example + "}\n```\n",
|
|
342
363
|
nodeType: ["prop"],
|
|
364
|
+
passedWhenReferred: false,
|
|
343
365
|
multiple: false,
|
|
344
366
|
validate(token, _args, _doc) {
|
|
345
367
|
const errors = [];
|
|
@@ -359,6 +381,7 @@ const dbIndexAnnotations = { index: {
|
|
|
359
381
|
plain: new AnnotationSpec({
|
|
360
382
|
description: "Standard (non-unique) index for query performance. Fields sharing the same index name form a composite index.\n\n**Example:**\n```atscript\n@db.index.plain \"idx_timeline\", \"desc\"\ncreatedAt: number.timestamp\n```\n",
|
|
361
383
|
nodeType: ["prop"],
|
|
384
|
+
passedWhenReferred: false,
|
|
362
385
|
multiple: true,
|
|
363
386
|
mergeStrategy: "append",
|
|
364
387
|
argument: [{
|
|
@@ -377,6 +400,7 @@ const dbIndexAnnotations = { index: {
|
|
|
377
400
|
unique: new AnnotationSpec({
|
|
378
401
|
description: "Unique index — ensures no two rows/documents have the same value(s). Fields sharing the same index name form a composite unique constraint.\n\n**Example:**\n```atscript\n@db.index.unique \"tenant_email\"\nemail: string.email\n```\n",
|
|
379
402
|
nodeType: ["prop"],
|
|
403
|
+
passedWhenReferred: false,
|
|
380
404
|
multiple: true,
|
|
381
405
|
mergeStrategy: "append",
|
|
382
406
|
argument: {
|
|
@@ -389,6 +413,7 @@ const dbIndexAnnotations = { index: {
|
|
|
389
413
|
fulltext: new AnnotationSpec({
|
|
390
414
|
description: "Full-text search index. Fields sharing the same index name form a composite full-text index.\n\n**Example:**\n```atscript\n@db.index.fulltext \"ft_content\"\ntitle: string\n\n@db.index.fulltext \"ft_content\", 5\nbio: string\n```\n",
|
|
391
415
|
nodeType: ["prop"],
|
|
416
|
+
passedWhenReferred: false,
|
|
392
417
|
multiple: true,
|
|
393
418
|
mergeStrategy: "append",
|
|
394
419
|
argument: [{
|
|
@@ -406,6 +431,7 @@ const dbIndexAnnotations = { index: {
|
|
|
406
431
|
geo: new AnnotationSpec({
|
|
407
432
|
description: "Geospatial index on a `db.geoPoint` field. Enables `geoSearch()` (distance-ranked) and accelerates `$geoWithin` filters.\n\n**Example:**\n```atscript\n@db.index.geo\ngeo: db.geoPoint\n```\n",
|
|
408
433
|
nodeType: ["prop"],
|
|
434
|
+
passedWhenReferred: false,
|
|
409
435
|
multiple: false,
|
|
410
436
|
argument: {
|
|
411
437
|
optional: true,
|
|
@@ -421,6 +447,7 @@ const dbRelAnnotations = { rel: {
|
|
|
421
447
|
FK: new AnnotationSpec({
|
|
422
448
|
description: "Declares a foreign key reference on this field. The field must use a chain reference type (e.g., `User.id`) whose target is a primary key (`@meta.id`) or unique (`@db.index.unique`) field.\n\n**Dual role:**\n- On a `@db.table` interface, `@db.rel.FK` additionally drives DB-relation semantics — relation loading with `@db.rel.to` / `@db.rel.from`, junction pairing with `@db.rel.via`, etc.\n- On any other interface (value-help sources, WF forms, plain interfaces), `@db.rel.FK` acts purely as the value-help indicator: the client-side picker resolver uses it to decide which fields render a value-help picker. The target's `@db.http.path` (stamped by its readable controller) supplies the picker URL.\n\n**Example:**\n```atscript\n@db.rel.FK\nauthorId: User.id\n\n// With alias (required when multiple FKs point to the same type)\n@db.rel.FK \"author\"\nauthorId: User.id\n```\n",
|
|
423
449
|
nodeType: ["prop"],
|
|
450
|
+
passedWhenReferred: false,
|
|
424
451
|
argument: {
|
|
425
452
|
optional: true,
|
|
426
453
|
name: "alias",
|
|
@@ -505,6 +532,7 @@ const dbRelAnnotations = { rel: {
|
|
|
505
532
|
to: new AnnotationSpec({
|
|
506
533
|
description: "Forward navigational property — the FK is on **this** interface. The compiler resolves the matching @db.rel.FK by target type or alias.\n\n**Example:**\n```atscript\n@db.rel.to\nauthor?: User\n\n// With alias\n@db.rel.to \"author\"\nauthor?: User\n```\n",
|
|
507
534
|
nodeType: ["prop"],
|
|
535
|
+
passedWhenReferred: false,
|
|
508
536
|
argument: {
|
|
509
537
|
optional: true,
|
|
510
538
|
name: "alias",
|
|
@@ -588,6 +616,7 @@ const dbRelAnnotations = { rel: {
|
|
|
588
616
|
from: new AnnotationSpec({
|
|
589
617
|
description: "Inverse navigational property — the FK is on the **target** interface, pointing back to this one.\n\n**Example:**\n```atscript\n@db.rel.from\nposts: Post[]\n\n// With alias\n@db.rel.from \"original\"\ncomments: Comment[]\n```\n",
|
|
590
618
|
nodeType: ["prop"],
|
|
619
|
+
passedWhenReferred: false,
|
|
591
620
|
argument: {
|
|
592
621
|
optional: true,
|
|
593
622
|
name: "alias",
|
|
@@ -676,6 +705,7 @@ const dbRelAnnotations = { rel: {
|
|
|
676
705
|
via: new AnnotationSpec({
|
|
677
706
|
description: "Declares a many-to-many navigational property through an explicit junction table. `@db.rel.via` is self-sufficient — no `@db.rel.from` pairing is needed.\n\n**Example:**\n```atscript\n@db.rel.via PostTag\ntags: Tag[]\n```\n",
|
|
678
707
|
nodeType: ["prop"],
|
|
708
|
+
passedWhenReferred: false,
|
|
679
709
|
argument: {
|
|
680
710
|
name: "junction",
|
|
681
711
|
type: "ref",
|
|
@@ -735,6 +765,7 @@ const dbRelAnnotations = { rel: {
|
|
|
735
765
|
filter: new AnnotationSpec({
|
|
736
766
|
description: "Applies a filter to a navigational property, restricting which related records are loaded.\n\n**Example:**\n```atscript\n@db.rel.from\n@db.rel.filter `Post.published = true`\npublishedPosts: Post[]\n```\n",
|
|
737
767
|
nodeType: ["prop"],
|
|
768
|
+
passedWhenReferred: false,
|
|
738
769
|
argument: {
|
|
739
770
|
name: "condition",
|
|
740
771
|
type: "query",
|
|
@@ -774,6 +805,7 @@ const dbSearchAnnotations = { search: {
|
|
|
774
805
|
$self: new AnnotationSpec({
|
|
775
806
|
description: "Marks a field as a **vector embedding** for **similarity search**.\n\n- Each adapter maps this to its native vector type and index:\n - **MongoDB** → Atlas `$vectorSearch` index\n - **MySQL 9+** → `VECTOR(N)` column + `VEC_DISTANCE_*` functions\n - **PostgreSQL** → pgvector `vector(N)` column + distance operators\n - **SQLite** → `BLOB` column + `vec0` virtual index (requires the `sqlite-vec` extension; falls back to JSON `TEXT` when unavailable)\n\n**Example:**\n```atscript\n@db.search.vector 1536, \"cosine\"\nembedding: db.vector\n```\n",
|
|
776
807
|
nodeType: ["prop"],
|
|
808
|
+
passedWhenReferred: false,
|
|
777
809
|
multiple: false,
|
|
778
810
|
argument: [
|
|
779
811
|
{
|
|
@@ -818,6 +850,7 @@ const dbSearchAnnotations = { search: {
|
|
|
818
850
|
threshold: new AnnotationSpec({
|
|
819
851
|
description: "Sets a **default minimum similarity threshold** for vector search queries on this field.\n\n- Results with a similarity score below this threshold are excluded.\n- Query-time `$threshold` control overrides this default.\n- Value range: `0` to `1` (where `1` means exact match).\n\n**Example:**\n```atscript\n@db.search.vector 1536, \"cosine\"\n@db.search.vector.threshold 0.7\nembedding: db.vector\n```\n",
|
|
820
852
|
nodeType: ["prop"],
|
|
853
|
+
passedWhenReferred: false,
|
|
821
854
|
multiple: false,
|
|
822
855
|
argument: {
|
|
823
856
|
optional: false,
|
|
@@ -830,6 +863,7 @@ const dbSearchAnnotations = { search: {
|
|
|
830
863
|
filter: new AnnotationSpec({
|
|
831
864
|
description: "Assigns a field as a **pre-filter** for a **vector search index**.\n\n- Filters allow vector search queries to return results only within a specific subset.\n- The referenced index must be defined using `@db.search.vector`.\n\n**Example:**\n```atscript\n@db.search.vector 1536, \"cosine\"\nembedding: db.vector\n\n@db.search.filter \"embedding\"\ncategory: string\n```\n",
|
|
832
865
|
nodeType: ["prop"],
|
|
866
|
+
passedWhenReferred: false,
|
|
833
867
|
multiple: true,
|
|
834
868
|
argument: {
|
|
835
869
|
optional: false,
|
|
@@ -1070,6 +1104,7 @@ const dbUnitAnnotations = { unit: {
|
|
|
1070
1104
|
ref: new AnnotationSpec({
|
|
1071
1105
|
description: "Binds this quantity to a **sibling field** that holds its unit. Use when different rows may carry different units (e.g. mixed kg/lb measurements).\n\nThe referenced field must be a `string`.\n\nValid on `decimal` and `number` fields. Aggregating this field forces the referenced unit field into `$groupBy` at runtime — summing rows with different units is rejected.\n\n**Example:**\n```atscript\nunit: string\n@db.unit.ref 'unit'\nweight: decimal\n```\n",
|
|
1072
1106
|
nodeType: ["prop"],
|
|
1107
|
+
passedWhenReferred: false,
|
|
1073
1108
|
multiple: false,
|
|
1074
1109
|
argument: {
|
|
1075
1110
|
name: "fieldName",
|
package/dist/shared.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_validation_utils = require("./validation-utils-
|
|
2
|
+
const require_validation_utils = require("./validation-utils-B7SXPkm7.cjs");
|
|
3
3
|
exports.findFKFieldsPointingTo = require_validation_utils.findFKFieldsPointingTo;
|
|
4
4
|
exports.getAnnotationAlias = require_validation_utils.getAnnotationAlias;
|
|
5
5
|
exports.getDbTableOwner = require_validation_utils.getDbTableOwner;
|
package/dist/shared.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as getAnnotationAlias, c as getParentStruct, d as validateExclusiveWith, f as validateFieldBaseType, i as validateRefArgument, l as getParentTypeName, n as hasAnyViewAnnotation, o as getDbTableOwner, p as validateSiblingStringField, r as validateQueryScope, s as getNavTargetTypeName, t as findFKFieldsPointingTo, u as refActionAnnotation } from "./validation-utils-
|
|
1
|
+
import { a as getAnnotationAlias, c as getParentStruct, d as validateExclusiveWith, f as validateFieldBaseType, i as validateRefArgument, l as getParentTypeName, n as hasAnyViewAnnotation, o as getDbTableOwner, p as validateSiblingStringField, r as validateQueryScope, s as getNavTargetTypeName, t as findFKFieldsPointingTo, u as refActionAnnotation } from "./validation-utils-MWOP1Ts4.mjs";
|
|
2
2
|
export { findFKFieldsPointingTo, getAnnotationAlias, getDbTableOwner, getNavTargetTypeName, getParentStruct, getParentTypeName, hasAnyViewAnnotation, refActionAnnotation, validateExclusiveWith, validateFieldBaseType, validateQueryScope, validateRefArgument, validateSiblingStringField };
|
package/dist/sync.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_db_view = require("./db-view-
|
|
2
|
+
const require_db_view = require("./db-view-UfGVUAol.cjs");
|
|
3
3
|
//#region src/schema/schema-hash.ts
|
|
4
4
|
/** Extracts sorted field snapshots from a readable's field descriptors. */
|
|
5
5
|
function extractFieldSnapshots(fields, typeMapper) {
|
|
@@ -930,6 +930,7 @@ var SchemaSync = class {
|
|
|
930
930
|
* Runs schema synchronization with distributed locking.
|
|
931
931
|
*/
|
|
932
932
|
async run(types, opts) {
|
|
933
|
+
this.logger = opts?.logger ?? this.logger;
|
|
933
934
|
const podId = opts?.podId ?? crypto.randomUUID();
|
|
934
935
|
const lockTtlMs = opts?.lockTtlMs ?? 3e4;
|
|
935
936
|
const waitTimeoutMs = opts?.waitTimeoutMs ?? 6e4;
|
package/dist/sync.d.cts
CHANGED
|
@@ -235,6 +235,11 @@ interface TSyncOptions {
|
|
|
235
235
|
force?: boolean;
|
|
236
236
|
/** Safe mode — skip destructive operations (column drops, table drops). Default: false. */
|
|
237
237
|
safe?: boolean;
|
|
238
|
+
/**
|
|
239
|
+
* Logger for sync progress and failures (index/FK DDL errors are logged,
|
|
240
|
+
* not thrown). Default: NoopLogger — pass `console` to surface them.
|
|
241
|
+
*/
|
|
242
|
+
logger?: TGenericLogger;
|
|
238
243
|
}
|
|
239
244
|
interface TSyncResult {
|
|
240
245
|
status: "up-to-date" | "synced" | "synced-by-peer";
|
|
@@ -244,7 +249,7 @@ interface TSyncResult {
|
|
|
244
249
|
declare class SchemaSync {
|
|
245
250
|
private readonly space;
|
|
246
251
|
private readonly store;
|
|
247
|
-
private
|
|
252
|
+
private logger;
|
|
248
253
|
constructor(space: DbSpace, logger?: TGenericLogger);
|
|
249
254
|
/**
|
|
250
255
|
* Resolves types into categorized readables and computes the schema hash.
|
package/dist/sync.d.mts
CHANGED
|
@@ -235,6 +235,11 @@ interface TSyncOptions {
|
|
|
235
235
|
force?: boolean;
|
|
236
236
|
/** Safe mode — skip destructive operations (column drops, table drops). Default: false. */
|
|
237
237
|
safe?: boolean;
|
|
238
|
+
/**
|
|
239
|
+
* Logger for sync progress and failures (index/FK DDL errors are logged,
|
|
240
|
+
* not thrown). Default: NoopLogger — pass `console` to surface them.
|
|
241
|
+
*/
|
|
242
|
+
logger?: TGenericLogger;
|
|
238
243
|
}
|
|
239
244
|
interface TSyncResult {
|
|
240
245
|
status: "up-to-date" | "synced" | "synced-by-peer";
|
|
@@ -244,7 +249,7 @@ interface TSyncResult {
|
|
|
244
249
|
declare class SchemaSync {
|
|
245
250
|
private readonly space;
|
|
246
251
|
private readonly store;
|
|
247
|
-
private
|
|
252
|
+
private logger;
|
|
248
253
|
constructor(space: DbSpace, logger?: TGenericLogger);
|
|
249
254
|
/**
|
|
250
255
|
* Resolves types into categorized readables and computes the schema hash.
|
package/dist/sync.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { C as NoopLogger } from "./db-view-BllUecjK.mjs";
|
|
2
2
|
//#region src/schema/schema-hash.ts
|
|
3
3
|
/** Extracts sorted field snapshots from a readable's field descriptors. */
|
|
4
4
|
function extractFieldSnapshots(fields, typeMapper) {
|
|
@@ -929,6 +929,7 @@ var SchemaSync = class {
|
|
|
929
929
|
* Runs schema synchronization with distributed locking.
|
|
930
930
|
*/
|
|
931
931
|
async run(types, opts) {
|
|
932
|
+
this.logger = opts?.logger ?? this.logger;
|
|
932
933
|
const podId = opts?.podId ?? crypto.randomUUID();
|
|
933
934
|
const lockTtlMs = opts?.lockTtlMs ?? 3e4;
|
|
934
935
|
const waitTimeoutMs = opts?.waitTimeoutMs ?? 6e4;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atscript/db",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.111",
|
|
4
4
|
"description": "Database adapter utilities for atscript.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"atscript",
|
|
@@ -71,14 +71,14 @@
|
|
|
71
71
|
"access": "public"
|
|
72
72
|
},
|
|
73
73
|
"devDependencies": {
|
|
74
|
-
"@atscript/core": "^0.1.
|
|
75
|
-
"@atscript/typescript": "^0.1.
|
|
74
|
+
"@atscript/core": "^0.1.79",
|
|
75
|
+
"@atscript/typescript": "^0.1.79",
|
|
76
76
|
"@uniqu/core": "^0.1.6",
|
|
77
|
-
"unplugin-atscript": "^0.1.
|
|
77
|
+
"unplugin-atscript": "^0.1.79"
|
|
78
78
|
},
|
|
79
79
|
"peerDependencies": {
|
|
80
|
-
"@atscript/core": "^0.1.
|
|
81
|
-
"@atscript/typescript": "^0.1.
|
|
80
|
+
"@atscript/core": "^0.1.79",
|
|
81
|
+
"@atscript/typescript": "^0.1.79",
|
|
82
82
|
"@uniqu/core": "^0.1.6"
|
|
83
83
|
},
|
|
84
84
|
"scripts": {
|