@storacha/encrypt-upload-client 1.1.56 → 1.1.58

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.
Files changed (72) hide show
  1. package/dist/config/constants.d.ts +3 -3
  2. package/dist/config/constants.js +4 -3
  3. package/dist/config/env.d.ts +9 -6
  4. package/dist/config/service.d.ts +13 -13
  5. package/dist/core/client.d.ts +54 -41
  6. package/dist/core/client.js +68 -56
  7. package/dist/core/errors.d.ts +6 -6
  8. package/dist/core/metadata/encrypted-metadata.d.ts +13 -8
  9. package/dist/core/metadata/kms-metadata.d.ts +68 -36
  10. package/dist/core/metadata/lit-metadata.d.ts +63 -28
  11. package/dist/crypto/adapters/kms-crypto-adapter.d.ts +172 -137
  12. package/dist/crypto/adapters/lit-crypto-adapter.d.ts +107 -86
  13. package/dist/crypto/factories.browser.d.ts +9 -5
  14. package/dist/crypto/factories.browser.js +15 -7
  15. package/dist/crypto/factories.node.d.ts +13 -6
  16. package/dist/crypto/factories.node.js +19 -13
  17. package/dist/crypto/index.d.ts +5 -5
  18. package/dist/crypto/index.js +5 -5
  19. package/dist/crypto/symmetric/generic-aes-ctr-streaming-crypto.d.ts +58 -54
  20. package/dist/crypto/symmetric/generic-aes-ctr-streaming-crypto.js +174 -146
  21. package/dist/crypto/symmetric/node-aes-cbc-crypto.d.ts +36 -32
  22. package/dist/crypto/symmetric/node-aes-cbc-crypto.js +101 -95
  23. package/dist/examples/decrypt-test.d.ts +2 -2
  24. package/dist/examples/decrypt-test.js +78 -69
  25. package/dist/examples/encrypt-test.d.ts +5 -3
  26. package/dist/examples/encrypt-test.js +58 -55
  27. package/dist/handlers/decrypt-handler.d.ts +19 -5
  28. package/dist/handlers/encrypt-handler.d.ts +9 -3
  29. package/dist/handlers/encrypt-handler.js +93 -57
  30. package/dist/index.d.ts +2 -2
  31. package/dist/index.js +2 -2
  32. package/dist/protocols/lit.d.ts +33 -9
  33. package/dist/protocols/lit.js +134 -98
  34. package/dist/test/cid-verification.spec.d.ts +2 -2
  35. package/dist/test/cid-verification.spec.js +341 -313
  36. package/dist/test/crypto-compatibility.spec.d.ts +2 -2
  37. package/dist/test/crypto-compatibility.spec.js +184 -120
  38. package/dist/test/crypto-counter-security.spec.d.ts +2 -2
  39. package/dist/test/crypto-counter-security.spec.js +177 -138
  40. package/dist/test/crypto-streaming.spec.d.ts +2 -2
  41. package/dist/test/crypto-streaming.spec.js +208 -126
  42. package/dist/test/encrypted-metadata.spec.d.ts +2 -2
  43. package/dist/test/encrypted-metadata.spec.js +89 -62
  44. package/dist/test/factories.spec.d.ts +2 -2
  45. package/dist/test/factories.spec.js +275 -139
  46. package/dist/test/file-metadata.spec.d.ts +2 -2
  47. package/dist/test/file-metadata.spec.js +472 -416
  48. package/dist/test/fixtures/test-fixtures.d.ts +25 -20
  49. package/dist/test/fixtures/test-fixtures.js +61 -53
  50. package/dist/test/helpers/test-file-utils.d.ts +19 -14
  51. package/dist/test/helpers/test-file-utils.js +78 -76
  52. package/dist/test/https-enforcement.spec.d.ts +2 -2
  53. package/dist/test/https-enforcement.spec.js +278 -124
  54. package/dist/test/kms-crypto-adapter.spec.d.ts +2 -2
  55. package/dist/test/kms-crypto-adapter.spec.js +473 -304
  56. package/dist/test/lit-crypto-adapter.spec.d.ts +2 -2
  57. package/dist/test/lit-crypto-adapter.spec.js +206 -118
  58. package/dist/test/memory-efficiency.spec.d.ts +2 -2
  59. package/dist/test/memory-efficiency.spec.js +100 -87
  60. package/dist/test/mocks/key-manager.d.ts +71 -38
  61. package/dist/test/mocks/key-manager.js +129 -113
  62. package/dist/test/node-crypto-adapter.spec.d.ts +2 -2
  63. package/dist/test/node-crypto-adapter.spec.js +155 -102
  64. package/dist/test/node-generic-crypto-adapter.spec.d.ts +2 -2
  65. package/dist/test/node-generic-crypto-adapter.spec.js +134 -94
  66. package/dist/test/setup.d.ts +2 -2
  67. package/dist/test/setup.js +8 -9
  68. package/dist/tsconfig.spec.tsbuildinfo +1 -1
  69. package/dist/types.d.ts +219 -181
  70. package/dist/utils/file-metadata.d.ts +19 -13
  71. package/dist/utils.d.ts +14 -5
  72. package/package.json +4 -4
@@ -2,27 +2,32 @@
2
2
  * Generate mock RSA key pair for testing that works with Web Crypto API
3
3
  */
4
4
  export function generateMockRSAKeyPair(): Promise<{
5
- keyPair: CryptoKeyPair;
6
- publicKeyPem: string;
7
- }>;
5
+ keyPair: CryptoKeyPair
6
+ publicKeyPem: string
7
+ }>
8
8
  /**
9
9
  * Helper to create test fixtures
10
10
  */
11
11
  export function createTestFixtures(): Promise<{
12
- keyManagerServiceDID: ed25519.EdSigner;
13
- spaceDID: `did:key:${string}`;
14
- spaceSigner: ed25519.EdSigner;
15
- issuer: ed25519.EdSigner;
16
- keyPair: CryptoKeyPair;
17
- publicKeyPem: string;
18
- delegationProof: Server.API.Delegation<[{
19
- with: `did:key:${string}`;
20
- can: "space/encryption/setup";
21
- }, {
22
- with: `did:key:${string}`;
23
- can: "space/encryption/key/decrypt";
24
- }]>;
25
- }>;
26
- import { ed25519 } from '@ucanto/principal';
27
- import * as Server from '@ucanto/server';
28
- //# sourceMappingURL=test-fixtures.d.ts.map
12
+ keyManagerServiceDID: ed25519.EdSigner
13
+ spaceDID: `did:key:${string}`
14
+ spaceSigner: ed25519.EdSigner
15
+ issuer: ed25519.EdSigner
16
+ keyPair: CryptoKeyPair
17
+ publicKeyPem: string
18
+ delegationProof: Server.API.Delegation<
19
+ [
20
+ {
21
+ with: `did:key:${string}`
22
+ can: 'space/encryption/setup'
23
+ },
24
+ {
25
+ with: `did:key:${string}`
26
+ can: 'space/encryption/key/decrypt'
27
+ }
28
+ ]
29
+ >
30
+ }>
31
+ import { ed25519 } from '@ucanto/principal'
32
+ import * as Server from '@ucanto/server'
33
+ //# sourceMappingURL=test-fixtures.d.ts.map
@@ -1,63 +1,71 @@
1
- import * as Server from '@ucanto/server';
2
- import { ed25519 } from '@ucanto/principal';
1
+ import * as Server from '@ucanto/server'
2
+ import { ed25519 } from '@ucanto/principal'
3
3
  /**
4
4
  * Generate mock RSA key pair for testing that works with Web Crypto API
5
5
  */
6
6
  export async function generateMockRSAKeyPair() {
7
- // Generate key pair using Web Crypto API first
8
- const keyPair = await globalThis.crypto.subtle.generateKey({
9
- name: 'RSA-OAEP',
10
- modulusLength: 2048,
11
- publicExponent: new Uint8Array([1, 0, 1]),
12
- hash: 'SHA-256',
13
- }, true, ['encrypt', 'decrypt']);
14
- // Export public key to SPKI format (this will work with our adapter)
15
- const publicKeyBuffer = await globalThis.crypto.subtle.exportKey('spki', keyPair.publicKey);
16
- // Convert to proper PEM format using standard base64 (not multibase)
17
- const base64String = Buffer.from(publicKeyBuffer).toString('base64');
18
- // Format as proper PEM with line breaks every 64 characters like real KMS
19
- const formattedBase64 = base64String.match(/.{1,64}/g)?.join('\n') || base64String;
20
- const publicKeyPem = `-----BEGIN PUBLIC KEY-----\n${formattedBase64}\n-----END PUBLIC KEY-----`;
21
- return {
22
- keyPair,
23
- publicKeyPem,
24
- };
7
+ // Generate key pair using Web Crypto API first
8
+ const keyPair = await globalThis.crypto.subtle.generateKey(
9
+ {
10
+ name: 'RSA-OAEP',
11
+ modulusLength: 2048,
12
+ publicExponent: new Uint8Array([1, 0, 1]),
13
+ hash: 'SHA-256',
14
+ },
15
+ true,
16
+ ['encrypt', 'decrypt']
17
+ )
18
+ // Export public key to SPKI format (this will work with our adapter)
19
+ const publicKeyBuffer = await globalThis.crypto.subtle.exportKey(
20
+ 'spki',
21
+ keyPair.publicKey
22
+ )
23
+ // Convert to proper PEM format using standard base64 (not multibase)
24
+ const base64String = Buffer.from(publicKeyBuffer).toString('base64')
25
+ // Format as proper PEM with line breaks every 64 characters like real KMS
26
+ const formattedBase64 =
27
+ base64String.match(/.{1,64}/g)?.join('\n') || base64String
28
+ const publicKeyPem = `-----BEGIN PUBLIC KEY-----\n${formattedBase64}\n-----END PUBLIC KEY-----`
29
+ return {
30
+ keyPair,
31
+ publicKeyPem,
32
+ }
25
33
  }
26
34
  /**
27
35
  * Helper to create test fixtures
28
36
  */
29
37
  export async function createTestFixtures() {
30
- // Create mock key manager service DID
31
- const keyManagerServiceDID = await ed25519.generate();
32
- // Create mock space DID - this will be the issuer
33
- const spaceSigner = await ed25519.generate();
34
- const spaceDID = spaceSigner.did();
35
- // Generate mock RSA key pair
36
- const { keyPair, publicKeyPem } = await generateMockRSAKeyPair();
37
- // Create mock delegation proof - space delegates to itself (self-issued)
38
- const delegationProof = await Server.delegate({
39
- issuer: spaceSigner,
40
- audience: spaceSigner, // Self-delegation for testing
41
- capabilities: [
42
- {
43
- with: spaceDID,
44
- can: 'space/encryption/setup',
45
- },
46
- {
47
- with: spaceDID,
48
- can: 'space/encryption/key/decrypt',
49
- },
50
- ],
51
- expiration: Infinity,
52
- });
53
- return {
54
- keyManagerServiceDID,
55
- spaceDID,
56
- spaceSigner,
57
- issuer: spaceSigner, // Use space signer as issuer
58
- keyPair,
59
- publicKeyPem,
60
- delegationProof,
61
- };
38
+ // Create mock key manager service DID
39
+ const keyManagerServiceDID = await ed25519.generate()
40
+ // Create mock space DID - this will be the issuer
41
+ const spaceSigner = await ed25519.generate()
42
+ const spaceDID = spaceSigner.did()
43
+ // Generate mock RSA key pair
44
+ const { keyPair, publicKeyPem } = await generateMockRSAKeyPair()
45
+ // Create mock delegation proof - space delegates to itself (self-issued)
46
+ const delegationProof = await Server.delegate({
47
+ issuer: spaceSigner,
48
+ audience: spaceSigner, // Self-delegation for testing
49
+ capabilities: [
50
+ {
51
+ with: spaceDID,
52
+ can: 'space/encryption/setup',
53
+ },
54
+ {
55
+ with: spaceDID,
56
+ can: 'space/encryption/key/decrypt',
57
+ },
58
+ ],
59
+ expiration: Infinity,
60
+ })
61
+ return {
62
+ keyManagerServiceDID,
63
+ spaceDID,
64
+ spaceSigner,
65
+ issuer: spaceSigner, // Use space signer as issuer
66
+ keyPair,
67
+ publicKeyPem,
68
+ delegationProof,
69
+ }
62
70
  }
63
- //# sourceMappingURL=test-fixtures.js.map
71
+ //# sourceMappingURL=test-fixtures.js.map
@@ -4,31 +4,31 @@
4
4
  * @param {number} sizeMB - Size of the test file in megabytes
5
5
  * @returns {Blob} A Blob containing test data with predictable patterns
6
6
  */
7
- export function createTestFile(sizeMB: number): Blob;
7
+ export function createTestFile(sizeMB: number): Blob
8
8
  /**
9
9
  * Convert ReadableStream to Uint8Array
10
10
  *
11
11
  * @param {ReadableStream} stream - The stream to convert
12
12
  * @returns {Promise<Uint8Array>} The stream content as a Uint8Array
13
13
  */
14
- export function streamToUint8Array(stream: ReadableStream): Promise<Uint8Array>;
14
+ export function streamToUint8Array(stream: ReadableStream): Promise<Uint8Array>
15
15
  /**
16
16
  * @param {Uint8Array} arr
17
17
  * @returns {string}
18
18
  */
19
- export function uint8ArrayToString(arr: Uint8Array): string;
19
+ export function uint8ArrayToString(arr: Uint8Array): string
20
20
  /**
21
21
  * @param {string} str
22
22
  * @returns {Uint8Array}
23
23
  */
24
- export function stringToUint8Array(str: string): Uint8Array;
24
+ export function stringToUint8Array(str: string): Uint8Array
25
25
  /**
26
26
  * Check if an error is a memory-related error (out of heap space, etc.)
27
27
  *
28
28
  * @param {unknown} error - The error to check
29
29
  * @returns {boolean} True if the error appears to be memory-related
30
30
  */
31
- export function isMemoryError(error: unknown): boolean;
31
+ export function isMemoryError(error: unknown): boolean
32
32
  /**
33
33
  * Test an encryption operation and expect it might fail with memory errors
34
34
  *
@@ -36,10 +36,13 @@ export function isMemoryError(error: unknown): boolean;
36
36
  * @param {string} operationName - Name of the operation for logging
37
37
  * @returns {Promise<{success: boolean, error?: Error}>} Result of the operation
38
38
  */
39
- export function testEncryptionWithMemoryHandling(encryptOperation: Function, operationName: string): Promise<{
40
- success: boolean;
41
- error?: Error;
42
- }>;
39
+ export function testEncryptionWithMemoryHandling(
40
+ encryptOperation: Function,
41
+ operationName: string
42
+ ): Promise<{
43
+ success: boolean
44
+ error?: Error
45
+ }>
43
46
  /**
44
47
  * Create a CAR file with KMS metadata content
45
48
  *
@@ -47,14 +50,16 @@ export function testEncryptionWithMemoryHandling(encryptOperation: Function, ope
47
50
  * @returns {Promise<{car: Uint8Array, actualRootCID: import('multiformats').UnknownLink}>}
48
51
  */
49
52
  export function createTestCar(content: any): Promise<{
50
- car: Uint8Array;
51
- actualRootCID: import("multiformats").UnknownLink;
52
- }>;
53
+ car: Uint8Array
54
+ actualRootCID: import('multiformats').UnknownLink
55
+ }>
53
56
  /**
54
57
  * Create a mock BlobLike object for testing
55
58
  *
56
59
  * @param {Uint8Array} data
57
60
  * @returns {import('../../src/types.js').BlobLike}
58
61
  */
59
- export function createMockBlob(data: Uint8Array): import("../../src/types.js").BlobLike;
60
- //# sourceMappingURL=test-file-utils.d.ts.map
62
+ export function createMockBlob(
63
+ data: Uint8Array
64
+ ): import('../../src/types.js').BlobLike
65
+ //# sourceMappingURL=test-file-utils.d.ts.map
@@ -1,4 +1,4 @@
1
- import { KMSMetadata } from '../../src/core/metadata/encrypted-metadata.js';
1
+ import { KMSMetadata } from '../../src/core/metadata/encrypted-metadata.js'
2
2
  /**
3
3
  * Create test data with specific patterns for easy verification
4
4
  *
@@ -6,24 +6,24 @@ import { KMSMetadata } from '../../src/core/metadata/encrypted-metadata.js';
6
6
  * @returns {Blob} A Blob containing test data with predictable patterns
7
7
  */
8
8
  export function createTestFile(sizeMB) {
9
- const chunkSize = 64 * 1024; // 64KB chunks
10
- const totalSize = sizeMB * 1024 * 1024;
11
- const numChunks = Math.ceil(totalSize / chunkSize);
12
- const chunks = [];
13
- for (let i = 0; i < numChunks; i++) {
14
- const isLastChunk = i === numChunks - 1;
15
- const currentChunkSize = isLastChunk
16
- ? totalSize % chunkSize || chunkSize
17
- : chunkSize;
18
- const chunk = new Uint8Array(currentChunkSize);
19
- // Create pattern: chunk index in first byte, then sequence
20
- chunk[0] = i % 256;
21
- for (let j = 1; j < currentChunkSize; j++) {
22
- chunk[j] = (i + j) % 256;
23
- }
24
- chunks.push(chunk);
9
+ const chunkSize = 64 * 1024 // 64KB chunks
10
+ const totalSize = sizeMB * 1024 * 1024
11
+ const numChunks = Math.ceil(totalSize / chunkSize)
12
+ const chunks = []
13
+ for (let i = 0; i < numChunks; i++) {
14
+ const isLastChunk = i === numChunks - 1
15
+ const currentChunkSize = isLastChunk
16
+ ? totalSize % chunkSize || chunkSize
17
+ : chunkSize
18
+ const chunk = new Uint8Array(currentChunkSize)
19
+ // Create pattern: chunk index in first byte, then sequence
20
+ chunk[0] = i % 256
21
+ for (let j = 1; j < currentChunkSize; j++) {
22
+ chunk[j] = (i + j) % 256
25
23
  }
26
- return new Blob(chunks, { type: 'application/octet-stream' });
24
+ chunks.push(chunk)
25
+ }
26
+ return new Blob(chunks, { type: 'application/octet-stream' })
27
27
  }
28
28
  /**
29
29
  * Convert ReadableStream to Uint8Array
@@ -32,37 +32,36 @@ export function createTestFile(sizeMB) {
32
32
  * @returns {Promise<Uint8Array>} The stream content as a Uint8Array
33
33
  */
34
34
  export async function streamToUint8Array(stream) {
35
- const reader = stream.getReader();
36
- const chunks = [];
37
- // eslint-disable-next-line no-constant-condition
38
- while (true) {
39
- const { done, value } = await reader.read();
40
- if (done)
41
- break;
42
- chunks.push(value);
43
- }
44
- const totalLength = chunks.reduce((acc, val) => acc + val.length, 0);
45
- const result = new Uint8Array(totalLength);
46
- let offset = 0;
47
- for (const chunk of chunks) {
48
- result.set(chunk, offset);
49
- offset += chunk.length;
50
- }
51
- return result;
35
+ const reader = stream.getReader()
36
+ const chunks = []
37
+ // eslint-disable-next-line no-constant-condition
38
+ while (true) {
39
+ const { done, value } = await reader.read()
40
+ if (done) break
41
+ chunks.push(value)
42
+ }
43
+ const totalLength = chunks.reduce((acc, val) => acc + val.length, 0)
44
+ const result = new Uint8Array(totalLength)
45
+ let offset = 0
46
+ for (const chunk of chunks) {
47
+ result.set(chunk, offset)
48
+ offset += chunk.length
49
+ }
50
+ return result
52
51
  }
53
52
  /**
54
53
  * @param {Uint8Array} arr
55
54
  * @returns {string}
56
55
  */
57
56
  export function uint8ArrayToString(arr) {
58
- return new TextDecoder().decode(arr);
57
+ return new TextDecoder().decode(arr)
59
58
  }
60
59
  /**
61
60
  * @param {string} str
62
61
  * @returns {Uint8Array}
63
62
  */
64
63
  export function stringToUint8Array(str) {
65
- return new TextEncoder().encode(str);
64
+ return new TextEncoder().encode(str)
66
65
  }
67
66
  /**
68
67
  * Check if an error is a memory-related error (out of heap space, etc.)
@@ -71,11 +70,13 @@ export function stringToUint8Array(str) {
71
70
  * @returns {boolean} True if the error appears to be memory-related
72
71
  */
73
72
  export function isMemoryError(error) {
74
- const errorMessage = error instanceof Error ? error.message : String(error);
75
- return (errorMessage.includes('heap') ||
76
- errorMessage.includes('memory') ||
77
- errorMessage.includes('allocation failed') ||
78
- errorMessage.includes('out of memory'));
73
+ const errorMessage = error instanceof Error ? error.message : String(error)
74
+ return (
75
+ errorMessage.includes('heap') ||
76
+ errorMessage.includes('memory') ||
77
+ errorMessage.includes('allocation failed') ||
78
+ errorMessage.includes('out of memory')
79
+ )
79
80
  }
80
81
  /**
81
82
  * Test an encryption operation and expect it might fail with memory errors
@@ -84,24 +85,25 @@ export function isMemoryError(error) {
84
85
  * @param {string} operationName - Name of the operation for logging
85
86
  * @returns {Promise<{success: boolean, error?: Error}>} Result of the operation
86
87
  */
87
- export async function testEncryptionWithMemoryHandling(encryptOperation, operationName) {
88
- try {
89
- await encryptOperation();
90
- return { success: true };
91
- }
92
- catch (error) {
93
- if (isMemoryError(error)) {
94
- console.log(`✓ ${operationName} failed as expected: Out of memory`);
95
- return {
96
- success: false,
97
- error: error instanceof Error ? error : new Error(String(error)),
98
- };
99
- }
100
- else {
101
- // Re-throw if it's not a memory error
102
- throw error;
103
- }
88
+ export async function testEncryptionWithMemoryHandling(
89
+ encryptOperation,
90
+ operationName
91
+ ) {
92
+ try {
93
+ await encryptOperation()
94
+ return { success: true }
95
+ } catch (error) {
96
+ if (isMemoryError(error)) {
97
+ console.log(`✓ ${operationName} failed as expected: Out of memory`)
98
+ return {
99
+ success: false,
100
+ error: error instanceof Error ? error : new Error(String(error)),
101
+ }
102
+ } else {
103
+ // Re-throw if it's not a memory error
104
+ throw error
104
105
  }
106
+ }
105
107
  }
106
108
  /**
107
109
  * Create a CAR file with KMS metadata content
@@ -110,13 +112,13 @@ export async function testEncryptionWithMemoryHandling(encryptOperation, operati
110
112
  * @returns {Promise<{car: Uint8Array, actualRootCID: import('multiformats').UnknownLink}>}
111
113
  */
112
114
  export async function createTestCar(content) {
113
- // Create KMS metadata and archive it to get the CAR
114
- const kmsMetadata = KMSMetadata.create(content);
115
- const { cid, bytes } = await kmsMetadata.archiveBlock();
116
- // Use UCANTO's CAR encoding to create a proper CAR file
117
- const { CAR } = await import('@ucanto/core');
118
- const car = CAR.encode({ roots: [{ cid, bytes }] });
119
- return { car, actualRootCID: cid };
115
+ // Create KMS metadata and archive it to get the CAR
116
+ const kmsMetadata = KMSMetadata.create(content)
117
+ const { cid, bytes } = await kmsMetadata.archiveBlock()
118
+ // Use UCANTO's CAR encoding to create a proper CAR file
119
+ const { CAR } = await import('@ucanto/core')
120
+ const car = CAR.encode({ roots: [{ cid, bytes }] })
121
+ return { car, actualRootCID: cid }
120
122
  }
121
123
  /**
122
124
  * Create a mock BlobLike object for testing
@@ -125,15 +127,15 @@ export async function createTestCar(content) {
125
127
  * @returns {import('../../src/types.js').BlobLike}
126
128
  */
127
129
  export function createMockBlob(data) {
128
- return {
129
- stream() {
130
- return new ReadableStream({
131
- start(controller) {
132
- controller.enqueue(data);
133
- controller.close();
134
- },
135
- });
130
+ return {
131
+ stream() {
132
+ return new ReadableStream({
133
+ start(controller) {
134
+ controller.enqueue(data)
135
+ controller.close()
136
136
  },
137
- };
137
+ })
138
+ },
139
+ }
138
140
  }
139
- //# sourceMappingURL=test-file-utils.js.map
141
+ //# sourceMappingURL=test-file-utils.js.map
@@ -1,2 +1,2 @@
1
- export {};
2
- //# sourceMappingURL=https-enforcement.spec.d.ts.map
1
+ export {}
2
+ //# sourceMappingURL=https-enforcement.spec.d.ts.map