@ggui-ai/cli 0.6.2 → 0.7.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/auth-keys.d.ts +3 -1
- package/dist/auth-keys.d.ts.map +1 -1
- package/dist/auth-keys.js +42 -2
- package/dist/blueprint-command.d.ts.map +1 -1
- package/dist/blueprint-command.js +13 -13
- package/dist/cli.js +10 -0
- package/dist/config-push.d.ts +0 -8
- package/dist/config-push.d.ts.map +1 -1
- package/dist/config-push.js +10 -35
- package/dist/gadget-command.d.ts +1 -1
- package/dist/gadget-command.d.ts.map +1 -1
- package/dist/gadget-command.js +35 -12
- package/dist/internal/artifact-install.d.ts.map +1 -1
- package/dist/internal/artifact-install.js +125 -100
- package/dist/internal/artifact-publish.d.ts +37 -35
- package/dist/internal/artifact-publish.d.ts.map +1 -1
- package/dist/internal/artifact-publish.js +33 -97
- package/dist/internal/artifact-search.d.ts +27 -21
- package/dist/internal/artifact-search.d.ts.map +1 -1
- package/dist/internal/artifact-search.js +14 -128
- package/dist/internal/artifact-uninstall.d.ts +8 -5
- package/dist/internal/artifact-uninstall.d.ts.map +1 -1
- package/dist/internal/artifact-uninstall.js +133 -26
- package/dist/internal/ggui-json.d.ts +35 -4
- package/dist/internal/ggui-json.d.ts.map +1 -1
- package/dist/internal/ggui-json.js +58 -7
- package/dist/internal/register-author-key.d.ts +10 -0
- package/dist/internal/register-author-key.d.ts.map +1 -1
- package/dist/internal/register-author-key.js +14 -7
- package/dist/internal/registry-url.d.ts +49 -0
- package/dist/internal/registry-url.d.ts.map +1 -0
- package/dist/internal/registry-url.js +137 -0
- package/dist/mcp-backend.d.ts +6 -0
- package/dist/mcp-backend.d.ts.map +1 -1
- package/dist/mcp-backend.js +9 -0
- package/dist/serve-command.d.ts +14 -1
- package/dist/serve-command.d.ts.map +1 -1
- package/dist/serve-command.js +29 -0
- package/package.json +17 -17
package/dist/auth-keys.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
export declare const KEYS_HELP = "ggui keys \u2014 manage CLI keys\n\nUsage:\n ggui keys list [--keys-file <path>]\n ggui keys create [--name <label>] [--expires-at <iso8601>] [--keys-file <path>]\n ggui keys revoke <id> [--keys-file <path>]\n ggui keys register --scope <@scope> [--registry <url>] [--auth=bearer [--token <token>]]\n\nlist Print the caller's keys (id, prefix, name, status, dates).\ncreate Mint a new connector key. The full secret is printed ONCE \u2014 copy it.\nrevoke Soft-revoke a connector key by id (the row stays for audit).\nregister Register a per-scope Ed25519 PUBLISHER key with the marketplace\n registry so future `ggui gadget publish` / `ggui blueprint publish`\n signed by the matching private key validate. The keypair is\n auto-generated on first publish under\n ~/.ggui/keys/<scope>/{private,public}.key \u2014 this verb ships\n the public half to the registry's POST /author-keys.\n\nregister-only Auth:\n --auth=bearer Use a bearer token (for self-hosted or local\n registries). Pair with --token <token> or set\n GGUI_REGISTRY_TOKEN in the environment.\n --token <token> Bearer token (paired with --auth=bearer).\n (default) Your `ggui login` session \u2014 the CLI reads\n ~/.ggui/auth.json and refreshes the token\n automatically when it has expired. Run\n `ggui login` first.\n\n\nPass --keys-file <path> to operate on the LOCAL JSON file instead of\nthe cloud (api.ggui.ai). The file format is the one written by\n`ggui serve --keys-file` \u2014 the two commands share the same store, so\nyou can mint a bearer here and have `ggui serve` accept it on next\nboot. Use this for self-host / personal-mode workflows. --keys-file\napplies to list/create/revoke only; `register` always talks to the\nmarketplace registry.\n";
|
|
1
|
+
export declare const KEYS_HELP = "ggui keys \u2014 manage CLI keys\n\nUsage:\n ggui keys list [--keys-file <path>]\n ggui keys create [--name <label>] [--expires-at <iso8601>] [--keys-file <path>]\n ggui keys revoke <id> [--keys-file <path>]\n ggui keys register --scope <@scope> [--label <name>] [--registry <url>] [--auth=bearer [--token <token>]]\n\nlist Print the caller's keys (id, prefix, name, status, dates).\ncreate Mint a new connector key. The full secret is printed ONCE \u2014 copy it.\nrevoke Soft-revoke a connector key by id (the row stays for audit).\nregister Register a per-scope Ed25519 PUBLISHER key with the marketplace\n registry so future `ggui gadget publish` / `ggui blueprint publish`\n signed by the matching private key validate. The keypair is\n auto-generated on first publish under\n ~/.ggui/keys/<scope>/{private,public}.key \u2014 this verb ships\n the public half to the registry's POST /author-keys.\n --label attaches a display name shown by the registry's key\n management surfaces (e.g. \"ci laptop\").\n\nregister-only Auth:\n --auth=bearer Use a bearer token (for self-hosted or local\n registries). Pair with --token <token> or set\n GGUI_REGISTRY_TOKEN in the environment.\n --token <token> Bearer token (paired with --auth=bearer).\n (default) Your `ggui login` session \u2014 the CLI reads\n ~/.ggui/auth.json and refreshes the token\n automatically when it has expired. Run\n `ggui login` first.\n\n\nPass --keys-file <path> to operate on the LOCAL JSON file instead of\nthe cloud (api.ggui.ai). The file format is the one written by\n`ggui serve --keys-file` \u2014 the two commands share the same store, so\nyou can mint a bearer here and have `ggui serve` accept it on next\nboot. Use this for self-host / personal-mode workflows. --keys-file\napplies to list/create/revoke only; `register` always talks to the\nmarketplace registry.\n";
|
|
2
2
|
export declare function runKeysCommand(args: readonly string[]): Promise<number>;
|
|
3
3
|
export interface RegisterFlags {
|
|
4
4
|
readonly scope?: string;
|
|
5
5
|
readonly registry?: string;
|
|
6
|
+
/** Optional display name stored on the registered key ([E]). */
|
|
7
|
+
readonly label?: string;
|
|
6
8
|
readonly help: boolean;
|
|
7
9
|
readonly error?: string;
|
|
8
10
|
}
|
package/dist/auth-keys.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-keys.d.ts","sourceRoot":"","sources":["../src/auth-keys.ts"],"names":[],"mappings":"AAwBA,eAAO,MAAM,SAAS,
|
|
1
|
+
{"version":3,"file":"auth-keys.d.ts","sourceRoot":"","sources":["../src/auth-keys.ts"],"names":[],"mappings":"AAwBA,eAAO,MAAM,SAAS,qkEA6BrB,CAAC;AAEF,wBAAsB,cAAc,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAoB7E;AA6PD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,gEAAgE;IAChE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,aAAa,CAuEzE"}
|
package/dist/auth-keys.js
CHANGED
|
@@ -21,7 +21,7 @@ Usage:
|
|
|
21
21
|
ggui keys list [--keys-file <path>]
|
|
22
22
|
ggui keys create [--name <label>] [--expires-at <iso8601>] [--keys-file <path>]
|
|
23
23
|
ggui keys revoke <id> [--keys-file <path>]
|
|
24
|
-
ggui keys register --scope <@scope> [--registry <url>] [--auth=bearer [--token <token>]]
|
|
24
|
+
ggui keys register --scope <@scope> [--label <name>] [--registry <url>] [--auth=bearer [--token <token>]]
|
|
25
25
|
|
|
26
26
|
list Print the caller's keys (id, prefix, name, status, dates).
|
|
27
27
|
create Mint a new connector key. The full secret is printed ONCE — copy it.
|
|
@@ -32,6 +32,8 @@ register Register a per-scope Ed25519 PUBLISHER key with the marketplace
|
|
|
32
32
|
auto-generated on first publish under
|
|
33
33
|
~/.ggui/keys/<scope>/{private,public}.key — this verb ships
|
|
34
34
|
the public half to the registry's POST /author-keys.
|
|
35
|
+
--label attaches a display name shown by the registry's key
|
|
36
|
+
management surfaces (e.g. "ci laptop").
|
|
35
37
|
|
|
36
38
|
register-only ${AUTH_HELP_FRAGMENT}
|
|
37
39
|
|
|
@@ -290,6 +292,7 @@ function printApiError(label, err) {
|
|
|
290
292
|
export function parseRegisterFlags(args) {
|
|
291
293
|
let scope;
|
|
292
294
|
let registry;
|
|
295
|
+
let label;
|
|
293
296
|
let help = false;
|
|
294
297
|
for (let i = 0; i < args.length; i++) {
|
|
295
298
|
const arg = args[i];
|
|
@@ -323,12 +326,39 @@ export function parseRegisterFlags(args) {
|
|
|
323
326
|
registry = arg.slice('--registry='.length);
|
|
324
327
|
continue;
|
|
325
328
|
}
|
|
329
|
+
if (arg === '--label') {
|
|
330
|
+
const value = args[i + 1];
|
|
331
|
+
if (typeof value !== 'string' || value.trim().length === 0) {
|
|
332
|
+
return {
|
|
333
|
+
help,
|
|
334
|
+
error: '--label requires a non-empty value (e.g. `ci laptop`)',
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
label = value;
|
|
338
|
+
i += 1;
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
if (arg && arg.startsWith('--label=')) {
|
|
342
|
+
// Same rule as the space form — an explicit empty (`--label=`)
|
|
343
|
+
// or whitespace-only value is a usage error, never a silent
|
|
344
|
+
// no-label register.
|
|
345
|
+
const value = arg.slice('--label='.length);
|
|
346
|
+
if (value.trim().length === 0) {
|
|
347
|
+
return {
|
|
348
|
+
help,
|
|
349
|
+
error: '--label requires a non-empty value (e.g. `ci laptop`)',
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
label = value;
|
|
353
|
+
continue;
|
|
354
|
+
}
|
|
326
355
|
return { help, error: `unknown flag: ${arg}` };
|
|
327
356
|
}
|
|
328
357
|
return {
|
|
329
358
|
help,
|
|
330
359
|
...(scope !== undefined ? { scope } : {}),
|
|
331
360
|
...(registry !== undefined ? { registry } : {}),
|
|
361
|
+
...(label !== undefined ? { label } : {}),
|
|
332
362
|
};
|
|
333
363
|
}
|
|
334
364
|
async function runKeysRegister(args) {
|
|
@@ -361,6 +391,7 @@ async function runKeysRegister(args) {
|
|
|
361
391
|
const outcome = await runRegisterAuthorKey({
|
|
362
392
|
scope: flags.scope,
|
|
363
393
|
...(flags.registry !== undefined ? { registry: flags.registry } : {}),
|
|
394
|
+
...(flags.label !== undefined ? { label: flags.label } : {}),
|
|
364
395
|
...(authFlags.auth !== undefined || authFlags.token !== undefined
|
|
365
396
|
? { auth: authFlags }
|
|
366
397
|
: {}),
|
|
@@ -380,7 +411,16 @@ async function runKeysRegister(args) {
|
|
|
380
411
|
process.stdout.write(`${verb} publisher key for ${flags.scope}.\n` +
|
|
381
412
|
` registry: ${outcome.registryUrl}\n` +
|
|
382
413
|
` subject: ${outcome.subject}\n` +
|
|
383
|
-
` keyId: ${outcome.keyId}\n`
|
|
414
|
+
` keyId: ${outcome.keyId}\n` +
|
|
415
|
+
(outcome.label !== undefined ? ` label: ${outcome.label}\n` : ''));
|
|
416
|
+
// Idempotent re-register keeps the STORED label — say so when the
|
|
417
|
+
// caller asked for a different one, so a silent "why didn't my
|
|
418
|
+
// label change" mystery never happens.
|
|
419
|
+
if (flags.label !== undefined && outcome.label !== flags.label) {
|
|
420
|
+
process.stdout.write(` note: the registry kept the key's existing label` +
|
|
421
|
+
`${outcome.label !== undefined ? ` ("${outcome.label}")` : ''} — ` +
|
|
422
|
+
`re-registering never rewrites it.\n`);
|
|
423
|
+
}
|
|
384
424
|
return 0;
|
|
385
425
|
}
|
|
386
426
|
process.stderr.write(`ggui keys register: ${outcome.code}: ${outcome.message}\n`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blueprint-command.d.ts","sourceRoot":"","sources":["../src/blueprint-command.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"blueprint-command.d.ts","sourceRoot":"","sources":["../src/blueprint-command.ts"],"names":[],"mappings":"AA+CA,eAAO,MAAM,cAAc,uiBAa1B,CAAC;AAEF,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,SAAS,MAAM,EAAE,GACtB,OAAO,CAAC,MAAM,CAAC,CAsBjB"}
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `ggui blueprint <create|publish|install|search>` —
|
|
3
|
-
* sibling of `gadget-command.ts`.
|
|
2
|
+
* `ggui blueprint <create|publish|install|uninstall|search>` —
|
|
3
|
+
* kind-discriminated sibling of `gadget-command.ts`.
|
|
4
4
|
*
|
|
5
|
-
* - `create`
|
|
6
|
-
* - `publish`
|
|
7
|
-
*
|
|
8
|
-
* - `install`
|
|
9
|
-
*
|
|
10
|
-
* - `
|
|
5
|
+
* - `create` — scaffold a new blueprint repo (TSX + contract stub)
|
|
6
|
+
* - `publish` — build, sign, and push to a registry; manifest-kind
|
|
7
|
+
* mismatch errors with a friendly redirect.
|
|
8
|
+
* - `install` — fetch, verify, and materialize a blueprint into
|
|
9
|
+
* `.ggui/installed-blueprints/<id>/`.
|
|
10
|
+
* - `uninstall` — remove the materialized directory (reverse of install).
|
|
11
|
+
* - `search` — query the registry, hard-locked to `kind=blueprint`.
|
|
11
12
|
*
|
|
12
13
|
* A thin router that passes `kind: 'blueprint'` to the shared
|
|
13
14
|
* `internal/artifact-*` implementations. Per-kind state (scaffolders,
|
|
14
15
|
* help text) lives in sibling files; the rest is shared.
|
|
15
16
|
*/
|
|
16
17
|
import { BLUEPRINT_CREATE_HELP, parseBlueprintCreateFlags, runBlueprintCreate, } from './blueprint-create.js';
|
|
17
|
-
import { buildPublishHelp, parseArtifactPublishFlags, runArtifactPublish, } from './internal/artifact-publish.js';
|
|
18
|
+
import { buildPublishHelp, parseArtifactPublishFlags, publishOptionsFromFlags, runArtifactPublish, } from './internal/artifact-publish.js';
|
|
18
19
|
import { buildInstallHelp, parseArtifactInstallFlags, runArtifactInstall, } from './internal/artifact-install.js';
|
|
19
20
|
import { buildUninstallHelp, parseArtifactUninstallFlags, runArtifactUninstall, } from './internal/artifact-uninstall.js';
|
|
20
21
|
import { buildSearchHelp, parseArtifactSearchFlags, runArtifactSearch, } from './internal/artifact-search.js';
|
|
@@ -110,12 +111,11 @@ async function runPublish(args) {
|
|
|
110
111
|
process.stderr.write(`ggui blueprint publish: ${flags.error}\n`);
|
|
111
112
|
return 2;
|
|
112
113
|
}
|
|
114
|
+
// Forward the WHOLE parsed-flag bundle — no per-field spreads (a
|
|
115
|
+
// hand-written spread is how `--identity-token` got dropped once).
|
|
113
116
|
const result = await runArtifactPublish({
|
|
114
117
|
kind: KIND,
|
|
115
|
-
...(flags
|
|
116
|
-
dryRun: flags.dryRun,
|
|
117
|
-
...(flags.key !== undefined ? { key: flags.key } : {}),
|
|
118
|
-
...(flags.auth !== undefined ? { auth: flags.auth } : {}),
|
|
118
|
+
...publishOptionsFromFlags(flags),
|
|
119
119
|
});
|
|
120
120
|
return result.exitCode;
|
|
121
121
|
}
|
package/dist/cli.js
CHANGED
|
@@ -615,6 +615,14 @@ async function runServeCommand(args) {
|
|
|
615
615
|
return 1;
|
|
616
616
|
}
|
|
617
617
|
}
|
|
618
|
+
// Browser-origin allowlist (ggui#438). CLI flags win; the env var is
|
|
619
|
+
// the container/compose ergonomic. Resolved HERE so the banner, the
|
|
620
|
+
// backend, and the server all see the same effective list.
|
|
621
|
+
const envBrowserOrigins = (process.env['GGUI_BROWSER_ORIGINS'] ?? '')
|
|
622
|
+
.split(',')
|
|
623
|
+
.map((o) => o.trim())
|
|
624
|
+
.filter((o) => o.length > 0);
|
|
625
|
+
const browserOrigins = parsed.browserOrigins.length > 0 ? parsed.browserOrigins : envBrowserOrigins;
|
|
618
626
|
try {
|
|
619
627
|
return await runServe({
|
|
620
628
|
flags: {
|
|
@@ -625,6 +633,7 @@ async function runServeCommand(args) {
|
|
|
625
633
|
publicDemo: parsed.publicDemo,
|
|
626
634
|
multiTenant: parsed.multiTenant,
|
|
627
635
|
oauth: parsed.oauth,
|
|
636
|
+
browserOrigins,
|
|
628
637
|
...(parsed.publicBaseUrl !== undefined
|
|
629
638
|
? { publicBaseUrl: parsed.publicBaseUrl }
|
|
630
639
|
: {}),
|
|
@@ -746,6 +755,7 @@ async function runServeCommand(args) {
|
|
|
746
755
|
generation: generationBinding.generation,
|
|
747
756
|
...(mcpMounts.length > 0 ? { mcpMounts } : {}),
|
|
748
757
|
...(seedPools.length > 0 ? { seedPools } : {}),
|
|
758
|
+
...(browserOrigins.length > 0 ? { browserOrigins } : {}),
|
|
749
759
|
// Marketplace-install bridge. Pass the projectRoot +
|
|
750
760
|
// filtered installed-blueprint subset so `buildMcpServerBackend`
|
|
751
761
|
// can construct an `InstalledBlueprintsProvider` rooted on the
|
package/dist/config-push.d.ts
CHANGED
|
@@ -1,12 +1,4 @@
|
|
|
1
1
|
import { type GadgetDescriptor, type AppTheme } from '@ggui-ai/protocol';
|
|
2
|
-
/**
|
|
3
|
-
* Extract and validate `app.gadgets` from a decoded ggui.json value.
|
|
4
|
-
*
|
|
5
|
-
* Returns `[]` when the field is absent.
|
|
6
|
-
* Throws with a descriptive message when any descriptor is malformed
|
|
7
|
-
* (schema parse fails).
|
|
8
|
-
*/
|
|
9
|
-
export declare function readGadgetsFromGguiJson(gguiJson: unknown): GadgetDescriptor[];
|
|
10
2
|
/**
|
|
11
3
|
* Extract and validate `app.publicEnv` from a decoded ggui.json value.
|
|
12
4
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-push.d.ts","sourceRoot":"","sources":["../src/config-push.ts"],"names":[],"mappings":"AAUA,OAAO,
|
|
1
|
+
{"version":3,"file":"config-push.d.ts","sourceRoot":"","sources":["../src/config-push.ts"],"names":[],"mappings":"AAUA,OAAO,EAIL,KAAK,gBAAgB,EACrB,KAAK,QAAQ,EACd,MAAM,mBAAmB,CAAC;AAmB3B;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAmBnF;AAED;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,OAAO,GAChB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,KAAK,GAAG,SAAS,CAAA;CAAE,GAAG,SAAS,CAkB7D;AA4BD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,OAAO,GAChB,QAAQ,GAAG,SAAS,CA4CtB;AAMD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAiB9E;AAMD;;;;;;;;;;GAUG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,MAAM,EACb,QAAQ,GAAE,MAAsB,GAC/B,OAAO,CAAC,MAAM,CAAC,CA2FjB"}
|
package/dist/config-push.js
CHANGED
|
@@ -8,41 +8,18 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import process from 'node:process';
|
|
10
10
|
import { dirname } from 'node:path';
|
|
11
|
-
import {
|
|
11
|
+
import { appPublicEnvSchema, appThemeSchema, LOOPBACK_HOST_RE, } from '@ggui-ai/protocol';
|
|
12
12
|
import { loadTheme, parseGguiJson } from '@ggui-ai/project-config/node';
|
|
13
13
|
import { z } from 'zod';
|
|
14
14
|
import { patchAppConfig } from './api-client.js';
|
|
15
|
-
import { findGguiJson, readGguiJson } from './internal/ggui-json.js';
|
|
15
|
+
import { findGguiJson, readGadgetsFromGguiJson, readGguiJson, } from './internal/ggui-json.js';
|
|
16
16
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
17
17
|
// Readers
|
|
18
18
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
* Throws with a descriptive message when any descriptor is malformed
|
|
24
|
-
* (schema parse fails).
|
|
25
|
-
*/
|
|
26
|
-
export function readGadgetsFromGguiJson(gguiJson) {
|
|
27
|
-
// Navigate to `app.gadgets` via a nested schema rather than casting +
|
|
28
|
-
// index access. `z.object` is non-strict by default, so ggui.json's other
|
|
29
|
-
// fields (schema / protocol / generation / app.publicEnv / …) ride through
|
|
30
|
-
// as allowed-and-stripped extras — only `app.gadgets` is validated here.
|
|
31
|
-
const schema = z.object({
|
|
32
|
-
app: z
|
|
33
|
-
.object({
|
|
34
|
-
gadgets: z.array(strictGadgetDescriptorSchema).optional(),
|
|
35
|
-
})
|
|
36
|
-
.optional(),
|
|
37
|
-
});
|
|
38
|
-
const result = schema.safeParse(gguiJson);
|
|
39
|
-
if (!result.success) {
|
|
40
|
-
throw new Error(`ggui.json: app.gadgets is invalid — ${result.error.issues[0]?.message ?? 'malformed descriptor'}`);
|
|
41
|
-
}
|
|
42
|
-
// result.data.app?.gadgets is GadgetDescriptor[] — strictGadgetDescriptorSchema
|
|
43
|
-
// parses to the same shape as GadgetDescriptor. Spread to a fresh mutable array.
|
|
44
|
-
return [...(result.data.app?.gadgets ?? [])];
|
|
45
|
-
}
|
|
19
|
+
// The gadget-catalog reader lives in `./internal/ggui-json.ts`
|
|
20
|
+
// (`readGadgetsFromGguiJson`) — ONE reader shared with the install
|
|
21
|
+
// write gate so deploy and install cannot drift on optionality or
|
|
22
|
+
// error shape.
|
|
46
23
|
/**
|
|
47
24
|
* Extract and validate `app.publicEnv` from a decoded ggui.json value.
|
|
48
25
|
*
|
|
@@ -235,17 +212,15 @@ export async function runConfigPushStep(appId, startDir = process.cwd()) {
|
|
|
235
212
|
process.stderr.write(`ggui deploy: ${readResult.error}\n`);
|
|
236
213
|
return 1;
|
|
237
214
|
}
|
|
238
|
-
let gadgets;
|
|
239
215
|
let publicEnv;
|
|
240
216
|
let generation;
|
|
241
217
|
let theme;
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
catch (err) {
|
|
246
|
-
process.stderr.write(`ggui deploy: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
218
|
+
const gadgetsRead = readGadgetsFromGguiJson(readResult.value);
|
|
219
|
+
if (!gadgetsRead.ok) {
|
|
220
|
+
process.stderr.write(`ggui deploy: ${gadgetsRead.error}\n`);
|
|
247
221
|
return 1;
|
|
248
222
|
}
|
|
223
|
+
const gadgets = gadgetsRead.gadgets;
|
|
249
224
|
try {
|
|
250
225
|
publicEnv = readPublicEnvFromGguiJson(readResult.value);
|
|
251
226
|
}
|
package/dist/gadget-command.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export declare const GADGET_HELP = "ggui gadget \u2014 author + manage marketplace gadgets\n\nUsage:\n ggui gadget <subcommand> [options]\n\nSubcommands:\n create Scaffold a new gadget repo.\n publish Build, sign, and push the gadget in CWD to a marketplace registry.\n install Fetch, verify, and register a gadget in ggui.json.\n search Search the marketplace registry for gadgets.\n\nRun `ggui gadget <subcommand> --help` for subcommand-specific options.\n";
|
|
1
|
+
export declare const GADGET_HELP = "ggui gadget \u2014 author + manage marketplace gadgets\n\nUsage:\n ggui gadget <subcommand> [options]\n\nSubcommands:\n create Scaffold a new gadget repo.\n publish Build, sign, and push the gadget in CWD to a marketplace registry.\n install Fetch, verify, and register a gadget in ggui.json.\n uninstall Remove an installed gadget from ggui.json (reverse of install).\n search Search the marketplace registry for gadgets.\n\nRun `ggui gadget <subcommand> --help` for subcommand-specific options.\n";
|
|
2
2
|
export declare function runGadgetCommand(args: readonly string[]): Promise<number>;
|
|
3
3
|
//# sourceMappingURL=gadget-command.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gadget-command.d.ts","sourceRoot":"","sources":["../src/gadget-command.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"gadget-command.d.ts","sourceRoot":"","sources":["../src/gadget-command.ts"],"names":[],"mappings":"AA+CA,eAAO,MAAM,WAAW,shBAavB,CAAC;AAEF,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,SAAS,MAAM,EAAE,GACtB,OAAO,CAAC,MAAM,CAAC,CAsBjB"}
|
package/dist/gadget-command.js
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `ggui gadget <create|publish|install|search>` — top-level
|
|
3
|
-
* the marketplace author + consumer surface.
|
|
2
|
+
* `ggui gadget <create|publish|install|uninstall|search>` — top-level
|
|
3
|
+
* router for the marketplace author + consumer surface.
|
|
4
4
|
*
|
|
5
5
|
* A thin sibling of `blueprint-command.ts`. Both commands dispatch into
|
|
6
6
|
* the shared `internal/artifact-*` modules with their own `kind`
|
|
7
7
|
* discriminator; per-kind state (scaffolders, help text) lives in
|
|
8
8
|
* sibling files.
|
|
9
9
|
*
|
|
10
|
-
* - `create`
|
|
11
|
-
* - `publish`
|
|
12
|
-
*
|
|
13
|
-
* - `install`
|
|
14
|
-
* - `
|
|
10
|
+
* - `create` — scaffold a new gadget repo (hook + bundle stub).
|
|
11
|
+
* - `publish` — build, sign, and push to a registry.
|
|
12
|
+
* Manifest-kind mismatch surfaces a redirect.
|
|
13
|
+
* - `install` — fetch, verify, append to ggui.json.
|
|
14
|
+
* - `uninstall` — remove the ggui.json#app.gadgets row (reverse of install).
|
|
15
|
+
* - `search` — query the registry, hard-locked to `kind=gadget`.
|
|
15
16
|
*/
|
|
16
17
|
import { GADGET_CREATE_HELP, parseGadgetCreateFlags, runGadgetCreate, } from './gadget-create.js';
|
|
17
|
-
import { buildPublishHelp, parseArtifactPublishFlags, runArtifactPublish, } from './internal/artifact-publish.js';
|
|
18
|
+
import { buildPublishHelp, parseArtifactPublishFlags, publishOptionsFromFlags, runArtifactPublish, } from './internal/artifact-publish.js';
|
|
18
19
|
import { buildInstallHelp, parseArtifactInstallFlags, runArtifactInstall, } from './internal/artifact-install.js';
|
|
20
|
+
import { buildUninstallHelp, parseArtifactUninstallFlags, runArtifactUninstall, } from './internal/artifact-uninstall.js';
|
|
19
21
|
import { buildSearchHelp, parseArtifactSearchFlags, runArtifactSearch, } from './internal/artifact-search.js';
|
|
20
22
|
const KIND = 'gadget';
|
|
21
23
|
export const GADGET_HELP = `ggui gadget — author + manage marketplace gadgets
|
|
@@ -27,6 +29,7 @@ Subcommands:
|
|
|
27
29
|
create Scaffold a new gadget repo.
|
|
28
30
|
publish Build, sign, and push the gadget in CWD to a marketplace registry.
|
|
29
31
|
install Fetch, verify, and register a gadget in ggui.json.
|
|
32
|
+
uninstall Remove an installed gadget from ggui.json (reverse of install).
|
|
30
33
|
search Search the marketplace registry for gadgets.
|
|
31
34
|
|
|
32
35
|
Run \`ggui gadget <subcommand> --help\` for subcommand-specific options.
|
|
@@ -44,6 +47,8 @@ export async function runGadgetCommand(args) {
|
|
|
44
47
|
return runPublish(rest);
|
|
45
48
|
case 'install':
|
|
46
49
|
return runInstall(rest);
|
|
50
|
+
case 'uninstall':
|
|
51
|
+
return runUninstall(rest);
|
|
47
52
|
case 'search':
|
|
48
53
|
return runSearch(rest);
|
|
49
54
|
default:
|
|
@@ -107,12 +112,11 @@ async function runPublish(args) {
|
|
|
107
112
|
process.stderr.write(`ggui gadget publish: ${flags.error}\n`);
|
|
108
113
|
return 2;
|
|
109
114
|
}
|
|
115
|
+
// Forward the WHOLE parsed-flag bundle — no per-field spreads (a
|
|
116
|
+
// hand-written spread is how `--identity-token` got dropped once).
|
|
110
117
|
const result = await runArtifactPublish({
|
|
111
118
|
kind: KIND,
|
|
112
|
-
...(flags
|
|
113
|
-
dryRun: flags.dryRun,
|
|
114
|
-
...(flags.key !== undefined ? { key: flags.key } : {}),
|
|
115
|
-
...(flags.auth !== undefined ? { auth: flags.auth } : {}),
|
|
119
|
+
...publishOptionsFromFlags(flags),
|
|
116
120
|
});
|
|
117
121
|
return result.exitCode;
|
|
118
122
|
}
|
|
@@ -137,6 +141,25 @@ async function runInstall(args) {
|
|
|
137
141
|
});
|
|
138
142
|
}
|
|
139
143
|
/* -------------------------------------------------------------------------- */
|
|
144
|
+
/* uninstall */
|
|
145
|
+
/* -------------------------------------------------------------------------- */
|
|
146
|
+
async function runUninstall(args) {
|
|
147
|
+
const parsed = parseArtifactUninstallFlags(KIND, args);
|
|
148
|
+
if ('error' in parsed) {
|
|
149
|
+
if (parsed.error === '__help__') {
|
|
150
|
+
process.stdout.write(buildUninstallHelp(KIND));
|
|
151
|
+
return 0;
|
|
152
|
+
}
|
|
153
|
+
process.stderr.write(`ggui gadget uninstall: ${parsed.error}\n\n`);
|
|
154
|
+
process.stderr.write(buildUninstallHelp(KIND));
|
|
155
|
+
return 2;
|
|
156
|
+
}
|
|
157
|
+
const result = await runArtifactUninstall(parsed, {
|
|
158
|
+
cwd: process.cwd(),
|
|
159
|
+
});
|
|
160
|
+
return result.exitCode;
|
|
161
|
+
}
|
|
162
|
+
/* -------------------------------------------------------------------------- */
|
|
140
163
|
/* search */
|
|
141
164
|
/* -------------------------------------------------------------------------- */
|
|
142
165
|
async function runSearch(args) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifact-install.d.ts","sourceRoot":"","sources":["../../src/internal/artifact-install.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"artifact-install.d.ts","sourceRoot":"","sources":["../../src/internal/artifact-install.ts"],"names":[],"mappings":"AAsFA,OAAO,EAAoB,KAAK,YAAY,EAAsB,MAAM,wBAAwB,CAAC;AAWjG;;;sCAGsC;AACtC,YAAY,EAAE,YAAY,EAAE,CAAC;AAM7B;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,wEAAwE;IACxE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,uDAAuD;IACvD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,wDAAwD;IACxD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,sDAAsD;IACtD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,sFAAsF;IACtF,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,yEAAyE;IACzE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB;;;;;;;OAOG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAED;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAAG,YAAY,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAElE;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAgD3D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,YAAY,EAClB,IAAI,EAAE,SAAS,MAAM,EAAE,GACtB,kBAAkB,CAsGpB;AA6DD;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACrC,kCAAkC;IAClC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,oDAAoD;IACpD,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IACrE,iEAAiE;IACjE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IAC9B,uDAAuD;IACvD,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,uDAAuD;IACvD,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC;;;;;;;OAOG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACjE;AA8ID;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,YAAY,EACnB,IAAI,GAAE,sBAA2B,GAChC,OAAO,CAAC,MAAM,CAAC,CAodjB;AA0JD;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,+BAA+B,CAAC;AAExE;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,8CACqB,CAAC;AAE5D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,wBAAwB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAOtE;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,MAAM,CAGT;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,MAAM,CAGT"}
|