Skip to content

Commit 7ea1c8c

Browse files
committed
feat: Finalize SDK for initial release (v0.1.0)
This commit includes the final updates and checks before the initial release of the KeyMint Node.js SDK (v0.1.0). Key changes: - docs: Completed and verified API reference in README.md for all SDK methods, ensuring consistency with type definitions. - docs: Updated usage examples in README.md and performed general cleanup. - feat(types): Added optional `metadata` field to `CreateKeyParams` in `types.d.ts`. - chore: Introduced [.gitignore](cci:7://file:///Users/kliff/Desktop/Source%20Control/KeymintSDK-nodejs/.gitignore:0:0-0:0) with standard Node.js/TypeScript ignores. - test: Confirmed successful SDK build and execution of the full manual test suite.
0 parents  commit 7ea1c8c

File tree

12 files changed

+5479
-0
lines changed

12 files changed

+5479
-0
lines changed

.gitignore

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Node.js & TypeScript
2+
3+
# Dependencies
4+
node_modules/
5+
6+
# Build output
7+
dist/
8+
9+
# Environment variables
10+
.env
11+
.env.*
12+
!.env.example
13+
14+
# Log files
15+
*.log
16+
npm-debug.log*
17+
yarn-error.log
18+
yarn-debug.log
19+
20+
# OS-specific files
21+
.DS_Store
22+
Thumbs.db
23+
24+
# IDE & Editor specific
25+
.vscode/
26+
.idea/
27+
28+
# Test coverage
29+
coverage/

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 Keymint
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.

README.md

Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
# KeyMint SDK
2+
3+
A TypeScript SDK for interacting with the KeyMint API, simplifying license key management for your applications.
4+
5+
## Features
6+
7+
- Create new license keys.
8+
- Activate license keys for specific devices.
9+
- Deactivate devices associated with a license key.
10+
- Retrieve detailed information about a license key.
11+
- Block license keys to prevent further activations.
12+
- Unblock previously blocked license keys.
13+
- Typed requests and responses for better developer experience.
14+
- Standardized error handling.
15+
16+
## Installation
17+
18+
```bash
19+
npm install keymint-nodejs-sdk
20+
# or
21+
yarn add keymint-nodejs-sdk
22+
```
23+
24+
## Usage
25+
26+
First, initialize the SDK with your access token:
27+
28+
```typescript
29+
import { KeyMintSDK } from "keymint-nodejs-sdk";
30+
31+
async function main() {
32+
const accessToken = process.env.KEYMINT_ACCESS_TOKEN;
33+
if (!accessToken) {
34+
console.error("Please set the KEYMINT_ACCESS_TOKEN environment variable.");
35+
return;
36+
}
37+
38+
// Optionally, provide a custom base URL if not using the default KeyMint API endpoint
39+
// const sdk = new KeyMintSDK(accessToken, "https://your-custom-api.example.com");
40+
const sdk = new KeyMintSDK(accessToken);
41+
42+
// ... use SDK methods
43+
}
44+
45+
main();
46+
```
47+
48+
## API Methods
49+
50+
All methods are asynchronous and return a Promise.
51+
52+
### `createKey`
53+
54+
Creates a new license key.
55+
56+
```typescript
57+
try {
58+
const params = {
59+
productId: "your_product_id",
60+
// Optional parameters:
61+
// maxActivations: "5", // String representation of a number
62+
// expiryDate: "2025-12-31T23:59:59Z", // ISO 8601 date string
63+
// customerId: "cust_existing_123",
64+
// newCustomer: { name: "New Customer Name", email: "[email protected]" },
65+
// metadata: { custom_field: "custom_value" }
66+
};
67+
const response = await sdk.createKey(params);
68+
console.log("Key created:", response.key); // { code: 0, key: "lk_xxxx..." }
69+
} catch (error) {
70+
console.error("Error creating key:", error);
71+
}
72+
```
73+
74+
### `activateKey`
75+
76+
Activates a license key for a device.
77+
78+
```typescript
79+
try {
80+
const params = {
81+
productId: "your_product_id",
82+
licenseKey: "lk_xxxx-xxxxx-xxxxx-xxxxx",
83+
// Optional parameters:
84+
// hostId: "unique_device_id_123",
85+
// deviceTag: "User's MacBook Pro"
86+
};
87+
const response = await sdk.activateKey(params);
88+
console.log("Key activated:", response.message); // { code: 0, message: "License valid", ... }
89+
} catch (error) {
90+
console.error("Error activating key:", error);
91+
}
92+
```
93+
94+
### `deactivateKey`
95+
96+
Deactivates a device associated with a license key. If `hostId` is omitted, all devices for that key are deactivated.
97+
98+
```typescript
99+
try {
100+
const params = {
101+
productId: "your_product_id",
102+
licenseKey: "lk_xxxx-xxxxx-xxxxx-xxxxx",
103+
// Optional:
104+
// hostId: "unique_device_id_123"
105+
};
106+
const response = await sdk.deactivateKey(params);
107+
console.log("Key deactivated:", response.message); // { message: "Device deactivated", code: 0 }
108+
} catch (error) {
109+
console.error("Error deactivating key:", error);
110+
}
111+
```
112+
113+
### `getKey`
114+
115+
Retrieves detailed information about a specific license key.
116+
117+
```typescript
118+
try {
119+
const params = {
120+
productId: "your_product_id",
121+
licenseKey: "lk_xxxx-xxxxx-xxxxx-xxxxx",
122+
};
123+
const response = await sdk.getKey(params);
124+
console.log("License details:", response.data.license);
125+
// response.data also contains optional 'customer' details
126+
// { code: 0, data: { license: { ... }, customer?: { ... } } }
127+
} catch (error) {
128+
console.error("Error getting key details:", error);
129+
}
130+
```
131+
132+
### `blockKey`
133+
134+
Blocks a license key, preventing further activations.
135+
136+
```typescript
137+
try {
138+
const params = {
139+
productId: "your_product_id",
140+
licenseKey: "lk_xxxx-xxxxx-xxxxx-xxxxx",
141+
};
142+
const response = await sdk.blockKey(params);
143+
console.log("Key blocked:", response.message); // { message: "Key blocked", code: 0 }
144+
} catch (error) {
145+
console.error("Error blocking key:", error);
146+
}
147+
```
148+
149+
### `unblockKey`
150+
151+
Unblocks a previously blocked license key.
152+
153+
```typescript
154+
try {
155+
const params = {
156+
productId: "your_product_id",
157+
licenseKey: "lk_xxxx-xxxxx-xxxxx-xxxxx",
158+
};
159+
const response = await sdk.unblockKey(params);
160+
console.log("Key unblocked:", response.message); // { message: "Key unblocked", code: 0 }
161+
} catch (error) {
162+
console.error("Error unblocking key:", error);
163+
}
164+
```
165+
166+
## Error Handling
167+
168+
The SDK methods throw an error object if the API call fails or an unexpected issue occurs. The error object typically includes `message`, `code` (API specific or -1 for generic errors), and `status` (HTTP status code).
169+
170+
```typescript
171+
// Example error structure:
172+
// {
173+
// message: "Invalid license key",
174+
// code: 1,
175+
// status: 404
176+
// }
177+
```
178+
179+
## Development
180+
181+
1. Clone the repository.
182+
2. Install dependencies: `npm install`
183+
3. Build the SDK: `npm run build`
184+
185+
## License
186+
187+
This SDK is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
188+
189+
## API Reference
190+
191+
Provides detailed information about the SDK's constructor and methods.
192+
193+
### `new KeyMintSDK(accessToken: string, baseUrl?: string)`
194+
195+
Initializes a new instance of the KeyMintSDK.
196+
197+
- `accessToken` (string, required): Your KeyMint API access token. This token will be used in the `Authorization` header for all API requests (e.g., `Bearer <accessToken>`).
198+
- `baseUrl` (string, optional): The base URL for the KeyMint API. If not provided, it defaults to `https://api.keymint.dev`.
199+
200+
### `async sdk.createKey(params: CreateKeyParams): Promise<CreateKeyResponse>`
201+
202+
Creates a new license key for a given product.
203+
204+
- `params` ([`CreateKeyParams`](#createkeyparams)): An object containing:
205+
- `productId` (string, required): The ID of the product for which to create the key.
206+
- `maxActivations` (string, optional): Maximum number of times this key can be activated (e.g., "5").
207+
- `expiryDate` (string, optional): The expiration date of the key in ISO 8601 format (e.g., "2025-12-31T23:59:59Z").
208+
- `customerId` (string, optional): The ID of an existing customer to associate with this key.
209+
- `newCustomer` ([`NewCustomer`](#newcustomer), optional): An object to create and associate a new customer with this key.
210+
- `name` (string, required): Name of the new customer.
211+
- `email` (string, optional): Email of the new customer.
212+
- `metadata` (object, optional): A flexible object to store any custom key-value pairs.
213+
- Returns: A `Promise` that resolves to a [`CreateKeyResponse`](#createkeyresponse) object containing the `code` and the new `key` string.
214+
- Throws: `KeyMintApiError` if the API call fails (e.g., product not found, invalid parameters).
215+
216+
### `async sdk.activateKey(params: ActivateKeyParams): Promise<ActivateKeyResponse>`
217+
218+
Activates a license key for a specific device (host). This typically consumes one activation from the key unless the key has unlimited activations or is being reactivated on the same host ID for which it was previously activated.
219+
220+
- `params` ([`ActivateKeyParams`](#activatekeyparams)): An object containing:
221+
- `productId` (string, required): The ID of the product.
222+
- `licenseKey` (string, required): The license key to activate.
223+
- `hostId` (string, optional): A unique identifier for the host machine or device. Providing a consistent `hostId` is crucial for tracking activations per device and for deactivation.
224+
- `deviceTag` (string, optional): A user-friendly name or tag for the device (e.g., "User's MacBook Pro").
225+
- Returns: A `Promise` that resolves to an [`ActivateKeyResponse`](#activatekeyresponse) object, often containing a `message`, `code`, and potentially details like `licensee_name` and `licensee_email`.
226+
- Throws: `KeyMintApiError` if activation fails (e.g., key invalid, max activations reached, key blocked).
227+
228+
### `async sdk.deactivateKey(params: DeactivateKeyParams): Promise<DeactivateKeyResponse>`
229+
230+
Deactivates one or all host IDs associated with a license key. If `hostId` is provided, only that specific host is deactivated. If `hostId` is omitted, all activations for the key are removed (global deactivation).
231+
232+
- `params` ([`DeactivateKeyParams`](#deactivatekeyparams)): An object containing:
233+
- `productId` (string, required): The ID of the product.
234+
- `licenseKey` (string, required): The license key.
235+
- `hostId` (string, optional): The unique identifier of the host to deactivate. If omitted, all hosts are deactivated.
236+
- Returns: A `Promise` that resolves to a [`DeactivateKeyResponse`](#deactivatekeyresponse) object with a `message` and `code` indicating success.
237+
- Throws: `KeyMintApiError` if deactivation fails (e.g., key not found).
238+
239+
### `async sdk.getKey(params: GetKeyParams): Promise<GetKeyResponse>`
240+
241+
Retrieves detailed information about a specific license key, including its status, activation records, and associated customer data.
242+
243+
- `params` ([`GetKeyParams`](#getkeyparams)): An object containing:
244+
- `productId` (string, required): The ID of the product.
245+
- `licenseKey` (string, required): The license key to retrieve details for.
246+
- Returns: A `Promise` that resolves to a [`GetKeyResponse`](#getkeyresponse) object containing detailed `data` about the license and customer.
247+
- Throws: `KeyMintApiError` if the API call fails (e.g., key not found).
248+
249+
### `async sdk.blockKey(params: BlockKeyParams): Promise<BlockKeyResponse>`
250+
251+
Blocks a license key, preventing further activations or validations.
252+
253+
- `params` ([`BlockKeyParams`](#blockkeyparams)): An object containing:
254+
- `productId` (string, required): The ID of the product.
255+
- `licenseKey` (string, required): The license key to block.
256+
- Returns: A `Promise` that resolves to a [`BlockKeyResponse`](#blockkeyresponse) object with a `message` and `code` indicating success.
257+
- Throws: `KeyMintApiError` if blocking fails (e.g., key not found).
258+
259+
### `async sdk.unblockKey(params: UnblockKeyParams): Promise<UnblockKeyResponse>`
260+
261+
Unblocks a previously blocked license key, allowing it to be activated again.
262+
263+
- `params` ([`UnblockKeyParams`](#unblockkeyparams)): An object containing:
264+
- `productId` (string, required): The ID of the product.
265+
- `licenseKey` (string, required): The license key to unblock.
266+
- Returns: A `Promise` that resolves to an [`UnblockKeyResponse`](#unblockkeyresponse) object with a `message` and `code` indicating success.
267+
- Throws: `KeyMintApiError` if unblocking fails (e.g., key not found, key not currently blocked).
268+
269+
---
270+
271+
_This SDK is currently under development._

jest.config.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
module.exports = {
2+
preset: 'ts-jest',
3+
testEnvironment: 'node',
4+
roots: ['<rootDir>/src', '<rootDir>/tests'],
5+
moduleNameMapper: {
6+
// This will map 'axios' imports to our mock implementation
7+
'^axios$': '<rootDir>/tests/__mocks__/axios.ts'
8+
},
9+
// Automatically clear mock calls and instances before every test
10+
clearMocks: true,
11+
};

0 commit comments

Comments
 (0)