@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.
@@ -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, StorageMutationResponse, DatastreamServiceResponse, Datastream, RecordAuditModel, RecordAuditParams, IntegrationAuditModel, IntegrationAuditParams, RecordModel, type DeletedRecordModel, BrandingModel, UserModel, RoleModel, RecordRelationshipExpandOptions, RecordRelationshipGraph, type RecordStorageMutationOptions, type StorageServiceCapabilities } from '@researchdatabox/redbox-core';
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
- private classifyStorageInitializationError;
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
- private createRecordSchemaIndices;
151
- private createRequiredIndexes;
152
- private recordSchemaSuccess;
153
- private recordSchemaFailure;
154
- private recordSchemaFailureFromError;
155
- private throwRecordSchemaReadFailure;
156
- private artifactCollection;
157
- private referenceCollection;
158
- private recordSchemaReferenceDocument;
159
- private existingArtifactMatches;
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<StorageMutationResponse>;
195
- provideUserAccessAndRemovePendingAccess(oid: string, _userid: unknown, _pendingValue: unknown): Promise<StorageMutationResponse>;
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, _permanentlyDelete?: boolean, options?: RecordStorageMutationOptions): Promise<StorageServiceResponse>;
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<unknown>>;
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<unknown>>;
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, options?: RecordStorageMutationOptions): Promise<StorageServiceResponse>;
243
- destroyDeletedRecord(oid: string, options?: RecordStorageMutationOptions): Promise<StorageServiceResponse>;
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
  }