@originals/sdk 1.1.0 → 1.4.2

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 (247) hide show
  1. package/package.json +3 -2
  2. package/src/did/DIDManager.ts +1 -1
  3. package/src/did/WebVHManager.ts +11 -2
  4. package/src/examples/create-module-original.ts +435 -0
  5. package/src/examples/full-lifecycle-flow.ts +514 -0
  6. package/src/examples/run.ts +59 -4
  7. package/src/index.ts +69 -3
  8. package/src/kinds/KindRegistry.ts +290 -0
  9. package/src/kinds/index.ts +74 -0
  10. package/src/kinds/types.ts +470 -0
  11. package/src/kinds/validators/AgentValidator.ts +257 -0
  12. package/src/kinds/validators/AppValidator.ts +211 -0
  13. package/src/kinds/validators/DatasetValidator.ts +242 -0
  14. package/src/kinds/validators/DocumentValidator.ts +311 -0
  15. package/src/kinds/validators/MediaValidator.ts +269 -0
  16. package/src/kinds/validators/ModuleValidator.ts +225 -0
  17. package/src/kinds/validators/base.ts +276 -0
  18. package/src/kinds/validators/index.ts +12 -0
  19. package/src/lifecycle/LifecycleManager.ts +909 -1
  20. package/src/resources/ResourceManager.ts +655 -0
  21. package/src/resources/index.ts +21 -0
  22. package/src/resources/types.ts +202 -0
  23. package/src/types/common.ts +1 -1
  24. package/src/vc/CredentialManager.ts +647 -2
  25. package/tests/integration/createTypedOriginal.test.ts +379 -0
  26. package/tests/performance/BatchOperations.perf.test.ts +2 -2
  27. package/tests/unit/kinds/KindRegistry.test.ts +329 -0
  28. package/tests/unit/kinds/types.test.ts +409 -0
  29. package/tests/unit/kinds/validators.test.ts +651 -0
  30. package/tests/unit/lifecycle/LifecycleManager.cleanapi.test.ts +441 -0
  31. package/tests/unit/resources/ResourceManager.test.ts +740 -0
  32. package/tests/unit/vc/CredentialManager.helpers.test.ts +527 -0
  33. package/tsconfig.json +0 -1
  34. package/.turbo/turbo-build.log +0 -1
  35. package/.turbo/turbo-test.log +0 -68353
  36. package/dist/adapters/FeeOracleMock.d.ts +0 -6
  37. package/dist/adapters/FeeOracleMock.js +0 -8
  38. package/dist/adapters/index.d.ts +0 -4
  39. package/dist/adapters/index.js +0 -4
  40. package/dist/adapters/providers/OrdHttpProvider.d.ts +0 -56
  41. package/dist/adapters/providers/OrdHttpProvider.js +0 -110
  42. package/dist/adapters/providers/OrdMockProvider.d.ts +0 -70
  43. package/dist/adapters/providers/OrdMockProvider.js +0 -75
  44. package/dist/adapters/types.d.ts +0 -71
  45. package/dist/adapters/types.js +0 -1
  46. package/dist/bitcoin/BitcoinManager.d.ts +0 -15
  47. package/dist/bitcoin/BitcoinManager.js +0 -262
  48. package/dist/bitcoin/BroadcastClient.d.ts +0 -30
  49. package/dist/bitcoin/BroadcastClient.js +0 -35
  50. package/dist/bitcoin/OrdinalsClient.d.ts +0 -21
  51. package/dist/bitcoin/OrdinalsClient.js +0 -105
  52. package/dist/bitcoin/PSBTBuilder.d.ts +0 -24
  53. package/dist/bitcoin/PSBTBuilder.js +0 -80
  54. package/dist/bitcoin/fee-calculation.d.ts +0 -14
  55. package/dist/bitcoin/fee-calculation.js +0 -31
  56. package/dist/bitcoin/providers/OrdNodeProvider.d.ts +0 -38
  57. package/dist/bitcoin/providers/OrdNodeProvider.js +0 -67
  58. package/dist/bitcoin/providers/OrdinalsProvider.d.ts +0 -33
  59. package/dist/bitcoin/providers/OrdinalsProvider.js +0 -50
  60. package/dist/bitcoin/providers/types.d.ts +0 -63
  61. package/dist/bitcoin/providers/types.js +0 -1
  62. package/dist/bitcoin/transactions/commit.d.ts +0 -89
  63. package/dist/bitcoin/transactions/commit.js +0 -311
  64. package/dist/bitcoin/transactions/index.d.ts +0 -7
  65. package/dist/bitcoin/transactions/index.js +0 -8
  66. package/dist/bitcoin/transfer.d.ts +0 -9
  67. package/dist/bitcoin/transfer.js +0 -26
  68. package/dist/bitcoin/utxo-selection.d.ts +0 -78
  69. package/dist/bitcoin/utxo-selection.js +0 -237
  70. package/dist/bitcoin/utxo.d.ts +0 -26
  71. package/dist/bitcoin/utxo.js +0 -78
  72. package/dist/contexts/credentials-v1.json +0 -195
  73. package/dist/contexts/credentials-v2-examples.json +0 -5
  74. package/dist/contexts/credentials-v2.json +0 -301
  75. package/dist/contexts/credentials.json +0 -195
  76. package/dist/contexts/data-integrity-v2.json +0 -81
  77. package/dist/contexts/dids.json +0 -57
  78. package/dist/contexts/ed255192020.json +0 -93
  79. package/dist/contexts/ordinals-plus.json +0 -23
  80. package/dist/contexts/originals.json +0 -22
  81. package/dist/core/OriginalsSDK.d.ts +0 -158
  82. package/dist/core/OriginalsSDK.js +0 -274
  83. package/dist/crypto/Multikey.d.ts +0 -30
  84. package/dist/crypto/Multikey.js +0 -149
  85. package/dist/crypto/Signer.d.ts +0 -21
  86. package/dist/crypto/Signer.js +0 -196
  87. package/dist/crypto/noble-init.d.ts +0 -18
  88. package/dist/crypto/noble-init.js +0 -106
  89. package/dist/did/BtcoDidResolver.d.ts +0 -57
  90. package/dist/did/BtcoDidResolver.js +0 -166
  91. package/dist/did/DIDManager.d.ts +0 -101
  92. package/dist/did/DIDManager.js +0 -493
  93. package/dist/did/Ed25519Verifier.d.ts +0 -30
  94. package/dist/did/Ed25519Verifier.js +0 -59
  95. package/dist/did/KeyManager.d.ts +0 -17
  96. package/dist/did/KeyManager.js +0 -207
  97. package/dist/did/WebVHManager.d.ts +0 -100
  98. package/dist/did/WebVHManager.js +0 -304
  99. package/dist/did/createBtcoDidDocument.d.ts +0 -10
  100. package/dist/did/createBtcoDidDocument.js +0 -42
  101. package/dist/did/providers/OrdinalsClientProviderAdapter.d.ts +0 -23
  102. package/dist/did/providers/OrdinalsClientProviderAdapter.js +0 -51
  103. package/dist/events/EventEmitter.d.ts +0 -115
  104. package/dist/events/EventEmitter.js +0 -198
  105. package/dist/events/index.d.ts +0 -7
  106. package/dist/events/index.js +0 -6
  107. package/dist/events/types.d.ts +0 -286
  108. package/dist/events/types.js +0 -9
  109. package/dist/examples/basic-usage.d.ts +0 -3
  110. package/dist/examples/basic-usage.js +0 -62
  111. package/dist/examples/run.d.ts +0 -1
  112. package/dist/examples/run.js +0 -4
  113. package/dist/index.d.ts +0 -39
  114. package/dist/index.js +0 -47
  115. package/dist/lifecycle/BatchOperations.d.ts +0 -147
  116. package/dist/lifecycle/BatchOperations.js +0 -251
  117. package/dist/lifecycle/LifecycleManager.d.ts +0 -116
  118. package/dist/lifecycle/LifecycleManager.js +0 -971
  119. package/dist/lifecycle/OriginalsAsset.d.ts +0 -164
  120. package/dist/lifecycle/OriginalsAsset.js +0 -380
  121. package/dist/lifecycle/ProvenanceQuery.d.ts +0 -126
  122. package/dist/lifecycle/ProvenanceQuery.js +0 -220
  123. package/dist/lifecycle/ResourceVersioning.d.ts +0 -73
  124. package/dist/lifecycle/ResourceVersioning.js +0 -127
  125. package/dist/migration/MigrationManager.d.ts +0 -86
  126. package/dist/migration/MigrationManager.js +0 -412
  127. package/dist/migration/audit/AuditLogger.d.ts +0 -51
  128. package/dist/migration/audit/AuditLogger.js +0 -156
  129. package/dist/migration/checkpoint/CheckpointManager.d.ts +0 -31
  130. package/dist/migration/checkpoint/CheckpointManager.js +0 -96
  131. package/dist/migration/checkpoint/CheckpointStorage.d.ts +0 -26
  132. package/dist/migration/checkpoint/CheckpointStorage.js +0 -89
  133. package/dist/migration/index.d.ts +0 -22
  134. package/dist/migration/index.js +0 -27
  135. package/dist/migration/operations/BaseMigration.d.ts +0 -48
  136. package/dist/migration/operations/BaseMigration.js +0 -83
  137. package/dist/migration/operations/PeerToBtcoMigration.d.ts +0 -25
  138. package/dist/migration/operations/PeerToBtcoMigration.js +0 -67
  139. package/dist/migration/operations/PeerToWebvhMigration.d.ts +0 -19
  140. package/dist/migration/operations/PeerToWebvhMigration.js +0 -46
  141. package/dist/migration/operations/WebvhToBtcoMigration.d.ts +0 -25
  142. package/dist/migration/operations/WebvhToBtcoMigration.js +0 -67
  143. package/dist/migration/rollback/RollbackManager.d.ts +0 -29
  144. package/dist/migration/rollback/RollbackManager.js +0 -146
  145. package/dist/migration/state/StateMachine.d.ts +0 -25
  146. package/dist/migration/state/StateMachine.js +0 -76
  147. package/dist/migration/state/StateTracker.d.ts +0 -36
  148. package/dist/migration/state/StateTracker.js +0 -123
  149. package/dist/migration/types.d.ts +0 -306
  150. package/dist/migration/types.js +0 -33
  151. package/dist/migration/validation/BitcoinValidator.d.ts +0 -13
  152. package/dist/migration/validation/BitcoinValidator.js +0 -83
  153. package/dist/migration/validation/CredentialValidator.d.ts +0 -13
  154. package/dist/migration/validation/CredentialValidator.js +0 -46
  155. package/dist/migration/validation/DIDCompatibilityValidator.d.ts +0 -16
  156. package/dist/migration/validation/DIDCompatibilityValidator.js +0 -127
  157. package/dist/migration/validation/LifecycleValidator.d.ts +0 -10
  158. package/dist/migration/validation/LifecycleValidator.js +0 -52
  159. package/dist/migration/validation/StorageValidator.d.ts +0 -10
  160. package/dist/migration/validation/StorageValidator.js +0 -65
  161. package/dist/migration/validation/ValidationPipeline.d.ts +0 -29
  162. package/dist/migration/validation/ValidationPipeline.js +0 -180
  163. package/dist/storage/LocalStorageAdapter.d.ts +0 -11
  164. package/dist/storage/LocalStorageAdapter.js +0 -53
  165. package/dist/storage/MemoryStorageAdapter.d.ts +0 -6
  166. package/dist/storage/MemoryStorageAdapter.js +0 -21
  167. package/dist/storage/StorageAdapter.d.ts +0 -16
  168. package/dist/storage/StorageAdapter.js +0 -1
  169. package/dist/storage/index.d.ts +0 -2
  170. package/dist/storage/index.js +0 -2
  171. package/dist/types/bitcoin.d.ts +0 -84
  172. package/dist/types/bitcoin.js +0 -1
  173. package/dist/types/common.d.ts +0 -82
  174. package/dist/types/common.js +0 -1
  175. package/dist/types/credentials.d.ts +0 -75
  176. package/dist/types/credentials.js +0 -1
  177. package/dist/types/did.d.ts +0 -26
  178. package/dist/types/did.js +0 -1
  179. package/dist/types/index.d.ts +0 -5
  180. package/dist/types/index.js +0 -5
  181. package/dist/types/network.d.ts +0 -78
  182. package/dist/types/network.js +0 -145
  183. package/dist/utils/EventLogger.d.ts +0 -71
  184. package/dist/utils/EventLogger.js +0 -232
  185. package/dist/utils/Logger.d.ts +0 -106
  186. package/dist/utils/Logger.js +0 -257
  187. package/dist/utils/MetricsCollector.d.ts +0 -110
  188. package/dist/utils/MetricsCollector.js +0 -264
  189. package/dist/utils/bitcoin-address.d.ts +0 -38
  190. package/dist/utils/bitcoin-address.js +0 -113
  191. package/dist/utils/cbor.d.ts +0 -2
  192. package/dist/utils/cbor.js +0 -9
  193. package/dist/utils/encoding.d.ts +0 -37
  194. package/dist/utils/encoding.js +0 -120
  195. package/dist/utils/hash.d.ts +0 -1
  196. package/dist/utils/hash.js +0 -5
  197. package/dist/utils/retry.d.ts +0 -10
  198. package/dist/utils/retry.js +0 -35
  199. package/dist/utils/satoshi-validation.d.ts +0 -60
  200. package/dist/utils/satoshi-validation.js +0 -156
  201. package/dist/utils/serialization.d.ts +0 -14
  202. package/dist/utils/serialization.js +0 -76
  203. package/dist/utils/telemetry.d.ts +0 -17
  204. package/dist/utils/telemetry.js +0 -24
  205. package/dist/utils/validation.d.ts +0 -5
  206. package/dist/utils/validation.js +0 -98
  207. package/dist/vc/CredentialManager.d.ts +0 -22
  208. package/dist/vc/CredentialManager.js +0 -227
  209. package/dist/vc/Issuer.d.ts +0 -27
  210. package/dist/vc/Issuer.js +0 -70
  211. package/dist/vc/Verifier.d.ts +0 -16
  212. package/dist/vc/Verifier.js +0 -50
  213. package/dist/vc/cryptosuites/bbs.d.ts +0 -44
  214. package/dist/vc/cryptosuites/bbs.js +0 -213
  215. package/dist/vc/cryptosuites/bbsSimple.d.ts +0 -9
  216. package/dist/vc/cryptosuites/bbsSimple.js +0 -12
  217. package/dist/vc/cryptosuites/eddsa.d.ts +0 -30
  218. package/dist/vc/cryptosuites/eddsa.js +0 -81
  219. package/dist/vc/documentLoader.d.ts +0 -16
  220. package/dist/vc/documentLoader.js +0 -59
  221. package/dist/vc/proofs/data-integrity.d.ts +0 -21
  222. package/dist/vc/proofs/data-integrity.js +0 -15
  223. package/dist/vc/utils/jsonld.d.ts +0 -2
  224. package/dist/vc/utils/jsonld.js +0 -15
  225. package/test/logs/did_webvh_QmQsRNhXxPSCSeLjpbKYcNMZj8b1kBQAoC6cZmkFAgmpHt_example_com.jsonl +0 -1
  226. package/test/logs/did_webvh_QmSQkpD58qxcqMWHYcEmDUn3wk7hHvJwzYTrZmhh6zjPQ8_example_com_users_alice123_profile.jsonl +0 -1
  227. package/test/logs/did_webvh_QmTMda6VW3cUPdKk5Yc3onnv1vdgEumvWWdP2noAYFSjeG_example_com.jsonl +0 -1
  228. package/test/logs/did_webvh_QmTkb8KnCYcsnKKDCY4eUQuKQdKJLrCinvhw13v3zETxpE_example_com_users_etc_passwd.jsonl +0 -1
  229. package/test/logs/did_webvh_QmTn9FdCfpXFDrxHH52pwB4iNrDFVvNDjJ5FQTcDbmM3Fg_example_com.jsonl +0 -1
  230. package/test/logs/did_webvh_QmUCQUi1xjtJjnSQ1XJZgKqcWgErx1v7E2dz4DAPraAyJP_example_com_etc_passwd.jsonl +0 -1
  231. package/test/logs/did_webvh_QmUENQJCDKBJVRS5BkL6zjaUvcRjkb9xHmy7foCgRjmv3W_example_com.jsonl +0 -1
  232. package/test/logs/did_webvh_QmUPdGyjYBEnQ3aQUkmqyyBKTyjvCP5RZQGiaEDeTtf6dc_example_com.jsonl +0 -1
  233. package/test/logs/did_webvh_QmUoHTuHMWzQM29ZFrE9VLtMxkZ5u869yqee8LwcCLN39M_example_com.jsonl +0 -1
  234. package/test/logs/did_webvh_QmUrnms8G65ggVKsr9oQeWrLUBuGChwQPPb2LCFvaoNxaw_example_com_users_alice.jsonl +0 -1
  235. package/test/logs/did_webvh_QmUwiw3eSXdHG1hPvoAGu3cuK5jF4aXRYDLBAjPXfv1qzb_example_com_level1_level2.jsonl +0 -1
  236. package/test/logs/did_webvh_QmW7bzKh6yFEKNAtmVsrPGvvsMHTUQdzJSNsTZkbuGFpbj_example_com_secret.jsonl +0 -1
  237. package/test/logs/did_webvh_QmXbFTFBBJ8zpjdz9WE1DNN44A2wprFmdvAubjSffeyoAG_example_com.jsonl +0 -1
  238. package/test/logs/did_webvh_QmXyVXFPCTffGb2mTUFDeMCsScjnpLWkyUkVkB6q6QoeBf_example_com_C_Windows_System32.jsonl +0 -1
  239. package/test/logs/did_webvh_QmZK9B81gxZtvo5fYHYKDtKt8zZfZZPhmCMhbujBJuRRzE_example_com_etc_passwd.jsonl +0 -1
  240. package/test/logs/did_webvh_QmbNLCVSdXSVLrwFBvCBQPAabjtRb1SGHjkGVyw3QUbfBL_example_com_users_etc_passwd.jsonl +0 -1
  241. package/test/logs/did_webvh_QmbeaicmGW3Q7Yzbqmftc8a9jLBngokveb5A2KVKfVGZRb_example_com_my_org_user_name_test_123.jsonl +0 -1
  242. package/test/logs/did_webvh_Qmdv7c7AjUreUfoKyvkN2UpAWTozxKsv99srQetPJMJEnp_example_com_users_etc_passwd.jsonl +0 -1
  243. package/test/logs/did_webvh_QmeioWY3uypYLkYpCXe9eCYnn4xBVruP9C1d79azMrTEHG_example_com.jsonl +0 -1
  244. package/test/logs/did_webvh_Qmf4QH5dsA6Ecr5HJ6KaJL9uJRyY8RxrQdqoRCM25DzvPi_example_com_users_alice.jsonl +0 -1
  245. package/tests/e2e/README.md +0 -97
  246. package/tests/e2e/example.spec.ts +0 -78
  247. package/tsconfig.tsbuildinfo +0 -1
@@ -0,0 +1,329 @@
1
+ /**
2
+ * Tests for KindRegistry
3
+ */
4
+
5
+ import { describe, expect, it, beforeEach } from 'bun:test';
6
+ import {
7
+ OriginalKind,
8
+ KindRegistry,
9
+ type AppManifest,
10
+ type ModuleManifest,
11
+ type ValidationResult,
12
+ BaseKindValidator,
13
+ ValidationUtils,
14
+ type OriginalManifest,
15
+ } from '../../../src/kinds';
16
+
17
+ // Helper to create a minimal valid resource
18
+ const createResource = (id: string, type = 'code', contentType = 'application/javascript') => ({
19
+ id,
20
+ type,
21
+ contentType,
22
+ hash: 'abcdef1234567890',
23
+ });
24
+
25
+ describe('KindRegistry', () => {
26
+ describe('getInstance', () => {
27
+ it('should return a singleton instance', () => {
28
+ const instance1 = KindRegistry.getInstance();
29
+ const instance2 = KindRegistry.getInstance();
30
+
31
+ expect(instance1).toBe(instance2);
32
+ });
33
+
34
+ it('should have all default validators registered', () => {
35
+ const registry = KindRegistry.getInstance();
36
+
37
+ expect(registry.hasKind(OriginalKind.App)).toBe(true);
38
+ expect(registry.hasKind(OriginalKind.Agent)).toBe(true);
39
+ expect(registry.hasKind(OriginalKind.Module)).toBe(true);
40
+ expect(registry.hasKind(OriginalKind.Dataset)).toBe(true);
41
+ expect(registry.hasKind(OriginalKind.Media)).toBe(true);
42
+ expect(registry.hasKind(OriginalKind.Document)).toBe(true);
43
+ });
44
+ });
45
+
46
+ describe('getRegisteredKinds', () => {
47
+ it('should return all registered kinds', () => {
48
+ const registry = KindRegistry.getInstance();
49
+ const kinds = registry.getRegisteredKinds();
50
+
51
+ expect(kinds.length).toBe(6);
52
+ expect(kinds).toContain(OriginalKind.App);
53
+ expect(kinds).toContain(OriginalKind.Agent);
54
+ expect(kinds).toContain(OriginalKind.Module);
55
+ expect(kinds).toContain(OriginalKind.Dataset);
56
+ expect(kinds).toContain(OriginalKind.Media);
57
+ expect(kinds).toContain(OriginalKind.Document);
58
+ });
59
+ });
60
+
61
+ describe('validate', () => {
62
+ it('should validate a valid App manifest', () => {
63
+ const registry = KindRegistry.getInstance();
64
+ const manifest: AppManifest = {
65
+ kind: OriginalKind.App,
66
+ name: 'test-app',
67
+ version: '1.0.0',
68
+ resources: [createResource('index.js')],
69
+ metadata: {
70
+ runtime: 'node',
71
+ entrypoint: 'index.js',
72
+ }
73
+ };
74
+
75
+ const result = registry.validate(manifest);
76
+ expect(result.isValid).toBe(true);
77
+ });
78
+
79
+ it('should fail for missing kind', () => {
80
+ const registry = KindRegistry.getInstance();
81
+ const manifest = {
82
+ name: 'test-app',
83
+ version: '1.0.0',
84
+ resources: [createResource('index.js')],
85
+ } as any;
86
+
87
+ const result = registry.validate(manifest);
88
+ expect(result.isValid).toBe(false);
89
+ expect(result.errors.some(e => e.code === 'MISSING_KIND')).toBe(true);
90
+ });
91
+
92
+ it('should fail for unknown kind', () => {
93
+ const registry = KindRegistry.getInstance();
94
+ const manifest = {
95
+ kind: 'originals:kind:unknown' as any,
96
+ name: 'test',
97
+ version: '1.0.0',
98
+ resources: [createResource('file.js')],
99
+ metadata: {},
100
+ } as any;
101
+
102
+ const result = registry.validate(manifest);
103
+ expect(result.isValid).toBe(false);
104
+ expect(result.errors.some(e => e.code === 'UNKNOWN_KIND')).toBe(true);
105
+ });
106
+
107
+ it('should treat warnings as errors in strict mode', () => {
108
+ const registry = KindRegistry.getInstance();
109
+ const manifest: AppManifest = {
110
+ kind: OriginalKind.App,
111
+ name: 'test-app',
112
+ version: '1.0.0',
113
+ resources: [createResource('index.js')],
114
+ metadata: {
115
+ runtime: 'node',
116
+ entrypoint: 'index.js',
117
+ // No runtimeVersion - will generate warning
118
+ }
119
+ };
120
+
121
+ // Without strict mode - should pass
122
+ const normalResult = registry.validate(manifest);
123
+ expect(normalResult.isValid).toBe(true);
124
+ expect(normalResult.warnings.length).toBeGreaterThan(0);
125
+
126
+ // With strict mode - should fail
127
+ const strictResult = registry.validate(manifest, { strictMode: true });
128
+ expect(strictResult.isValid).toBe(false);
129
+ });
130
+ });
131
+
132
+ describe('validateOrThrow', () => {
133
+ it('should not throw for valid manifest', () => {
134
+ const registry = KindRegistry.getInstance();
135
+ const manifest: ModuleManifest = {
136
+ kind: OriginalKind.Module,
137
+ name: 'test-module',
138
+ version: '1.0.0',
139
+ resources: [createResource('index.js')],
140
+ metadata: {
141
+ format: 'esm',
142
+ main: 'index.js',
143
+ }
144
+ };
145
+
146
+ expect(() => registry.validateOrThrow(manifest)).not.toThrow();
147
+ });
148
+
149
+ it('should throw for invalid manifest', () => {
150
+ const registry = KindRegistry.getInstance();
151
+ const manifest = {
152
+ kind: OriginalKind.Module,
153
+ name: '', // invalid empty name
154
+ version: '1.0.0',
155
+ resources: [createResource('index.js')],
156
+ metadata: {
157
+ format: 'esm',
158
+ main: 'index.js',
159
+ }
160
+ } as ModuleManifest;
161
+
162
+ expect(() => registry.validateOrThrow(manifest)).toThrow('Manifest validation failed');
163
+ });
164
+
165
+ it('should skip validation when skipValidation is true', () => {
166
+ const registry = KindRegistry.getInstance();
167
+ const invalidManifest = {
168
+ kind: OriginalKind.Module,
169
+ name: '', // invalid
170
+ version: 'invalid', // invalid
171
+ resources: [], // invalid
172
+ metadata: {} as any
173
+ } as ModuleManifest;
174
+
175
+ expect(() => registry.validateOrThrow(invalidManifest, { skipValidation: true })).not.toThrow();
176
+ });
177
+ });
178
+
179
+ describe('registerValidator', () => {
180
+ it('should allow registering custom validators', () => {
181
+ const registry = KindRegistry.getInstance();
182
+
183
+ // Create a custom validator
184
+ class CustomAppValidator extends BaseKindValidator<OriginalKind.App> {
185
+ readonly kind = OriginalKind.App;
186
+
187
+ protected validateKind(manifest: OriginalManifest<OriginalKind.App>): ValidationResult {
188
+ // Custom validation that always adds a warning
189
+ return ValidationUtils.success([
190
+ ValidationUtils.warning('CUSTOM_WARNING', 'Custom validator was used')
191
+ ]);
192
+ }
193
+ }
194
+
195
+ // Register the custom validator
196
+ registry.registerValidator(OriginalKind.App, new CustomAppValidator());
197
+
198
+ // Validate a manifest
199
+ const manifest: AppManifest = {
200
+ kind: OriginalKind.App,
201
+ name: 'test-app',
202
+ version: '1.0.0',
203
+ resources: [createResource('index.js')],
204
+ metadata: {
205
+ runtime: 'node',
206
+ entrypoint: 'index.js',
207
+ }
208
+ };
209
+
210
+ const result = registry.validate(manifest);
211
+ expect(result.warnings.some(w => w.code === 'CUSTOM_WARNING')).toBe(true);
212
+ });
213
+ });
214
+
215
+ describe('static helpers', () => {
216
+ describe('isValidKind', () => {
217
+ it('should return true for valid kinds', () => {
218
+ expect(KindRegistry.isValidKind(OriginalKind.App)).toBe(true);
219
+ expect(KindRegistry.isValidKind(OriginalKind.Module)).toBe(true);
220
+ expect(KindRegistry.isValidKind('originals:kind:app')).toBe(true);
221
+ });
222
+
223
+ it('should return false for invalid kinds', () => {
224
+ expect(KindRegistry.isValidKind('invalid')).toBe(false);
225
+ expect(KindRegistry.isValidKind('originals:kind:unknown')).toBe(false);
226
+ expect(KindRegistry.isValidKind(null)).toBe(false);
227
+ expect(KindRegistry.isValidKind(undefined)).toBe(false);
228
+ expect(KindRegistry.isValidKind(123)).toBe(false);
229
+ });
230
+ });
231
+
232
+ describe('parseKind', () => {
233
+ it('should parse full kind URIs', () => {
234
+ expect(KindRegistry.parseKind('originals:kind:app')).toBe(OriginalKind.App);
235
+ expect(KindRegistry.parseKind('originals:kind:module')).toBe(OriginalKind.Module);
236
+ });
237
+
238
+ it('should parse short names', () => {
239
+ expect(KindRegistry.parseKind('app')).toBe(OriginalKind.App);
240
+ expect(KindRegistry.parseKind('module')).toBe(OriginalKind.Module);
241
+ expect(KindRegistry.parseKind('dataset')).toBe(OriginalKind.Dataset);
242
+ expect(KindRegistry.parseKind('agent')).toBe(OriginalKind.Agent);
243
+ expect(KindRegistry.parseKind('media')).toBe(OriginalKind.Media);
244
+ expect(KindRegistry.parseKind('document')).toBe(OriginalKind.Document);
245
+ });
246
+
247
+ it('should be case-insensitive for short names', () => {
248
+ expect(KindRegistry.parseKind('APP')).toBe(OriginalKind.App);
249
+ expect(KindRegistry.parseKind('Module')).toBe(OriginalKind.Module);
250
+ expect(KindRegistry.parseKind('DATASET')).toBe(OriginalKind.Dataset);
251
+ });
252
+
253
+ it('should return null for unknown kinds', () => {
254
+ expect(KindRegistry.parseKind('unknown')).toBe(null);
255
+ expect(KindRegistry.parseKind('')).toBe(null);
256
+ });
257
+ });
258
+
259
+ describe('getShortName', () => {
260
+ it('should extract short name from kind URI', () => {
261
+ expect(KindRegistry.getShortName(OriginalKind.App)).toBe('app');
262
+ expect(KindRegistry.getShortName(OriginalKind.Module)).toBe('module');
263
+ expect(KindRegistry.getShortName(OriginalKind.Dataset)).toBe('dataset');
264
+ });
265
+ });
266
+
267
+ describe('getDisplayName', () => {
268
+ it('should return capitalized display name', () => {
269
+ expect(KindRegistry.getDisplayName(OriginalKind.App)).toBe('App');
270
+ expect(KindRegistry.getDisplayName(OriginalKind.Module)).toBe('Module');
271
+ expect(KindRegistry.getDisplayName(OriginalKind.Dataset)).toBe('Dataset');
272
+ });
273
+ });
274
+
275
+ describe('createTemplate', () => {
276
+ it('should create App template', () => {
277
+ const template = KindRegistry.createTemplate(OriginalKind.App, 'my-app', '1.0.0');
278
+
279
+ expect(template.kind).toBe(OriginalKind.App);
280
+ expect(template.name).toBe('my-app');
281
+ expect(template.version).toBe('1.0.0');
282
+ expect((template.metadata as any)?.runtime).toBe('node');
283
+ expect((template.metadata as any)?.entrypoint).toBe('index.js');
284
+ });
285
+
286
+ it('should create Module template', () => {
287
+ const template = KindRegistry.createTemplate(OriginalKind.Module, 'my-module');
288
+
289
+ expect(template.kind).toBe(OriginalKind.Module);
290
+ expect((template.metadata as any)?.format).toBe('esm');
291
+ expect((template.metadata as any)?.main).toBe('index.js');
292
+ });
293
+
294
+ it('should create Dataset template', () => {
295
+ const template = KindRegistry.createTemplate(OriginalKind.Dataset, 'my-dataset');
296
+
297
+ expect(template.kind).toBe(OriginalKind.Dataset);
298
+ expect((template.metadata as any)?.format).toBe('json');
299
+ });
300
+
301
+ it('should create Agent template', () => {
302
+ const template = KindRegistry.createTemplate(OriginalKind.Agent, 'my-agent');
303
+
304
+ expect(template.kind).toBe(OriginalKind.Agent);
305
+ expect((template.metadata as any)?.capabilities).toEqual([]);
306
+ });
307
+
308
+ it('should create Media template', () => {
309
+ const template = KindRegistry.createTemplate(OriginalKind.Media, 'my-media');
310
+
311
+ expect(template.kind).toBe(OriginalKind.Media);
312
+ expect((template.metadata as any)?.mediaType).toBe('image');
313
+ });
314
+
315
+ it('should create Document template', () => {
316
+ const template = KindRegistry.createTemplate(OriginalKind.Document, 'my-doc');
317
+
318
+ expect(template.kind).toBe(OriginalKind.Document);
319
+ expect((template.metadata as any)?.format).toBe('markdown');
320
+ });
321
+
322
+ it('should use default version if not provided', () => {
323
+ const template = KindRegistry.createTemplate(OriginalKind.App, 'my-app');
324
+ expect(template.version).toBe('1.0.0');
325
+ });
326
+ });
327
+ });
328
+ });
329
+