@nestm/storage 0.1.0-alpha.14 → 0.1.0-alpha.16
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/CHANGELOG.md +12 -0
- package/README.md +40 -0
- package/dist/ai-sdk/ai-sdk-file-workflow-tools.d.ts +16 -2
- package/dist/ai-sdk/ai-sdk-file-workflow-tools.d.ts.map +1 -1
- package/dist/ai-sdk/ai-sdk-file-workflow-tools.js +99 -11
- package/dist/ai-sdk/ai-sdk-file-workflow-tools.js.map +1 -1
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/storage-text-edit.d.ts +38 -0
- package/dist/core/storage-text-edit.d.ts.map +1 -0
- package/dist/core/storage-text-edit.js +86 -0
- package/dist/core/storage-text-edit.js.map +1 -0
- package/dist/core/storage-text.d.ts +1 -12
- package/dist/core/storage-text.d.ts.map +1 -1
- package/dist/core/storage-text.js +1 -30
- package/dist/core/storage-text.js.map +1 -1
- package/dist/workspace/index.d.ts +1 -0
- package/dist/workspace/index.d.ts.map +1 -1
- package/dist/workspace/index.js +1 -0
- package/dist/workspace/index.js.map +1 -1
- package/dist/workspace/storage-catalog-checkout.d.ts +7 -0
- package/dist/workspace/storage-catalog-checkout.d.ts.map +1 -0
- package/dist/workspace/storage-catalog-checkout.js +46 -0
- package/dist/workspace/storage-catalog-checkout.js.map +1 -0
- package/dist/workspace/storage-file-workflow.d.ts.map +1 -1
- package/dist/workspace/storage-file-workflow.js +116 -1
- package/dist/workspace/storage-file-workflow.js.map +1 -1
- package/dist/workspace/storage-file-workflow.protection.d.ts.map +1 -1
- package/dist/workspace/storage-file-workflow.protection.js +41 -5
- package/dist/workspace/storage-file-workflow.protection.js.map +1 -1
- package/dist/workspace/storage-file-workflow.types.d.ts +24 -0
- package/dist/workspace/storage-file-workflow.types.d.ts.map +1 -1
- package/dist/workspace/storage-file-workflow.types.js +2 -0
- package/dist/workspace/storage-file-workflow.types.js.map +1 -1
- package/dist/workspace/storage-text-draft.d.ts +20 -0
- package/dist/workspace/storage-text-draft.d.ts.map +1 -0
- package/dist/workspace/storage-text-draft.js +80 -0
- package/dist/workspace/storage-text-draft.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { StorageStagedContent } from '../core/storage-staged-content.js';
|
|
2
|
+
import type { StorageFileDraftRecord, StorageFileWorkflowLimits, StorageFileWorkflowTransaction } from './storage-file-workflow.types.js';
|
|
3
|
+
/** Stage bytes outside the host transaction, then atomically publish all part references. */
|
|
4
|
+
export declare function stageStorageTextDraft<Scope, Receipt>(options: {
|
|
5
|
+
readonly scope: Scope;
|
|
6
|
+
readonly signal: AbortSignal;
|
|
7
|
+
readonly limits: Readonly<StorageFileWorkflowLimits>;
|
|
8
|
+
readonly content: StorageStagedContent<Scope>;
|
|
9
|
+
readonly idempotencyKey: string;
|
|
10
|
+
readonly fingerprint: string;
|
|
11
|
+
readonly requireMutation: (expectedEtag: string | null) => void;
|
|
12
|
+
readonly transaction: <T>(work: (tx: StorageFileWorkflowTransaction<Receipt>) => Promise<T>) => Promise<T>;
|
|
13
|
+
readonly load: () => Promise<{
|
|
14
|
+
content: string;
|
|
15
|
+
path: string;
|
|
16
|
+
expectedEtag: string | null;
|
|
17
|
+
source: StorageFileDraftRecord<Receipt> | null;
|
|
18
|
+
}>;
|
|
19
|
+
}): Promise<StorageFileDraftRecord<Receipt>>;
|
|
20
|
+
//# sourceMappingURL=storage-text-draft.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-text-draft.d.ts","sourceRoot":"","sources":["../../src/workspace/storage-text-draft.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,KAAK,EACV,sBAAsB,EAEtB,yBAAyB,EACzB,8BAA8B,EAC/B,MAAM,kCAAkC,CAAC;AAE1C,6FAA6F;AAC7F,wBAAsB,qBAAqB,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE;IACnE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,yBAAyB,CAAC,CAAC;IACrD,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAC9C,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,eAAe,EAAE,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAChE,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,EACtB,IAAI,EAAE,CAAC,EAAE,EAAE,8BAA8B,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,KAC9D,OAAO,CAAC,CAAC,CAAC,CAAC;IAChB,QAAQ,CAAC,IAAI,EAAE,MAAM,OAAO,CAAC;QAC3B,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,MAAM,EAAE,sBAAsB,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;KAChD,CAAC,CAAC;CACJ,GAAG,OAAO,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC,CAuF3C"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
2
|
+
import { StorageError } from '../storage.error.js';
|
|
3
|
+
import { storageBytesStream } from '../core/storage-streams.js';
|
|
4
|
+
/** Stage bytes outside the host transaction, then atomically publish all part references. */
|
|
5
|
+
export async function stageStorageTextDraft(options) {
|
|
6
|
+
const { transaction, signal, limits } = options;
|
|
7
|
+
const replay = async (tx) => {
|
|
8
|
+
const prior = await tx.findDraftByKey(options.idempotencyKey);
|
|
9
|
+
if (prior !== null) {
|
|
10
|
+
options.requireMutation(prior.expectedEtag);
|
|
11
|
+
if (prior.requestFingerprint !== options.fingerprint)
|
|
12
|
+
throw new StorageError('Draft key was already used for different input.', { code: 'CONFLICT' });
|
|
13
|
+
}
|
|
14
|
+
return prior;
|
|
15
|
+
};
|
|
16
|
+
const prior = await transaction(replay);
|
|
17
|
+
if (prior !== null)
|
|
18
|
+
return prior;
|
|
19
|
+
const loaded = await options.load();
|
|
20
|
+
options.requireMutation(loaded.expectedEtag);
|
|
21
|
+
if (/[\uD800-\uDFFF]/u.test(loaded.content))
|
|
22
|
+
throw new StorageError('Text must be well-formed UTF-8.', {
|
|
23
|
+
code: 'INVALID_ARGUMENT',
|
|
24
|
+
});
|
|
25
|
+
const bytes = new TextEncoder().encode(loaded.content);
|
|
26
|
+
if (bytes.byteLength > limits.maxTextBytes)
|
|
27
|
+
throw new StorageError('Text checkpoint exceeds the buffered text limit.', {
|
|
28
|
+
code: 'LIMIT_EXCEEDED',
|
|
29
|
+
});
|
|
30
|
+
if (limits.maxChunkBytes < 4)
|
|
31
|
+
throw new StorageError('Text checkpoints require a chunk limit of at least four bytes.', { code: 'LIMIT_EXCEEDED' });
|
|
32
|
+
const parts = [];
|
|
33
|
+
for (let offset = 0; offset < bytes.length;) {
|
|
34
|
+
signal.throwIfAborted();
|
|
35
|
+
let end = Math.min(bytes.length, offset + limits.maxChunkBytes);
|
|
36
|
+
while (end < bytes.length && (bytes[end] & 0xc0) === 0x80)
|
|
37
|
+
end--;
|
|
38
|
+
const chunk = bytes.subarray(offset, end);
|
|
39
|
+
const body = await options.content.write(options.scope, storageBytesStream(chunk), { maxBytes: limits.maxChunkBytes, signal });
|
|
40
|
+
if (body.size !== chunk.length ||
|
|
41
|
+
body.sha256 !== createHash('sha256').update(chunk).digest('hex'))
|
|
42
|
+
throw new StorageError('Invalid text chunk receipt.', {
|
|
43
|
+
code: 'PROVIDER',
|
|
44
|
+
});
|
|
45
|
+
parts.push({ offset, size: body.size, sha256: body.sha256, body });
|
|
46
|
+
offset = end;
|
|
47
|
+
}
|
|
48
|
+
return transaction(async (tx) => {
|
|
49
|
+
const concurrent = await replay(tx);
|
|
50
|
+
if (concurrent !== null)
|
|
51
|
+
return concurrent;
|
|
52
|
+
if (loaded.source !== null) {
|
|
53
|
+
const current = await tx.getDraft(loaded.source.id);
|
|
54
|
+
if (current === null ||
|
|
55
|
+
current.size !== loaded.source.size ||
|
|
56
|
+
!['open', 'sealed'].includes(current.status))
|
|
57
|
+
throw new StorageError('The source draft changed while editing. Read its latest size.', { code: 'CONFLICT' });
|
|
58
|
+
await tx.saveDraft({ ...current, status: 'sealed' });
|
|
59
|
+
}
|
|
60
|
+
const draft = {
|
|
61
|
+
id: randomUUID(),
|
|
62
|
+
path: loaded.path,
|
|
63
|
+
expectedEtag: loaded.expectedEtag,
|
|
64
|
+
sourceDraftId: loaded.source?.id ?? null,
|
|
65
|
+
text: true,
|
|
66
|
+
status: 'sealed',
|
|
67
|
+
size: bytes.length,
|
|
68
|
+
result: null,
|
|
69
|
+
createdAt: new Date().toISOString(),
|
|
70
|
+
idempotencyKey: options.idempotencyKey,
|
|
71
|
+
requestFingerprint: options.fingerprint,
|
|
72
|
+
body: null,
|
|
73
|
+
};
|
|
74
|
+
await tx.saveDraft(draft);
|
|
75
|
+
for (const part of parts)
|
|
76
|
+
await tx.putPart(draft.id, part);
|
|
77
|
+
return draft;
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=storage-text-draft.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-text-draft.js","sourceRoot":"","sources":["../../src/workspace/storage-text-draft.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, randomUUID } from 'node:crypto';\nimport { StorageError } from '../storage.error.js';\nimport { storageBytesStream } from '../core/storage-streams.js';\nimport type { StorageStagedContent } from '../core/storage-staged-content.js';\nimport type {\n StorageFileDraftRecord,\n StorageFilePartRecord,\n StorageFileWorkflowLimits,\n StorageFileWorkflowTransaction,\n} from './storage-file-workflow.types.js';\n\n/** Stage bytes outside the host transaction, then atomically publish all part references. */\nexport async function stageStorageTextDraft<Scope, Receipt>(options: {\n readonly scope: Scope;\n readonly signal: AbortSignal;\n readonly limits: Readonly<StorageFileWorkflowLimits>;\n readonly content: StorageStagedContent<Scope>;\n readonly idempotencyKey: string;\n readonly fingerprint: string;\n readonly requireMutation: (expectedEtag: string | null) => void;\n readonly transaction: <T>(\n work: (tx: StorageFileWorkflowTransaction<Receipt>) => Promise<T>,\n ) => Promise<T>;\n readonly load: () => Promise<{\n content: string;\n path: string;\n expectedEtag: string | null;\n source: StorageFileDraftRecord<Receipt> | null;\n }>;\n}): Promise<StorageFileDraftRecord<Receipt>> {\n const { transaction, signal, limits } = options;\n const replay = async (tx: StorageFileWorkflowTransaction<Receipt>) => {\n const prior = await tx.findDraftByKey(options.idempotencyKey);\n if (prior !== null) {\n options.requireMutation(prior.expectedEtag);\n if (prior.requestFingerprint !== options.fingerprint)\n throw new StorageError(\n 'Draft key was already used for different input.',\n { code: 'CONFLICT' },\n );\n }\n return prior;\n };\n const prior = await transaction(replay);\n if (prior !== null) return prior;\n const loaded = await options.load();\n options.requireMutation(loaded.expectedEtag);\n if (/[\\uD800-\\uDFFF]/u.test(loaded.content))\n throw new StorageError('Text must be well-formed UTF-8.', {\n code: 'INVALID_ARGUMENT',\n });\n const bytes = new TextEncoder().encode(loaded.content);\n if (bytes.byteLength > limits.maxTextBytes)\n throw new StorageError('Text checkpoint exceeds the buffered text limit.', {\n code: 'LIMIT_EXCEEDED',\n });\n if (limits.maxChunkBytes < 4)\n throw new StorageError(\n 'Text checkpoints require a chunk limit of at least four bytes.',\n { code: 'LIMIT_EXCEEDED' },\n );\n const parts: StorageFilePartRecord[] = [];\n for (let offset = 0; offset < bytes.length;) {\n signal.throwIfAborted();\n let end = Math.min(bytes.length, offset + limits.maxChunkBytes);\n while (end < bytes.length && (bytes[end]! & 0xc0) === 0x80) end--;\n const chunk = bytes.subarray(offset, end);\n const body = await options.content.write(\n options.scope,\n storageBytesStream(chunk),\n { maxBytes: limits.maxChunkBytes, signal },\n );\n if (\n body.size !== chunk.length ||\n body.sha256 !== createHash('sha256').update(chunk).digest('hex')\n )\n throw new StorageError('Invalid text chunk receipt.', {\n code: 'PROVIDER',\n });\n parts.push({ offset, size: body.size, sha256: body.sha256, body });\n offset = end;\n }\n return transaction(async (tx) => {\n const concurrent = await replay(tx);\n if (concurrent !== null) return concurrent;\n if (loaded.source !== null) {\n const current = await tx.getDraft(loaded.source.id);\n if (\n current === null ||\n current.size !== loaded.source.size ||\n !['open', 'sealed'].includes(current.status)\n )\n throw new StorageError(\n 'The source draft changed while editing. Read its latest size.',\n { code: 'CONFLICT' },\n );\n await tx.saveDraft({ ...current, status: 'sealed' });\n }\n const draft: StorageFileDraftRecord<Receipt> = {\n id: randomUUID(),\n path: loaded.path,\n expectedEtag: loaded.expectedEtag,\n sourceDraftId: loaded.source?.id ?? null,\n text: true,\n status: 'sealed',\n size: bytes.length,\n result: null,\n createdAt: new Date().toISOString(),\n idempotencyKey: options.idempotencyKey,\n requestFingerprint: options.fingerprint,\n body: null,\n };\n await tx.saveDraft(draft);\n for (const part of parts) await tx.putPart(draft.id, part);\n return draft;\n });\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nestm/storage",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.16",
|
|
4
4
|
"description": "Framework-neutral storage clients, capability-scoped agent workspaces, NestJS 12 integration, and guarded HTTP access.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Kauan Guesser",
|