@labacacia/nps-sdk 1.0.0-alpha.4 → 1.0.0-alpha.5

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 (54) hide show
  1. package/CHANGELOG.cn.md +20 -0
  2. package/CHANGELOG.md +20 -0
  3. package/README.cn.md +10 -3
  4. package/README.md +10 -3
  5. package/dist/core/status-codes.d.ts +1 -0
  6. package/dist/core/status-codes.d.ts.map +1 -1
  7. package/dist/core/status-codes.js +1 -0
  8. package/dist/core/status-codes.js.map +1 -1
  9. package/dist/ndp/dns-txt.d.ts +35 -0
  10. package/dist/ndp/dns-txt.d.ts.map +1 -0
  11. package/dist/ndp/dns-txt.js +67 -0
  12. package/dist/ndp/dns-txt.js.map +1 -0
  13. package/dist/ndp/index.d.ts +1 -0
  14. package/dist/ndp/index.d.ts.map +1 -1
  15. package/dist/ndp/index.js +1 -0
  16. package/dist/ndp/index.js.map +1 -1
  17. package/dist/ndp/ndp-registry.d.ts +2 -0
  18. package/dist/ndp/ndp-registry.d.ts.map +1 -1
  19. package/dist/ndp/ndp-registry.js +25 -0
  20. package/dist/ndp/ndp-registry.js.map +1 -1
  21. package/dist/nip/assurance-level.d.ts +5 -0
  22. package/dist/nip/assurance-level.d.ts.map +1 -1
  23. package/dist/nip/assurance-level.js +7 -2
  24. package/dist/nip/assurance-level.js.map +1 -1
  25. package/dist/nip/error-codes.d.ts +2 -0
  26. package/dist/nip/error-codes.d.ts.map +1 -1
  27. package/dist/nip/error-codes.js +2 -0
  28. package/dist/nip/error-codes.js.map +1 -1
  29. package/dist/nop/client.js.map +1 -1
  30. package/dist/nwp/client.js.map +1 -1
  31. package/dist/nwp/error-codes.d.ts +42 -0
  32. package/dist/nwp/error-codes.d.ts.map +1 -0
  33. package/dist/nwp/error-codes.js +53 -0
  34. package/dist/nwp/error-codes.js.map +1 -0
  35. package/dist/nwp/index.d.ts +1 -0
  36. package/dist/nwp/index.d.ts.map +1 -1
  37. package/dist/nwp/index.js +1 -0
  38. package/dist/nwp/index.js.map +1 -1
  39. package/doc/nps-sdk.nip.cn.md +30 -0
  40. package/doc/nps-sdk.nip.md +30 -0
  41. package/doc/nps-sdk.nwp.cn.md +71 -0
  42. package/doc/nps-sdk.nwp.md +71 -0
  43. package/package.json +1 -1
  44. package/src/core/status-codes.ts +1 -0
  45. package/src/ndp/dns-txt.ts +86 -0
  46. package/src/ndp/index.ts +1 -0
  47. package/src/ndp/ndp-registry.ts +34 -0
  48. package/src/nip/assurance-level.ts +6 -1
  49. package/src/nip/error-codes.ts +4 -2
  50. package/src/nop/client.ts +1 -1
  51. package/src/nwp/client.ts +4 -4
  52. package/src/nwp/error-codes.ts +62 -0
  53. package/src/nwp/index.ts +1 -0
  54. package/tests/ndp.test.ts +106 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-codes.js","sourceRoot":"","sources":["../../src/nwp/error-codes.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,sCAAsC;AAEtC,mFAAmF;AAEnF,gFAAgF;AAChF,MAAM,CAAC,MAAM,wBAAwB,GAAM,8BAA8B,CAAC;AAC1E,MAAM,CAAC,MAAM,gBAAgB,GAAc,sBAAsB,CAAC;AAClE,MAAM,CAAC,MAAM,gBAAgB,GAAc,sBAAsB,CAAC;AAClE,MAAM,CAAC,MAAM,yBAAyB,GAAK,+BAA+B,CAAC;AAC3E,MAAM,CAAC,MAAM,2BAA2B,GAAG,iCAAiC,CAAC;AAC7E,MAAM,CAAC,MAAM,sBAAsB,GAAQ,4BAA4B,CAAC;AACxE,MAAM,CAAC,MAAM,uBAAuB,GAAO,6BAA6B,CAAC;AAEzE,iFAAiF;AACjF,MAAM,CAAC,MAAM,oBAAoB,GAAU,0BAA0B,CAAC;AACtE,MAAM,CAAC,MAAM,mBAAmB,GAAW,yBAAyB,CAAC;AACrE,MAAM,CAAC,MAAM,oBAAoB,GAAU,0BAA0B,CAAC;AACtE,MAAM,CAAC,MAAM,kBAAkB,GAAY,wBAAwB,CAAC;AACpE,MAAM,CAAC,MAAM,wBAAwB,GAAM,8BAA8B,CAAC;AAC1E,MAAM,CAAC,MAAM,2BAA2B,GAAG,iCAAiC,CAAC;AAC7E,MAAM,CAAC,MAAM,uBAAuB,GAAO,6BAA6B,CAAC;AACzE,MAAM,CAAC,MAAM,wBAAwB,GAAM,8BAA8B,CAAC;AAE1E,iFAAiF;AACjF,MAAM,CAAC,MAAM,gBAAgB,GAAc,sBAAsB,CAAC;AAClE,MAAM,CAAC,MAAM,qBAAqB,GAAS,2BAA2B,CAAC;AACvE,MAAM,CAAC,MAAM,2BAA2B,GAAG,iCAAiC,CAAC;AAE7E,iFAAiF;AACjF,MAAM,CAAC,MAAM,cAAc,GAAW,oBAAoB,CAAC;AAC3D,MAAM,CAAC,MAAM,sBAAsB,GAAG,4BAA4B,CAAC;AACnE,MAAM,CAAC,MAAM,sBAAsB,GAAG,4BAA4B,CAAC;AACnE,MAAM,CAAC,MAAM,mBAAmB,GAAM,yBAAyB,CAAC;AAEhE,iFAAiF;AACjF,MAAM,CAAC,MAAM,0BAA0B,GAAK,gCAAgC,CAAC;AAC7E,MAAM,CAAC,MAAM,wBAAwB,GAAO,8BAA8B,CAAC;AAC3E,MAAM,CAAC,MAAM,4BAA4B,GAAG,kCAAkC,CAAC;AAC/E,MAAM,CAAC,MAAM,qBAAqB,GAAU,2BAA2B,CAAC;AACxE,MAAM,CAAC,MAAM,qBAAqB,GAAU,2BAA2B,CAAC;AAExE,iFAAiF;AACjF,MAAM,CAAC,MAAM,eAAe,GAAQ,qBAAqB,CAAC;AAC1D,MAAM,CAAC,MAAM,cAAc,GAAS,oBAAoB,CAAC;AACzD,MAAM,CAAC,MAAM,WAAW,GAAY,iBAAiB,CAAC;AACtD,MAAM,CAAC,MAAM,gBAAgB,GAAO,sBAAsB,CAAC;AAC3D,MAAM,CAAC,MAAM,mBAAmB,GAAI,yBAAyB,CAAC;AAE9D,iFAAiF;AACjF,MAAM,CAAC,MAAM,4BAA4B,GAAG,kCAAkC,CAAC;AAC/E,MAAM,CAAC,MAAM,0BAA0B,GAAK,gCAAgC,CAAC;AAC7E,MAAM,CAAC,MAAM,0BAA0B,GAAK,gCAAgC,CAAC;AAE7E,iFAAiF;AACjF,MAAM,CAAC,MAAM,qBAAqB,GAAS,2BAA2B,CAAC;AACvE,MAAM,CAAC,MAAM,0BAA0B,GAAI,gCAAgC,CAAC;AAC5E,MAAM,CAAC,MAAM,0BAA0B,GAAI,gCAAgC,CAAC;AAC5E,MAAM,CAAC,MAAM,2BAA2B,GAAG,iCAAiC,CAAC;AAE7E,gFAAgF;AAChF,MAAM,CAAC,MAAM,yBAAyB,GAAG,+BAA+B,CAAC"}
@@ -1,4 +1,5 @@
1
1
  export * from "./frames.js";
2
2
  export * from "./registry.js";
3
3
  export * from "./client.js";
4
+ export * as NwpErrorCodes from "./error-codes.js";
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/nwp/index.ts"],"names":[],"mappings":"AAGA,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/nwp/index.ts"],"names":[],"mappings":"AAGA,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,OAAO,KAAK,aAAa,MAAM,kBAAkB,CAAC"}
package/dist/nwp/index.js CHANGED
@@ -3,4 +3,5 @@
3
3
  export * from "./frames.js";
4
4
  export * from "./registry.js";
5
5
  export * from "./client.js";
6
+ export * as NwpErrorCodes from "./error-codes.js";
6
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/nwp/index.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,sCAAsC;AAEtC,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/nwp/index.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,sCAAsC;AAEtC,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,OAAO,KAAK,aAAa,MAAM,kBAAkB,CAAC"}
@@ -19,6 +19,7 @@ NIP 是 NPS 的 TLS/PKI。本模块暴露三个身份帧
19
19
  - [`RevokeFrame` (0x22)](#revokeframe-0x22)
20
20
  - [`NipIdentity`](#nipidentity)
21
21
  - [规范化 JSON 与签名格式](#规范化-json-与签名格式)
22
+ - [`NipErrorCodes`](#niperrorecodes)
22
23
 
23
24
  ---
24
25
 
@@ -233,3 +234,32 @@ const signed = new IdentFrame(unsigned.nid, unsigned.pubKey, meta, signature)
233
234
  const ok = id.verify(signed.unsignedDict(), signed.signature);
234
235
  // → true
235
236
  ```
237
+
238
+ ---
239
+
240
+ ## `NipErrorCodes`
241
+
242
+ NIP wire 错误码字符串常量。从 `@labacacia/nps-sdk/nip` 导入。
243
+
244
+ ```typescript
245
+ import { NipErrorCodes } from "@labacacia/nps-sdk/nip";
246
+ ```
247
+
248
+ | 常量 | Wire 值 | 起始版本 |
249
+ |------|---------|----------|
250
+ | `NipErrorCodes.IDENT_SIG_INVALID` | `"NIP-IDENT-SIG-INVALID"` | alpha.4 |
251
+ | `NipErrorCodes.IDENT_NID_MISMATCH` | `"NIP-IDENT-NID-MISMATCH"` | alpha.4 |
252
+ | `NipErrorCodes.IDENT_EXPIRED` | `"NIP-IDENT-EXPIRED"` | alpha.4 |
253
+ | `NipErrorCodes.IDENT_REVOKED` | `"NIP-IDENT-REVOKED"` | alpha.4 |
254
+ | `NipErrorCodes.TRUST_CHAIN_BROKEN` | `"NIP-TRUST-CHAIN-BROKEN"` | alpha.4 |
255
+ | `NipErrorCodes.TRUST_SCOPE_VIOLATION` | `"NIP-TRUST-SCOPE-VIOLATION"` | alpha.4 |
256
+ | `NipErrorCodes.ACME_CHALLENGE_FAILED` | `"NIP-ACME-CHALLENGE-FAILED"` | alpha.4 |
257
+ | `NipErrorCodes.ACME_ORDER_EXPIRED` | `"NIP-ACME-ORDER-EXPIRED"` | alpha.4 |
258
+ | `NipErrorCodes.X509_CERT_INVALID` | `"NIP-X509-CERT-INVALID"` | alpha.4 |
259
+ | `NipErrorCodes.X509_CHAIN_UNTRUSTED` | `"NIP-X509-CHAIN-UNTRUSTED"` | alpha.4 |
260
+ | `NipErrorCodes.REPUTATION_LOG_UNREACHABLE` | `"NIP-REPUTATION-LOG-UNREACHABLE"` | alpha.4 |
261
+ | `NipErrorCodes.REPUTATION_GOSSIP_FORK` | `"NIP-REPUTATION-GOSSIP-FORK"` | **alpha.5** |
262
+ | `NipErrorCodes.REPUTATION_GOSSIP_SIG_INVALID` | `"NIP-REPUTATION-GOSSIP-SIG-INVALID"` | **alpha.5** |
263
+
264
+ `REPUTATION_GOSSIP_FORK`:跨节点 STH 一致性检查失败时返回。
265
+ `REPUTATION_GOSSIP_SIG_INVALID`:gossip 交换中对端 STH 签名验证失败时返回。
@@ -19,6 +19,7 @@ AES-256-GCM + PBKDF2-SHA256 key-file encryption.
19
19
  - [`RevokeFrame` (0x22)](#revokeframe-0x22)
20
20
  - [`NipIdentity`](#nipidentity)
21
21
  - [Canonical JSON & signing format](#canonical-json--signing-format)
22
+ - [`NipErrorCodes`](#niperrorecodes)
22
23
 
23
24
  ---
24
25
 
@@ -240,3 +241,32 @@ const signed = new IdentFrame(unsigned.nid, unsigned.pubKey, meta, signature)
240
241
  const ok = id.verify(signed.unsignedDict(), signed.signature);
241
242
  // → true
242
243
  ```
244
+
245
+ ---
246
+
247
+ ## `NipErrorCodes`
248
+
249
+ String constants for NIP wire error codes. Import from `@labacacia/nps-sdk/nip`.
250
+
251
+ ```typescript
252
+ import { NipErrorCodes } from "@labacacia/nps-sdk/nip";
253
+ ```
254
+
255
+ | Constant | Wire value | Since |
256
+ |----------|------------|-------|
257
+ | `NipErrorCodes.IDENT_SIG_INVALID` | `"NIP-IDENT-SIG-INVALID"` | alpha.4 |
258
+ | `NipErrorCodes.IDENT_NID_MISMATCH` | `"NIP-IDENT-NID-MISMATCH"` | alpha.4 |
259
+ | `NipErrorCodes.IDENT_EXPIRED` | `"NIP-IDENT-EXPIRED"` | alpha.4 |
260
+ | `NipErrorCodes.IDENT_REVOKED` | `"NIP-IDENT-REVOKED"` | alpha.4 |
261
+ | `NipErrorCodes.TRUST_CHAIN_BROKEN` | `"NIP-TRUST-CHAIN-BROKEN"` | alpha.4 |
262
+ | `NipErrorCodes.TRUST_SCOPE_VIOLATION` | `"NIP-TRUST-SCOPE-VIOLATION"` | alpha.4 |
263
+ | `NipErrorCodes.ACME_CHALLENGE_FAILED` | `"NIP-ACME-CHALLENGE-FAILED"` | alpha.4 |
264
+ | `NipErrorCodes.ACME_ORDER_EXPIRED` | `"NIP-ACME-ORDER-EXPIRED"` | alpha.4 |
265
+ | `NipErrorCodes.X509_CERT_INVALID` | `"NIP-X509-CERT-INVALID"` | alpha.4 |
266
+ | `NipErrorCodes.X509_CHAIN_UNTRUSTED` | `"NIP-X509-CHAIN-UNTRUSTED"` | alpha.4 |
267
+ | `NipErrorCodes.REPUTATION_LOG_UNREACHABLE` | `"NIP-REPUTATION-LOG-UNREACHABLE"` | alpha.4 |
268
+ | `NipErrorCodes.REPUTATION_GOSSIP_FORK` | `"NIP-REPUTATION-GOSSIP-FORK"` | **alpha.5** |
269
+ | `NipErrorCodes.REPUTATION_GOSSIP_SIG_INVALID` | `"NIP-REPUTATION-GOSSIP-SIG-INVALID"` | **alpha.5** |
270
+
271
+ `REPUTATION_GOSSIP_FORK` is returned when an STH consistency check fails across peers.
272
+ `REPUTATION_GOSSIP_SIG_INVALID` is returned when a peer STH signature fails verification during a gossip exchange.
@@ -18,6 +18,7 @@ NWP 是 AI 的 HTTP。本模块提供两个 NWP 帧
18
18
  - [`QueryFrame` (0x10)](#queryframe-0x10)
19
19
  - [`ActionFrame` (0x11)](#actionframe-0x11)
20
20
  - [`NwpClient`](#nwpclient)
21
+ - [`NwpErrorCodes`](#nwperrorcodes)
21
22
 
22
23
  ---
23
24
 
@@ -215,3 +216,73 @@ const resp = await nwp.invoke(new ActionFrame(
215
216
  ));
216
217
  // resp 是 AsyncActionResponse
217
218
  ```
219
+
220
+ ---
221
+
222
+ ## `NwpErrorCodes`
223
+
224
+ 30 个 NWP wire 错误码字符串常量(alpha.5 新增)。
225
+
226
+ ```typescript
227
+ import { NwpErrorCodes } from "@labacacia/nps-sdk/nwp";
228
+ ```
229
+
230
+ ### Auth 组(`NWP-AUTH-*`)
231
+
232
+ | 常量 | Wire 值 |
233
+ |------|---------|
234
+ | `NwpErrorCodes.AUTH_NID_SCOPE_VIOLATION` | `"NWP-AUTH-NID-SCOPE-VIOLATION"` |
235
+ | `NwpErrorCodes.AUTH_NID_NOT_TRUSTED` | `"NWP-AUTH-NID-NOT-TRUSTED"` |
236
+ | `NwpErrorCodes.AUTH_NID_EXPIRED` | `"NWP-AUTH-NID-EXPIRED"` |
237
+ | `NwpErrorCodes.AUTH_NID_REVOKED` | `"NWP-AUTH-NID-REVOKED"` |
238
+ | `NwpErrorCodes.AUTH_SIG_INVALID` | `"NWP-AUTH-SIG-INVALID"` |
239
+ | `NwpErrorCodes.AUTH_TOKEN_BUDGET_EXCEEDED` | `"NWP-AUTH-TOKEN-BUDGET-EXCEEDED"` |
240
+ | `NwpErrorCodes.AUTH_RATE_LIMIT` | `"NWP-AUTH-RATE-LIMIT"` |
241
+
242
+ ### Query 组(`NWP-QUERY-*`)
243
+
244
+ | 常量 | Wire 值 |
245
+ |------|---------|
246
+ | `NwpErrorCodes.QUERY_ANCHOR_NOT_FOUND` | `"NWP-QUERY-ANCHOR-NOT-FOUND"` |
247
+ | `NwpErrorCodes.QUERY_ANCHOR_EXPIRED` | `"NWP-QUERY-ANCHOR-EXPIRED"` |
248
+ | `NwpErrorCodes.QUERY_SCHEMA_MISMATCH` | `"NWP-QUERY-SCHEMA-MISMATCH"` |
249
+ | `NwpErrorCodes.QUERY_LIMIT_EXCEEDED` | `"NWP-QUERY-LIMIT-EXCEEDED"` |
250
+ | `NwpErrorCodes.QUERY_DEPTH_EXCEEDED` | `"NWP-QUERY-DEPTH-EXCEEDED"` |
251
+ | `NwpErrorCodes.QUERY_FILTER_INVALID` | `"NWP-QUERY-FILTER-INVALID"` |
252
+ | `NwpErrorCodes.QUERY_VECTOR_UNSUPPORTED` | `"NWP-QUERY-VECTOR-UNSUPPORTED"` |
253
+ | `NwpErrorCodes.QUERY_CURSOR_INVALID` | `"NWP-QUERY-CURSOR-INVALID"` |
254
+
255
+ ### Action、Task、Subscribe、Infrastructure 组
256
+
257
+ | 常量 | Wire 值 |
258
+ |------|---------|
259
+ | `NwpErrorCodes.ACTION_NOT_FOUND` | `"NWP-ACTION-NOT-FOUND"` |
260
+ | `NwpErrorCodes.ACTION_PARAM_INVALID` | `"NWP-ACTION-PARAM-INVALID"` |
261
+ | `NwpErrorCodes.ACTION_IDEMPOTENCY_CONFLICT` | `"NWP-ACTION-IDEMPOTENCY-CONFLICT"` |
262
+ | `NwpErrorCodes.TASK_NOT_FOUND` | `"NWP-TASK-NOT-FOUND"` |
263
+ | `NwpErrorCodes.TASK_ALREADY_COMPLETE` | `"NWP-TASK-ALREADY-COMPLETE"` |
264
+ | `NwpErrorCodes.TASK_TIMEOUT` | `"NWP-TASK-TIMEOUT"` |
265
+ | `NwpErrorCodes.TASK_CANCELLED` | `"NWP-TASK-CANCELLED"` |
266
+ | `NwpErrorCodes.SUBSCRIBE_TOPIC_NOT_FOUND` | `"NWP-SUBSCRIBE-TOPIC-NOT-FOUND"` |
267
+ | `NwpErrorCodes.SUBSCRIBE_ALREADY_ACTIVE` | `"NWP-SUBSCRIBE-ALREADY-ACTIVE"` |
268
+ | `NwpErrorCodes.SUBSCRIBE_QUOTA_EXCEEDED` | `"NWP-SUBSCRIBE-QUOTA-EXCEEDED"` |
269
+ | `NwpErrorCodes.SUBSCRIBE_FILTER_INVALID` | `"NWP-SUBSCRIBE-FILTER-INVALID"` |
270
+ | `NwpErrorCodes.SUBSCRIBE_NOT_FOUND` | `"NWP-SUBSCRIBE-NOT-FOUND"` |
271
+ | `NwpErrorCodes.INFRA_NODE_OVERLOADED` | `"NWP-INFRA-NODE-OVERLOADED"` |
272
+ | `NwpErrorCodes.INFRA_UPSTREAM_TIMEOUT` | `"NWP-INFRA-UPSTREAM-TIMEOUT"` |
273
+ | `NwpErrorCodes.INFRA_UPSTREAM_ERROR` | `"NWP-INFRA-UPSTREAM-ERROR"` |
274
+ | `NwpErrorCodes.INFRA_STORAGE_ERROR` | `"NWP-INFRA-STORAGE-ERROR"` |
275
+ | `NwpErrorCodes.INFRA_CONFIG_ERROR` | `"NWP-INFRA-CONFIG-ERROR"` |
276
+
277
+ ### Manifest、Topology、Reserved 组
278
+
279
+ | 常量 | Wire 值 |
280
+ |------|---------|
281
+ | `NwpErrorCodes.MANIFEST_NOT_FOUND` | `"NWP-MANIFEST-NOT-FOUND"` |
282
+ | `NwpErrorCodes.MANIFEST_PARSE_ERROR` | `"NWP-MANIFEST-PARSE-ERROR"` |
283
+ | `NwpErrorCodes.MANIFEST_VERSION_MISMATCH` | `"NWP-MANIFEST-VERSION-MISMATCH"` |
284
+ | `NwpErrorCodes.TOPOLOGY_UNAUTHORIZED` | `"NWP-TOPOLOGY-UNAUTHORIZED"` |
285
+ | `NwpErrorCodes.TOPOLOGY_NOT_AVAILABLE` | `"NWP-TOPOLOGY-NOT-AVAILABLE"` |
286
+ | `NwpErrorCodes.TOPOLOGY_SNAPSHOT_TOO_LARGE` | `"NWP-TOPOLOGY-SNAPSHOT-TOO-LARGE"` |
287
+ | `NwpErrorCodes.TOPOLOGY_STREAM_INTERRUPTED` | `"NWP-TOPOLOGY-STREAM-INTERRUPTED"` |
288
+ | `NwpErrorCodes.RESERVED_TYPE_UNSUPPORTED` | `"NWP-RESERVED-TYPE-UNSUPPORTED"` |
@@ -19,6 +19,7 @@ action responses.
19
19
  - [`QueryFrame` (0x10)](#queryframe-0x10)
20
20
  - [`ActionFrame` (0x11)](#actionframe-0x11)
21
21
  - [`NwpClient`](#nwpclient)
22
+ - [`NwpErrorCodes`](#nwperrorcodes)
22
23
 
23
24
  ---
24
25
 
@@ -222,3 +223,73 @@ const resp = await nwp.invoke(new ActionFrame(
222
223
  ));
223
224
  // resp is AsyncActionResponse
224
225
  ```
226
+
227
+ ---
228
+
229
+ ## `NwpErrorCodes`
230
+
231
+ String constants for the 30 NWP wire error codes (added in alpha.5).
232
+
233
+ ```typescript
234
+ import { NwpErrorCodes } from "@labacacia/nps-sdk/nwp";
235
+ ```
236
+
237
+ ### Auth group (`NWP-AUTH-*`)
238
+
239
+ | Constant | Wire value |
240
+ |----------|------------|
241
+ | `NwpErrorCodes.AUTH_NID_SCOPE_VIOLATION` | `"NWP-AUTH-NID-SCOPE-VIOLATION"` |
242
+ | `NwpErrorCodes.AUTH_NID_NOT_TRUSTED` | `"NWP-AUTH-NID-NOT-TRUSTED"` |
243
+ | `NwpErrorCodes.AUTH_NID_EXPIRED` | `"NWP-AUTH-NID-EXPIRED"` |
244
+ | `NwpErrorCodes.AUTH_NID_REVOKED` | `"NWP-AUTH-NID-REVOKED"` |
245
+ | `NwpErrorCodes.AUTH_SIG_INVALID` | `"NWP-AUTH-SIG-INVALID"` |
246
+ | `NwpErrorCodes.AUTH_TOKEN_BUDGET_EXCEEDED` | `"NWP-AUTH-TOKEN-BUDGET-EXCEEDED"` |
247
+ | `NwpErrorCodes.AUTH_RATE_LIMIT` | `"NWP-AUTH-RATE-LIMIT"` |
248
+
249
+ ### Query group (`NWP-QUERY-*`)
250
+
251
+ | Constant | Wire value |
252
+ |----------|------------|
253
+ | `NwpErrorCodes.QUERY_ANCHOR_NOT_FOUND` | `"NWP-QUERY-ANCHOR-NOT-FOUND"` |
254
+ | `NwpErrorCodes.QUERY_ANCHOR_EXPIRED` | `"NWP-QUERY-ANCHOR-EXPIRED"` |
255
+ | `NwpErrorCodes.QUERY_SCHEMA_MISMATCH` | `"NWP-QUERY-SCHEMA-MISMATCH"` |
256
+ | `NwpErrorCodes.QUERY_LIMIT_EXCEEDED` | `"NWP-QUERY-LIMIT-EXCEEDED"` |
257
+ | `NwpErrorCodes.QUERY_DEPTH_EXCEEDED` | `"NWP-QUERY-DEPTH-EXCEEDED"` |
258
+ | `NwpErrorCodes.QUERY_FILTER_INVALID` | `"NWP-QUERY-FILTER-INVALID"` |
259
+ | `NwpErrorCodes.QUERY_VECTOR_UNSUPPORTED` | `"NWP-QUERY-VECTOR-UNSUPPORTED"` |
260
+ | `NwpErrorCodes.QUERY_CURSOR_INVALID` | `"NWP-QUERY-CURSOR-INVALID"` |
261
+
262
+ ### Action, Task, Subscribe, Infrastructure groups
263
+
264
+ | Constant | Wire value |
265
+ |----------|------------|
266
+ | `NwpErrorCodes.ACTION_NOT_FOUND` | `"NWP-ACTION-NOT-FOUND"` |
267
+ | `NwpErrorCodes.ACTION_PARAM_INVALID` | `"NWP-ACTION-PARAM-INVALID"` |
268
+ | `NwpErrorCodes.ACTION_IDEMPOTENCY_CONFLICT` | `"NWP-ACTION-IDEMPOTENCY-CONFLICT"` |
269
+ | `NwpErrorCodes.TASK_NOT_FOUND` | `"NWP-TASK-NOT-FOUND"` |
270
+ | `NwpErrorCodes.TASK_ALREADY_COMPLETE` | `"NWP-TASK-ALREADY-COMPLETE"` |
271
+ | `NwpErrorCodes.TASK_TIMEOUT` | `"NWP-TASK-TIMEOUT"` |
272
+ | `NwpErrorCodes.TASK_CANCELLED` | `"NWP-TASK-CANCELLED"` |
273
+ | `NwpErrorCodes.SUBSCRIBE_TOPIC_NOT_FOUND` | `"NWP-SUBSCRIBE-TOPIC-NOT-FOUND"` |
274
+ | `NwpErrorCodes.SUBSCRIBE_ALREADY_ACTIVE` | `"NWP-SUBSCRIBE-ALREADY-ACTIVE"` |
275
+ | `NwpErrorCodes.SUBSCRIBE_QUOTA_EXCEEDED` | `"NWP-SUBSCRIBE-QUOTA-EXCEEDED"` |
276
+ | `NwpErrorCodes.SUBSCRIBE_FILTER_INVALID` | `"NWP-SUBSCRIBE-FILTER-INVALID"` |
277
+ | `NwpErrorCodes.SUBSCRIBE_NOT_FOUND` | `"NWP-SUBSCRIBE-NOT-FOUND"` |
278
+ | `NwpErrorCodes.INFRA_NODE_OVERLOADED` | `"NWP-INFRA-NODE-OVERLOADED"` |
279
+ | `NwpErrorCodes.INFRA_UPSTREAM_TIMEOUT` | `"NWP-INFRA-UPSTREAM-TIMEOUT"` |
280
+ | `NwpErrorCodes.INFRA_UPSTREAM_ERROR` | `"NWP-INFRA-UPSTREAM-ERROR"` |
281
+ | `NwpErrorCodes.INFRA_STORAGE_ERROR` | `"NWP-INFRA-STORAGE-ERROR"` |
282
+ | `NwpErrorCodes.INFRA_CONFIG_ERROR` | `"NWP-INFRA-CONFIG-ERROR"` |
283
+
284
+ ### Manifest, Topology, Reserved groups
285
+
286
+ | Constant | Wire value |
287
+ |----------|------------|
288
+ | `NwpErrorCodes.MANIFEST_NOT_FOUND` | `"NWP-MANIFEST-NOT-FOUND"` |
289
+ | `NwpErrorCodes.MANIFEST_PARSE_ERROR` | `"NWP-MANIFEST-PARSE-ERROR"` |
290
+ | `NwpErrorCodes.MANIFEST_VERSION_MISMATCH` | `"NWP-MANIFEST-VERSION-MISMATCH"` |
291
+ | `NwpErrorCodes.TOPOLOGY_UNAUTHORIZED` | `"NWP-TOPOLOGY-UNAUTHORIZED"` |
292
+ | `NwpErrorCodes.TOPOLOGY_NOT_AVAILABLE` | `"NWP-TOPOLOGY-NOT-AVAILABLE"` |
293
+ | `NwpErrorCodes.TOPOLOGY_SNAPSHOT_TOO_LARGE` | `"NWP-TOPOLOGY-SNAPSHOT-TOO-LARGE"` |
294
+ | `NwpErrorCodes.TOPOLOGY_STREAM_INTERRUPTED` | `"NWP-TOPOLOGY-STREAM-INTERRUPTED"` |
295
+ | `NwpErrorCodes.RESERVED_TYPE_UNSUPPORTED` | `"NWP-RESERVED-TYPE-UNSUPPORTED"` |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@labacacia/nps-sdk",
3
- "version": "1.0.0-alpha.4",
3
+ "version": "1.0.0-alpha.5",
4
4
  "description": "TypeScript SDK for the Neural Protocol Suite (NPS) — NCP, NWP, NIP, NDP, NOP",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -27,6 +27,7 @@ export const NpsStatusCodes = {
27
27
  NPS_SERVER_UNAVAILABLE: "NPS-SERVER-UNAVAILABLE",
28
28
  NPS_SERVER_TIMEOUT: "NPS-SERVER-TIMEOUT",
29
29
  NPS_SERVER_ENCODING_UNSUPPORTED: "NPS-SERVER-ENCODING-UNSUPPORTED",
30
+ NPS_SERVER_UNSUPPORTED: "NPS-SERVER-UNSUPPORTED",
30
31
 
31
32
  // Stream
32
33
  NPS_STREAM_SEQ_GAP: "NPS-STREAM-SEQ-GAP",
@@ -0,0 +1,86 @@
1
+ // Copyright 2026 INNO LOTUS PTY LTD
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import type { NdpResolveResult } from "./frames.js";
5
+
6
+ export const DNS_TXT_DEFAULT_TTL = 300;
7
+
8
+ /**
9
+ * Extract the hostname from an NWP target URI.
10
+ * e.g. "nwp://api.example.com/products" → "api.example.com"
11
+ */
12
+ export function extractHostFromTarget(target: string): string | undefined {
13
+ if (!target.startsWith("nwp://")) return undefined;
14
+ const rest = target.slice("nwp://".length);
15
+ const slashIdx = rest.indexOf("/");
16
+ const host = slashIdx === -1 ? rest : rest.slice(0, slashIdx);
17
+ return host.length > 0 ? host : undefined;
18
+ }
19
+
20
+ /**
21
+ * Parse one TXT record (array of string chunks) into an NdpResolveResult.
22
+ *
23
+ * Expected format (chunks joined with a single space):
24
+ * v=nps1 type=<type> port=<port> nid=<nid> fp=sha256:<fingerprint>
25
+ *
26
+ * Rules:
27
+ * - `v` MUST be present and equal to "nps1"
28
+ * - `nid` MUST be present
29
+ * - `port` defaults to 17433 when absent
30
+ * - `fp` is mapped to certFingerprint
31
+ */
32
+ export function parseNpsTxtRecord(
33
+ parts: string[],
34
+ host: string,
35
+ ): NdpResolveResult | undefined {
36
+ const joined = parts.join(" ");
37
+ const kv = new Map<string, string>();
38
+
39
+ for (const token of joined.split(/\s+/)) {
40
+ const eq = token.indexOf("=");
41
+ if (eq === -1) continue;
42
+ const key = token.slice(0, eq);
43
+ const val = token.slice(eq + 1);
44
+ kv.set(key, val);
45
+ }
46
+
47
+ if (kv.get("v") !== "nps1") return undefined;
48
+
49
+ const nid = kv.get("nid");
50
+ if (!nid) return undefined;
51
+
52
+ const rawPort = kv.get("port");
53
+ const port = rawPort !== undefined ? Number(rawPort) : 17433;
54
+ const fp = kv.get("fp");
55
+
56
+ const result: NdpResolveResult = {
57
+ host,
58
+ port,
59
+ ttl: DNS_TXT_DEFAULT_TTL,
60
+ };
61
+
62
+ if (fp !== undefined) {
63
+ result.certFingerprint = fp;
64
+ }
65
+
66
+ return result;
67
+ }
68
+
69
+ /**
70
+ * Abstraction over DNS TXT lookups.
71
+ * The default implementation uses Node's `dns.promises`; pass a mock in tests.
72
+ */
73
+ export interface DnsTxtLookup {
74
+ resolveTxt(hostname: string): Promise<string[][]>;
75
+ }
76
+
77
+ /**
78
+ * System DNS TXT resolver backed by Node's built-in `dns.promises`.
79
+ * The dynamic `import()` keeps browser bundles from failing at parse time.
80
+ */
81
+ export class SystemDnsTxtLookup implements DnsTxtLookup {
82
+ async resolveTxt(hostname: string): Promise<string[][]> {
83
+ const { promises: dns } = await import("node:dns");
84
+ return dns.resolveTxt(hostname);
85
+ }
86
+ }
package/src/ndp/index.ts CHANGED
@@ -5,3 +5,4 @@ export * from "./frames.js";
5
5
  export * from "./registry.js";
6
6
  export * from "./ndp-registry.js";
7
7
  export * from "./validator.js";
8
+ export * from "./dns-txt.js";
@@ -2,6 +2,12 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import type { AnnounceFrame, NdpResolveResult } from "./frames.js";
5
+ import {
6
+ extractHostFromTarget,
7
+ parseNpsTxtRecord,
8
+ SystemDnsTxtLookup,
9
+ type DnsTxtLookup,
10
+ } from "./dns-txt.js";
5
11
 
6
12
  interface RegistryEntry {
7
13
  frame: AnnounceFrame;
@@ -54,6 +60,34 @@ export class InMemoryNdpRegistry {
54
60
  return result;
55
61
  }
56
62
 
63
+ async resolveWithDns(
64
+ target: string,
65
+ resolver: DnsTxtLookup = new SystemDnsTxtLookup(),
66
+ ): Promise<NdpResolveResult | undefined> {
67
+ // 1. Try in-memory registry first
68
+ const cached = this.resolve(target);
69
+ if (cached !== undefined) return cached;
70
+
71
+ // 2. Extract hostname and fall back to DNS TXT lookup
72
+ const host = extractHostFromTarget(target);
73
+ if (host === undefined) return undefined;
74
+
75
+ const txtHost = `_nps-node.${host}`;
76
+ let records: string[][];
77
+ try {
78
+ records = await resolver.resolveTxt(txtHost);
79
+ } catch {
80
+ return undefined;
81
+ }
82
+
83
+ for (const record of records) {
84
+ const result = parseNpsTxtRecord(record, host);
85
+ if (result !== undefined) return result;
86
+ }
87
+
88
+ return undefined;
89
+ }
90
+
57
91
  static nwpTargetMatchesNid(nid: string, target: string): boolean {
58
92
  // NID: urn:nps:node:{authority}:{path-segment}
59
93
  // target: nwp://{authority}/{path}
@@ -18,8 +18,13 @@ export class AssuranceLevel {
18
18
  return this.rank >= required.rank;
19
19
  }
20
20
 
21
+ /**
22
+ * Parse a wire string. `null`, `undefined`, or `""` → `ANONYMOUS`
23
+ * (backward compat per NPS-RFC-0003 §5.1.1). Any other unrecognised
24
+ * non-empty value throws — callers MUST surface it as `NIP-ASSURANCE-UNKNOWN`.
25
+ */
21
26
  static fromWire(wire: string | null | undefined): AssuranceLevel {
22
- if (wire == null) return AssuranceLevel.ANONYMOUS;
27
+ if (!wire) return AssuranceLevel.ANONYMOUS; // null, undefined, or ""
23
28
  for (const level of [AssuranceLevel.ANONYMOUS, AssuranceLevel.ATTESTED, AssuranceLevel.VERIFIED]) {
24
29
  if (level.wire === wire) return level;
25
30
  }
@@ -26,8 +26,10 @@ export const ASSURANCE_MISMATCH = "NIP-ASSURANCE-MISMATCH";
26
26
  export const ASSURANCE_UNKNOWN = "NIP-ASSURANCE-UNKNOWN";
27
27
 
28
28
  // ── RFC-0004 (reputation log) ────────────────────────────────────────────────
29
- export const REPUTATION_ENTRY_INVALID = "NIP-REPUTATION-ENTRY-INVALID";
30
- export const REPUTATION_LOG_UNREACHABLE = "NIP-REPUTATION-LOG-UNREACHABLE";
29
+ export const REPUTATION_ENTRY_INVALID = "NIP-REPUTATION-ENTRY-INVALID";
30
+ export const REPUTATION_LOG_UNREACHABLE = "NIP-REPUTATION-LOG-UNREACHABLE";
31
+ export const REPUTATION_GOSSIP_FORK = "NIP-REPUTATION-GOSSIP-FORK";
32
+ export const REPUTATION_GOSSIP_SIG_INVALID = "NIP-REPUTATION-GOSSIP-SIG-INVALID";
31
33
 
32
34
  // ── RFC-0002 (X.509 + ACME) ──────────────────────────────────────────────────
33
35
  export const CERT_FORMAT_INVALID = "NIP-CERT-FORMAT-INVALID";
package/src/nop/client.ts CHANGED
@@ -57,7 +57,7 @@ export class NopClient {
57
57
  const wire = this._codec.encode(frame, { overrideTier: this._tier });
58
58
  const res = await fetch(`${this._baseUrl}/task`, {
59
59
  method: "POST",
60
- body: wire,
60
+ body: wire as BodyInit,
61
61
  headers: { "Content-Type": "application/x-nps-frame", "Accept": "application/json" },
62
62
  });
63
63
  if (!res.ok) throw new Error(`NOP /task failed: HTTP ${res.status}`);
package/src/nwp/client.ts CHANGED
@@ -44,7 +44,7 @@ export class NwpClient {
44
44
  const wire = this._codec.encode(frame, { overrideTier: this._tier });
45
45
  const res = await fetch(`${this._baseUrl}/anchor`, {
46
46
  method: "POST",
47
- body: wire,
47
+ body: wire as BodyInit,
48
48
  headers: { "Content-Type": CONTENT_TYPE, "Accept": CONTENT_TYPE },
49
49
  });
50
50
  if (!res.ok) throw new Error(`NWP /anchor failed: HTTP ${res.status}`);
@@ -54,7 +54,7 @@ export class NwpClient {
54
54
  const wire = this._codec.encode(frame, { overrideTier: this._tier });
55
55
  const res = await fetch(`${this._baseUrl}/query`, {
56
56
  method: "POST",
57
- body: wire,
57
+ body: wire as BodyInit,
58
58
  headers: { "Content-Type": CONTENT_TYPE, "Accept": CONTENT_TYPE },
59
59
  });
60
60
  if (!res.ok) throw new Error(`NWP /query failed: HTTP ${res.status}`);
@@ -71,7 +71,7 @@ export class NwpClient {
71
71
  const wire = this._codec.encode(frame, { overrideTier: this._tier });
72
72
  const res = await fetch(`${this._baseUrl}/stream`, {
73
73
  method: "POST",
74
- body: wire,
74
+ body: wire as BodyInit,
75
75
  headers: { "Content-Type": CONTENT_TYPE, "Accept": CONTENT_TYPE },
76
76
  });
77
77
  if (!res.ok) throw new Error(`NWP /stream failed: HTTP ${res.status}`);
@@ -95,7 +95,7 @@ export class NwpClient {
95
95
  const wire = this._codec.encode(frame, { overrideTier: this._tier });
96
96
  const res = await fetch(`${this._baseUrl}/invoke`, {
97
97
  method: "POST",
98
- body: wire,
98
+ body: wire as BodyInit,
99
99
  headers: { "Content-Type": CONTENT_TYPE, "Accept": CONTENT_TYPE },
100
100
  });
101
101
  if (!res.ok) throw new Error(`NWP /invoke failed: HTTP ${res.status}`);
@@ -0,0 +1,62 @@
1
+ // Copyright 2026 INNO LOTUS PTY LTD
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ /** NWP error code wire constants — mirror of `spec/error-codes.md` NWP section. */
5
+
6
+ // ── Auth ─────────────────────────────────────────────────────────────────────
7
+ export const AUTH_NID_SCOPE_VIOLATION = "NWP-AUTH-NID-SCOPE-VIOLATION";
8
+ export const AUTH_NID_EXPIRED = "NWP-AUTH-NID-EXPIRED";
9
+ export const AUTH_NID_REVOKED = "NWP-AUTH-NID-REVOKED";
10
+ export const AUTH_NID_UNTRUSTED_ISSUER = "NWP-AUTH-NID-UNTRUSTED-ISSUER";
11
+ export const AUTH_NID_CAPABILITY_MISSING = "NWP-AUTH-NID-CAPABILITY-MISSING";
12
+ export const AUTH_ASSURANCE_TOO_LOW = "NWP-AUTH-ASSURANCE-TOO-LOW";
13
+ export const AUTH_REPUTATION_BLOCKED = "NWP-AUTH-REPUTATION-BLOCKED";
14
+
15
+ // ── Query ─────────────────────────────────────────────────────────────────────
16
+ export const QUERY_FILTER_INVALID = "NWP-QUERY-FILTER-INVALID";
17
+ export const QUERY_FIELD_UNKNOWN = "NWP-QUERY-FIELD-UNKNOWN";
18
+ export const QUERY_CURSOR_INVALID = "NWP-QUERY-CURSOR-INVALID";
19
+ export const QUERY_REGEX_UNSAFE = "NWP-QUERY-REGEX-UNSAFE";
20
+ export const QUERY_VECTOR_UNSUPPORTED = "NWP-QUERY-VECTOR-UNSUPPORTED";
21
+ export const QUERY_AGGREGATE_UNSUPPORTED = "NWP-QUERY-AGGREGATE-UNSUPPORTED";
22
+ export const QUERY_AGGREGATE_INVALID = "NWP-QUERY-AGGREGATE-INVALID";
23
+ export const QUERY_STREAM_UNSUPPORTED = "NWP-QUERY-STREAM-UNSUPPORTED";
24
+
25
+ // ── Action ────────────────────────────────────────────────────────────────────
26
+ export const ACTION_NOT_FOUND = "NWP-ACTION-NOT-FOUND";
27
+ export const ACTION_PARAMS_INVALID = "NWP-ACTION-PARAMS-INVALID";
28
+ export const ACTION_IDEMPOTENCY_CONFLICT = "NWP-ACTION-IDEMPOTENCY-CONFLICT";
29
+
30
+ // ── Task ──────────────────────────────────────────────────────────────────────
31
+ export const TASK_NOT_FOUND = "NWP-TASK-NOT-FOUND";
32
+ export const TASK_ALREADY_CANCELLED = "NWP-TASK-ALREADY-CANCELLED";
33
+ export const TASK_ALREADY_COMPLETED = "NWP-TASK-ALREADY-COMPLETED";
34
+ export const TASK_ALREADY_FAILED = "NWP-TASK-ALREADY-FAILED";
35
+
36
+ // ── Subscribe ─────────────────────────────────────────────────────────────────
37
+ export const SUBSCRIBE_STREAM_NOT_FOUND = "NWP-SUBSCRIBE-STREAM-NOT-FOUND";
38
+ export const SUBSCRIBE_LIMIT_EXCEEDED = "NWP-SUBSCRIBE-LIMIT-EXCEEDED";
39
+ export const SUBSCRIBE_FILTER_UNSUPPORTED = "NWP-SUBSCRIBE-FILTER-UNSUPPORTED";
40
+ export const SUBSCRIBE_INTERRUPTED = "NWP-SUBSCRIBE-INTERRUPTED";
41
+ export const SUBSCRIBE_SEQ_TOO_OLD = "NWP-SUBSCRIBE-SEQ-TOO-OLD";
42
+
43
+ // ── Infrastructure ────────────────────────────────────────────────────────────
44
+ export const BUDGET_EXCEEDED = "NWP-BUDGET-EXCEEDED";
45
+ export const DEPTH_EXCEEDED = "NWP-DEPTH-EXCEEDED";
46
+ export const GRAPH_CYCLE = "NWP-GRAPH-CYCLE";
47
+ export const NODE_UNAVAILABLE = "NWP-NODE-UNAVAILABLE";
48
+ export const RATE_LIMIT_EXCEEDED = "NWP-RATE-LIMIT-EXCEEDED";
49
+
50
+ // ── Manifest ──────────────────────────────────────────────────────────────────
51
+ export const MANIFEST_VERSION_UNSUPPORTED = "NWP-MANIFEST-VERSION-UNSUPPORTED";
52
+ export const MANIFEST_NODE_TYPE_REMOVED = "NWP-MANIFEST-NODE-TYPE-REMOVED";
53
+ export const MANIFEST_NODE_TYPE_UNKNOWN = "NWP-MANIFEST-NODE-TYPE-UNKNOWN";
54
+
55
+ // ── Topology (alpha.4+) ───────────────────────────────────────────────────────
56
+ export const TOPOLOGY_UNAUTHORIZED = "NWP-TOPOLOGY-UNAUTHORIZED";
57
+ export const TOPOLOGY_UNSUPPORTED_SCOPE = "NWP-TOPOLOGY-UNSUPPORTED-SCOPE";
58
+ export const TOPOLOGY_DEPTH_UNSUPPORTED = "NWP-TOPOLOGY-DEPTH-UNSUPPORTED";
59
+ export const TOPOLOGY_FILTER_UNSUPPORTED = "NWP-TOPOLOGY-FILTER-UNSUPPORTED";
60
+
61
+ // ── Reserved type (alpha.5+) ─────────────────────────────────────────────────
62
+ export const RESERVED_TYPE_UNSUPPORTED = "NWP-RESERVED-TYPE-UNSUPPORTED";
package/src/nwp/index.ts CHANGED
@@ -4,3 +4,4 @@
4
4
  export * from "./frames.js";
5
5
  export * from "./registry.js";
6
6
  export * from "./client.js";
7
+ export * as NwpErrorCodes from "./error-codes.js";