@anis-ly/partners 0.0.0-stage → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/LICENSE +21 -0
- package/README.md +96 -2
- package/SECURITY.md +13 -0
- package/dist/index.cjs +3002 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1053 -0
- package/dist/index.d.ts +1053 -0
- package/dist/index.js +2946 -0
- package/dist/index.js.map +1 -0
- package/package.json +73 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Versions follow [Semantic Versioning](https://semver.org/).
|
|
4
|
+
|
|
5
|
+
## [1.0.0] - 2026-10-06
|
|
6
|
+
|
|
7
|
+
First Node.js release. The package provides all 19 Partner API routes, P-256 signed requests, verified responses, typed order recovery, key enrollment and safety-code support, generated error-code types, cursor paging, and OpenTelemetry instrumentation. It supports Node.js 22 and later with ESM and CommonJS entry points.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Aniscom for Technical Services (Anis)
|
|
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,3 +1,97 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Anis Partner SDK for Node.js
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The `@anis-ly/partners` package calls the Anis Partner API with signed requests, verifies every response before parsing it, and returns typed models and order outcomes. It targets Node.js 22 and later.
|
|
4
|
+
|
|
5
|
+
> **Disclaimer.** This SDK is an optional helper provided free of charge under the MIT License, "as is", without
|
|
6
|
+
> warranty of any kind. Anis (Aniscom for Technical Services) accepts no responsibility or liability for its use or for
|
|
7
|
+
> any loss arising from it. You remain responsible for your own integration — recording orders before you send them,
|
|
8
|
+
> recovery, key custody and testing. The source code is public: read it to understand exactly what it does before you
|
|
9
|
+
> rely on it. You do not need an SDK — you can integrate directly with the Anis Partner API using the documentation at
|
|
10
|
+
> https://developers.anis.ly.
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install @anis-ly/partners
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Quick start
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
import { writeFile } from 'node:fs/promises';
|
|
20
|
+
import { AnisPartnersClient, PemP256Signer } from '@anis-ly/partners';
|
|
21
|
+
function setting(name: string): string {
|
|
22
|
+
return process.env[name] ?? missing(name);
|
|
23
|
+
}
|
|
24
|
+
function missing(name: string): never {
|
|
25
|
+
throw new Error(`Set ${name}.`);
|
|
26
|
+
}
|
|
27
|
+
const first = async <T>(items: AsyncIterable<T>) => {
|
|
28
|
+
for await (const item of items) return item;
|
|
29
|
+
};
|
|
30
|
+
const signer = (await PemP256Signer.fromPemFile('/secure/partner-key.pem')).forKey(setting('SAMPLE_KEY_ID'));
|
|
31
|
+
const client = AnisPartnersClient.create({ options: { authority: setting('ANIS_PARTNERS_AUTHORITY') }, signer });
|
|
32
|
+
const profile = await client.profile.get();
|
|
33
|
+
console.log(profile.application?.scopes);
|
|
34
|
+
const [walletId, subcategoryId] = [setting('WALLET_ID'), setting('SUBCATEGORY_ID')];
|
|
35
|
+
const card = await first(client.catalogue.listCards(walletId, subcategoryId));
|
|
36
|
+
if (!card?.unitPrice) throw new Error('No price is available for this wallet.');
|
|
37
|
+
const operationId = crypto.randomUUID();
|
|
38
|
+
const quantity = 1;
|
|
39
|
+
const request = {
|
|
40
|
+
cardId: card.id,
|
|
41
|
+
quantity,
|
|
42
|
+
expectedUnitPrice: card.unitPrice,
|
|
43
|
+
expectedTotal: card.unitPrice.multiply(quantity),
|
|
44
|
+
};
|
|
45
|
+
await writeFile('order-intent.json', JSON.stringify({ operationId, walletId, request }), { flag: 'wx', mode: 0o600 });
|
|
46
|
+
const result = await client.orders.create(walletId, operationId, request);
|
|
47
|
+
if (result.kind === 'completed') {
|
|
48
|
+
if (result.credentials.length > 0)
|
|
49
|
+
await writeFile('credentials.json', JSON.stringify(result.credentials), { mode: 0o600 });
|
|
50
|
+
if (result.codesWithheld) console.log('Completed; Anis withheld the credentials.');
|
|
51
|
+
else console.log('Completed; credentials saved.');
|
|
52
|
+
} else if (result.kind === 'processing' || result.kind === 'unknown')
|
|
53
|
+
console.log('Resume', result.operationId, result.suggestedDelayMs);
|
|
54
|
+
else if (result.kind === 'replayed') console.log('Previously completed', result.order.invoiceId);
|
|
55
|
+
else console.log('Not placed', result.refusal.code);
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
CommonJS users can load the package with: `const { AnisPartnersClient } = require('@anis-ly/partners');`
|
|
59
|
+
|
|
60
|
+
- [Getting started](https://github.com/anis-ly/anis.partners-sdk-node/blob/main/docs/getting-started.md) — enrollment, configuration, first call, and serverless hosts
|
|
61
|
+
- [Orders and recovery](https://github.com/anis-ly/anis.partners-sdk-node/blob/main/docs/orders-and-recovery.md) — safe purchase retries and the five outcomes
|
|
62
|
+
- [Routes and permissions](https://github.com/anis-ly/anis.partners-sdk-node/blob/main/docs/routes-and-permissions.md) — all routes, permissions, profiles, and bodies
|
|
63
|
+
- [Errors](https://github.com/anis-ly/anis.partners-sdk-node/blob/main/docs/errors.md) — stable error codes and typed errors
|
|
64
|
+
- [Security and key custody](https://github.com/anis-ly/anis.partners-sdk-node/blob/main/docs/security.md)
|
|
65
|
+
- [Observability](https://github.com/anis-ly/anis.partners-sdk-node/blob/main/docs/observability.md)
|
|
66
|
+
- [Runnable console sample](https://github.com/anis-ly/anis.partners-sdk-node/blob/main/samples/console/README.md)
|
|
67
|
+
|
|
68
|
+
## Refusals built into the design
|
|
69
|
+
|
|
70
|
+
- The caller supplies and persists each order id. A timeout is unresolved, so recovery repeats the same id and body; it never silently creates a second purchase.
|
|
71
|
+
- `OrderResult` is a discriminated union. Credentials appear only on `completed`; a `replayed` result is state only.
|
|
72
|
+
- Credential objects and completed order results contain secret fields. `JSON.stringify` includes voucher and serial values; do not log or serialize them casually. Persist released credentials in a secret store with owner-only permissions.
|
|
73
|
+
- A refusal that may follow an earlier attempt is `unknown`; a final business refusal is `notPlaced`.
|
|
74
|
+
- Every response is verified before the SDK returns or parses it. An unverifiable read is discarded, and an unverifiable order has an unknown outcome.
|
|
75
|
+
- Logging and telemetry are opt-in listeners and omit signatures, signature bases, nonces, enrollment tokens, and credentials.
|
|
76
|
+
|
|
77
|
+
## What is covered
|
|
78
|
+
|
|
79
|
+
All 19 published API routes are grouped under `profile`, `wallets`, `catalogue`, `orders`, `ownedCards`, and `diagnostics`, with `AnisEnrollmentClient` for enrollment. Lists can be consumed page by page with `listPage({ cursor, signal })` or walked as an `AsyncIterable` with `list()`.
|
|
80
|
+
|
|
81
|
+
## How it is proven
|
|
82
|
+
|
|
83
|
+
The tests include 9 request vectors, 39 response vectors, 2 enrollment proof vectors, and 4 safety-code vector files; in-memory client and transport tests; and contract drift checks against the checked-in route and error contracts. `npm run check` runs formatting, strict type checks, lint, tests, and a package build.
|
|
84
|
+
|
|
85
|
+
Verified end to end against a live Anis environment (October 2026).
|
|
86
|
+
|
|
87
|
+
## Supported Node versions
|
|
88
|
+
|
|
89
|
+
Node.js 22 or later with ESM or CommonJS. Error code types are generated from `contracts/error-catalogue.json`:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
npm run generate:errors
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## License
|
|
96
|
+
|
|
97
|
+
[MIT](LICENSE) © 2026 Aniscom for Technical Services (Anis).
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Security
|
|
2
|
+
|
|
3
|
+
## Reporting a vulnerability
|
|
4
|
+
|
|
5
|
+
Please do not open a public issue for a security problem. Email **support@anis.ly** with a description, the package version, and steps to reproduce it. You will receive an answer within five working days.
|
|
6
|
+
|
|
7
|
+
## Supported versions
|
|
8
|
+
|
|
9
|
+
Security fixes are made to the latest released version.
|
|
10
|
+
|
|
11
|
+
## Your private key
|
|
12
|
+
|
|
13
|
+
The SDK does not send, store, or log your private key. It asks your `RequestSigner` for signatures. Keep the key in storage controlled by your organization; see [key custody](docs/security.md).
|