@corelicense/node 0.5.0 → 0.5.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.
- package/LICENSE +21 -0
- package/README.md +52 -162
- package/dist/client/http-error-utils.d.ts +10 -0
- package/dist/client/http-error-utils.d.ts.map +1 -0
- package/dist/client/http-error-utils.js +38 -0
- package/dist/client/http-error-utils.js.map +1 -0
- package/dist/client/license-api-client.d.ts.map +1 -1
- package/dist/client/license-api-client.js +26 -6
- package/dist/client/license-api-client.js.map +1 -1
- package/dist/client/map-client-error.d.ts.map +1 -1
- package/dist/client/map-client-error.js +38 -12
- package/dist/client/map-client-error.js.map +1 -1
- package/dist/client/public-keys-client.d.ts.map +1 -1
- package/dist/client/public-keys-client.js +48 -4
- package/dist/client/public-keys-client.js.map +1 -1
- package/dist/core-license.js +1 -1
- package/dist/crypto/key-loader.d.ts +1 -1
- package/dist/crypto/key-loader.d.ts.map +1 -1
- package/dist/crypto/key-loader.js +34 -9
- package/dist/crypto/key-loader.js.map +1 -1
- package/dist/errors/api-error.d.ts +1 -0
- package/dist/errors/api-error.d.ts.map +1 -1
- package/dist/errors/api-error.js +2 -2
- package/dist/errors/api-error.js.map +1 -1
- package/dist/errors/codes.d.ts +5 -0
- package/dist/errors/codes.d.ts.map +1 -1
- package/dist/errors/codes.js +5 -0
- package/dist/errors/codes.js.map +1 -1
- package/dist/errors/license-error.d.ts +2 -0
- package/dist/errors/license-error.d.ts.map +1 -1
- package/dist/errors/license-error.js +13 -2
- package/dist/errors/license-error.js.map +1 -1
- package/dist/errors/throw-for-status.d.ts.map +1 -1
- package/dist/errors/throw-for-status.js +3 -1
- package/dist/errors/throw-for-status.js.map +1 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -2
- package/dist/index.js.map +1 -1
- package/dist/types/status.d.ts +1 -1
- package/dist/types/status.d.ts.map +1 -1
- package/docs/api-reference.md +261 -0
- package/docs/installation.md +188 -0
- package/docs/integration.md +789 -0
- package/package.json +6 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 CoreLicense
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,193 +1,83 @@
|
|
|
1
1
|
# @corelicense/node
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Runtime license và policy layer cho ứng dụng Node.js — không chỉ middleware HTTP, mà là lớp kiểm soát **bootstrap**, **module registry**, **DI**, **worker/CLI**, **quota** và **feature gate** theo policy đã ký.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**Phiên bản:** `0.5.1`
|
|
6
|
+
**License:** [MIT](./LICENSE)
|
|
7
|
+
**Repository:** [github.com/trailanglc/corelicense](https://github.com/trailanglc/corelicense)
|
|
8
|
+
**Docs trực tuyến:** [corelicense.net/docs](https://corelicense.net/docs/nodejs-sdk/quick-start)
|
|
6
9
|
|
|
7
|
-
|
|
10
|
+
---
|
|
8
11
|
|
|
9
|
-
CoreLicense
|
|
12
|
+
## CoreLicense là gì?
|
|
10
13
|
|
|
11
|
-
|
|
14
|
+
CoreLicense gồm **License Server** (API Go) và **Node.js SDK** (package này). Admin cấp license key + policy (features, limits, quotas). SDK:
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
```bash
|
|
20
|
-
npm install express # Express middleware
|
|
21
|
-
npm install fastify # Fastify plugin
|
|
22
|
-
npm install @nestjs/common # NestJS module/guard
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
## Quick start
|
|
26
|
-
|
|
27
|
-
Chỉ cần **2 biến môi trường**. SDK mặc định kết nối `https://api.corelicense.net` — không cần cấu hình thêm cho production.
|
|
28
|
-
|
|
29
|
-
License key mới (CL1.*) vẫn ưu tiên URL nhúng trong key nếu server generate với `SDK_PUBLIC_URL` khác.
|
|
30
|
-
|
|
31
|
-
```env
|
|
32
|
-
CORELICENSE_KEY=CL1.xxxxx.CL-AAAAA-BBBBB-...
|
|
33
|
-
CORELICENSE_PRODUCT_ID=demo
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
`CORELICENSE_PUBLIC_KEY` **optional** — pin public key (enterprise / air-gapped).
|
|
37
|
-
`CORELICENSE_API_URL` **optional** — override thủ công (dev local hoặc legacy key).
|
|
38
|
-
|
|
39
|
-
Dev local với server Go chạy localhost:
|
|
40
|
-
|
|
41
|
-
```env
|
|
42
|
-
CORELICENSE_API_URL=http://localhost:8080
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
```ts
|
|
46
|
-
import express from 'express';
|
|
47
|
-
import { CoreLicense, loadOptionsFromEnv } from '@corelicense/node';
|
|
16
|
+
1. Kích hoạt / kiểm tra license với server
|
|
17
|
+
2. Verify **policy token** bằng public key (EdDSA)
|
|
18
|
+
3. Cache policy local, refresh định kỳ
|
|
19
|
+
4. Chặn runtime khi revoke / suspend / expired
|
|
20
|
+
5. (Tùy chọn) Chỉ bind module & service được cấp trong policy
|
|
48
21
|
|
|
49
|
-
|
|
22
|
+
---
|
|
50
23
|
|
|
51
|
-
|
|
52
|
-
cachePath: './storage/corelicense',
|
|
53
|
-
instance: {
|
|
54
|
-
strategy: 'install-id-domain-hash',
|
|
55
|
-
domain: process.env.APP_DOMAIN,
|
|
56
|
-
},
|
|
57
|
-
}));
|
|
24
|
+
## Tài liệu
|
|
58
25
|
|
|
59
|
-
|
|
60
|
-
|
|
26
|
+
| Tài liệu | Nội dung |
|
|
27
|
+
|----------|----------|
|
|
28
|
+
| [Cài đặt](./docs/installation.md) | `npm install`, biến môi trường, boot lần đầu, dev/prod |
|
|
29
|
+
| [Tích hợp](./docs/integration.md) | **Hướng dẫn chi tiết** — Express, Fastify, NestJS, registry/DI, worker, quota, production |
|
|
30
|
+
| [API Reference](./docs/api-reference.md) | Public API, options, error codes |
|
|
31
|
+
| [LICENSE](./LICENSE) | MIT |
|
|
61
32
|
|
|
62
|
-
|
|
63
|
-
allowPaths: ['/health', '/license/status'],
|
|
64
|
-
}));
|
|
33
|
+
> Dành cho agent / CI: đọc [docs/integration.md](./docs/integration.md) trước khi generate code tích hợp.
|
|
65
34
|
|
|
66
|
-
|
|
67
|
-
res.json(await license.getStatus());
|
|
68
|
-
});
|
|
35
|
+
---
|
|
69
36
|
|
|
70
|
-
|
|
71
|
-
}
|
|
37
|
+
## Quick links
|
|
72
38
|
|
|
73
|
-
|
|
39
|
+
```bash
|
|
40
|
+
npm install @corelicense/node
|
|
74
41
|
```
|
|
75
42
|
|
|
76
|
-
|
|
43
|
+
Production mặc định: `https://api.corelicense.net` — chỉ cần `CORELICENSE_KEY` + `CORELICENSE_PRODUCT_ID`.
|
|
77
44
|
|
|
78
45
|
```ts
|
|
79
|
-
|
|
80
|
-
publicKey: process.env.CORELICENSE_PUBLIC_KEY, // pinned mode
|
|
81
|
-
}));
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
Khi pin, SDK không fetch keys từ server. Nếu verify fail sau key rotation, cập nhật `CORELICENSE_PUBLIC_KEY` thủ công.
|
|
85
|
-
|
|
86
|
-
## Public API
|
|
87
|
-
|
|
88
|
-
| Method | Mô tả |
|
|
89
|
-
|--------|-------|
|
|
90
|
-
| `boot()` | Khởi tạo SDK, fetch/cache public keys, load cache, verify token |
|
|
91
|
-
| `refresh()` | Refresh policy token từ server |
|
|
92
|
-
| `requireActive()` | Yêu cầu license active |
|
|
93
|
-
| `requireFeature(name)` | Kiểm tra feature flag |
|
|
94
|
-
| `checkLimit(name, value)` | Kiểm tra limit |
|
|
95
|
-
| `consumeQuota(name, amount?)` | Tiêu thụ quota local |
|
|
96
|
-
| `getStatus()` | Trạng thái license hiện tại |
|
|
97
|
-
| `getPolicy()` | Policy đang active |
|
|
98
|
-
| `getRuntimeConfig()` | Runtime config cho app bootstrap |
|
|
99
|
-
| `express(options?)` | Express middleware |
|
|
100
|
-
| `fastifyPlugin(options?)` | Fastify plugin |
|
|
101
|
-
| `guardWorker(name)` | Guard worker |
|
|
102
|
-
| `guardCommand(name)` | Guard CLI/cron command |
|
|
103
|
-
| `createLicensedRegistry()` | Module registry gắn license |
|
|
104
|
-
| `createLicensedContainer()` | DI container gắn license |
|
|
105
|
-
| `bootstrap(options?)` | Bootstrap modules + services theo policy |
|
|
106
|
-
|
|
107
|
-
## Tích hợp sâu (v0.4)
|
|
46
|
+
import { CoreLicense, loadOptionsFromEnv } from '@corelicense/node';
|
|
108
47
|
|
|
109
|
-
|
|
48
|
+
const license = new CoreLicense(loadOptionsFromEnv({ cachePath: './storage/corelicense' }));
|
|
110
49
|
await license.boot();
|
|
111
|
-
|
|
112
|
-
const { modules, services, skipped } = await license.bootstrap({
|
|
113
|
-
modules: [
|
|
114
|
-
{ name: 'automation', feature: 'automation', factory: ({ license }) => new AutomationModule(license) },
|
|
115
|
-
],
|
|
116
|
-
services: [
|
|
117
|
-
{ name: 'ExportService', feature: 'export', factory: ({ license }) => new ExportService(license) },
|
|
118
|
-
],
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
const automation = await modules.get<AutomationModule>('automation');
|
|
122
|
-
const exportService = await services.resolve<ExportService>('ExportService');
|
|
123
|
-
|
|
124
|
-
import { registerLicensedRoutes } from '@corelicense/node';
|
|
125
|
-
registerLicensedRoutes(app, modules, [
|
|
126
|
-
{ path: '/automation', module: 'automation', router: automationRouter },
|
|
127
|
-
]);
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
`get()` và `resolve()` gọi `requireFeature` mỗi lần truy cập — revoke/suspend chặn ngay. Đổi feature trong policy vẫn cần **restart** để bind/unbind module mới.
|
|
131
|
-
|
|
132
|
-
Xem [Tích hợp sâu](https://corelicense.net/docs/nodejs-sdk/deep-integration) trên docs site.
|
|
133
|
-
|
|
134
|
-
## Xử lý lỗi
|
|
135
|
-
|
|
136
|
-
Mọi lỗi SDK đều có `code` (mã định vị) và `source` (module SDK phát sinh):
|
|
137
|
-
|
|
138
|
-
```ts
|
|
139
|
-
import { isLicenseError, formatLicenseError, LicenseErrorCode } from '@corelicense/node';
|
|
140
|
-
|
|
141
|
-
try {
|
|
142
|
-
await license.boot();
|
|
143
|
-
} catch (error) {
|
|
144
|
-
if (isLicenseError(error)) {
|
|
145
|
-
console.error(error.code, error.source); // e.g. CONFIG_MISSING_ENV, load-options-from-env
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
50
|
```
|
|
149
51
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
## Production deploy
|
|
52
|
+
Chi tiết: [docs/installation.md](./docs/installation.md) → [docs/integration.md](./docs/integration.md).
|
|
153
53
|
|
|
154
|
-
|
|
54
|
+
---
|
|
155
55
|
|
|
156
|
-
|
|
56
|
+
## Subpath exports
|
|
157
57
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
errors/ # Error hierarchy
|
|
165
|
-
crypto/ # Policy token verification + public key resolver
|
|
166
|
-
client/ # License API + public keys client
|
|
167
|
-
cache/ # File/memory cache
|
|
168
|
-
instance/ # Instance ID resolution
|
|
169
|
-
guards/ # Express, Fastify, NestJS, worker, CLI
|
|
170
|
-
runtime/ # Runtime config, module registry, DI container
|
|
171
|
-
audit/ # Local audit log
|
|
172
|
-
events/ # Event bus
|
|
173
|
-
```
|
|
58
|
+
| Import | Mục đích |
|
|
59
|
+
|--------|----------|
|
|
60
|
+
| `@corelicense/node` | Core API |
|
|
61
|
+
| `@corelicense/node/express` | Express middleware |
|
|
62
|
+
| `@corelicense/node/fastify` | Fastify plugin |
|
|
63
|
+
| `@corelicense/node/nestjs` | NestJS module, guards, filter |
|
|
174
64
|
|
|
175
|
-
|
|
65
|
+
---
|
|
176
66
|
|
|
177
|
-
|
|
67
|
+
## Yêu cầu
|
|
178
68
|
|
|
179
|
-
|
|
69
|
+
- Node.js **≥ 18**
|
|
70
|
+
- License Server reachable (hoặc cache + offline grace hợp lệ)
|
|
180
71
|
|
|
181
|
-
|
|
182
|
-
- **v0.2** — Auto-fetch public keys, key rotation retry, worker/CLI guard, offline grace
|
|
183
|
-
- **v0.3** — Production default URL, activate flow, revoke handling, server contract sync
|
|
184
|
-
- **v0.4** — Licensed module registry, DI container, Express routes, NestJS `@RequireFeature`
|
|
185
|
-
- **v0.4.1** — Runtime re-check license trên `get()` / `resolve()`, fix `ModuleNotLicensedError` status
|
|
186
|
-
- **v0.4.2** — Mã lỗi (`code`) + `source` trên mọi `LicenseError`, `LicenseErrorCode`, `formatLicenseError()`
|
|
187
|
-
- **v0.4.3** — Re-check registry/DI không ghi audit; middleware 403 trả `source` qua `toClientPayload()`
|
|
188
|
-
- **v0.5.0** — Fail-closed offline boot, quota/limit gates, apiUrl pin, Nest 403 filter, sync mutex
|
|
189
|
-
- **v1.0** — Stable API, production-ready, security review
|
|
72
|
+
---
|
|
190
73
|
|
|
191
|
-
##
|
|
74
|
+
## Changelog (tóm tắt)
|
|
192
75
|
|
|
193
|
-
|
|
76
|
+
| Version | Highlights |
|
|
77
|
+
|---------|------------|
|
|
78
|
+
| **0.5.1** | Tách tài liệu (installation, integration, api-reference), sửa repository URL |
|
|
79
|
+
| **0.5.0** | Fail-closed offline boot, quota/limit gates, apiUrl pin, sync mutex, Nest 403 filter |
|
|
80
|
+
| **0.4.x** | Deep integration (registry/DI), error `code` + `source`, runtime re-check |
|
|
81
|
+
| **0.3.x** | Production default URL, activate/revoke sync |
|
|
82
|
+
| **0.2.x** | Auto-fetch public keys, worker/CLI guard |
|
|
83
|
+
| **0.1.x** | Boot, express middleware, file cache |
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface ApiErrorBody {
|
|
2
|
+
code?: string;
|
|
3
|
+
message?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function parseApiErrorBody(response: Response): Promise<ApiErrorBody | null>;
|
|
6
|
+
export declare function isNetworkUnreachable(error: unknown): boolean;
|
|
7
|
+
/** Retry only when a repeat request may succeed (transient server/network errors). */
|
|
8
|
+
export declare function isRetryableHttpStatus(status: number): boolean;
|
|
9
|
+
export declare function serverMessage(body: ApiErrorBody | null, fallback: string): string;
|
|
10
|
+
//# sourceMappingURL=http-error-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-error-utils.d.ts","sourceRoot":"","sources":["../../src/client/http-error-utils.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAUxF;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAsB5D;AAED,sFAAsF;AACtF,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEjF"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export async function parseApiErrorBody(response) {
|
|
2
|
+
try {
|
|
3
|
+
const data = (await response.json());
|
|
4
|
+
if (data && (typeof data.code === 'string' || typeof data.message === 'string')) {
|
|
5
|
+
return data;
|
|
6
|
+
}
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export function isNetworkUnreachable(error) {
|
|
14
|
+
if (!(error instanceof Error)) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
const code = error.code;
|
|
18
|
+
if (code === 'ECONNREFUSED' || code === 'ENOTFOUND' || code === 'EHOSTUNREACH' || code === 'ENETUNREACH') {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
const cause = error.cause;
|
|
22
|
+
if (cause instanceof Error) {
|
|
23
|
+
const causeCode = cause.code;
|
|
24
|
+
return (causeCode === 'ECONNREFUSED' ||
|
|
25
|
+
causeCode === 'ENOTFOUND' ||
|
|
26
|
+
causeCode === 'EHOSTUNREACH' ||
|
|
27
|
+
causeCode === 'ENETUNREACH');
|
|
28
|
+
}
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
/** Retry only when a repeat request may succeed (transient server/network errors). */
|
|
32
|
+
export function isRetryableHttpStatus(status) {
|
|
33
|
+
return status === 408 || status === 429 || status >= 500;
|
|
34
|
+
}
|
|
35
|
+
export function serverMessage(body, fallback) {
|
|
36
|
+
return body?.message?.trim() || fallback;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=http-error-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-error-utils.js","sourceRoot":"","sources":["../../src/client/http-error-utils.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,QAAkB;IACxD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAiB,CAAC;QACrD,IAAI,IAAI,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC,EAAE,CAAC;YAChF,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAc;IACjD,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,IAAI,GAAI,KAA+B,CAAC,IAAI,CAAC;IACnD,IAAI,IAAI,KAAK,cAAc,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,cAAc,IAAI,IAAI,KAAK,aAAa,EAAE,CAAC;QACzG,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IAC1B,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,MAAM,SAAS,GAAI,KAA+B,CAAC,IAAI,CAAC;QACxD,OAAO,CACL,SAAS,KAAK,cAAc;YAC5B,SAAS,KAAK,WAAW;YACzB,SAAS,KAAK,cAAc;YAC5B,SAAS,KAAK,aAAa,CAC5B,CAAC;IACJ,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,qBAAqB,CAAC,MAAc;IAClD,OAAO,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,IAAI,GAAG,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAyB,EAAE,QAAgB;IACvE,OAAO,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,QAAQ,CAAC;AAC3C,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"license-api-client.d.ts","sourceRoot":"","sources":["../../src/client/license-api-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,EACrB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"license-api-client.d.ts","sourceRoot":"","sources":["../../src/client/license-api-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,EACrB,MAAM,qBAAqB,CAAC;AAY7B,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAcD,qBAAa,gBAAgB;IACf,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,uBAAuB;IAEvD,QAAQ,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAIxE,KAAK,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAIlE,OAAO,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC;YAI5D,aAAa;YAuBb,IAAI;CA6DnB"}
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import { LicenseApiError } from '../errors/api-error.js';
|
|
2
2
|
import { LicenseErrorCode } from '../errors/codes.js';
|
|
3
3
|
import { LicenseRateLimitError } from '../errors/license-error.js';
|
|
4
|
+
import { isNetworkUnreachable, isRetryableHttpStatus, parseApiErrorBody, serverMessage, } from './http-error-utils.js';
|
|
4
5
|
const RETRY_DELAYS_MS = [1000, 3000];
|
|
6
|
+
function mapHttpError(status, statusText, body) {
|
|
7
|
+
const message = serverMessage(body, `License API error: ${status} ${statusText}`);
|
|
8
|
+
return new LicenseApiError(message, {
|
|
9
|
+
code: LicenseErrorCode.LICENSE_API_ERROR,
|
|
10
|
+
httpStatus: status,
|
|
11
|
+
retryable: isRetryableHttpStatus(status),
|
|
12
|
+
});
|
|
13
|
+
}
|
|
5
14
|
export class LicenseApiClient {
|
|
6
15
|
options;
|
|
7
16
|
constructor(options) {
|
|
@@ -39,17 +48,17 @@ export class LicenseApiClient {
|
|
|
39
48
|
try {
|
|
40
49
|
const response = await fetch(url, {
|
|
41
50
|
method: 'POST',
|
|
42
|
-
headers: { 'Content-Type': 'application/json' },
|
|
51
|
+
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
|
|
43
52
|
body: JSON.stringify(body),
|
|
44
53
|
signal: controller.signal,
|
|
45
54
|
});
|
|
46
55
|
if (response.status === 429) {
|
|
47
|
-
|
|
56
|
+
const body = await parseApiErrorBody(response);
|
|
57
|
+
throw new LicenseRateLimitError(serverMessage(body, 'License API rate limit exceeded'));
|
|
48
58
|
}
|
|
49
59
|
if (!response.ok) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
});
|
|
60
|
+
const errorBody = await parseApiErrorBody(response);
|
|
61
|
+
throw mapHttpError(response.status, response.statusText, errorBody);
|
|
53
62
|
}
|
|
54
63
|
return (await response.json());
|
|
55
64
|
}
|
|
@@ -61,9 +70,20 @@ export class LicenseApiClient {
|
|
|
61
70
|
throw new LicenseApiError('License API request timed out', {
|
|
62
71
|
code: LicenseErrorCode.LICENSE_API_TIMEOUT,
|
|
63
72
|
cause: error,
|
|
73
|
+
retryable: true,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
if (isNetworkUnreachable(error)) {
|
|
77
|
+
throw new LicenseApiError('License API is unreachable', {
|
|
78
|
+
code: LicenseErrorCode.LICENSE_API_UNREACHABLE,
|
|
79
|
+
cause: error,
|
|
80
|
+
retryable: true,
|
|
64
81
|
});
|
|
65
82
|
}
|
|
66
|
-
throw new LicenseApiError('License API request failed', {
|
|
83
|
+
throw new LicenseApiError('License API request failed', {
|
|
84
|
+
cause: error,
|
|
85
|
+
retryable: true,
|
|
86
|
+
});
|
|
67
87
|
}
|
|
68
88
|
finally {
|
|
69
89
|
clearTimeout(timeout);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"license-api-client.js","sourceRoot":"","sources":["../../src/client/license-api-client.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"license-api-client.js","sourceRoot":"","sources":["../../src/client/license-api-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"map-client-error.d.ts","sourceRoot":"","sources":["../../src/client/map-client-error.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"map-client-error.d.ts","sourceRoot":"","sources":["../../src/client/map-client-error.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAEhE,OAAO,EAEL,YAAY,EAMb,MAAM,4BAA4B,CAAC;AA2BpC,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,oBAAoB,GAAG,OAAO,CAUhF;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,oBAAoB,GAAG,YAAY,CAuD3E"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { LicenseErrorCode } from '../errors/codes.js';
|
|
1
2
|
import { InstanceBlockedError, LicenseExpiredError, LicenseInvalidError, LicenseRevokedError, LicenseSuspendedError, MaxInstancesError, } from '../errors/license-error.js';
|
|
2
3
|
import { PolicySignatureError } from '../errors/policy-error.js';
|
|
3
4
|
const TERMINAL_STATUSES = new Set([
|
|
@@ -13,6 +14,8 @@ const TERMINAL_CODES = new Set([
|
|
|
13
14
|
'LICENSE_SUSPENDED',
|
|
14
15
|
'LICENSE_EXPIRED',
|
|
15
16
|
'LICENSE_INVALID',
|
|
17
|
+
'LICENSE_NOT_FOUND',
|
|
18
|
+
'PRODUCT_NOT_FOUND',
|
|
16
19
|
'INVALID_LICENSE',
|
|
17
20
|
'INVALID_PRODUCT',
|
|
18
21
|
'INSTANCE_BLOCKED',
|
|
@@ -31,33 +34,56 @@ export function isTerminalClientResponse(response) {
|
|
|
31
34
|
}
|
|
32
35
|
export function mapClientError(response) {
|
|
33
36
|
const message = response.message ?? 'License check failed';
|
|
37
|
+
const source = 'map-client-error';
|
|
34
38
|
switch (response.code) {
|
|
35
39
|
case 'LICENSE_REVOKED':
|
|
36
|
-
return new LicenseRevokedError(message);
|
|
40
|
+
return new LicenseRevokedError(message, source);
|
|
37
41
|
case 'LICENSE_SUSPENDED':
|
|
38
|
-
return new LicenseSuspendedError(message);
|
|
42
|
+
return new LicenseSuspendedError(message, source);
|
|
39
43
|
case 'LICENSE_EXPIRED':
|
|
40
|
-
return new LicenseExpiredError(message);
|
|
44
|
+
return new LicenseExpiredError(message, source);
|
|
45
|
+
case 'LICENSE_NOT_STARTED':
|
|
46
|
+
return new LicenseInvalidError(message, {
|
|
47
|
+
code: LicenseErrorCode.LICENSE_NOT_STARTED,
|
|
48
|
+
source,
|
|
49
|
+
});
|
|
50
|
+
case 'PRODUCT_NOT_FOUND':
|
|
51
|
+
case 'INVALID_PRODUCT':
|
|
52
|
+
return new LicenseInvalidError(message, {
|
|
53
|
+
code: LicenseErrorCode.PRODUCT_NOT_FOUND,
|
|
54
|
+
source,
|
|
55
|
+
});
|
|
56
|
+
case 'LICENSE_NOT_FOUND':
|
|
57
|
+
return new LicenseInvalidError(message, {
|
|
58
|
+
code: LicenseErrorCode.LICENSE_NOT_FOUND,
|
|
59
|
+
source,
|
|
60
|
+
});
|
|
61
|
+
case 'LICENSE_INVALID':
|
|
62
|
+
case 'INVALID_LICENSE':
|
|
63
|
+
return new LicenseInvalidError(message, {
|
|
64
|
+
code: LicenseErrorCode.LICENSE_INVALID,
|
|
65
|
+
source,
|
|
66
|
+
});
|
|
41
67
|
case 'INSTANCE_BLOCKED':
|
|
42
|
-
return new InstanceBlockedError(message);
|
|
68
|
+
return new InstanceBlockedError(message, source);
|
|
43
69
|
case 'MAX_INSTANCES':
|
|
44
|
-
return new MaxInstancesError(message);
|
|
70
|
+
return new MaxInstancesError(message, source);
|
|
45
71
|
case 'POLICY_SIGN_FAILED':
|
|
46
|
-
return new PolicySignatureError(message, {
|
|
47
|
-
source: 'map-client-error',
|
|
48
|
-
});
|
|
72
|
+
return new PolicySignatureError(message, { source });
|
|
49
73
|
default:
|
|
50
74
|
break;
|
|
51
75
|
}
|
|
52
76
|
switch (response.status) {
|
|
53
77
|
case 'revoked':
|
|
54
|
-
return new LicenseRevokedError(message);
|
|
78
|
+
return new LicenseRevokedError(message, source);
|
|
55
79
|
case 'suspended':
|
|
56
|
-
return new LicenseSuspendedError(message);
|
|
80
|
+
return new LicenseSuspendedError(message, source);
|
|
57
81
|
case 'expired':
|
|
58
|
-
return new LicenseExpiredError(message);
|
|
82
|
+
return new LicenseExpiredError(message, source);
|
|
83
|
+
case 'blocked':
|
|
84
|
+
return new InstanceBlockedError(message, source);
|
|
59
85
|
default:
|
|
60
|
-
return new LicenseInvalidError(message);
|
|
86
|
+
return new LicenseInvalidError(message, { source });
|
|
61
87
|
}
|
|
62
88
|
}
|
|
63
89
|
//# sourceMappingURL=map-client-error.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"map-client-error.js","sourceRoot":"","sources":["../../src/client/map-client-error.ts"],"names":[],"mappings":"AACA,OAAO,EACL,oBAAoB,EAEpB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,iBAAiB,GAClB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEjE,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC;IAChC,SAAS;IACT,WAAW;IACX,SAAS;IACT,SAAS;IACT,SAAS;IACT,eAAe;CAChB,CAAC,CAAC;AAEH,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC;IAC7B,iBAAiB;IACjB,mBAAmB;IACnB,iBAAiB;IACjB,iBAAiB;IACjB,iBAAiB;IACjB,iBAAiB;IACjB,kBAAkB;IAClB,eAAe;IACf,oBAAoB;IACpB,qBAAqB;CACtB,CAAC,CAAC;AAEH,MAAM,UAAU,wBAAwB,CAAC,QAA8B;IACrE,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;QAChB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,QAAQ,CAAC,IAAI,IAAI,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACvD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,QAA8B;IAC3D,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,IAAI,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"map-client-error.js","sourceRoot":"","sources":["../../src/client/map-client-error.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-keys-client.d.ts","sourceRoot":"","sources":["../../src/client/public-keys-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"public-keys-client.d.ts","sourceRoot":"","sources":["../../src/client/public-keys-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAWnE,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AA2CD,qBAAa,gBAAgB;IACf,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,uBAAuB;IAEvD,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;CA2DxE"}
|
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
import { PublicKeysError } from '../errors/api-error.js';
|
|
2
2
|
import { LicenseErrorCode } from '../errors/codes.js';
|
|
3
|
+
import { isNetworkUnreachable, isRetryableHttpStatus, parseApiErrorBody, serverMessage, } from './http-error-utils.js';
|
|
4
|
+
function mapHttpError(status, statusText, body) {
|
|
5
|
+
const message = serverMessage(body, `Public keys API error: ${status} ${statusText}`);
|
|
6
|
+
const retryable = isRetryableHttpStatus(status);
|
|
7
|
+
if (status === 429 || body?.code === 'RATE_LIMITED') {
|
|
8
|
+
return new PublicKeysError(message, {
|
|
9
|
+
code: LicenseErrorCode.RATE_LIMITED,
|
|
10
|
+
httpStatus: status,
|
|
11
|
+
retryable: true,
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
if (status === 404) {
|
|
15
|
+
if (body?.code === 'PRODUCT_NOT_FOUND') {
|
|
16
|
+
return new PublicKeysError(message, {
|
|
17
|
+
code: LicenseErrorCode.PRODUCT_NOT_FOUND,
|
|
18
|
+
httpStatus: status,
|
|
19
|
+
retryable: false,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
if (body?.code === 'PUBLIC_KEYS_NOT_PUBLISHED' || body?.code === 'NOT_FOUND') {
|
|
23
|
+
return new PublicKeysError(message, {
|
|
24
|
+
code: LicenseErrorCode.PUBLIC_KEYS_NOT_PUBLISHED,
|
|
25
|
+
httpStatus: status,
|
|
26
|
+
retryable: false,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return new PublicKeysError(message, {
|
|
31
|
+
code: LicenseErrorCode.PUBLIC_KEYS_FETCH_FAILED,
|
|
32
|
+
httpStatus: status,
|
|
33
|
+
retryable,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
3
36
|
export class PublicKeysClient {
|
|
4
37
|
options;
|
|
5
38
|
constructor(options) {
|
|
@@ -17,14 +50,14 @@ export class PublicKeysClient {
|
|
|
17
50
|
signal: controller.signal,
|
|
18
51
|
});
|
|
19
52
|
if (!response.ok) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
});
|
|
53
|
+
const body = await parseApiErrorBody(response);
|
|
54
|
+
throw mapHttpError(response.status, response.statusText, body);
|
|
23
55
|
}
|
|
24
56
|
const data = (await response.json());
|
|
25
57
|
if (!data.keys?.length) {
|
|
26
58
|
throw new PublicKeysError('Public keys API returned no keys', {
|
|
27
59
|
code: LicenseErrorCode.PUBLIC_KEYS_EMPTY,
|
|
60
|
+
retryable: false,
|
|
28
61
|
});
|
|
29
62
|
}
|
|
30
63
|
return data;
|
|
@@ -37,9 +70,20 @@ export class PublicKeysClient {
|
|
|
37
70
|
throw new PublicKeysError('Public keys API request timed out', {
|
|
38
71
|
code: LicenseErrorCode.LICENSE_API_TIMEOUT,
|
|
39
72
|
cause: error,
|
|
73
|
+
retryable: true,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
if (isNetworkUnreachable(error)) {
|
|
77
|
+
throw new PublicKeysError('Public keys API is unreachable', {
|
|
78
|
+
code: LicenseErrorCode.LICENSE_API_UNREACHABLE,
|
|
79
|
+
cause: error,
|
|
80
|
+
retryable: true,
|
|
40
81
|
});
|
|
41
82
|
}
|
|
42
|
-
throw new PublicKeysError('Public keys API request failed', {
|
|
83
|
+
throw new PublicKeysError('Public keys API request failed', {
|
|
84
|
+
cause: error,
|
|
85
|
+
retryable: true,
|
|
86
|
+
});
|
|
43
87
|
}
|
|
44
88
|
finally {
|
|
45
89
|
clearTimeout(timeout);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-keys-client.js","sourceRoot":"","sources":["../../src/client/public-keys-client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"public-keys-client.js","sourceRoot":"","sources":["../../src/client/public-keys-client.ts"],"names":[],"mappings":"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"}
|
package/dist/core-license.js
CHANGED
|
@@ -25,7 +25,7 @@ import { PolicySignatureError } from './errors/policy-error.js';
|
|
|
25
25
|
import { throwForTerminalStatus } from './errors/throw-for-status.js';
|
|
26
26
|
import { resolveApiUrl, parseEmbeddedApiUrl } from './env/resolve-api-url.js';
|
|
27
27
|
const SDK_NAME = '@corelicense/node';
|
|
28
|
-
const SDK_VERSION = '0.5.
|
|
28
|
+
const SDK_VERSION = '0.5.1';
|
|
29
29
|
const DEFAULT_CHECK_INTERVAL_MS = 6 * 60 * 60 * 1000;
|
|
30
30
|
function hashPolicyToken(token) {
|
|
31
31
|
return createHash('sha256').update(token).digest('hex');
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type KeyFormat = 'spki' | 'pkcs8';
|
|
1
|
+
export type KeyFormat = 'spki' | 'pkcs8' | 'raw';
|
|
2
2
|
export declare function loadPublicKey(keyMaterial: string, algorithm?: 'Ed25519' | 'RS256' | 'ES256'): Promise<CryptoKey>;
|
|
3
3
|
export declare function loadPrivateKey(keyMaterial: string, algorithm?: 'Ed25519' | 'RS256' | 'ES256'): Promise<CryptoKey>;
|
|
4
4
|
//# sourceMappingURL=key-loader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"key-loader.d.ts","sourceRoot":"","sources":["../../src/crypto/key-loader.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"key-loader.d.ts","sourceRoot":"","sources":["../../src/crypto/key-loader.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;AAIjD,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,EACnB,SAAS,GAAE,SAAS,GAAG,OAAO,GAAG,OAAmB,GACnD,OAAO,CAAC,SAAS,CAAC,CAcpB;AAED,wBAAsB,cAAc,CAClC,WAAW,EAAE,MAAM,EACnB,SAAS,GAAE,SAAS,GAAG,OAAO,GAAG,OAAmB,GACnD,OAAO,CAAC,SAAS,CAAC,CAQpB"}
|