@researchdatabox/sails-hook-redbox-storage-mongo 5.0.4-beta.12498 → 5.0.4
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/README.md +0 -41
- package/dist/config/storage.d.ts +0 -52
- package/dist/config/storage.js +3 -18
- package/dist/index.d.ts +0 -2
- package/dist/index.js +1 -3
- package/dist/models/DeletedRecord.d.ts +0 -8
- package/dist/models/DeletedRecord.js +1 -55
- package/dist/models/Record.d.ts +2 -5
- package/dist/models/Record.js +11 -43
- package/dist/models/RecordAudit.d.ts +1 -2
- package/dist/models/RecordAudit.js +6 -11
- package/dist/models/index.d.ts +0 -4
- package/dist/models/index.js +1 -7
- package/dist/services/MongoStorageService.d.ts +19 -174
- package/dist/services/MongoStorageService.js +306 -1679
- package/package.json +3 -4
- package/dist/migrations/index.d.ts +0 -5
- package/dist/migrations/index.js +0 -26
- package/dist/migrations/recordRevisionBackfill.d.ts +0 -26
- package/dist/migrations/recordRevisionBackfill.js +0 -115
- package/dist/models/RecordSchemaArtifact.d.ts +0 -14
- package/dist/models/RecordSchemaArtifact.js +0 -75
- package/dist/models/RecordSchemaReference.d.ts +0 -25
- package/dist/models/RecordSchemaReference.js +0 -128
- package/dist/services/recordSchemaPersistence.d.ts +0 -27
- package/dist/services/recordSchemaPersistence.js +0 -258
|
@@ -2,8 +2,7 @@ import { Observable } from 'rxjs';
|
|
|
2
2
|
import mongodb = require('mongodb');
|
|
3
3
|
import type { Collection, Db, Document, FindCursor, FindOptions, GridFSFile } from 'mongodb';
|
|
4
4
|
import stream = require('node:stream');
|
|
5
|
-
import { Services as services, StorageManagerService as StorageManagerServiceTypes, DatastreamService, StorageService, StorageServiceResponse,
|
|
6
|
-
import type { RecordSchemaArtifactInput, RecordSchemaArtifactModel, RecordSchemaArtifactQuery, RecordSchemaArtifactSummary, RecordSchemaAuthorizationGrantQuery, RecordSchemaReferenceInput, RecordSchemaReferenceModel, RecordSchemaReferenceQuery } from '@researchdatabox/redbox-core';
|
|
5
|
+
import { Services as services, StorageManagerService as StorageManagerServiceTypes, DatastreamService, StorageService, StorageServiceResponse, DatastreamServiceResponse, Datastream, RecordAuditModel, RecordAuditParams, IntegrationAuditModel, IntegrationAuditParams, RecordModel, RecordWriteOptions, RecordFieldWriteResult, BrandingModel, UserModel, RoleModel, RecordRelationshipExpandOptions, RecordRelationshipGraph } from '@researchdatabox/redbox-core';
|
|
7
6
|
type JsonMap = Record<string, unknown>;
|
|
8
7
|
type StorageRecord = RecordModel;
|
|
9
8
|
type MongoRecordDocument = Document;
|
|
@@ -11,188 +10,36 @@ type DatastreamContent = {
|
|
|
11
10
|
readstream?: NodeJS.ReadableStream;
|
|
12
11
|
body?: Buffer | string;
|
|
13
12
|
} & Record<string, unknown>;
|
|
14
|
-
export declare const RECORD_SCHEMA_ARTIFACT_INDEXES: mongodb.IndexDescription[];
|
|
15
|
-
export declare const RECORD_SCHEMA_AUTHORIZATION_CURSOR_INDEX_NAME = "record_schema_reference_authorization_cursor_lookup";
|
|
16
|
-
export declare const RECORD_SCHEMA_AUTHORIZATION_CURSOR_INDEX_KEY: {
|
|
17
|
-
readonly digest: 1;
|
|
18
|
-
readonly kind: 1;
|
|
19
|
-
readonly brand: 1;
|
|
20
|
-
readonly portal: 1;
|
|
21
|
-
readonly schemaKind: 1;
|
|
22
|
-
readonly recordType: 1;
|
|
23
|
-
readonly operation: 1;
|
|
24
|
-
readonly referenceKey: 1;
|
|
25
|
-
};
|
|
26
|
-
export declare const RECORD_SCHEMA_REFERENCE_INDEXES: mongodb.IndexDescription[];
|
|
27
|
-
/**
|
|
28
|
-
* Authorization lookups fail as unavailable instead of consuming an
|
|
29
|
-
* unbounded database work budget. This is a time/availability boundary, not
|
|
30
|
-
* a result cap: a query that cannot complete is never reported as a denial.
|
|
31
|
-
*/
|
|
32
|
-
export declare const RECORD_SCHEMA_AUTHORIZATION_LOOKUP_MAX_TIME_MS = 1000;
|
|
33
13
|
export declare namespace Services {
|
|
34
14
|
class MongoStorageService extends services.Core.Service implements StorageService, DatastreamService {
|
|
35
15
|
gridFsBucket: mongodb.GridFSBucket;
|
|
36
16
|
db: Db;
|
|
37
17
|
recordCol: Collection<MongoRecordDocument>;
|
|
38
18
|
deletedRecordCol: Collection<MongoRecordDocument>;
|
|
39
|
-
recordIdentityCol: Collection<MongoRecordDocument>;
|
|
40
|
-
recordSchemaArtifactCol: Collection<MongoRecordDocument>;
|
|
41
|
-
recordSchemaReferenceCol: Collection<MongoRecordDocument>;
|
|
42
19
|
private _readyHookRegistered;
|
|
43
|
-
private _requiredIndicesReady;
|
|
44
|
-
private _initializationPromise?;
|
|
45
20
|
protected _exportedMethods: string[];
|
|
46
21
|
constructor();
|
|
47
22
|
private getUuid;
|
|
48
23
|
private getErrorMessage;
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Resolve the native driver collection behind a Waterline model. Strict
|
|
52
|
-
* concurrency needs `findOneAndUpdate`/`findOneAndDelete` facts that
|
|
53
|
-
* Waterline cannot certify, so the compare-and-set paths talk to the
|
|
54
|
-
* driver directly. Discovery never throws: an adapter that cannot supply a
|
|
55
|
-
* native collection is simply unsupported.
|
|
56
|
-
*/
|
|
57
|
-
private getNativeCollection;
|
|
58
|
-
private getNativeRecordCollection;
|
|
59
|
-
private getNativeTombstoneCollection;
|
|
60
|
-
private getNativeRecordIdentityCollection;
|
|
61
|
-
private supportsAtomicMutation;
|
|
62
|
-
getCapabilities(): StorageServiceCapabilities;
|
|
63
|
-
private createMutationResponse;
|
|
64
|
-
private notApplied;
|
|
65
|
-
private unknownMutation;
|
|
66
|
-
/**
|
|
67
|
-
* Normalize the caller's precondition. Returning `null` means the response
|
|
68
|
-
* already carries a certified non-application: a malformed precondition is
|
|
69
|
-
* a caller defect, and answering it with a definite no-write is safer than
|
|
70
|
-
* guessing which revision was meant.
|
|
71
|
-
*/
|
|
72
|
-
private expectedRevision;
|
|
73
|
-
/**
|
|
74
|
-
* The lazy compatibility clause matches only a genuinely absent revision.
|
|
75
|
-
* An explicit null is corrupt state: `$inc` cannot advance it and must not
|
|
76
|
-
* be made to look like a safe first revision.
|
|
77
|
-
*/
|
|
78
|
-
private revisionSelector;
|
|
79
|
-
private mutationSelector;
|
|
80
|
-
private lifecycleMutationSelector;
|
|
81
|
-
private isDuplicateKeyError;
|
|
82
|
-
/**
|
|
83
|
-
* Whether the driver fact proves that `insertOne` did not commit. Local
|
|
84
|
-
* argument rejection and a server command error without retry/write-
|
|
85
|
-
* concern ambiguity are definitive. Network, selection, timeout, and
|
|
86
|
-
* write-concern failures retain the reservation for later reconciliation.
|
|
87
|
-
*/
|
|
88
|
-
private isCertifiedCreateNonApplication;
|
|
89
|
-
private storedIncarnationId;
|
|
90
|
-
/**
|
|
91
|
-
* Establish the permanent OID owner for a state that already exists. The
|
|
92
|
-
* ledger outlives active records and tombstones, so purge cannot reopen a
|
|
93
|
-
* revision-zero alias. Duplicate insertion is an ordinary concurrent
|
|
94
|
-
* winner; its durable identity is re-read and adopted.
|
|
95
|
-
*/
|
|
96
|
-
private ensureRecordIdentity;
|
|
97
|
-
/** Claim a never-before-used OID. Any durable owner or active/tombstone state is a collision. */
|
|
98
|
-
private claimNewRecordIdentity;
|
|
99
|
-
/**
|
|
100
|
-
* Compensate an ownership claim this call made but never used.
|
|
101
|
-
*
|
|
102
|
-
* The ledger is otherwise permanent, and deliberately so: a purge must not
|
|
103
|
-
* let an old revision-zero tag alias a recreated incarnation. Releasing is
|
|
104
|
-
* only safe — and only necessary — for a row that still carries the
|
|
105
|
-
* incarnation this call minted and that no active record or tombstone
|
|
106
|
-
* refers to. That is exactly the state a create leaves behind when its
|
|
107
|
-
* insert never reached the collection, and without this the caller-selected
|
|
108
|
-
* OID would be permanently unusable with no operator recovery path. While
|
|
109
|
-
* this row exists its unique index prevents another ordinary create from
|
|
110
|
-
* becoming owner; the exact incarnation selector also cannot remove a row
|
|
111
|
-
* replaced during an operator recovery race.
|
|
112
|
-
*/
|
|
113
|
-
private releaseUnusedRecordIdentity;
|
|
114
|
-
/**
|
|
115
|
-
* Interpret a `findOneAndUpdate`/`findOneAndDelete` result issued with
|
|
116
|
-
* `includeResultMetadata: false`: `null` is a certified no-match and a
|
|
117
|
-
* document is the committed state. Anything else is an unrecognized driver
|
|
118
|
-
* fact that must stay `unknown` rather than being certified either way.
|
|
119
|
-
*/
|
|
120
|
-
private mutationDocument;
|
|
121
|
-
private committed;
|
|
122
|
-
private brandIdOf;
|
|
123
|
-
private activeIdentity;
|
|
124
|
-
private tombstoneIdentity;
|
|
125
|
-
private static readonly BRAND_ID_PATHS;
|
|
126
|
-
private storedBrandId;
|
|
127
|
-
/**
|
|
128
|
-
* Reject candidate keys the driver would read as update operators or
|
|
129
|
-
* dotted paths. Waterline rejected them before the compare-and-set paths
|
|
130
|
-
* started building `$set` documents directly, and honouring them would let
|
|
131
|
-
* a candidate reach fields — such as the stored brand — that the explicit
|
|
132
|
-
* checks above deliberately guard.
|
|
133
|
-
*/
|
|
134
|
-
private unsafeCandidateField;
|
|
135
|
-
/**
|
|
136
|
-
* Read the current state behind a certified no-match so the caller can be
|
|
137
|
-
* told why nothing was written. Cross-brand state is never returned: the
|
|
138
|
-
* reason alone is bounded, and callers outside the brand map it onto the
|
|
139
|
-
* same not-found answer an absent record produces.
|
|
140
|
-
*/
|
|
141
|
-
private readCurrentState;
|
|
142
|
-
private isRequestedBrand;
|
|
143
|
-
private classifyActiveNoMatch;
|
|
144
|
-
private classifyLifecycleTombstoneNoMatch;
|
|
145
|
-
init(): Promise<void>;
|
|
24
|
+
init(): void;
|
|
146
25
|
private registerReadyHook;
|
|
147
26
|
private collectionExists;
|
|
148
27
|
private performInit;
|
|
149
28
|
private createIndices;
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
putRecordSchemaArtifact(artifact: RecordSchemaArtifactInput): Promise<StorageServiceResponse>;
|
|
161
|
-
getRecordSchemaArtifact(digest: string): Promise<RecordSchemaArtifactModel | null>;
|
|
162
|
-
listRecordSchemaArtifacts(query: RecordSchemaArtifactQuery): Promise<RecordSchemaArtifactSummary[]>;
|
|
163
|
-
touchRecordSchemaArtifact(digest: string): Promise<StorageServiceResponse>;
|
|
164
|
-
private storeRecordSchemaReference;
|
|
165
|
-
putRecordSchemaReference(reference: RecordSchemaReferenceInput): Promise<StorageServiceResponse>;
|
|
166
|
-
private recordSchemaQueryString;
|
|
167
|
-
private recordSchemaQueryLimit;
|
|
168
|
-
findRecordSchemaGrantForAuthorization(query: RecordSchemaAuthorizationGrantQuery): Promise<RecordSchemaReferenceModel | null>;
|
|
169
|
-
listRecordSchemaReferences(query: RecordSchemaReferenceQuery): Promise<RecordSchemaReferenceModel[]>;
|
|
170
|
-
private storedRecordSchemaDate;
|
|
171
|
-
create(_brand: BrandingModel, record: JsonMap, _recordType: unknown, _user?: unknown, options?: RecordStorageMutationOptions): Promise<StorageMutationResponse>;
|
|
172
|
-
updateMeta(brand: BrandingModel | null | undefined, oid: string, record: JsonMap, user?: UserModel, options?: RecordStorageMutationOptions): Promise<StorageMutationResponse>;
|
|
173
|
-
/**
|
|
174
|
-
* Dispatch one atomic conditional mutation and turn its single driver fact
|
|
175
|
-
* into a mutation response.
|
|
176
|
-
*
|
|
177
|
-
* The three outcomes are deliberately distinct: a returned document is an
|
|
178
|
-
* applied commit, `null` certifies that the selector matched nothing and
|
|
179
|
-
* therefore that no write happened, and anything else — including a throw
|
|
180
|
-
* after dispatch — stays `unknown`. A failed follow-up classification only
|
|
181
|
-
* costs the precise reason; it never turns a certified no-match into a
|
|
182
|
-
* write, and it never issues one.
|
|
183
|
-
*/
|
|
184
|
-
private commitConditionalMutation;
|
|
185
|
-
removeActiveRecord(brand: BrandingModel | null | undefined, oid: string, options?: RecordStorageMutationOptions): Promise<StorageMutationResponse>;
|
|
186
|
-
createTombstone(brand: BrandingModel | null | undefined, oid: string, record: JsonMap, options?: RecordStorageMutationOptions): Promise<StorageMutationResponse>;
|
|
187
|
-
updateTombstone(brand: BrandingModel | null | undefined, oid: string, record: JsonMap, options?: RecordStorageMutationOptions): Promise<StorageMutationResponse>;
|
|
188
|
-
removeTombstone(brand: BrandingModel | null | undefined, oid: string, options?: RecordStorageMutationOptions): Promise<StorageMutationResponse>;
|
|
189
|
-
createActiveRecordFromTombstone(brand: BrandingModel | null | undefined, oid: string, record: JsonMap, options?: RecordStorageMutationOptions): Promise<StorageMutationResponse>;
|
|
190
|
-
getTombstone(brand: BrandingModel | null | undefined, oid: string): Promise<DeletedRecordModel | null>;
|
|
191
|
-
getLifecycleTombstones(states: readonly string[], limit?: number): Promise<DeletedRecordModel[]>;
|
|
29
|
+
create(_brand: BrandingModel, record: JsonMap, _recordType: unknown, _user?: unknown, options?: RecordWriteOptions): Promise<StorageServiceResponse>;
|
|
30
|
+
updateMeta(brand: BrandingModel, oid: string, record: JsonMap, user?: UserModel, options?: RecordWriteOptions): Promise<StorageServiceResponse>;
|
|
31
|
+
scanFigshareRecords(afterOid: string, limit: number): Promise<RecordModel[]>;
|
|
32
|
+
findFigshareArticleRecords(path: string, articleId: string): Promise<RecordModel[]>;
|
|
33
|
+
setRecordFields(oid: string, fields: JsonMap, expectedVersion: number, allowedPaths: string[]): Promise<RecordFieldWriteResult>;
|
|
34
|
+
readyFigshareIntent(oid: string, saveToken: string): Promise<boolean>;
|
|
35
|
+
pendingFigshareIntents(limit: number, afterOid?: string): Promise<RecordModel[]>;
|
|
36
|
+
abandonFigshareIntent(oid: string, saveToken: string): Promise<boolean>;
|
|
37
|
+
recoverStaleFigshareIntents(staleBefore: string): Promise<number>;
|
|
38
|
+
acknowledgeFigshareIntent(oid: string, generation: number): Promise<boolean>;
|
|
192
39
|
getMeta(oid: string): Promise<RecordModel>;
|
|
193
40
|
getDeletedRecordMeta(oid: string): Promise<RecordModel | null>;
|
|
194
|
-
createBatch(type: string, data: JsonMap[], harvestIdFldName: string): Promise<
|
|
195
|
-
provideUserAccessAndRemovePendingAccess(oid:
|
|
41
|
+
createBatch(type: string, data: JsonMap[], harvestIdFldName: string): Promise<unknown>;
|
|
42
|
+
provideUserAccessAndRemovePendingAccess(oid: any, userid: any, pendingValue: any): void;
|
|
196
43
|
getRelatedRecords(oid: string, brand: BrandingModel, options?: RecordRelationshipExpandOptions): Promise<RecordRelationshipGraph>;
|
|
197
44
|
private walkRelatedRecords;
|
|
198
45
|
private addRelatedObject;
|
|
@@ -200,12 +47,12 @@ export declare namespace Services {
|
|
|
200
47
|
private buildRelationshipCriteria;
|
|
201
48
|
private findRelatedRecords;
|
|
202
49
|
private buildRelationshipEdge;
|
|
203
|
-
delete(oid: string,
|
|
50
|
+
delete(oid: string, permanentlyDelete?: boolean): Promise<StorageServiceResponse>;
|
|
204
51
|
updateNotificationLog(oid: string, record: JsonMap, options: JsonMap): Promise<unknown>;
|
|
205
52
|
private getSortDirection;
|
|
206
53
|
private getRecordSort;
|
|
207
|
-
getDeletedRecords(workflowState: string, recordType: any, start: number, rows: number, username: string, roles: RoleModel[], brand: BrandingModel, _editAccessOnly?: any, packageType?: any, sort?: any, filterFields?: any, filterString?: any, filterMode?: string, secondarySort?: any): Promise<StorageServiceResponse
|
|
208
|
-
getRecords(workflowState: string, recordType: string, start: number, rows: number, username: string, roles: RoleModel[], brand: BrandingModel, _editAccessOnly?: any, packageType?: any, sort?: any, filterFields?: any, filterString?: any, filterMode?: any, secondarySort?: any): Promise<StorageServiceResponse
|
|
54
|
+
getDeletedRecords(workflowState: string, recordType: any, start: number, rows: number, username: string, roles: RoleModel[], brand: BrandingModel, _editAccessOnly?: any, packageType?: any, sort?: any, filterFields?: any, filterString?: any, filterMode?: string, secondarySort?: any): Promise<StorageServiceResponse>;
|
|
55
|
+
getRecords(workflowState: string, recordType: string, start: number, rows: number, username: string, roles: RoleModel[], brand: BrandingModel, _editAccessOnly?: any, packageType?: any, sort?: any, filterFields?: any, filterString?: any, filterMode?: any, secondarySort?: any): Promise<StorageServiceResponse>;
|
|
209
56
|
private escapeRegExp;
|
|
210
57
|
protected runRecordQuery(colName: any, query: any, options: any): Promise<{
|
|
211
58
|
items: mongodb.WithId<mongodb.BSON.Document>[];
|
|
@@ -222,7 +69,6 @@ export declare namespace Services {
|
|
|
222
69
|
addDatastreams(oid: string, fileIds: Datastream[]): Promise<DatastreamServiceResponse>;
|
|
223
70
|
updateDatastream(oid: string, record: StorageRecord, newMetadata: JsonMap, fileRoot: string | StorageManagerServiceTypes.Services.IDisk | null, fileIdsAdded: Datastream[]): Observable<Promise<unknown>[]>;
|
|
224
71
|
removeDatastream(oid: any, datastream: Datastream): Promise<void>;
|
|
225
|
-
removeStagedDatastream(fileId: string): Promise<void>;
|
|
226
72
|
addDatastream(oid: any, datastream: Datastream, stagingDisk?: StorageManagerServiceTypes.Services.IDisk): Promise<void>;
|
|
227
73
|
private streamFileToBucket;
|
|
228
74
|
addAndRemoveDatastreams(oid: any, addIds: Datastream[], removeIds: Datastream[], stagingDisk?: StorageManagerServiceTypes.Services.IDisk): Promise<void>;
|
|
@@ -230,7 +76,6 @@ export declare namespace Services {
|
|
|
230
76
|
private getDatastreamAsync;
|
|
231
77
|
listDatastreams(oid: string, fileId?: string | null): Promise<Record<string, unknown>[]>;
|
|
232
78
|
private toJsonSafe;
|
|
233
|
-
private sanitizeRecordHookExecutionSummary;
|
|
234
79
|
private sanitizeRecordAudit;
|
|
235
80
|
private sanitizeIntegrationAudit;
|
|
236
81
|
createRecordAudit(recordAudit: RecordAuditModel): Promise<StorageServiceResponse>;
|
|
@@ -239,8 +84,8 @@ export declare namespace Services {
|
|
|
239
84
|
private buildIntegrationAuditStartedAtCriteria;
|
|
240
85
|
getIntegrationAudit(params: IntegrationAuditParams): Promise<unknown>;
|
|
241
86
|
countIntegrationAudit(params: IntegrationAuditParams): Promise<number>;
|
|
242
|
-
restoreRecord(oid: string
|
|
243
|
-
destroyDeletedRecord(oid: string
|
|
87
|
+
restoreRecord(oid: string): Promise<StorageServiceResponse>;
|
|
88
|
+
destroyDeletedRecord(oid: string): Promise<StorageServiceResponse>;
|
|
244
89
|
protected getFileWithName(fileName: string, options?: FindOptions): FindCursor<GridFSFile>;
|
|
245
90
|
exists(oid: string): Promise<boolean>;
|
|
246
91
|
}
|