@minia2a/sdk 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/README.md +71 -0
- package/cli.js +295 -0
- package/index.js +80 -0
- package/package.json +36 -0
package/README.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# @minia2a/sdk
|
|
2
|
+
|
|
3
|
+
The marketplace companion for [@x402/express](https://www.npmjs.com/package/@x402/express) — discover, list, and trial 299 agent-to-agent services from the command line.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install -g @minia2a/sdk
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Quickstart
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Discover services your agent can call
|
|
13
|
+
minia2a discover "gas price"
|
|
14
|
+
|
|
15
|
+
# See what's popular
|
|
16
|
+
minia2a list
|
|
17
|
+
|
|
18
|
+
# Try a service for free
|
|
19
|
+
minia2a trial x402-gas
|
|
20
|
+
|
|
21
|
+
# Register your agent (500 free credits)
|
|
22
|
+
minia2a register
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Commands
|
|
26
|
+
|
|
27
|
+
| Command | Description |
|
|
28
|
+
|---------|-------------|
|
|
29
|
+
| `minia2a discover <query>` | Search 299 services by keyword |
|
|
30
|
+
| `minia2a list` | Show top 20 most-used services |
|
|
31
|
+
| `minia2a trial <id>` | Call a service's free trial endpoint |
|
|
32
|
+
| `minia2a register` | Get your 500 free credits ($2.50 value) |
|
|
33
|
+
| `minia2a publish` | List your x402 endpoint on the marketplace |
|
|
34
|
+
|
|
35
|
+
## For @x402/express Users
|
|
36
|
+
|
|
37
|
+
Already charging agents with `@x402/express`? List your endpoint:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
minia2a publish
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Your service gets:
|
|
44
|
+
- Listed in the 299-service catalog on [minia2a.uk](https://minia2a.uk)
|
|
45
|
+
- Free trial traffic from agent developers
|
|
46
|
+
- USDC revenue on Base — direct to your wallet
|
|
47
|
+
- 5% marketplace fee only on paid calls
|
|
48
|
+
|
|
49
|
+
## Programmatic API
|
|
50
|
+
|
|
51
|
+
```js
|
|
52
|
+
const { discover, getServices, trial, stats } = require('@minia2a/sdk');
|
|
53
|
+
|
|
54
|
+
const matches = await discover('captcha');
|
|
55
|
+
console.log(matches[0].name); // "CAPTCHA Solver"
|
|
56
|
+
|
|
57
|
+
const { body } = await trial('x402-gas');
|
|
58
|
+
console.log(body);
|
|
59
|
+
|
|
60
|
+
const { services, walletUsers } = await stats();
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Links
|
|
64
|
+
|
|
65
|
+
- [minia2a.uk](https://minia2a.uk) — Web UI + full catalog
|
|
66
|
+
- [@x402/express](https://www.npmjs.com/package/@x402/express) — x402 payment middleware
|
|
67
|
+
- [x402 Protocol](https://x402.org) — Agent payment standard
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
Powered by [minia2a.uk](https://minia2a.uk) — 299 services, USDC on Base
|
package/cli.js
ADDED
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* minia2a CLI — The marketplace companion for @x402/express
|
|
4
|
+
*
|
|
5
|
+
* Discover, list, and trial agent-to-agent x402 services.
|
|
6
|
+
* 299 services, USDC on Base, zero API keys.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const BASE_URL = "https://minia2a.uk";
|
|
10
|
+
|
|
11
|
+
async function fetchJSON(path) {
|
|
12
|
+
const url = `${BASE_URL}${path}`;
|
|
13
|
+
try {
|
|
14
|
+
const res = await fetch(url);
|
|
15
|
+
if (!res.ok) {
|
|
16
|
+
throw new Error(`HTTP ${res.status} from ${url}`);
|
|
17
|
+
}
|
|
18
|
+
return await res.json();
|
|
19
|
+
} catch (err) {
|
|
20
|
+
if (err.cause?.code === "ENOTFOUND" || err.cause?.code === "ECONNREFUSED") {
|
|
21
|
+
console.error(`\n❌ Could not reach minia2a.uk — check your network.\n`);
|
|
22
|
+
} else if (err.message?.includes("HTTP")) {
|
|
23
|
+
console.error(`\n❌ API returned ${err.message}\n`);
|
|
24
|
+
} else {
|
|
25
|
+
console.error(`\n❌ ${err.message}\n`);
|
|
26
|
+
}
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function footer() {
|
|
32
|
+
console.log("\n" + "─".repeat(50));
|
|
33
|
+
console.log("Powered by minia2a.uk — 299 services, USDC on Base");
|
|
34
|
+
console.log("─".repeat(50) + "\n");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function usage() {
|
|
38
|
+
console.log(`
|
|
39
|
+
minia2a <command> [args]
|
|
40
|
+
|
|
41
|
+
Commands:
|
|
42
|
+
discover <query> Search the 299-service marketplace
|
|
43
|
+
list Show popular x402 services
|
|
44
|
+
trial <service> Get trial instructions for a service
|
|
45
|
+
register Register your agent (500 free credits)
|
|
46
|
+
|
|
47
|
+
Examples:
|
|
48
|
+
minia2a discover "gas price"
|
|
49
|
+
minia2a list
|
|
50
|
+
minia2a trial x402-gas
|
|
51
|
+
minia2a register
|
|
52
|
+
|
|
53
|
+
For x402/express users:
|
|
54
|
+
minia2a publish Register your x402 endpoint on minia2a.uk
|
|
55
|
+
`);
|
|
56
|
+
footer();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async function discover(query) {
|
|
60
|
+
if (!query || query.trim() === "") {
|
|
61
|
+
console.error("Usage: minia2a discover <query>");
|
|
62
|
+
console.error("Example: minia2a discover \"gas price\"\n");
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
console.log(`\n🔍 Searching for "${query}"...\n`);
|
|
67
|
+
|
|
68
|
+
const data = await fetchJSON("/api/services");
|
|
69
|
+
|
|
70
|
+
const services = data.services || [];
|
|
71
|
+
const q = query.toLowerCase().split(/\s+/);
|
|
72
|
+
|
|
73
|
+
// Score each service by keyword match in name + description
|
|
74
|
+
const scored = services
|
|
75
|
+
.filter(s => s.active)
|
|
76
|
+
.map(s => {
|
|
77
|
+
const text = `${s.name} ${s.description} ${s.id} ${s.category || ""}`.toLowerCase();
|
|
78
|
+
let score = 0;
|
|
79
|
+
for (const word of q) {
|
|
80
|
+
if (text.includes(word)) score += 10;
|
|
81
|
+
// Exact match in name = very relevant
|
|
82
|
+
if (s.name.toLowerCase().includes(word)) score += 20;
|
|
83
|
+
// In the service ID
|
|
84
|
+
if (s.id.toLowerCase().includes(word)) score += 5;
|
|
85
|
+
}
|
|
86
|
+
return { ...s, _score: score };
|
|
87
|
+
})
|
|
88
|
+
.filter(s => s._score > 0)
|
|
89
|
+
.sort((a, b) => b._score - a._score)
|
|
90
|
+
.slice(0, 15);
|
|
91
|
+
|
|
92
|
+
if (scored.length === 0) {
|
|
93
|
+
console.log(`No services matched "${query}". Try broader keywords.\n`);
|
|
94
|
+
footer();
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
console.log(`Found ${scored.length} matching service(s):\n`);
|
|
99
|
+
|
|
100
|
+
for (const s of scored) {
|
|
101
|
+
const price = s.priceCents != null
|
|
102
|
+
? `$${(s.priceCents / 100).toFixed(3).replace(/0+$/, "").replace(/\.$/, "")}`
|
|
103
|
+
: "?";
|
|
104
|
+
const trials = s.trialCount != null ? `${s.trialCount} trials` : "";
|
|
105
|
+
const emoji = s.priceCents === 0 ? "🆓" : s.priceCents <= 0.1 ? "💰" : "💎";
|
|
106
|
+
console.log(` ${emoji} ${s.name}`);
|
|
107
|
+
console.log(` id: ${s.id}`);
|
|
108
|
+
console.log(` price: ${price}/call`);
|
|
109
|
+
console.log(` endpoint: ${s.endpoint}`);
|
|
110
|
+
console.log(` about: ${s.description?.slice(0, 80) || ""}...`);
|
|
111
|
+
console.log();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
console.log(`\nTry one: minia2a trial ${scored[0].id}`);
|
|
115
|
+
footer();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async function list() {
|
|
119
|
+
console.log("\n📡 Fetching services from minia2a.uk...\n");
|
|
120
|
+
|
|
121
|
+
const data = await fetchJSON("/api/services");
|
|
122
|
+
const services = (data.services || []).filter(s => s.active);
|
|
123
|
+
|
|
124
|
+
// Sort by trial count (popularity) descending
|
|
125
|
+
const popular = [...services]
|
|
126
|
+
.sort((a, b) => (b.trialCount || 0) - (a.trialCount || 0))
|
|
127
|
+
.slice(0, 20);
|
|
128
|
+
|
|
129
|
+
console.log(`Top ${Math.min(20, popular.length)} of ${services.length} services:\n`);
|
|
130
|
+
|
|
131
|
+
for (const s of popular) {
|
|
132
|
+
const price = s.priceCents != null
|
|
133
|
+
? `$${(s.priceCents / 100).toFixed(3).replace(/0+$/, "").replace(/\.$/, "")}`
|
|
134
|
+
: "?";
|
|
135
|
+
const trials = s.trialCount || 0;
|
|
136
|
+
const id = (s.id || "").padEnd(30);
|
|
137
|
+
console.log(` ${id} ${price.padStart(8)}/call ${String(trials).padStart(5)} trials`);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
console.log(`\n ...and ${services.length - 20} more. Search: minia2a discover <keyword>`);
|
|
141
|
+
console.log("\nRegister your own: minia2a publish");
|
|
142
|
+
footer();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
async function trial(serviceId) {
|
|
146
|
+
if (!serviceId || serviceId.trim() === "") {
|
|
147
|
+
console.error("Usage: minia2a trial <service-id>");
|
|
148
|
+
console.error("Example: minia2a trial x402-gas\n");
|
|
149
|
+
process.exit(1);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
console.log(`\n🧪 ${serviceId} — trial mode\n`);
|
|
153
|
+
|
|
154
|
+
// Fetch service details
|
|
155
|
+
const data = await fetchJSON("/api/services");
|
|
156
|
+
const svc = data.services?.find(s => s.id === serviceId);
|
|
157
|
+
|
|
158
|
+
if (!svc) {
|
|
159
|
+
console.log(`Service "${serviceId}" not found.`);
|
|
160
|
+
console.log(`Run 'minia2a list' to see available services.\n`);
|
|
161
|
+
footer();
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const price = svc.priceCents != null
|
|
166
|
+
? `$${(svc.priceCents / 100).toFixed(3).replace(/0+$/, "").replace(/\.$/, "")}`
|
|
167
|
+
: "?";
|
|
168
|
+
const trialEndpoint = `${svc.endpoint}?trial=1`;
|
|
169
|
+
|
|
170
|
+
console.log(` Service: ${svc.name}`);
|
|
171
|
+
console.log(` Price: ${price}/call`);
|
|
172
|
+
console.log(` Endpoint: ${svc.endpoint}`);
|
|
173
|
+
console.log(` Trial URL: ${trialEndpoint}`);
|
|
174
|
+
console.log(` About: ${svc.description?.slice(0, 120) || ""}...`);
|
|
175
|
+
console.log();
|
|
176
|
+
|
|
177
|
+
console.log(" curl example:");
|
|
178
|
+
console.log(` curl -s '${trialEndpoint}'`);
|
|
179
|
+
console.log();
|
|
180
|
+
|
|
181
|
+
// Actually call the trial endpoint
|
|
182
|
+
console.log(" Trying now...\n");
|
|
183
|
+
try {
|
|
184
|
+
const start = Date.now();
|
|
185
|
+
const res = await fetch(trialEndpoint);
|
|
186
|
+
const elapsed = Date.now() - start;
|
|
187
|
+
const body = await res.text();
|
|
188
|
+
const preview = body.length > 300 ? body.slice(0, 300) + "..." : body;
|
|
189
|
+
|
|
190
|
+
console.log(` Status: ${res.status} ${res.statusText} (${elapsed}ms)`);
|
|
191
|
+
console.log(` Response: ${preview}`);
|
|
192
|
+
console.log();
|
|
193
|
+
} catch (err) {
|
|
194
|
+
console.log(` ⚠ Could not reach trial endpoint: ${err.message}`);
|
|
195
|
+
console.log(` Try manually: curl -s '${trialEndpoint}'\n`);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
footer();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
async function register() {
|
|
202
|
+
console.log(`
|
|
203
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
204
|
+
║ Register Your Agent on minia2a.uk ║
|
|
205
|
+
╠══════════════════════════════════════════════════════════════╣
|
|
206
|
+
║ ║
|
|
207
|
+
║ To register and get 500 free credits ($2.50 value): ║
|
|
208
|
+
║ ║
|
|
209
|
+
║ curl -X POST https://minia2a.uk/api/v1/register-simple ║
|
|
210
|
+
║ -H "Content-Type: application/json" ║
|
|
211
|
+
║ -d '{"agentName":"your-agent-name"}' ║
|
|
212
|
+
║ ║
|
|
213
|
+
║ Already registered? Check your stats: ║
|
|
214
|
+
║ ║
|
|
215
|
+
║ curl -s https://minia2a.uk/api/stats ║
|
|
216
|
+
║ ║
|
|
217
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
218
|
+
`);
|
|
219
|
+
footer();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
async function publish() {
|
|
223
|
+
console.log(`
|
|
224
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
225
|
+
║ List Your x402 Endpoint on minia2a.uk ║
|
|
226
|
+
╠══════════════════════════════════════════════════════════════╣
|
|
227
|
+
║ ║
|
|
228
|
+
║ Already using @x402/express or @minia2a/x402-express? ║
|
|
229
|
+
║ Register your endpoint in one command: ║
|
|
230
|
+
║ ║
|
|
231
|
+
║ curl -X POST https://minia2a.uk/api/v1/register-simple ║
|
|
232
|
+
║ -H "Content-Type: application/json" ║
|
|
233
|
+
║ -d '{ ║
|
|
234
|
+
║ "agentName":"my-service", ║
|
|
235
|
+
║ "endpoint":"https://my-api.com/x402/ai-summary", ║
|
|
236
|
+
║ "description":"AI summary service — $0.01/call" ║
|
|
237
|
+
║ }' ║
|
|
238
|
+
║ ║
|
|
239
|
+
║ Your service gets: ║
|
|
240
|
+
║ • Listed in the 299-service catalog ║
|
|
241
|
+
║ • Free trial traffic from agent developers ║
|
|
242
|
+
║ • USDC revenue on Base — direct to your wallet ║
|
|
243
|
+
║ • 5% marketplace fee only on paid calls ║
|
|
244
|
+
║ ║
|
|
245
|
+
║ Docs: https://minia2a.uk/docs ║
|
|
246
|
+
║ ║
|
|
247
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
248
|
+
`);
|
|
249
|
+
footer();
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// --- Main ---
|
|
253
|
+
async function main() {
|
|
254
|
+
const args = process.argv.slice(2);
|
|
255
|
+
const cmd = args[0]?.toLowerCase();
|
|
256
|
+
const arg = args.slice(1).join(" ");
|
|
257
|
+
|
|
258
|
+
switch (cmd) {
|
|
259
|
+
case "discover":
|
|
260
|
+
case "search":
|
|
261
|
+
await discover(arg);
|
|
262
|
+
break;
|
|
263
|
+
case "list":
|
|
264
|
+
case "ls":
|
|
265
|
+
await list();
|
|
266
|
+
break;
|
|
267
|
+
case "trial":
|
|
268
|
+
case "try":
|
|
269
|
+
await trial(args[1] || "");
|
|
270
|
+
break;
|
|
271
|
+
case "register":
|
|
272
|
+
case "signup":
|
|
273
|
+
await register();
|
|
274
|
+
break;
|
|
275
|
+
case "publish":
|
|
276
|
+
case "add":
|
|
277
|
+
await publish();
|
|
278
|
+
break;
|
|
279
|
+
case "help":
|
|
280
|
+
case "--help":
|
|
281
|
+
case "-h":
|
|
282
|
+
case undefined:
|
|
283
|
+
usage();
|
|
284
|
+
break;
|
|
285
|
+
default:
|
|
286
|
+
console.error(`\nUnknown command: ${cmd}\n`);
|
|
287
|
+
usage();
|
|
288
|
+
process.exitCode = 1;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
main().catch(err => {
|
|
293
|
+
console.error(`\n❌ Unexpected error: ${err.message}\n`);
|
|
294
|
+
process.exit(1);
|
|
295
|
+
});
|
package/index.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* minia2a SDK — Programmatic API
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* const { discover, getServices, trial } = require('@minia2a/sdk');
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const BASE_URL = "https://minia2a.uk";
|
|
9
|
+
|
|
10
|
+
async function fetchJSON(path) {
|
|
11
|
+
const res = await fetch(`${BASE_URL}${path}`);
|
|
12
|
+
if (!res.ok) throw new Error(`minia2a API: HTTP ${res.status} from ${path}`);
|
|
13
|
+
return res.json();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Search services by keyword query.
|
|
18
|
+
* Returns scored & sorted matches from the 299-service catalog.
|
|
19
|
+
*/
|
|
20
|
+
async function discover(query) {
|
|
21
|
+
const data = await fetchJSON("/api/services");
|
|
22
|
+
const services = data.services || [];
|
|
23
|
+
const q = query.toLowerCase().split(/\s+/);
|
|
24
|
+
|
|
25
|
+
return services
|
|
26
|
+
.filter(s => s.active)
|
|
27
|
+
.map(s => {
|
|
28
|
+
const text = `${s.name} ${s.description} ${s.id} ${s.category || ""}`.toLowerCase();
|
|
29
|
+
let score = 0;
|
|
30
|
+
for (const word of q) {
|
|
31
|
+
if (text.includes(word)) score += 10;
|
|
32
|
+
if (s.name.toLowerCase().includes(word)) score += 20;
|
|
33
|
+
if (s.id.toLowerCase().includes(word)) score += 5;
|
|
34
|
+
}
|
|
35
|
+
return { ...s, _score: score };
|
|
36
|
+
})
|
|
37
|
+
.filter(s => s._score > 0)
|
|
38
|
+
.sort((a, b) => b._score - a._score);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Get all active services.
|
|
43
|
+
*/
|
|
44
|
+
async function getServices() {
|
|
45
|
+
const data = await fetchJSON("/api/services");
|
|
46
|
+
return (data.services || []).filter(s => s.active);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Get a single service by ID.
|
|
51
|
+
*/
|
|
52
|
+
async function getService(id) {
|
|
53
|
+
const data = await fetchJSON("/api/services");
|
|
54
|
+
return (data.services || []).find(s => s.id === id) || null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Make a trial call to a service endpoint.
|
|
59
|
+
*/
|
|
60
|
+
async function trial(serviceId) {
|
|
61
|
+
const svc = await getService(serviceId);
|
|
62
|
+
if (!svc) throw new Error(`Service "${serviceId}" not found`);
|
|
63
|
+
|
|
64
|
+
const res = await fetch(`${svc.endpoint}?trial=1`);
|
|
65
|
+
return {
|
|
66
|
+
service: svc,
|
|
67
|
+
status: res.status,
|
|
68
|
+
ok: res.ok,
|
|
69
|
+
body: await res.text(),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Get marketplace stats.
|
|
75
|
+
*/
|
|
76
|
+
async function stats() {
|
|
77
|
+
return fetchJSON("/api/stats");
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
module.exports = { discover, getServices, getService, trial, stats };
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@minia2a/sdk",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "The marketplace companion for @x402/express — discover, list, and trial 299 agent-to-agent services from the command line.",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"minia2a": "./cli.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"cli.js",
|
|
11
|
+
"index.js",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/minia2a-org/minia2a-sdk.git"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"x402",
|
|
20
|
+
"agent-payments",
|
|
21
|
+
"micropayments",
|
|
22
|
+
"usdc",
|
|
23
|
+
"base",
|
|
24
|
+
"cli",
|
|
25
|
+
"minia2a",
|
|
26
|
+
"agent-economy",
|
|
27
|
+
"m2m",
|
|
28
|
+
"pay-per-call"
|
|
29
|
+
],
|
|
30
|
+
"author": "minia2a",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"homepage": "https://minia2a.uk",
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">=16"
|
|
35
|
+
}
|
|
36
|
+
}
|