create-stellar-service 0.0.0-stage → 0.1.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/dist/main.js ADDED
@@ -0,0 +1,510 @@
1
+ // create-stellar-service, run as `npm create stellar-service`: a new project that sells an AI service on Stellar,
2
+ // ready to run, try and deploy.
3
+ //
4
+ // It asks at most five questions: the folder; what to make (an API the developer already runs, behind the gateway, or
5
+ // a new TypeScript or Python service); for an API, its OpenAPI document or the URL a paid call goes to; one sentence on
6
+ // what the service offers, which is what search matches; and the price of a call. Then it writes the project
7
+ // (files.ts), with fly.toml, and installs it. No wallet is needed to start: `npm run dev` makes a throwaway testnet
8
+ // account to be paid to, and `npm run launch` sets up the developer's own wallet when the service goes live. --wallet
9
+ // sets it up now instead, with `provider-kit trustline`. Flags answer every question, for scripts and coding agents.
10
+ //
11
+ // Testnet unless --network mainnet, which writes mainnet's facilitator (it wants an API key, FACILITATOR_AUTH) and a
12
+ // Soroban RPC instead, and leaves out the testnet-only steps. It never asks for, makes or stores a secret key, and
13
+ // never pays.
14
+ import { spawn } from "node:child_process";
15
+ import { existsSync, readdirSync, statSync } from "node:fs";
16
+ import { chmod, mkdir, readFile, rm, writeFile } from "node:fs/promises";
17
+ import { basename, dirname, join, resolve } from "node:path";
18
+ import { createInterface } from "node:readline/promises";
19
+ import { parseArgs } from "node:util";
20
+ import { adaptInitConfig, DEFAULT_PRICE, dockerignore, envFile, FACILITATOR_KEYS, gitignore, KINDS, packageJson, pythonGatewayConfig, readme, TEMPLATE_DESCRIPTION, TEMPLATE_FILES, template, } from "./files.js";
21
+ import { KIT_CLI, KIT_PACKAGES, kitDependencies, kitSource, unbuilt } from "./kit.js";
22
+ const OPTIONS = {
23
+ kind: { type: "string" },
24
+ openapi: { type: "string" },
25
+ upstream: { type: "string" },
26
+ name: { type: "string" },
27
+ description: { type: "string" },
28
+ price: { type: "string" },
29
+ network: { type: "string" },
30
+ "pay-to": { type: "string" },
31
+ wallet: { type: "boolean" },
32
+ yes: { type: "boolean", short: "y" },
33
+ help: { type: "boolean", short: "h" },
34
+ };
35
+ export const USAGE = `create-stellar-service: a new paid AI service on Stellar, ready to run, try and deploy
36
+
37
+ Usage:
38
+ npm create stellar-service [<folder>] [-- <options>]
39
+ create-stellar-service [<folder>] [--kind wrap|typescript|python] [--openapi <file | url>]
40
+ [--upstream <url>] [--name <text>] [--description <text>] [--price <usdc>]
41
+ [--network testnet|mainnet] [--wallet | --pay-to <G...>] [--yes]
42
+
43
+ --kind wrap: an API you already run, in any language, behind the Provider Kit gateway. No
44
+ code changes: --openapi reads its OpenAPI document (FastAPI serves /openapi.json) and
45
+ makes a service of each POST endpoint; without one, --upstream is the URL a paid call
46
+ goes to.
47
+ typescript: a new service, with the Provider Kit library.
48
+ python: a new FastAPI service, behind the gateway.
49
+ --description One sentence on what it offers. Search matches it and the name: use the words buyers type.
50
+ --name The provider's name. Default: the folder's, or the OpenAPI document's title.
51
+ --price What a call costs, in USDC. Default 0.01.
52
+ --network testnet (default): test money, nothing to set up. mainnet: real USDC, through mainnet's
53
+ facilitator, which wants an API key (FACILITATOR_AUTH in .env); no throwaway accounts.
54
+ --wallet Sets up the account clients pay now: a page opens where your own wallet approves a USDC
55
+ trustline, and the address goes in .env as PAY_TO. --pay-to takes an address you have.
56
+ Without either, nothing is needed until npm run launch: on testnet, npm run dev pays a
57
+ throwaway account meanwhile.
58
+ --yes Takes the defaults for questions no flag answers. Without a terminal it never asks, and
59
+ --kind is needed.
60
+
61
+ Testnet unless --network mainnet. It never asks for a secret key, and never pays.`;
62
+ const DEFAULT_FOLDER = "my-stellar-service";
63
+ const MAKING = { wrap: "a gateway in front of your API", typescript: "a new TypeScript service", python: "a new Python service" };
64
+ const DEFAULT_OPENAPI = "http://127.0.0.1:8000/openapi.json";
65
+ const STELLAR_ACCOUNT = /^G[A-Z2-7]{55}$/;
66
+ /** A price in USDC: up to 7 decimals, as Stellar counts USDC. */
67
+ const PRICE = /^(?:0|[1-9]\d{0,8})(?:\.\d{1,7})?$/;
68
+ /** A mistake in how it was called: printed with the usage text, exit code 2. */
69
+ export class UsageError extends Error {
70
+ name = "UsageError";
71
+ }
72
+ /** Ctrl+C or Ctrl+D at a question. */
73
+ export class Cancelled extends Error {
74
+ name = "Cancelled";
75
+ }
76
+ export function createIo() {
77
+ const tty = process.stdout.isTTY === true;
78
+ return {
79
+ log: (text = "") => console.log(text),
80
+ status: (text) => {
81
+ if (tty)
82
+ process.stdout.write(`\r\x1b[K${text}`);
83
+ },
84
+ interactive: tty && process.stdin.isTTY === true,
85
+ async ask(question) {
86
+ const terminal = createInterface({ input: process.stdin, output: process.stdout });
87
+ const stop = new AbortController();
88
+ terminal.on("SIGINT", () => stop.abort());
89
+ terminal.on("close", () => stop.abort());
90
+ try {
91
+ return (await terminal.question(question, { signal: stop.signal })).trim();
92
+ }
93
+ catch {
94
+ throw new Cancelled("cancelled");
95
+ }
96
+ finally {
97
+ terminal.close();
98
+ }
99
+ },
100
+ run: runProgram,
101
+ has: async (program) => (await runProgram(program, ["--version"], { cwd: process.cwd() }).catch(() => ({ code: 1, output: "" }))).code === 0,
102
+ fetch: (input, init) => fetch(input, init),
103
+ kit: kitSource(),
104
+ };
105
+ }
106
+ export async function create(argv, io = createIo()) {
107
+ const { values: flags, positionals } = parseArgs({ args: argv, options: OPTIONS, allowPositionals: true, allowNegative: true, strict: true });
108
+ if (flags.help) {
109
+ io.log(USAGE);
110
+ return 0;
111
+ }
112
+ if (positionals.length > 1)
113
+ throw new UsageError("give one folder");
114
+ if (flags["pay-to"] !== undefined && !STELLAR_ACCOUNT.test(flags["pay-to"]))
115
+ throw new UsageError("--pay-to must be a public Stellar account address, G...");
116
+ if (flags["pay-to"] !== undefined && flags.wallet === true)
117
+ throw new UsageError("--pay-to and --wallet both set the payout account: pick one");
118
+ if (flags.price !== undefined && !validPrice(flags.price))
119
+ throw new UsageError(`--price must be a price in USDC above zero, such as 0.05, not "${flags.price}"`);
120
+ if (flags.network !== undefined && parseNetwork(flags.network) === undefined)
121
+ throw new UsageError(`--network must be testnet or mainnet, not "${flags.network}"`);
122
+ if (io.kit.from === "clone") {
123
+ const missing = unbuilt(io.kit.packages);
124
+ if (missing.length > 0)
125
+ throw new Error(`the Provider Kit in ${dirname(io.kit.packages)} isn't built (no ${missing[0]}): run npm install && npm run build there first`);
126
+ }
127
+ let answers;
128
+ try {
129
+ answers = await answer(flags, positionals[0], io);
130
+ }
131
+ catch (error) {
132
+ if (error instanceof Cancelled) {
133
+ io.log("\nCancelled. Nothing was written.");
134
+ return 130;
135
+ }
136
+ throw error;
137
+ }
138
+ return build(answers, io);
139
+ }
140
+ /** The answers: from flags, else from questions on a terminal, else the defaults. */
141
+ async function answer(flags, folder, io) {
142
+ const asking = io.interactive && !flags.yes;
143
+ const directory = await askUntil(io, asking, folder, `Project folder [${DEFAULT_FOLDER}]: `, DEFAULT_FOLDER, (value) => {
144
+ const path = resolve(value);
145
+ if (!existsSync(path))
146
+ return undefined;
147
+ if (!statSync(path).isDirectory() || readdirSync(path).length > 0)
148
+ return `${value} already exists and isn't empty: pick another folder`;
149
+ return undefined;
150
+ });
151
+ const kind = await askKind(flags.kind, asking, io);
152
+ let source;
153
+ if (kind === "wrap") {
154
+ if (flags.openapi !== undefined) {
155
+ source = { openapi: flags.openapi, ...(flags.upstream === undefined ? {} : { upstream: flags.upstream }) };
156
+ const problem = await unreadable(flags.openapi, io.fetch);
157
+ if (problem !== undefined)
158
+ throw new Error(`can't read the OpenAPI document ${flags.openapi}: ${problem}. Start the API, or pass the URL a paid call goes to (--upstream). Nothing was written.`);
159
+ }
160
+ else if (flags.upstream !== undefined) {
161
+ source = { upstream: flags.upstream };
162
+ }
163
+ else if (!asking) {
164
+ throw new UsageError("--kind wrap needs --openapi <file | url>, or --upstream <url>");
165
+ }
166
+ else {
167
+ // The document is read now, so a mistyped URL or a stopped API is caught before anything is written.
168
+ for (;;) {
169
+ source = classify((await io.ask(`Your API's OpenAPI document, or the URL a paid call goes to [${DEFAULT_OPENAPI}]: `)) || DEFAULT_OPENAPI);
170
+ const problem = "openapi" in source ? await unreadable(source.openapi, io.fetch) : undefined;
171
+ if (problem === undefined)
172
+ break;
173
+ io.log(` Can't read it: ${problem}. Start the API and press Enter, or give the URL a paid call goes to.`);
174
+ }
175
+ }
176
+ }
177
+ else if (flags.openapi !== undefined || flags.upstream !== undefined) {
178
+ throw new UsageError("--openapi and --upstream are for --kind wrap");
179
+ }
180
+ let description = flags.description;
181
+ if (description === undefined && asking) {
182
+ const keep = kind !== "wrap" ? clip(TEMPLATE_DESCRIPTION, 40) : source !== undefined && "openapi" in source ? "Enter: the document's" : "Enter: write it later";
183
+ io.log("In one sentence, what does it offer? Agents search for it by these words and its name.");
184
+ description = (await io.ask(`[${keep}]: `)) || undefined;
185
+ }
186
+ let price = flags.price;
187
+ if (price === undefined && asking) {
188
+ price = await askUntil(io, true, undefined, `What does a call cost, in USDC? [${DEFAULT_PRICE}]: `, DEFAULT_PRICE, (value) => (validPrice(value) ? undefined : "a price in USDC above zero, such as 0.05"));
189
+ }
190
+ return {
191
+ directory: resolve(directory),
192
+ kind,
193
+ ...(source === undefined ? {} : { source }),
194
+ ...(flags.name === undefined ? {} : { name: flags.name }),
195
+ ...(description === undefined ? {} : { description }),
196
+ price: price ?? DEFAULT_PRICE,
197
+ network: flags.network === undefined ? "stellar:testnet" : parseNetwork(flags.network),
198
+ wallet: flags.wallet ?? false,
199
+ ...(flags["pay-to"] === undefined ? {} : { payTo: flags["pay-to"] }),
200
+ };
201
+ }
202
+ /** A price in USDC above zero, with at most 7 decimals. */
203
+ function validPrice(value) {
204
+ return PRICE.test(value) && Number(value) > 0;
205
+ }
206
+ /** --network as a network id: testnet, or mainnet (also written pubnet), as provider-kit takes them. */
207
+ function parseNetwork(value) {
208
+ if (["testnet", "stellar:testnet"].includes(value))
209
+ return "stellar:testnet";
210
+ if (["mainnet", "pubnet", "public", "stellar:pubnet"].includes(value))
211
+ return "stellar:pubnet";
212
+ return undefined;
213
+ }
214
+ /** Writes and installs the project, then sets up the payout account if asked. */
215
+ async function build(answers, io) {
216
+ const { directory, kind, network } = answers;
217
+ const testnet = network === "stellar:testnet";
218
+ const folder = basename(directory);
219
+ const vendored = io.kit.from === "clone";
220
+ io.log(`\nCreating ${folder}: ${MAKING[kind]}, paid in USDC on Stellar ${testnet ? "testnet" : "mainnet, real money"}\n`);
221
+ await mkdir(directory, { recursive: true });
222
+ const write = (file, text) => writeAt(directory, file, text);
223
+ const project = {
224
+ kind,
225
+ package: packageName(folder),
226
+ app: flyAppName(folder),
227
+ name: answers.name ?? titleCase(folder),
228
+ description: answers.description ?? TEMPLATE_DESCRIPTION,
229
+ price: answers.price,
230
+ network,
231
+ vendored,
232
+ // uv runs a Python API with its packages, so there is no virtual environment to make first.
233
+ ...(kind === "python" ? { uv: await io.has("uv") } : {}),
234
+ };
235
+ const packed = vendored ? await step(io, "Packed the Provider Kit from your clone into vendor/", () => pack(io, directory)) : {};
236
+ await write("package.json", packageJson(project, kitDependencies(io.kit, packed)));
237
+ await write(".gitignore", gitignore(project));
238
+ const installed = await step(io, "Installed packages (npm install)", async () => {
239
+ const result = await io.run("npm", ["install", "--no-audit", "--no-fund"], { cwd: directory });
240
+ if (result.code !== 0)
241
+ throw new Error(`npm install failed:\n${tail(result.output)}`);
242
+ }).then(() => true, (error) => {
243
+ io.log(`\n${error.message}\n\nThe project is in ${directory}, without its packages. Fix the problem, then run npm install there.`);
244
+ return false;
245
+ });
246
+ if (!installed)
247
+ return 1;
248
+ let variables = [];
249
+ let services = "the summarize service, in front of app.py";
250
+ let upstream;
251
+ if (kind === "wrap") {
252
+ const made = await gatewayFromInit(answers, project, io);
253
+ project.name = made.name;
254
+ project.description = made.description;
255
+ ({ variables, services } = made);
256
+ upstream = made.upstream;
257
+ }
258
+ else if (kind === "python") {
259
+ await write("provider.config.json", pythonGatewayConfig(project));
260
+ upstream = "http://127.0.0.1:8000/summarize";
261
+ }
262
+ for (const [templates, file] of TEMPLATE_FILES[kind])
263
+ await write(file, template(templates, file, project));
264
+ if (kind === "python")
265
+ await chmod(join(directory, "start.sh"), 0o755);
266
+ await write(".dockerignore", dockerignore(project));
267
+ await write(".env.example", envFile(project, { variables }, true));
268
+ await write(".env", envFile(project, { ...(answers.payTo === undefined ? {} : { payTo: answers.payTo }), variables }));
269
+ await write("README.md", readme(project, { services, ...(upstream === undefined ? {} : { upstream }) }));
270
+ io.log(` ✓ Wrote ${kind === "typescript" ? "the service, " : "provider.config.json, "}.env, a Dockerfile, fly.toml and a README`);
271
+ let payTo = answers.payTo;
272
+ if (answers.wallet) {
273
+ payTo = await connectWallet(io, directory, network);
274
+ if (payTo !== undefined)
275
+ await write(".env", envFile(project, { payTo, variables }));
276
+ }
277
+ io.log(`\n✓ Created ${folder} in ${directory}`);
278
+ const first = [];
279
+ if (variables.length > 0)
280
+ first.push(`set ${variables.join(", ")} in .env the gateway sends ${variables.length === 1 ? "it" : "them"} to your API`);
281
+ // Without uv, the Python packages are left to the developer's own shell: a Python started from here could pick
282
+ // packages for another processor, such as when Node runs under Rosetta on an Apple silicon Mac.
283
+ if (kind === "python" && !project.uv)
284
+ first.push("python3 -m venv .venv && .venv/bin/pip install -r requirements.txt installs the API's packages, once");
285
+ const starts = { wrap: "the gateway in front of your API,", typescript: "the service", python: "the API and the gateway in front of it," }[kind];
286
+ const steps = testnet
287
+ ? [
288
+ `cd ${shellWord(folder)}`,
289
+ ...first,
290
+ `npm run dev starts ${starts} at http://localhost:8787${payTo === undefined ? ": no wallet needed yet" : ""}`,
291
+ "npm run try pays for one call with test money, from another terminal",
292
+ "npm run launch takes it live: one approval in your wallet, then Fly.io",
293
+ ]
294
+ : [
295
+ `cd ${shellWord(folder)}`,
296
+ ...first,
297
+ `set FACILITATOR_AUTH in .env mainnet's facilitator key, as "Bearer <key>": ${FACILITATOR_KEYS}`,
298
+ "npm run launch takes it live on mainnet: one approval in your wallet (with a few XLM), then Fly.io",
299
+ `npm run dev starts ${starts} at http://localhost:8787${payTo === undefined ? ", once launch has set PAY_TO" : ""}`,
300
+ ];
301
+ io.log(`\nNext:\n${steps.map((line) => ` ${line}`).join("\n")}\n\nnpm run status shows where it stands at any time. README.md has the rest.`);
302
+ return 0;
303
+ }
304
+ /** The wrap kind's config: `provider-kit init` from the OpenAPI document or for the one URL, made to run anywhere. */
305
+ async function gatewayFromInit(answers, project, io) {
306
+ const { directory } = answers;
307
+ const source = answers.source;
308
+ const out = join(directory, "provider.config.json");
309
+ const init = (args) => io.run(process.execPath, [KIT_CLI, "init", ...args, "--out", "provider.config.json"], { cwd: directory });
310
+ let result;
311
+ if ("openapi" in source) {
312
+ const document = /^https?:\/\//i.test(source.openapi) ? source.openapi : resolve(source.openapi);
313
+ result = await init(["--openapi", document, ...(source.upstream === undefined ? [] : ["--upstream", source.upstream])]);
314
+ // init's own next steps are for a config on its own; this project's come at the end.
315
+ const shown = result.output.split("\n");
316
+ const next = shown.findIndex((line) => line === "Next:");
317
+ const lines = shown.slice(0, next === -1 ? undefined : next).join("\n").trimEnd().split("\n");
318
+ io.log(`\n${lines.map((line) => (line === "" ? line : ` ${line}`)).join("\n")}\n`);
319
+ if (result.code !== 0 && existsSync(out))
320
+ await rm(out);
321
+ }
322
+ const fromDocument = result !== undefined && result.code === 0;
323
+ if (!fromDocument) {
324
+ const url = "upstream" in source && !("openapi" in source) ? source.upstream : undefined;
325
+ const starter = await init(url === undefined ? [] : ["--upstream", url]);
326
+ if (starter.code !== 0)
327
+ throw new Error(`provider-kit init failed:\n${tail(starter.output)}`);
328
+ io.log(result === undefined
329
+ ? ` ✓ provider.config.json: a service to edit, my-service, which calls ${url}`
330
+ : " ! provider.config.json is a starter instead, with one service to edit: see the reason above");
331
+ }
332
+ const adapted = adaptInitConfig(await readFile(out, "utf8"), {
333
+ ...(answers.name !== undefined || !fromDocument ? { name: project.name } : {}),
334
+ ...(answers.description === undefined ? {} : { description: answers.description }),
335
+ price: project.price,
336
+ }, project.network);
337
+ await writeFile(out, adapted.config);
338
+ const config = JSON.parse(adapted.config);
339
+ const names = config.services.map((service) => service.name);
340
+ return {
341
+ name: config.provider.name,
342
+ description: config.provider.description ?? "",
343
+ variables: adapted.variables,
344
+ services: `${names.length === 1 ? "1 service" : `${names.length} services`}: ${names.join(", ")}`,
345
+ ...(config.services[0]?.upstream.url.startsWith("http") ? { upstream: new URL(config.services[0].upstream.url).origin } : {}),
346
+ };
347
+ }
348
+ /** Packs each kit package from the clone into vendor/, and returns the file names. */
349
+ async function pack(io, directory) {
350
+ if (io.kit.from !== "clone")
351
+ return {};
352
+ const vendor = join(directory, "vendor");
353
+ await mkdir(vendor, { recursive: true });
354
+ const files = {};
355
+ for (const name of KIT_PACKAGES) {
356
+ const result = await io.run("npm", ["pack", "--json", "--pack-destination", vendor], { cwd: join(io.kit.packages, name) });
357
+ if (result.code !== 0)
358
+ throw new Error(`npm pack failed for ${name}:\n${tail(result.output)}`);
359
+ const parsed = JSON.parse(result.output.slice(result.output.indexOf("[")));
360
+ files[name] = basename(parsed[0].filename);
361
+ }
362
+ return files;
363
+ }
364
+ /**
365
+ * Sets up the account clients pay: `provider-kit trustline` opens a page where the developer's own wallet approves a
366
+ * USDC trustline on the project's network, then prints the account as PAY_TO=G.... Its address, or undefined if it
367
+ * didn't finish.
368
+ */
369
+ async function connectWallet(io, directory, network) {
370
+ io.log("\nSetting up the account clients pay, in your wallet:\n");
371
+ // Ctrl+C on the approval page stops provider-kit trustline, not the rest of this.
372
+ const ignore = () => { };
373
+ process.on("SIGINT", ignore);
374
+ try {
375
+ const result = await io.run(process.execPath, [KIT_CLI, "trustline", "--network", network === "stellar:testnet" ? "testnet" : "mainnet"], { cwd: directory, echo: true });
376
+ const address = /PAY_TO=(G[A-Z2-7]{55})\b/.exec(result.output)?.[1];
377
+ if (result.code === 0 && address !== undefined) {
378
+ io.log(` ✓ PAY_TO=${address} in .env`);
379
+ return address;
380
+ }
381
+ }
382
+ finally {
383
+ process.off("SIGINT", ignore);
384
+ }
385
+ io.log(" ! The account wasn't set up. npm run launch sets it up when the service goes live.");
386
+ return undefined;
387
+ }
388
+ /** Asks until `check` passes, or takes `given` (from a flag or argument), or `fallback` when not asking. */
389
+ async function askUntil(io, asking, given, question, fallback, check) {
390
+ if (given !== undefined || !asking) {
391
+ const value = given ?? fallback;
392
+ const problem = check(value);
393
+ if (problem !== undefined)
394
+ throw new UsageError(problem);
395
+ return value;
396
+ }
397
+ for (;;) {
398
+ const value = (await io.ask(question)) || fallback;
399
+ const problem = check(value);
400
+ if (problem === undefined)
401
+ return value;
402
+ io.log(` ${problem}`);
403
+ }
404
+ }
405
+ /** What to make: --kind, else a question. */
406
+ async function askKind(flag, asking, io) {
407
+ if (flag !== undefined) {
408
+ const kind = parseKind(flag);
409
+ if (kind === undefined)
410
+ throw new UsageError(`--kind must be wrap, typescript or python, not "${flag}"`);
411
+ return kind;
412
+ }
413
+ if (!asking)
414
+ throw new UsageError("--kind is needed when there are no questions: wrap, typescript or python");
415
+ const menu = Object.values(KINDS).map((label, index) => ` ${index + 1}. ${label}`);
416
+ io.log(`What are you making?\n${menu.join("\n")}`);
417
+ return parseKind(await askUntil(io, true, undefined, "Pick 1, 2 or 3 [1]: ", "1", (value) => (parseKind(value) === undefined ? "answer 1, 2 or 3" : undefined)));
418
+ }
419
+ function parseKind(value) {
420
+ const kinds = Object.keys(KINDS);
421
+ return kinds.find((kind, index) => value === kind || value === String(index + 1));
422
+ }
423
+ /** An answer that names a document (a file, or a URL that looks like one) or else the URL a paid call goes to. */
424
+ export function classify(answer) {
425
+ if (!/^https?:\/\//i.test(answer))
426
+ return { openapi: answer };
427
+ const path = new URL(answer).pathname;
428
+ return /openapi|swagger|api-docs|schema|\.(json|ya?ml)$/i.test(path) ? { openapi: answer } : { upstream: answer };
429
+ }
430
+ /** Why the document can't be read now, or undefined. Checked before anything is written. */
431
+ async function unreadable(source, fetcher) {
432
+ if (!/^https?:\/\//i.test(source))
433
+ return existsSync(source) ? undefined : "there's no such file";
434
+ try {
435
+ const response = await fetcher(source, { signal: AbortSignal.timeout(10_000) });
436
+ await response.body?.cancel();
437
+ return response.ok ? undefined : `it answered ${response.status}`;
438
+ }
439
+ catch (error) {
440
+ const cause = error.cause?.code;
441
+ return cause === "ECONNREFUSED" ? "nothing answers there" : error.message;
442
+ }
443
+ }
444
+ /** Runs one step: " … label" while it runs, on a terminal, then " ✓ label", or " ✗ label" and the error. */
445
+ async function step(io, label, work) {
446
+ io.status(` … ${label}`);
447
+ try {
448
+ const value = await work();
449
+ io.status("");
450
+ io.log(` ✓ ${label}`);
451
+ return value;
452
+ }
453
+ catch (error) {
454
+ io.status("");
455
+ io.log(` ✗ ${label}`);
456
+ throw error;
457
+ }
458
+ }
459
+ async function writeAt(directory, file, text) {
460
+ const path = join(directory, file);
461
+ await mkdir(dirname(path), { recursive: true });
462
+ await writeFile(path, text);
463
+ }
464
+ function runProgram(command, args, options) {
465
+ return new Promise((done, fail) => {
466
+ // npm is npm.cmd on Windows, which only a shell runs.
467
+ const child = spawn(command, args, { cwd: options.cwd, stdio: ["inherit", "pipe", "pipe"], shell: process.platform === "win32" && command === "npm" });
468
+ let output = "";
469
+ child.stdout.on("data", (chunk) => {
470
+ output += chunk.toString();
471
+ if (options.echo)
472
+ process.stdout.write(chunk);
473
+ });
474
+ child.stderr.on("data", (chunk) => {
475
+ output += chunk.toString();
476
+ if (options.echo)
477
+ process.stderr.write(chunk);
478
+ });
479
+ child.on("error", fail);
480
+ child.on("close", (code) => done({ code: code ?? 1, output }));
481
+ });
482
+ }
483
+ /** An npm package name from a folder name. */
484
+ export function packageName(folder) {
485
+ return folder.toLowerCase().replace(/[^a-z0-9._~-]+/g, "-").replace(/^[._-]+|-+$/g, "") || "stellar-service";
486
+ }
487
+ /** A Fly.io app name from a folder name: lowercase letters, digits and dashes, starting with a letter. */
488
+ export function flyAppName(folder) {
489
+ const name = folder.toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/-+/g, "-").replace(/^[^a-z]+|-+$/g, "").slice(0, 63);
490
+ return name === "" ? "stellar-service" : name;
491
+ }
492
+ /** "my-stellar-service" as a name: "My Stellar Service". */
493
+ export function titleCase(folder) {
494
+ return folder
495
+ .split(/[-_\s]+/)
496
+ .filter(Boolean)
497
+ .map((word) => word[0].toUpperCase() + word.slice(1))
498
+ .join(" ");
499
+ }
500
+ function shellWord(value) {
501
+ return /^[\w@%+=:,./-]+$/.test(value) ? value : `'${value.replaceAll("'", "'\\''")}'`;
502
+ }
503
+ function clip(value, max) {
504
+ return value.length > max ? `${value.slice(0, max - 1)}…` : value;
505
+ }
506
+ /** The last lines of a program's output, for an error message. */
507
+ function tail(output, lines = 15) {
508
+ return output.trimEnd().split("\n").slice(-lines).join("\n");
509
+ }
510
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,26 @@
1
1
  {
2
2
  "name": "create-stellar-service",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "description": "npm create stellar-service: a new paid AI service on Stellar, or an existing API made one, ready to run, try and deploy (Provider Standard v1, x402 USDC).",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/AlgoriaLabs/stellar-agent-services.git",
10
+ "directory": "packages/create-stellar-service"
11
+ },
12
+ "engines": {
13
+ "node": ">=22.13"
14
+ },
15
+ "bin": {
16
+ "create-stellar-service": "./dist/index.js"
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "templates",
21
+ "!dist/.tsbuildinfo"
22
+ ],
23
+ "scripts": {
24
+ "build": "tsc -b"
25
+ }
26
+ }
@@ -0,0 +1,36 @@
1
+ # {{name}} on Fly.io (https://fly.io/docs/reference/configuration/).
2
+ #
3
+ # Its public address is https://{{app}}.fly.dev, known before the first deploy, so `npm run launch` registers the service
4
+ # with it, writes PUBLIC_ORIGIN, PAY_TO and AGENT_ID under [env], and deploys. If the name is taken, change "app" first.
5
+ # Only public values go in this file. Your API's own key goes in Fly's secrets: launch stages it from .env.
6
+
7
+ app = "{{app}}"
8
+ primary_region = "iad"
9
+
10
+ [build]
11
+ dockerfile = "Dockerfile"
12
+
13
+ [env]
14
+ JOB_DB_PATH = "/data/jobs.sqlite"
15
+
16
+ # Paid jobs live in SQLite on this volume, so a client can still collect a result after a restart. Fly makes the volume
17
+ # on the first deploy; one machine holds it.
18
+ [[mounts]]
19
+ source = "jobs"
20
+ destination = "/data"
21
+ initial_size = "1gb"
22
+
23
+ [http_service]
24
+ internal_port = 8787
25
+ force_https = true
26
+ # Queued jobs run in the background, and uncertain payments are settled from the chain: keep the machine running.
27
+ auto_stop_machines = "off"
28
+ auto_start_machines = true
29
+ min_machines_running = 1
30
+
31
+ [[http_service.checks]]
32
+ grace_period = "20s"
33
+ interval = "30s"
34
+ method = "GET"
35
+ path = "/healthz"
36
+ timeout = "5s"
@@ -0,0 +1,24 @@
1
+ # {{name}}: the Provider Kit gateway in front of your API, with its job database, on any host that runs a container.
2
+ #
3
+ # docker build -t {{package}} .
4
+ # docker run -p 8787:8787 -v {{package}}-jobs:/data -e PAY_TO=G... -e PUBLIC_ORIGIN=https://your.domain {{package}}
5
+ #
6
+ # In the container, 127.0.0.1 is the container itself: point each upstream.url in provider.config.json at an address
7
+ # the container reaches your API on. Paid jobs are kept in /data/jobs.sqlite: give /data a persistent volume. The
8
+ # image holds no Stellar secret key.
9
+
10
+ FROM node:24-slim
11
+ ENV NODE_ENV=production JOB_DB_PATH=/data/jobs.sqlite
12
+ WORKDIR /app
13
+ COPY package.json package-lock.json ./
14
+ {{vendor}}
15
+ RUN npm ci --omit=dev --ignore-scripts && npm cache clean --force
16
+ COPY provider.config.json ./
17
+ RUN mkdir -p /data && chown node:node /data
18
+ VOLUME /data
19
+ EXPOSE 8787
20
+ HEALTHCHECK --interval=30s --timeout=5s CMD node -e "fetch('http://127.0.0.1:' + (process.env.PORT || 8787) + '/healthz').then((r) => process.exit(r.ok ? 0 : 1), () => process.exit(1))"
21
+ # A host's new volume may belong to root, as Fly.io's do: started as root, the container only gives /data to the node
22
+ # user, then runs the service as node. Started as another user, it runs as that user.
23
+ ENTRYPOINT ["sh", "-c", "if [ \"$(id -u)\" = 0 ]; then chown node:node /data 2>/dev/null || true; exec setpriv --reuid=node --regid=node --init-groups -- \"$@\"; fi; exec \"$@\"", "sh"]
24
+ CMD ["node", "node_modules/@stellar-agent-services/provider-kit/dist/cli/index.js", "serve", "--config", "provider.config.json"]