@lossless.org/client 0.1.1 → 1.1.0
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_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/core/drivers.d.ts +17 -0
- package/dist_ts/core/drivers.js +27 -0
- package/dist_ts/core/interfaces.d.ts +1 -1
- package/dist_ts/index.d.ts +2 -0
- package/dist_ts/index.js +2 -1
- package/dist_ts/nosqldb/classes.atomicupdate.d.ts +21 -0
- package/dist_ts/nosqldb/classes.atomicupdate.js +41 -1
- package/dist_ts/nosqldb/classes.collection.d.ts +31 -0
- package/dist_ts/nosqldb/classes.collection.js +120 -13
- package/dist_ts/nosqldb/classes.doc.d.ts +58 -0
- package/dist_ts/nosqldb/classes.doc.js +287 -22
- package/dist_ts/nosqldb/classes.ordinarypersistence.d.ts +6 -0
- package/dist_ts/nosqldb/classes.ordinarypersistence.js +7 -1
- package/dist_ts/nosqldb/index.d.ts +2 -0
- package/dist_ts/nosqldb/index.js +2 -1
- package/dist_ts/nosqldb/lineage.d.ts +13 -0
- package/dist_ts/nosqldb/lineage.js +13 -0
- package/dist_ts/objectstorage/classes.bucket.js +34 -36
- package/dist_ts/plugins.js +6 -4
- package/package.json +24 -7
- package/readme.md +30 -2
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/core/drivers.ts +43 -0
- package/ts/core/interfaces.ts +1 -1
- package/ts/index.ts +2 -0
- package/ts/nosqldb/classes.atomicupdate.ts +67 -0
- package/ts/nosqldb/classes.collection.ts +181 -10
- package/ts/nosqldb/classes.doc.ts +525 -19
- package/ts/nosqldb/classes.ordinarypersistence.ts +8 -0
- package/ts/nosqldb/index.ts +2 -0
- package/ts/nosqldb/lineage.ts +25 -0
- package/ts/objectstorage/classes.bucket.ts +39 -43
- package/ts/plugins.ts +6 -3
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@lossless.org/client',
|
|
6
|
-
version: '
|
|
6
|
+
version: '1.1.0',
|
|
7
7
|
description: 'One typed client for NoSQLDB, MongoDB, SQLDB, MariaDB, ClickHouse and S3 object storage.'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxzQkFBc0I7SUFDNUIsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLDBGQUEwRjtDQUN4RyxDQUFBIn0=
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { TBackend } from './interfaces.js';
|
|
2
|
+
/** Backends whose driver package ships as an optional peer dependency instead of a dependency. */
|
|
3
|
+
export type TOptionalDriverBackend = Extract<TBackend, 'mariadb' | 'clickhouse' | 's3'>;
|
|
4
|
+
export interface IOptionalDriver {
|
|
5
|
+
/** npm package the consumer installs. */
|
|
6
|
+
readonly package: string;
|
|
7
|
+
/** Entry point that needs it, so the refusal names the import the consumer already wrote. */
|
|
8
|
+
readonly subpath: string;
|
|
9
|
+
/** Connections the driver enables, phrased as the aggregate client configuration names them. */
|
|
10
|
+
readonly usage: string;
|
|
11
|
+
}
|
|
12
|
+
export declare const optionalDrivers: Readonly<Record<TOptionalDriverBackend, IOptionalDriver>>;
|
|
13
|
+
/**
|
|
14
|
+
* Rejection handler for a lazy family import. An absent optional driver becomes an instruction naming the package and
|
|
15
|
+
* the entry point; every other failure keeps its original identity so real load errors stay visible.
|
|
16
|
+
*/
|
|
17
|
+
export declare const requireDriver: (backend: TOptionalDriverBackend) => (error: unknown) => never;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { LosslessClientError } from './classes.error.js';
|
|
2
|
+
export const optionalDrivers = Object.freeze({
|
|
3
|
+
mariadb: { package: 'mariadb', subpath: '@lossless.org/client/sqldb',
|
|
4
|
+
usage: 'sqldb connections with backend "sqldb" or "mariadb"' },
|
|
5
|
+
clickhouse: { package: '@clickhouse/client', subpath: '@lossless.org/client/sqldb',
|
|
6
|
+
usage: 'sqldb connections with backend "clickhouse"' },
|
|
7
|
+
s3: { package: '@aws-sdk/client-s3', subpath: '@lossless.org/client/objectstorage',
|
|
8
|
+
usage: 'objectstorage connections with backend "s3"' },
|
|
9
|
+
});
|
|
10
|
+
/** Node names the unresolved package in its message; anything else is a defect of this package, not a missing install. */
|
|
11
|
+
const isUninstalled = (error, packageName) => {
|
|
12
|
+
const details = error;
|
|
13
|
+
return !!details && details.code === 'ERR_MODULE_NOT_FOUND' &&
|
|
14
|
+
typeof details.message === 'string' && details.message.includes(`'${packageName}'`);
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Rejection handler for a lazy family import. An absent optional driver becomes an instruction naming the package and
|
|
18
|
+
* the entry point; every other failure keeps its original identity so real load errors stay visible.
|
|
19
|
+
*/
|
|
20
|
+
export const requireDriver = (backend) => (error) => {
|
|
21
|
+
const driver = optionalDrivers[backend];
|
|
22
|
+
if (!isUninstalled(error, driver.package))
|
|
23
|
+
throw error;
|
|
24
|
+
throw new LosslessClientError('driver_missing', `Install the optional peer dependency "${driver.package}" to use ${driver.usage} (${driver.subpath}). ` +
|
|
25
|
+
`Run: pnpm add ${driver.package}`, { cause: error, retryability: 'permanent' });
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHJpdmVycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2NvcmUvZHJpdmVycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQWV6RCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQThELE1BQU0sQ0FBQyxNQUFNLENBQUM7SUFDdEcsT0FBTyxFQUFFLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsNEJBQTRCO1FBQ2xFLEtBQUssRUFBRSxxREFBcUQsRUFBRTtJQUNoRSxVQUFVLEVBQUUsRUFBRSxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsT0FBTyxFQUFFLDRCQUE0QjtRQUNoRixLQUFLLEVBQUUsNkNBQTZDLEVBQUU7SUFDeEQsRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE9BQU8sRUFBRSxvQ0FBb0M7UUFDaEYsS0FBSyxFQUFFLDZDQUE2QyxFQUFFO0NBQ3pELENBQUMsQ0FBQztBQUVILDBIQUEwSDtBQUMxSCxNQUFNLGFBQWEsR0FBRyxDQUFDLEtBQWMsRUFBRSxXQUFtQixFQUFXLEVBQUU7SUFDckUsTUFBTSxPQUFPLEdBQUcsS0FBaUUsQ0FBQztJQUNsRixPQUFPLENBQUMsQ0FBQyxPQUFPLElBQUksT0FBTyxDQUFDLElBQUksS0FBSyxzQkFBc0I7UUFDekQsT0FBTyxPQUFPLENBQUMsT0FBTyxLQUFLLFFBQVEsSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLFdBQVcsR0FBRyxDQUFDLENBQUM7QUFDeEYsQ0FBQyxDQUFDO0FBRUY7OztHQUdHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sYUFBYSxHQUFHLENBQUMsT0FBK0IsRUFBRSxFQUFFLENBQUMsQ0FBQyxLQUFjLEVBQVMsRUFBRTtJQUMxRixNQUFNLE1BQU0sR0FBRyxlQUFlLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDeEMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQztRQUFFLE1BQU0sS0FBSyxDQUFDO0lBQ3ZELE1BQU0sSUFBSSxtQkFBbUIsQ0FBQyxnQkFBZ0IsRUFDNUMseUNBQXlDLE1BQU0sQ0FBQyxPQUFPLFlBQVksTUFBTSxDQUFDLEtBQUssS0FBSyxNQUFNLENBQUMsT0FBTyxLQUFLO1FBQ3ZHLGlCQUFpQixNQUFNLENBQUMsT0FBTyxFQUFFLEVBQ2pDLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxZQUFZLEVBQUUsV0FBVyxFQUFFLENBQUMsQ0FBQztBQUNqRCxDQUFDLENBQUMifQ==
|
|
@@ -15,4 +15,4 @@ export interface IReadiness {
|
|
|
15
15
|
ready: boolean;
|
|
16
16
|
reason?: string;
|
|
17
17
|
}
|
|
18
|
-
export type TClientErrorCode = 'invalid_argument' | 'unsupported_capability' | 'not_connected' | 'closed' | 'timeout' | 'cancelled' | 'result_limit' | 'authentication' | 'conflict' | 'backend_error' | 'ambiguous_write' | 'partial_write';
|
|
18
|
+
export type TClientErrorCode = 'invalid_argument' | 'unsupported_capability' | 'driver_missing' | 'not_connected' | 'closed' | 'timeout' | 'cancelled' | 'result_limit' | 'authentication' | 'conflict' | 'backend_error' | 'ambiguous_write' | 'partial_write';
|
package/dist_ts/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export { LosslessOrgClient } from './classes.losslessorgclient.js';
|
|
2
2
|
export type { ILosslessOrgClientOptions } from './classes.losslessorgclient.js';
|
|
3
3
|
export { LosslessClientError } from './core/classes.error.js';
|
|
4
|
+
export { optionalDrivers } from './core/drivers.js';
|
|
5
|
+
export type { IOptionalDriver, TOptionalDriverBackend } from './core/drivers.js';
|
|
4
6
|
export type { ICapabilities, IOperationOptions, IReadiness, TBackend, TCapability, TClientErrorCode } from './core/interfaces.js';
|
package/dist_ts/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { LosslessOrgClient } from './classes.losslessorgclient.js';
|
|
2
2
|
export { LosslessClientError } from './core/classes.error.js';
|
|
3
|
-
|
|
3
|
+
export { optionalDrivers } from './core/drivers.js';
|
|
4
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUVuRSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUM5RCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sbUJBQW1CLENBQUMifQ==
|
|
@@ -12,6 +12,27 @@ export declare const executeAtomicUpdate: <T>(collectionArg: SmartdataCollection
|
|
|
12
12
|
upsert?: boolean;
|
|
13
13
|
session?: TSmartdataOrdinarySession;
|
|
14
14
|
}) => Promise<plugins.mongodb.UpdateResult>;
|
|
15
|
+
/**
|
|
16
|
+
* Executes a bounded batch of model-validated atomic upserts against MongoDB.
|
|
17
|
+
*
|
|
18
|
+
* This helper is package-internal. `SmartDataDbDoc.atomicUpsertMany()` owns the
|
|
19
|
+
* public API and must validate and normalize every filter and update before
|
|
20
|
+
* calling this raw persistence boundary. Each entry applies atomically; the
|
|
21
|
+
* batch as a whole is not isolated unless the caller supplies a transaction
|
|
22
|
+
* session.
|
|
23
|
+
*/
|
|
24
|
+
export declare const executeAtomicUpsertMany: <T>(collectionArg: SmartdataCollection<T>, operationsArg: ReadonlyArray<{
|
|
25
|
+
filter: plugins.mongodb.Filter<plugins.mongodb.Document>;
|
|
26
|
+
update: plugins.mongodb.UpdateFilter<plugins.mongodb.Document>;
|
|
27
|
+
}>, optsArg?: {
|
|
28
|
+
session?: TSmartdataOrdinarySession;
|
|
29
|
+
timeoutMS?: number;
|
|
30
|
+
}) => Promise<{
|
|
31
|
+
acknowledged: boolean;
|
|
32
|
+
matchedCount: number;
|
|
33
|
+
modifiedCount: number;
|
|
34
|
+
upsertedCount: number;
|
|
35
|
+
}>;
|
|
15
36
|
/**
|
|
16
37
|
* Executes a model-validated atomic update-many against MongoDB.
|
|
17
38
|
*
|
|
@@ -26,6 +26,46 @@ export const executeAtomicUpdate = async (collectionArg, filterArg, updateArg, o
|
|
|
26
26
|
}
|
|
27
27
|
});
|
|
28
28
|
};
|
|
29
|
+
/**
|
|
30
|
+
* Executes a bounded batch of model-validated atomic upserts against MongoDB.
|
|
31
|
+
*
|
|
32
|
+
* This helper is package-internal. `SmartDataDbDoc.atomicUpsertMany()` owns the
|
|
33
|
+
* public API and must validate and normalize every filter and update before
|
|
34
|
+
* calling this raw persistence boundary. Each entry applies atomically; the
|
|
35
|
+
* batch as a whole is not isolated unless the caller supplies a transaction
|
|
36
|
+
* session.
|
|
37
|
+
*/
|
|
38
|
+
export const executeAtomicUpsertMany = async (collectionArg, operationsArg, optsArg) => {
|
|
39
|
+
return runWithOrdinarySmartdataSession(optsArg?.session, collectionArg.smartdataDb, {
|
|
40
|
+
ordinaryWrite: true,
|
|
41
|
+
prepared: collectionArg.isInitializedForCurrentDatabase(),
|
|
42
|
+
preparationMessage: `Initialize collection "${collectionArg.collectionName}" before using an owned SmartData session.`,
|
|
43
|
+
}, async (rawSessionArg) => {
|
|
44
|
+
await collectionArg.init();
|
|
45
|
+
try {
|
|
46
|
+
const result = await collectionArg.mongoDbCollection.bulkWrite(operationsArg.map((operationArg) => ({
|
|
47
|
+
updateOne: {
|
|
48
|
+
filter: operationArg.filter,
|
|
49
|
+
update: operationArg.update,
|
|
50
|
+
upsert: true,
|
|
51
|
+
},
|
|
52
|
+
})), {
|
|
53
|
+
ordered: false,
|
|
54
|
+
session: rawSessionArg,
|
|
55
|
+
timeoutMS: optsArg?.timeoutMS,
|
|
56
|
+
});
|
|
57
|
+
return {
|
|
58
|
+
acknowledged: result.isOk(),
|
|
59
|
+
matchedCount: result.matchedCount,
|
|
60
|
+
modifiedCount: result.modifiedCount,
|
|
61
|
+
upsertedCount: result.upsertedCount,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
catch (errorArg) {
|
|
65
|
+
return normalizeOrdinaryPersistenceError(errorArg, `Atomic upsert-many conflicts with a unique index in collection "${collectionArg.collectionName}".`);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
};
|
|
29
69
|
/**
|
|
30
70
|
* Executes a model-validated atomic update-many against MongoDB.
|
|
31
71
|
*
|
|
@@ -52,4 +92,4 @@ export const executeAtomicUpdateMany = async (collectionArg, filterArg, updateAr
|
|
|
52
92
|
}
|
|
53
93
|
});
|
|
54
94
|
};
|
|
55
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
95
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5hdG9taWN1cGRhdGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9ub3NxbGRiL2NsYXNzZXMuYXRvbWljdXBkYXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBRXhDLE9BQU8sRUFBRSxpQ0FBaUMsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzdFLE9BQU8sRUFDTCwrQkFBK0IsR0FFaEMsTUFBTSxzQkFBc0IsQ0FBQztBQUU5Qjs7Ozs7O0dBTUc7QUFDSCxNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBRyxLQUFLLEVBQ3RDLGFBQXFDLEVBQ3JDLFNBQTJELEVBQzNELFNBQWlFLEVBQ2pFLE9BR0MsRUFDc0MsRUFBRTtJQUN6QyxPQUFPLCtCQUErQixDQUNwQyxPQUFPLEVBQUUsT0FBTyxFQUNoQixhQUFhLENBQUMsV0FBVyxFQUN6QjtRQUNFLGFBQWEsRUFBRSxJQUFJO1FBQ25CLFFBQVEsRUFBRSxhQUFhLENBQUMsK0JBQStCLEVBQUU7UUFDekQsa0JBQWtCLEVBQ2hCLDBCQUEwQixhQUFhLENBQUMsY0FBYyw0Q0FBNEM7S0FDckcsRUFDRCxLQUFLLEVBQUUsYUFBYSxFQUFFLEVBQUU7UUFDdEIsTUFBTSxhQUFhLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDM0IsSUFBSSxDQUFDO1lBQ0gsT0FBTyxNQUFNLGFBQWEsQ0FBQyxpQkFBaUIsQ0FBQyxTQUFTLENBQ3BELFNBQVMsRUFDVCxTQUFTLEVBQ1Q7Z0JBQ0UsTUFBTSxFQUFFLE9BQU8sRUFBRSxNQUFNLEtBQUssSUFBSTtnQkFDaEMsT0FBTyxFQUFFLGFBQWE7YUFDdkIsQ0FDRixDQUFDO1FBQ0osQ0FBQztRQUFDLE9BQU8sUUFBUSxFQUFFLENBQUM7WUFDbEIsT0FBTyxpQ0FBaUMsQ0FDdEMsUUFBUSxFQUNSLDhEQUE4RCxhQUFhLENBQUMsY0FBYyxJQUFJLENBQy9GLENBQUM7UUFDSixDQUFD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
|
|
@@ -22,6 +22,14 @@ export interface ICollectionBindingOptions {
|
|
|
22
22
|
* its legacy collection without changing stored data.
|
|
23
23
|
*/
|
|
24
24
|
collectionName?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Stores one declared `@unI()` string identity as the document `_id`, making
|
|
27
|
+
* the primary key itself the uniqueness authority. The field keeps its own
|
|
28
|
+
* stored value and receives no separate unique index. Irreversible for an
|
|
29
|
+
* existing collection: every stored document must already satisfy
|
|
30
|
+
* `_id === document[field]`.
|
|
31
|
+
*/
|
|
32
|
+
identityAsDocumentId?: string;
|
|
25
33
|
}
|
|
26
34
|
export type TCollectionModelIndexDirection = 1 | -1 | 'text';
|
|
27
35
|
export interface ICollectionModelIndexOptions {
|
|
@@ -63,6 +71,13 @@ export interface ICollectionModelConfig<TModel extends object = any> {
|
|
|
63
71
|
* ascending unique index in `indexes`.
|
|
64
72
|
*/
|
|
65
73
|
identityFields?: ReadonlyArray<TStringFieldKey<TModel>>;
|
|
74
|
+
/**
|
|
75
|
+
* Stores one declared string identity as the document `_id`. The primary key
|
|
76
|
+
* becomes the uniqueness authority, so the field must not declare its own
|
|
77
|
+
* unique index. Irreversible for an existing collection: every stored
|
|
78
|
+
* document must already satisfy `_id === document[field]`.
|
|
79
|
+
*/
|
|
80
|
+
identityAsDocumentId?: TStringFieldKey<TModel>;
|
|
66
81
|
/**
|
|
67
82
|
* Persisted fields used by SmartData's search helpers.
|
|
68
83
|
*/
|
|
@@ -78,6 +93,8 @@ export interface INormalizedCollectionModelSchema {
|
|
|
78
93
|
readonly persistedFields: readonly string[];
|
|
79
94
|
readonly numericFields: readonly string[];
|
|
80
95
|
readonly identityFields: readonly string[];
|
|
96
|
+
/** Declared identity field stored as the document `_id`, if any. */
|
|
97
|
+
readonly identityAsDocumentId?: string;
|
|
81
98
|
readonly identityValueTypes: Readonly<Record<string, TSmartdataIdentityValueType>>;
|
|
82
99
|
readonly searchableFields: readonly string[];
|
|
83
100
|
readonly indexes: ReadonlyArray<{
|
|
@@ -111,6 +128,11 @@ type TCollectionModelConstructor<TModel extends SmartDataDbDoc<any, any>> = {
|
|
|
111
128
|
name: string;
|
|
112
129
|
prototype: TModel;
|
|
113
130
|
};
|
|
131
|
+
/**
|
|
132
|
+
* Returns the declared identity field a model stores as its document `_id`.
|
|
133
|
+
* Reading the bound schema resolver never resolves a database.
|
|
134
|
+
*/
|
|
135
|
+
export declare const getIdentityDocumentIdField: (modelArg: any) => string | undefined;
|
|
114
136
|
/**
|
|
115
137
|
* Programmatically declares and binds an ordinary SmartData model.
|
|
116
138
|
*
|
|
@@ -229,6 +251,15 @@ export declare class SmartdataCollection<T> {
|
|
|
229
251
|
* create an object in the database
|
|
230
252
|
*/
|
|
231
253
|
private prepareOrdinaryInsert;
|
|
254
|
+
/**
|
|
255
|
+
* Keys a stored document by its declared identity when the model opted into
|
|
256
|
+
* `identityAsDocumentId`. The identity keeps its own stored field, but reads
|
|
257
|
+
* address `_id`, so a document written before the option was declared is
|
|
258
|
+
* reachable only if its `_id` already equals that identity.
|
|
259
|
+
*/
|
|
260
|
+
private applyIdentityDocumentId;
|
|
261
|
+
/** True when stored documents need SmartData-owned preparation before a write. */
|
|
262
|
+
private get preparesStoredDocuments();
|
|
232
263
|
insert(dbDocArg: T & SmartDataDbDoc<T, unknown>, opts?: {
|
|
233
264
|
session?: TSmartdataOrdinarySession;
|
|
234
265
|
}): Promise<any>;
|