@durable-streams/server 0.3.5 → 0.3.6
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/index.cjs +4 -2
- package/dist/index.js +4 -2
- package/package.json +3 -3
- package/src/file-store.ts +15 -7
- package/src/store.ts +15 -7
package/dist/index.cjs
CHANGED
|
@@ -187,6 +187,7 @@ var StreamStore = class {
|
|
|
187
187
|
if (sourceStream.softDeleted) throw new Error(`Source stream is soft-deleted: ${options.forkedFrom}`);
|
|
188
188
|
if (this.isExpired(sourceStream)) throw new Error(`Source stream not found: ${options.forkedFrom}`);
|
|
189
189
|
sourceContentType = sourceStream.contentType;
|
|
190
|
+
if (options.contentType && options.contentType.trim() !== `` && normalizeContentType(options.contentType) !== normalizeContentType(sourceContentType)) throw new Error(`Content type mismatch with source stream`);
|
|
190
191
|
if (options.forkOffset) forkOffset = options.forkOffset;
|
|
191
192
|
else forkOffset = sourceStream.currentOffset;
|
|
192
193
|
const zeroOffset = `0000000000000000_0000000000000000`;
|
|
@@ -197,7 +198,7 @@ var StreamStore = class {
|
|
|
197
198
|
let contentType = options.contentType;
|
|
198
199
|
if (!contentType || contentType.trim() === ``) {
|
|
199
200
|
if (isFork) contentType = sourceContentType;
|
|
200
|
-
}
|
|
201
|
+
}
|
|
201
202
|
let effectiveExpiresAt = options.expiresAt;
|
|
202
203
|
let effectiveTtlSeconds = options.ttlSeconds;
|
|
203
204
|
if (isFork) {
|
|
@@ -1385,6 +1386,7 @@ var FileBackedStreamStore = class {
|
|
|
1385
1386
|
if (sourceMeta.softDeleted) throw new Error(`Source stream is soft-deleted: ${options.forkedFrom}`);
|
|
1386
1387
|
if (this.isExpired(sourceMeta)) throw new Error(`Source stream not found: ${options.forkedFrom}`);
|
|
1387
1388
|
sourceContentType = sourceMeta.contentType;
|
|
1389
|
+
if (options.contentType && options.contentType.trim() !== `` && normalizeContentType(options.contentType) !== normalizeContentType(sourceContentType)) throw new Error(`Content type mismatch with source stream`);
|
|
1388
1390
|
if (options.forkOffset) forkOffset = options.forkOffset;
|
|
1389
1391
|
else forkOffset = sourceMeta.currentOffset;
|
|
1390
1392
|
const zeroOffset = `0000000000000000_0000000000000000`;
|
|
@@ -1400,7 +1402,7 @@ var FileBackedStreamStore = class {
|
|
|
1400
1402
|
let contentType = options.contentType;
|
|
1401
1403
|
if (!contentType || contentType.trim() === ``) {
|
|
1402
1404
|
if (isFork) contentType = sourceContentType;
|
|
1403
|
-
}
|
|
1405
|
+
}
|
|
1404
1406
|
let effectiveExpiresAt = options.expiresAt;
|
|
1405
1407
|
let effectiveTtlSeconds = options.ttlSeconds;
|
|
1406
1408
|
if (isFork) {
|
package/dist/index.js
CHANGED
|
@@ -163,6 +163,7 @@ var StreamStore = class {
|
|
|
163
163
|
if (sourceStream.softDeleted) throw new Error(`Source stream is soft-deleted: ${options.forkedFrom}`);
|
|
164
164
|
if (this.isExpired(sourceStream)) throw new Error(`Source stream not found: ${options.forkedFrom}`);
|
|
165
165
|
sourceContentType = sourceStream.contentType;
|
|
166
|
+
if (options.contentType && options.contentType.trim() !== `` && normalizeContentType(options.contentType) !== normalizeContentType(sourceContentType)) throw new Error(`Content type mismatch with source stream`);
|
|
166
167
|
if (options.forkOffset) forkOffset = options.forkOffset;
|
|
167
168
|
else forkOffset = sourceStream.currentOffset;
|
|
168
169
|
const zeroOffset = `0000000000000000_0000000000000000`;
|
|
@@ -173,7 +174,7 @@ var StreamStore = class {
|
|
|
173
174
|
let contentType = options.contentType;
|
|
174
175
|
if (!contentType || contentType.trim() === ``) {
|
|
175
176
|
if (isFork) contentType = sourceContentType;
|
|
176
|
-
}
|
|
177
|
+
}
|
|
177
178
|
let effectiveExpiresAt = options.expiresAt;
|
|
178
179
|
let effectiveTtlSeconds = options.ttlSeconds;
|
|
179
180
|
if (isFork) {
|
|
@@ -1361,6 +1362,7 @@ var FileBackedStreamStore = class {
|
|
|
1361
1362
|
if (sourceMeta.softDeleted) throw new Error(`Source stream is soft-deleted: ${options.forkedFrom}`);
|
|
1362
1363
|
if (this.isExpired(sourceMeta)) throw new Error(`Source stream not found: ${options.forkedFrom}`);
|
|
1363
1364
|
sourceContentType = sourceMeta.contentType;
|
|
1365
|
+
if (options.contentType && options.contentType.trim() !== `` && normalizeContentType(options.contentType) !== normalizeContentType(sourceContentType)) throw new Error(`Content type mismatch with source stream`);
|
|
1364
1366
|
if (options.forkOffset) forkOffset = options.forkOffset;
|
|
1365
1367
|
else forkOffset = sourceMeta.currentOffset;
|
|
1366
1368
|
const zeroOffset = `0000000000000000_0000000000000000`;
|
|
@@ -1376,7 +1378,7 @@ var FileBackedStreamStore = class {
|
|
|
1376
1378
|
let contentType = options.contentType;
|
|
1377
1379
|
if (!contentType || contentType.trim() === ``) {
|
|
1378
1380
|
if (isFork) contentType = sourceContentType;
|
|
1379
|
-
}
|
|
1381
|
+
}
|
|
1380
1382
|
let effectiveExpiresAt = options.expiresAt;
|
|
1381
1383
|
let effectiveTtlSeconds = options.ttlSeconds;
|
|
1382
1384
|
if (isFork) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@durable-streams/server",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.6",
|
|
4
4
|
"description": "Node.js reference server implementation for Durable Streams",
|
|
5
5
|
"author": "Durable Stream contributors",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -40,14 +40,14 @@
|
|
|
40
40
|
"@neophi/sieve-cache": "^1.0.0",
|
|
41
41
|
"lmdb": "^3.3.0",
|
|
42
42
|
"@durable-streams/client": "0.2.6",
|
|
43
|
-
"@durable-streams/state": "0.
|
|
43
|
+
"@durable-streams/state": "0.3.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/node": "^22.0.0",
|
|
47
47
|
"tsdown": "^0.9.0",
|
|
48
48
|
"typescript": "^5.0.0",
|
|
49
49
|
"vitest": "^4.0.0",
|
|
50
|
-
"@durable-streams/server-conformance-tests": "0.3.
|
|
50
|
+
"@durable-streams/server-conformance-tests": "0.3.5"
|
|
51
51
|
},
|
|
52
52
|
"files": [
|
|
53
53
|
"dist",
|
package/src/file-store.ts
CHANGED
|
@@ -818,6 +818,18 @@ export class FileBackedStreamStore {
|
|
|
818
818
|
|
|
819
819
|
sourceContentType = sourceMeta.contentType
|
|
820
820
|
|
|
821
|
+
// Reject a content-type mismatch up front, before taking a reference on
|
|
822
|
+
// the source. Doing this after the refCount increment below would leak a
|
|
823
|
+
// reference on the failed fork and pin the source in a soft-deleted state.
|
|
824
|
+
if (
|
|
825
|
+
options.contentType &&
|
|
826
|
+
options.contentType.trim() !== `` &&
|
|
827
|
+
normalizeContentType(options.contentType) !==
|
|
828
|
+
normalizeContentType(sourceContentType)
|
|
829
|
+
) {
|
|
830
|
+
throw new Error(`Content type mismatch with source stream`)
|
|
831
|
+
}
|
|
832
|
+
|
|
821
833
|
// Resolve fork offset: use provided or source's currentOffset
|
|
822
834
|
if (options.forkOffset) {
|
|
823
835
|
forkOffset = options.forkOffset
|
|
@@ -851,18 +863,14 @@ export class FileBackedStreamStore {
|
|
|
851
863
|
this.db.putSync(sourceKey, updatedSource)
|
|
852
864
|
}
|
|
853
865
|
|
|
854
|
-
// Determine content type: use options, or inherit from source if fork
|
|
866
|
+
// Determine content type: use options, or inherit from source if fork. A
|
|
867
|
+
// fork content-type mismatch is already rejected above, before the source
|
|
868
|
+
// refCount is taken.
|
|
855
869
|
let contentType = options.contentType
|
|
856
870
|
if (!contentType || contentType.trim() === ``) {
|
|
857
871
|
if (isFork) {
|
|
858
872
|
contentType = sourceContentType
|
|
859
873
|
}
|
|
860
|
-
} else if (
|
|
861
|
-
isFork &&
|
|
862
|
-
normalizeContentType(contentType) !==
|
|
863
|
-
normalizeContentType(sourceContentType)
|
|
864
|
-
) {
|
|
865
|
-
throw new Error(`Content type mismatch with source stream`)
|
|
866
874
|
}
|
|
867
875
|
|
|
868
876
|
// Compute effective expiry for forks
|
package/src/store.ts
CHANGED
|
@@ -329,6 +329,18 @@ export class StreamStore {
|
|
|
329
329
|
|
|
330
330
|
sourceContentType = sourceStream.contentType
|
|
331
331
|
|
|
332
|
+
// Reject a content-type mismatch up front, before taking a reference on
|
|
333
|
+
// the source. Doing this after the refCount increment below would leak a
|
|
334
|
+
// reference on the failed fork and pin the source in a soft-deleted state.
|
|
335
|
+
if (
|
|
336
|
+
options.contentType &&
|
|
337
|
+
options.contentType.trim() !== `` &&
|
|
338
|
+
normalizeContentType(options.contentType) !==
|
|
339
|
+
normalizeContentType(sourceContentType)
|
|
340
|
+
) {
|
|
341
|
+
throw new Error(`Content type mismatch with source stream`)
|
|
342
|
+
}
|
|
343
|
+
|
|
332
344
|
// Resolve fork offset: use provided or source's currentOffset
|
|
333
345
|
if (options.forkOffset) {
|
|
334
346
|
forkOffset = options.forkOffset
|
|
@@ -358,18 +370,14 @@ export class StreamStore {
|
|
|
358
370
|
sourceStream.refCount++
|
|
359
371
|
}
|
|
360
372
|
|
|
361
|
-
// Determine content type: use options, or inherit from source if fork
|
|
373
|
+
// Determine content type: use options, or inherit from source if fork. A
|
|
374
|
+
// fork content-type mismatch is already rejected above, before the source
|
|
375
|
+
// refCount is taken.
|
|
362
376
|
let contentType = options.contentType
|
|
363
377
|
if (!contentType || contentType.trim() === ``) {
|
|
364
378
|
if (isFork) {
|
|
365
379
|
contentType = sourceContentType
|
|
366
380
|
}
|
|
367
|
-
} else if (
|
|
368
|
-
isFork &&
|
|
369
|
-
normalizeContentType(contentType) !==
|
|
370
|
-
normalizeContentType(sourceContentType)
|
|
371
|
-
) {
|
|
372
|
-
throw new Error(`Content type mismatch with source stream`)
|
|
373
381
|
}
|
|
374
382
|
|
|
375
383
|
// Compute effective expiry for forks
|