@myapihq/cli 2.7.0 → 2.7.1
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/commands/container.js +50 -26
- package/dist/commands/database.js +21 -14
- package/dist/commands/fn.js +3 -3
- package/dist/skills/my-container-api/SKILL.md +26 -30
- package/dist/skills/my-database-api/README.md +1 -1
- package/dist/skills/my-database-api/SKILL.md +4 -4
- package/dist/skills/my-function-api/SKILL.md +10 -10
- package/dist/skills/my-git-api/SKILL.md +4 -4
- package/package.json +2 -2
|
@@ -133,7 +133,7 @@ export async function create(nameArg, flags) {
|
|
|
133
133
|
info(`Name: ${result.container.name}`);
|
|
134
134
|
info(`Type: ${result.container.type}${result.container.cron_schedule ? ` (${result.container.cron_schedule})` : ''}`);
|
|
135
135
|
info(`Resources: ${result.container.cpu} CPU, ${result.container.memory}, instances ${result.container.min_instances}-${result.container.max_instances}`);
|
|
136
|
-
// The scoped key is returned ONCE — it's delivered to the running
|
|
136
|
+
// The scoped API key is returned ONCE — it's delivered to the running
|
|
137
137
|
// container as the MYAPI_KEY env var. Deploy rotates it.
|
|
138
138
|
info('');
|
|
139
139
|
info(`Scoped API key (returned once — save it if you need it):`);
|
|
@@ -221,6 +221,36 @@ export async function deploy(id, image, flags) {
|
|
|
221
221
|
const orgId = requireOrg(flags, config, 'myapi container deploy <id> <image-ref> | --source <dir|tar> [--org <id>]');
|
|
222
222
|
if (!id)
|
|
223
223
|
error('Missing id.\nUsage: myapi container deploy <id> <image-ref> (or --source <dir|tar>)');
|
|
224
|
+
// --no-promote and --smoke are REFUSED, not honoured, as of 2026-07-28.
|
|
225
|
+
//
|
|
226
|
+
// They shipped in 2.7.0 and do not work on either deploy path. A customer
|
|
227
|
+
// found it by testing rather than trusting the flags, which is the outcome
|
|
228
|
+
// this CLI spends most of its error messages trying to prevent:
|
|
229
|
+
//
|
|
230
|
+
// --source: the multipart body accepts only `source`. The flags were
|
|
231
|
+
// silently dropped — accepted by our flag parser, never sent. That was
|
|
232
|
+
// our bug, and it is the exact failure these flags exist to stop.
|
|
233
|
+
//
|
|
234
|
+
// image ref: the API accepts promote/smoke, then the deploy fails with a
|
|
235
|
+
// runtime error setting traffic to the revision it just created. The
|
|
236
|
+
// previous revision keeps serving, so it is safe, but it does not work.
|
|
237
|
+
//
|
|
238
|
+
// Refusing is strictly better than accepting. A missing guard makes people
|
|
239
|
+
// write their own; a guard that silently passes makes them stop. Restore
|
|
240
|
+
// these the moment the upstream fix lands — see
|
|
241
|
+
// docs/cross-repo-prompts/backend-consolidated-2026-07-28.md.
|
|
242
|
+
if (flags['no-promote'] === true || typeof flags.smoke === 'string') {
|
|
243
|
+
const which = flags['no-promote'] === true ? '--no-promote' : '--smoke';
|
|
244
|
+
error(`${which} is not honoured yet, so this CLI refuses it rather than letting you believe a deploy was guarded.\n\n` +
|
|
245
|
+
'It shipped in 2.7.0 and does not work end to end on either deploy path:\n' +
|
|
246
|
+
' --source the API accepts only the tarball on that path; the flag never reaches it\n' +
|
|
247
|
+
' <image-ref> the API accepts the flag, then fails while moving traffic\n\n' +
|
|
248
|
+
'Until it lands, the safe sequence is:\n' +
|
|
249
|
+
` 1. deploy to a non-production container first\n` +
|
|
250
|
+
` 2. check it yourself (curl for a string only a real build emits)\n` +
|
|
251
|
+
` 3. deploy the same image to production\n\n` +
|
|
252
|
+
'Reported upstream; this message goes away when the flag works.');
|
|
253
|
+
}
|
|
224
254
|
const source = typeof flags.source === 'string' ? flags.source : undefined;
|
|
225
255
|
// --image is an alias for the positional image ref.
|
|
226
256
|
if (!image && typeof flags.image === 'string')
|
|
@@ -290,15 +320,10 @@ export async function deploy(id, image, flags) {
|
|
|
290
320
|
// ── Pre-built image path (sync) ─────────────────────────────────────────
|
|
291
321
|
if (!image)
|
|
292
322
|
error('Missing image ref.\nUsage: myapi container deploy <id> <image-ref>\n or: myapi container deploy <id> --source <dir|tar>\n\n→ <image-ref> is a pre-built container image (e.g. a registry path).');
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
opts.smoke = _parseSmoke(flags.smoke);
|
|
298
|
-
if (opts.promote === false && opts.smoke) {
|
|
299
|
-
error('--smoke already withholds traffic until the check passes, then promotes.\nUse one or the other: --smoke to verify-and-promote, --no-promote to hold the revision back.');
|
|
300
|
-
}
|
|
301
|
-
const result = await sdkContainer.deployContainer(config.api_key, orgId, id, image, opts);
|
|
323
|
+
// No DeployOptions built here: --no-promote and --smoke are refused above
|
|
324
|
+
// until the upstream fix lands. The SDK still carries them so the wiring is
|
|
325
|
+
// one commit away, and sdk-container.test.ts keeps them covered.
|
|
326
|
+
const result = await sdkContainer.deployContainer(config.api_key, orgId, id, image);
|
|
302
327
|
if (flags.json) {
|
|
303
328
|
printJson(result);
|
|
304
329
|
return;
|
|
@@ -306,6 +331,9 @@ export async function deploy(id, image, flags) {
|
|
|
306
331
|
// An unpromoted revision must NOT read like a completed deploy. A response
|
|
307
332
|
// that looked the same either way is how an agent concludes it has shipped
|
|
308
333
|
// when it has not — the original outage in miniature.
|
|
334
|
+
// Unreachable while the flags are refused above. Kept because it is the
|
|
335
|
+
// render we want the moment they are restored, and deleting it would mean
|
|
336
|
+
// rewriting it from memory later.
|
|
309
337
|
if (result.promoted === false) {
|
|
310
338
|
success(`Revision ${result.revision_id} built — NOT serving traffic`);
|
|
311
339
|
info(`Test it: ${result.revision_url ?? '(no revision URL returned)'}`);
|
|
@@ -392,8 +420,10 @@ export async function revisions(id, flags) {
|
|
|
392
420
|
if (revs.length > 0 && revs.every(r => !r.serving && !r.traffic_percent) && container?.status === 'active') {
|
|
393
421
|
info('');
|
|
394
422
|
info('Note: every revision reports 0% traffic while this container is active and serving.');
|
|
395
|
-
info('
|
|
396
|
-
info('
|
|
423
|
+
info('The traffic column is wrong, not the container. Verified on a container created');
|
|
424
|
+
info('today, so this is not limited to older ones — an earlier version of this message');
|
|
425
|
+
info('said redeploying fixes it, which was wrong.');
|
|
426
|
+
info('promote depends on this data and currently fails. Reported upstream.');
|
|
397
427
|
}
|
|
398
428
|
}
|
|
399
429
|
// promote moves all traffic to one revision. Omitting the revision rolls back
|
|
@@ -535,23 +565,19 @@ Two ways to deploy:
|
|
|
535
565
|
built server-side (typically ~4 minutes), then deployed.
|
|
536
566
|
Asynchronous — the CLI polls until it's live.
|
|
537
567
|
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
previous revision serving.
|
|
568
|
+
TEMPORARILY REFUSED: --no-promote and --smoke
|
|
569
|
+
|
|
570
|
+
Both shipped in 2.7.0 and do not work end to end. Rather than accept a flag
|
|
571
|
+
and deploy anyway, the CLI now refuses them and explains what to do instead.
|
|
572
|
+
A guard that silently passes is worse than no guard.
|
|
544
573
|
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
true of a placeholder page too.
|
|
574
|
+
Until they land: deploy to a non-production container, verify it yourself,
|
|
575
|
+
then deploy the same image to production.
|
|
548
576
|
|
|
549
577
|
Examples:
|
|
550
578
|
myapi container deploy <id> registry.example.com/my-app:v2
|
|
551
579
|
myapi container deploy <id> --source ./my-app
|
|
552
|
-
myapi container deploy <id> --source ./context.tar.gz
|
|
553
|
-
myapi container deploy <id> <image> --no-promote
|
|
554
|
-
myapi container deploy <id> <image> --smoke 'GET / contains assets/'`,
|
|
580
|
+
myapi container deploy <id> --source ./context.tar.gz`,
|
|
555
581
|
'revisions': `myapi container revisions <id> [--org <id>] [--json]
|
|
556
582
|
|
|
557
583
|
Every revision the runtime currently holds, newest first, with the traffic
|
|
@@ -595,10 +621,8 @@ dependencies and long execution.
|
|
|
595
621
|
Subcommands:
|
|
596
622
|
build-logs <id> Why the last --source build failed (--tail N; default 100)
|
|
597
623
|
create Register a container and get its scoped API key (returned once)
|
|
598
|
-
(--health-check /livez to probe with HTTP, not a bare TCP connect)
|
|
599
624
|
delete <id> Soft-delete and revoke its scoped API key
|
|
600
625
|
deploy <id> <image> Ship a pre-built image (or --source <dir|tar> to build) and go live
|
|
601
|
-
(--no-promote to hold it back; --smoke to verify before promoting)
|
|
602
626
|
domain <id> <domain> Bind a custom domain (--remove to unbind)
|
|
603
627
|
get <id> Inspect a container
|
|
604
628
|
list List containers in your org
|
|
@@ -106,8 +106,8 @@ async function nsDelete(name, flags) {
|
|
|
106
106
|
// ── Keys ─────────────────────────────────────────────────────────────────
|
|
107
107
|
async function keysList(flags) {
|
|
108
108
|
const config = requireConfig();
|
|
109
|
-
const orgId = requireOrg(flags, config, 'myapi database
|
|
110
|
-
const ns = requireNs(flags, 'myapi database
|
|
109
|
+
const orgId = requireOrg(flags, config, 'myapi database entries --ns <ns> [--prefix <p>] [--limit N] [--values] [--cursor <c>] [--org <id>]');
|
|
110
|
+
const ns = requireNs(flags, 'myapi database entries --ns <ns> [--prefix <p>] [--limit N] [--values]');
|
|
111
111
|
const opts = {};
|
|
112
112
|
if (typeof flags.prefix === 'string')
|
|
113
113
|
opts.prefix = flags.prefix;
|
|
@@ -197,12 +197,16 @@ const SUBCOMMAND_USAGE = {
|
|
|
197
197
|
'create': 'myapi database create <name> [--org <id>]',
|
|
198
198
|
'delete-namespace': `myapi database delete-namespace <name> [--org <id>]
|
|
199
199
|
|
|
200
|
-
Deletes the namespace AND all
|
|
201
|
-
'
|
|
200
|
+
Deletes the namespace AND all entries in it. Irreversible.`,
|
|
201
|
+
'entries': `myapi database entries --ns <namespace> [--prefix <p>] [--limit N] [--values] [--cursor <c>] [--org <id>] [--json]
|
|
202
202
|
|
|
203
|
-
Default render is one key per line. --values inlines each value
|
|
204
|
-
its key + etag. --cursor takes the next_cursor printed at the end
|
|
205
|
-
previous page
|
|
203
|
+
Default render is one entry key per line. --values inlines each value
|
|
204
|
+
alongside its key + etag. --cursor takes the next_cursor printed at the end
|
|
205
|
+
of a previous page.
|
|
206
|
+
|
|
207
|
+
(\`myapi database keys\` still works. It was renamed because "key" also means
|
|
208
|
+
an API credential everywhere else on the platform, and an agent reading
|
|
209
|
+
"list keys" could not tell which was meant.)`,
|
|
206
210
|
'get': `myapi database get <key> --ns <namespace> [--org <id>] [--json]
|
|
207
211
|
|
|
208
212
|
Prints the value as compact JSON on stdout; etag + updated_at go to
|
|
@@ -226,17 +230,17 @@ export async function run(subcommand, args, flags) {
|
|
|
226
230
|
|
|
227
231
|
Namespaces:
|
|
228
232
|
create <name> Create a namespace
|
|
229
|
-
delete-namespace <name> Delete a namespace AND all its
|
|
233
|
+
delete-namespace <name> Delete a namespace AND all its entries (irreversible)
|
|
230
234
|
namespaces List namespaces in the org
|
|
231
235
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
get <key> Get
|
|
235
|
-
set <key> <value-json> Set
|
|
236
|
-
del <key> Delete
|
|
236
|
+
Entries (require --ns <namespace>):
|
|
237
|
+
entries List entries in a namespace
|
|
238
|
+
get <key> Get an entry's value + etag
|
|
239
|
+
set <key> <value-json> Set an entry. Value is JSON; CAS via --if-match
|
|
240
|
+
del <key> Delete an entry (CAS via --if-match)
|
|
237
241
|
|
|
238
242
|
All commands accept --org <id> (or set default: myapi config set-org <id>).
|
|
239
|
-
Values are JSON; per-
|
|
243
|
+
Values are JSON; per-entry size cap is 256 KB. Use myapi storage for binary.`);
|
|
240
244
|
return;
|
|
241
245
|
}
|
|
242
246
|
if (flags.help) {
|
|
@@ -251,6 +255,9 @@ Values are JSON; per-key size cap is 256 KB. Use myapi storage for binary.`);
|
|
|
251
255
|
case 'namespaces': return nsList(flags);
|
|
252
256
|
case 'create': return nsCreate(args[0], flags);
|
|
253
257
|
case 'delete-namespace': return nsDelete(args[0], flags);
|
|
258
|
+
// `keys` kept as an undocumented alias: renaming a verb people have in
|
|
259
|
+
// scripts should not break them. Dropped no earlier than the next minor.
|
|
260
|
+
case 'entries':
|
|
254
261
|
case 'keys': return keysList(flags);
|
|
255
262
|
case 'get': return keyGet(args[0], flags);
|
|
256
263
|
case 'set': return keySet(args[0], args[1], flags);
|
package/dist/commands/fn.js
CHANGED
|
@@ -22,7 +22,7 @@ export const SCHEMA = {
|
|
|
22
22
|
scope: 'list',
|
|
23
23
|
set: 'string',
|
|
24
24
|
};
|
|
25
|
-
// Backend: Story 1 (function CRUD + scoped key) and Story 2/4/5 (deploy a
|
|
25
|
+
// Backend: Story 1 (function CRUD + scoped API key) and Story 2/4/5 (deploy a
|
|
26
26
|
// JS bundle to the edge runtime, list runs, set env secrets).
|
|
27
27
|
// Mirrors validateName in myapi-hq/internal/routes/function/crud.go. We
|
|
28
28
|
// pre-validate client-side so typos fail before the network call; backend
|
|
@@ -89,7 +89,7 @@ export async function create(nameArg, flags) {
|
|
|
89
89
|
success(`Function created: ${result.function.id}`);
|
|
90
90
|
info(`Name: ${result.function.name}`);
|
|
91
91
|
info(`Trigger: ${result.function.trigger_type}${result.function.cron_schedule ? ` (${result.function.cron_schedule})` : ''}`);
|
|
92
|
-
// The scoped key is returned ONCE — surface it prominently. It's used by
|
|
92
|
+
// The scoped API key is returned ONCE — surface it prominently. It's used by
|
|
93
93
|
// the function runtime shim to call other slot endpoints without a
|
|
94
94
|
// baked-in auth token. Deploy rotates this key.
|
|
95
95
|
info('');
|
|
@@ -205,7 +205,7 @@ async function waitForLive(url, budgetMs = 75_000) {
|
|
|
205
205
|
clearLine();
|
|
206
206
|
info(`Status: not serving yet after ${Math.round(budgetMs / 1000)}s.`);
|
|
207
207
|
info(` The deploy itself succeeded — give it another minute.`);
|
|
208
|
-
info(` Do NOT redeploy to "fix" it: that rotates the scoped key again.`);
|
|
208
|
+
info(` Do NOT redeploy to "fix" it: that rotates the scoped API key again.`);
|
|
209
209
|
}
|
|
210
210
|
// _parseSetPairs parses `--set K=V` entries into a map. Accepts a single
|
|
211
211
|
// string (comma-joined: K=V,K2=V2) or an array of strings (when the flag is
|
|
@@ -4,7 +4,7 @@ version: 1.0.0
|
|
|
4
4
|
description: >
|
|
5
5
|
Run containers on demand — long-running services, background workers, and scheduled jobs. The heavier-duty sibling of edge functions, for native deps and long execution.
|
|
6
6
|
triggers: [container, cloud run, dynamic app, custom domain app, service, worker, scheduled job, deploy container, docker image]
|
|
7
|
-
checksum: sha256-
|
|
7
|
+
checksum: sha256-3864bbb98fab89ba9e937c38bed072e22f33663ec7cbc23a43f24192275bcffd
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# MyContainerAPI
|
|
@@ -19,22 +19,26 @@ The lifecycle is **create → deploy → (optionally) bind a custom domain**.
|
|
|
19
19
|
- `deploy` ships a pre-built image reference to the runtime and makes the container live at a generated URL.
|
|
20
20
|
- `domain` puts the container on a **custom domain** — how you serve a dynamic app at `app.yourbrand.com`.
|
|
21
21
|
|
|
22
|
-
### Deploying safely
|
|
22
|
+
### Deploying safely — NOT YET POSSIBLE ON THIS PLATFORM
|
|
23
23
|
|
|
24
|
-
A deploy takes 100% of traffic the moment it lands
|
|
25
|
-
|
|
24
|
+
A deploy takes 100% of traffic the moment it lands. There is no dry run, no
|
|
25
|
+
definition of correct beyond "something is listening on the port", and no way
|
|
26
|
+
back. Plan for that.
|
|
26
27
|
|
|
27
|
-
- `--smoke
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
- `--no-promote` — build the revision and hold it back. You get a URL to
|
|
32
|
-
exercise it, then `myapi container promote <id> <revision>`.
|
|
28
|
+
`--no-promote` and `--smoke` exist as flags and **the CLI refuses them**: they
|
|
29
|
+
shipped before the platform could honour them, and a guard that silently
|
|
30
|
+
passes is worse than no guard. `--health-check` is accepted at create but does
|
|
31
|
+
not appear on the container afterwards, so do not rely on it either.
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
Until they work, the only safe sequence is:
|
|
34
|
+
|
|
35
|
+
1. deploy to a **non-production** container
|
|
36
|
+
2. verify it yourself — `curl` for a string only a real build emits, not just
|
|
37
|
+
a 200, because a broken build returns 200 too
|
|
38
|
+
3. deploy the same image to production
|
|
39
|
+
|
|
40
|
+
`myapi container promote <id> <revision>` currently fails, so a bad deploy
|
|
41
|
+
must be fixed by deploying forward. Keep a known-good image reference to hand.
|
|
38
42
|
|
|
39
43
|
### Custom domains (dynamic apps)
|
|
40
44
|
|
|
@@ -53,7 +57,7 @@ Get it right:
|
|
|
53
57
|
| Command | What it does |
|
|
54
58
|
|---|---|
|
|
55
59
|
| `myapi container create --name <name> [--type service\|worker\|job] [--cron <expr>] [--cpu <n>] [--memory <size>] [--port <n>] [--env K=V,...]` | Register a container, get its scoped API key (once) |
|
|
56
|
-
| `myapi container deploy <id> <image-ref> [--no-promote] [--smoke '<assertion>']` | Ship a pre-built image (rotates the scoped key) |
|
|
60
|
+
| `myapi container deploy <id> <image-ref> [--no-promote] [--smoke '<assertion>']` | Ship a pre-built image (rotates the scoped API key) |
|
|
57
61
|
| `myapi container revisions <id>` | List revisions and the traffic each takes |
|
|
58
62
|
| `myapi container promote <id> <revision>` | Move all traffic to a revision (seconds, no rebuild) |
|
|
59
63
|
| `myapi container list` | List containers in your org |
|
|
@@ -66,25 +70,17 @@ Get it right:
|
|
|
66
70
|
## Examples
|
|
67
71
|
<!-- llm:start -->
|
|
68
72
|
```bash
|
|
69
|
-
# 1. Register a service container
|
|
70
|
-
|
|
71
|
-
myapi container create --name api --type service --port 8080 --health-check /livez
|
|
73
|
+
# 1. Register a service container
|
|
74
|
+
myapi container create --name api --type service --port 8080
|
|
72
75
|
# → prints a scoped API key ONCE — save it if your code needs it
|
|
73
76
|
|
|
74
|
-
#
|
|
77
|
+
# 2. Deploy. This takes 100% of traffic immediately — there is no staging
|
|
78
|
+
# step, so verify on a non-production container FIRST.
|
|
75
79
|
myapi container deploy <id> registry.example.com/my-app:v1
|
|
76
80
|
|
|
77
|
-
#
|
|
78
|
-
#
|
|
79
|
-
|
|
80
|
-
myapi container deploy <id> registry.example.com/my-app:v1 \
|
|
81
|
-
--smoke 'GET / contains assets/'
|
|
82
|
-
|
|
83
|
-
# 2c. Or hold it back and look yourself.
|
|
84
|
-
myapi container deploy <id> registry.example.com/my-app:v1 --no-promote
|
|
85
|
-
# → prints a revision URL serving 0% of traffic
|
|
86
|
-
myapi container revisions <id>
|
|
87
|
-
myapi container promote <id> <revision>
|
|
81
|
+
# 3. Check what you actually shipped. Assert on content: a build whose
|
|
82
|
+
# frontend never bundled still binds its port and returns 200.
|
|
83
|
+
curl -s https://<your-domain>/ | grep -q 'assets/' || echo "BROKEN BUILD"
|
|
88
84
|
|
|
89
85
|
# 3. Serve it on a custom domain. The parent domain must already be
|
|
90
86
|
# registered: myapi domain register synthesisdaily.com
|
|
@@ -15,7 +15,7 @@ Per-org KV store with namespaces. JSON values up to 256 KB per key. Compare-and-
|
|
|
15
15
|
myapi database create my-app
|
|
16
16
|
myapi database set users '{"alice":{"plan":"pro"}}' --ns my-app
|
|
17
17
|
myapi database get users --ns my-app
|
|
18
|
-
myapi database
|
|
18
|
+
myapi database entries --ns my-app --values
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
## Authentication
|
|
@@ -4,7 +4,7 @@ version: 1.0.0
|
|
|
4
4
|
description: >
|
|
5
5
|
Per-org KV store with named namespaces, JSON values up to 256 KB, prefix-scan listing, and compare-and-swap via etag. The substrate for any stateful agent-built app on MyAPI — user tables, session stores, idempotency keys, per-user lookup maps.
|
|
6
6
|
triggers: [database, kv, key value, namespace, store, state, etag, cas, session, idempotency]
|
|
7
|
-
checksum: sha256-
|
|
7
|
+
checksum: sha256-f098cb574a1773135b09cbe79bb75eb33e34b1dc90737aa80da2452bb53e972e
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# MyDatabaseAPI
|
|
@@ -51,7 +51,7 @@ Pass `--if-match <etag>` from a previous `get` to make `set` or `del` conditiona
|
|
|
51
51
|
| `myapi database namespaces [--json]` | List namespaces in the org |
|
|
52
52
|
| `myapi database create <name>` | Create a namespace |
|
|
53
53
|
| `myapi database delete-namespace <name>` | Delete namespace AND all its keys (irreversible) |
|
|
54
|
-
| `myapi database
|
|
54
|
+
| `myapi database entries --ns <ns> [--prefix <p>] [--limit N] [--values] [--cursor <c>]` | List keys, optionally with inline values |
|
|
55
55
|
| `myapi database get <key> --ns <ns>` | Get value + etag (etag printed to stderr) |
|
|
56
56
|
| `myapi database set <key> <value-json> --ns <ns> [--if-match <etag>] [--file <path>]` | Set key. CAS via --if-match |
|
|
57
57
|
| `myapi database del <key> --ns <ns> [--if-match <etag>]` | Delete key. CAS via --if-match |
|
|
@@ -62,7 +62,7 @@ Pass `-` as `<value-json>` to read the value from stdin, or `--file <path>` to r
|
|
|
62
62
|
## Examples
|
|
63
63
|
<!-- llm:start -->
|
|
64
64
|
```bash
|
|
65
|
-
# Create a namespace, set
|
|
65
|
+
# Create a namespace, set an entry, read it back
|
|
66
66
|
myapi database create my-app
|
|
67
67
|
myapi database set user:alice '{"plan":"pro","trial_ends":"2026-06-01"}' --ns my-app
|
|
68
68
|
myapi database get user:alice --ns my-app
|
|
@@ -70,7 +70,7 @@ myapi database get user:alice --ns my-app
|
|
|
70
70
|
# stderr: — etag=A1B2C3 · updated=2026-05-12T17:00:00Z
|
|
71
71
|
|
|
72
72
|
# List keys with a prefix
|
|
73
|
-
myapi database
|
|
73
|
+
myapi database entries --ns my-app --prefix user: --values
|
|
74
74
|
|
|
75
75
|
# Compare-and-swap update
|
|
76
76
|
ETAG=$(myapi database get user:alice --ns my-app --json | jq -r .etag)
|
|
@@ -4,7 +4,7 @@ version: 1.0.0
|
|
|
4
4
|
description: >
|
|
5
5
|
Deploy JavaScript functions to the MyAPI edge runtime. Register a function, upload a single-file JS bundle, get a live HTTP invocation URL or run it on a cron schedule. Each function gets a scoped capability key for cross-slot calls.
|
|
6
6
|
triggers: [function, deploy function, edge function, serverless, cloudflare worker, cron, scoped api key, capability key, invocation url, bundle]
|
|
7
|
-
checksum: sha256-
|
|
7
|
+
checksum: sha256-08524ea08e91dcb6c8b68b64a7b4034d24a98a18968acd4ba80e45dbd6f85d09
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# MyFunctionAPI
|
|
@@ -35,12 +35,12 @@ Name rules (validated client- and server-side, kept identical):
|
|
|
35
35
|
| Command | What it does |
|
|
36
36
|
|---|---|
|
|
37
37
|
| `myapi fn create --name <name> [--cron <expr>] [--scope <slot>[,<slot>...]]` | Register a function record + receive scoped API key (returned once). `--scope` narrows the key's slot grants |
|
|
38
|
-
| `myapi fn deploy <id> <bundle.js>` | Upload a single-file JS bundle (≤4MB) and go live; rotates the scoped key |
|
|
38
|
+
| `myapi fn deploy <id> <bundle.js>` | Upload a single-file JS bundle (≤4MB) and go live; rotates the scoped API key |
|
|
39
39
|
| `myapi fn env <id> <name> <value>` | Set an encrypted secret on a deployed function |
|
|
40
40
|
| `myapi fn runs <id>` | List recent invocation records (status, duration, errors) |
|
|
41
41
|
| `myapi fn list` | List functions in your org |
|
|
42
42
|
| `myapi fn get <id>` | Inspect a function (name, trigger, invocation URL) |
|
|
43
|
-
| `myapi fn delete <id>` | Soft-delete the record + revoke the scoped key |
|
|
43
|
+
| `myapi fn delete <id>` | Soft-delete the record + revoke the scoped API key |
|
|
44
44
|
<!-- generated:end -->
|
|
45
45
|
|
|
46
46
|
## Examples
|
|
@@ -50,9 +50,9 @@ Name rules (validated client- and server-side, kept identical):
|
|
|
50
50
|
myapi fn create --name my-app-api
|
|
51
51
|
# → Function created: fn_abc123
|
|
52
52
|
# Scoped API key (returned once — save it if you need it):
|
|
53
|
-
# hq_live_... (scoped keys are not visually distinct from account keys)
|
|
53
|
+
# hq_live_... (scoped API keys are not visually distinct from account keys)
|
|
54
54
|
|
|
55
|
-
# Deploy a single-file JS bundle → goes live, scoped key is rotated
|
|
55
|
+
# Deploy a single-file JS bundle → goes live, scoped API key is rotated
|
|
56
56
|
myapi fn deploy fn_abc123 ./dist/bundle.js
|
|
57
57
|
# → Deployed function fn_abc123
|
|
58
58
|
# Invocation URL: https://fn-abc123.<...>.workers.dev
|
|
@@ -74,17 +74,17 @@ myapi fn create --name mailer --scope email,storage
|
|
|
74
74
|
myapi fn list
|
|
75
75
|
myapi fn get fn_abc123
|
|
76
76
|
|
|
77
|
-
# Delete (revokes the scoped key — future calls with it return 401)
|
|
77
|
+
# Delete (revokes the scoped API key — future calls with it return 401)
|
|
78
78
|
myapi fn delete fn_abc123
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
-
### Using the scoped key
|
|
81
|
+
### Using the scoped API key
|
|
82
82
|
|
|
83
83
|
```bash
|
|
84
|
-
# Save the key returned at create/deploy time
|
|
84
|
+
# Save the API key returned at create/deploy time
|
|
85
85
|
SCOPED_KEY="hq_live_..."
|
|
86
86
|
|
|
87
|
-
# Call slots the key was granted — works (within its org + grants)
|
|
87
|
+
# Call slots the API key was granted — works (within its org + grants)
|
|
88
88
|
curl -H "Authorization: Bearer $SCOPED_KEY" \
|
|
89
89
|
https://api.myapihq.com/database/orgs/$ORG_ID/namespaces
|
|
90
90
|
|
|
@@ -99,6 +99,6 @@ curl -H "Authorization: Bearer $SCOPED_KEY" \
|
|
|
99
99
|
|
|
100
100
|
- The bundle is a **single JavaScript file** (≤4MB). Bundle your dependencies before deploy (esbuild/rollup/etc.).
|
|
101
101
|
- `--cron` is set at create time; the trigger type is fixed for the function's lifetime.
|
|
102
|
-
- Deploy rotates the scoped key on every call — re-capture the printed value if other systems use it.
|
|
102
|
+
- Deploy rotates the scoped API key on every call — re-capture the printed value if other systems use it.
|
|
103
103
|
|
|
104
104
|
Run `myapi fn --help` or `myapi fn <subcommand> --help` for full flag reference.
|
|
@@ -4,7 +4,7 @@ version: 1.0.0
|
|
|
4
4
|
description: >
|
|
5
5
|
Hosted git repositories over HTTP. Create repos, read history (log/show/tree/blob/diff), and write atomically (commit/branch/tag/merge) — no clone needed. Real `git clone`/`push` also work over HTTPS with your API key as the password.
|
|
6
6
|
triggers: [git, repo, repository, clone, push, commit, branch, tag, merge, diff, version control, source control, vcs]
|
|
7
|
-
checksum: sha256-
|
|
7
|
+
checksum: sha256-921cedea836edac33fefabfb46102e241d2618529db2e307cc73f4d910e7fee3
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# MyGitAPI
|
|
@@ -90,7 +90,7 @@ myapi git delete-branch my-app feature
|
|
|
90
90
|
### Clone & push with real git
|
|
91
91
|
Hosted repos speak the real git smart-HTTP protocol. Clone, fetch, and push
|
|
92
92
|
over HTTPS with **HTTP Basic auth — your MyAPI API key is the password**, any
|
|
93
|
-
username works (git accepts the key in either field).
|
|
93
|
+
username works (git accepts the API key in either field).
|
|
94
94
|
|
|
95
95
|
```bash
|
|
96
96
|
# URL: https://git.mygitapi.com/<org-slug>/<repo>.git
|
|
@@ -100,7 +100,7 @@ username works (git accepts the key in either field).
|
|
|
100
100
|
# Clone (key as password; "x" is a throwaway username)
|
|
101
101
|
git clone https://x:$MYAPI_KEY@git.mygitapi.com/my-org-slug/my-app.git
|
|
102
102
|
|
|
103
|
-
# Or set the remote and let git prompt for the password (paste the key)
|
|
103
|
+
# Or set the remote and let git prompt for the password (paste the API key)
|
|
104
104
|
git remote add origin https://git.mygitapi.com/my-org-slug/my-app.git
|
|
105
105
|
git push origin main
|
|
106
106
|
```
|
|
@@ -117,6 +117,6 @@ surface never leaks which repos exist).
|
|
|
117
117
|
- **`commit --base`** is the concurrency guard: pass the expected tip SHA to reject a stale write, or `--base ""` to require the branch be newly created. Omit it to create-or-update.
|
|
118
118
|
- **Metering.** A `git push` (and `myapi git commit`) is metered like a commit. Clone/fetch (`upload-pack`) is free.
|
|
119
119
|
- **Limits.** A push body is capped at 100 MiB; per-repo size limits apply (a push past the cap is reported as a receive-pack failure).
|
|
120
|
-
- **Auth field.** git may put the key in the username or password slot — both work. Embedding it in the URL (`https://x:$KEY@…`) avoids the interactive prompt but writes the key into `.git/config`; use a credential helper for anything persistent.
|
|
120
|
+
- **Auth field.** git may put the API key in the username or password slot — both work. Embedding it in the URL (`https://x:$KEY@…`) avoids the interactive prompt but writes the API key into `.git/config`; use a credential helper for anything persistent.
|
|
121
121
|
|
|
122
122
|
Run `myapi git --help` for the full flag reference.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@myapihq/cli",
|
|
3
3
|
"license": "Apache-2.0",
|
|
4
|
-
"version": "2.7.
|
|
4
|
+
"version": "2.7.1",
|
|
5
5
|
"description": "MyAPI command-line interface",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"lint:skills:strict": "node scripts/copy-skills.js && node scripts/lint-skills.js --strict"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@myapihq/sdk": "^2.7.
|
|
44
|
+
"@myapihq/sdk": "^2.7.1"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@types/node": "^25.6.0",
|