@modularizer/plat 0.16.1 → 0.17.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/README.md +28 -0
- package/dist/args/index.d.ts +2 -1
- package/dist/args/index.d.ts.map +1 -1
- package/dist/args/index.js +1 -0
- package/dist/args/index.js.map +1 -1
- package/dist/args/method_name.d.ts +27 -0
- package/dist/args/method_name.d.ts.map +1 -0
- package/dist/args/method_name.js +52 -0
- package/dist/args/method_name.js.map +1 -0
- package/dist/args/validate.d.ts +1 -1
- package/dist/args/z2.d.ts +2 -2
- package/dist/bridge/http-forwarder.d.ts +2 -2
- package/dist/bridge/index.d.ts +3 -3
- package/dist/cli/commands/api-proxy.d.ts.map +1 -1
- package/dist/cli/commands/api-proxy.js +23 -2
- package/dist/cli/commands/api-proxy.js.map +1 -1
- package/dist/cli/core.d.ts +103 -0
- package/dist/cli/core.d.ts.map +1 -0
- package/dist/cli/core.js +177 -0
- package/dist/cli/core.js.map +1 -0
- package/dist/cli/format.d.ts +13 -0
- package/dist/cli/format.d.ts.map +1 -0
- package/dist/cli/format.js +160 -0
- package/dist/cli/format.js.map +1 -0
- package/dist/cli/http.d.ts +25 -0
- package/dist/cli/http.d.ts.map +1 -0
- package/dist/cli/http.js +56 -0
- package/dist/cli/http.js.map +1 -0
- package/dist/cli/index.d.ts +10 -10
- package/dist/cli/proxy.d.ts +2 -2
- package/dist/cli/runtime.d.ts +9 -2
- package/dist/cli/runtime.d.ts.map +1 -1
- package/dist/cli/runtime.js +24 -275
- package/dist/cli/runtime.js.map +1 -1
- package/dist/cli-bin.d.ts +3 -0
- package/dist/cli-bin.d.ts.map +1 -0
- package/dist/cli-bin.js +21 -0
- package/dist/cli-bin.js.map +1 -0
- package/dist/cli-entry.d.ts +5 -0
- package/dist/cli-entry.d.ts.map +1 -0
- package/dist/cli-entry.js +6 -0
- package/dist/cli-entry.js.map +1 -0
- package/dist/client/css-transport-plugin.d.ts +4 -4
- package/dist/client/file-transport-plugin.d.ts +1 -1
- package/dist/client/http-transport-plugin.d.ts +3 -3
- package/dist/client/index.d.ts +6 -6
- package/dist/client/openapi-client.d.ts +16 -8
- package/dist/client/openapi-client.d.ts.map +1 -1
- package/dist/client/openapi-client.js +59 -24
- package/dist/client/openapi-client.js.map +1 -1
- package/dist/client/proxy.d.ts +2 -2
- package/dist/client/request-builder.d.ts +2 -2
- package/dist/client/rpc-transport-plugin.d.ts +2 -2
- package/dist/client/tools.d.ts +1 -1
- package/dist/client/transport-plugin.d.ts +4 -4
- package/dist/client-entry.d.ts +29 -29
- package/dist/client-lite-entry.d.ts +6 -0
- package/dist/client-lite-entry.d.ts.map +1 -0
- package/dist/client-lite-entry.js +8 -0
- package/dist/client-lite-entry.js.map +1 -0
- package/dist/client-server-entry.d.ts +19 -19
- package/dist/client-side-python/runtime.d.ts +3 -3
- package/dist/client-side-server/bootstrap.d.ts +1 -1
- package/dist/client-side-server/channel.d.ts +1 -1
- package/dist/client-side-server/mqtt-webrtc.d.ts +6 -6
- package/dist/client-side-server/mqtt-webrtc.d.ts.map +1 -1
- package/dist/client-side-server/mqtt-webrtc.js +11 -3
- package/dist/client-side-server/mqtt-webrtc.js.map +1 -1
- package/dist/client-side-server/plat-bridge.d.ts +1 -1
- package/dist/client-side-server/plat-fetch.d.ts +2 -2
- package/dist/client-side-server/plat-service-worker-client.d.ts +1 -1
- package/dist/client-side-server/plat-service-worker.d.ts +1 -1
- package/dist/client-side-server/protocol.d.ts +2 -2
- package/dist/client-side-server/runtime.d.ts +5 -5
- package/dist/client-side-server/server.d.ts +8 -8
- package/dist/client-side-server/server.js +1 -1
- package/dist/client-side-server/worker-pool.d.ts +3 -3
- package/dist/generated/python-browser-sources.js +1 -1
- package/dist/generated/python-browser-sources.js.map +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/python-browser-entry.d.ts +1 -1
- package/dist/server/auth/index.d.ts +1 -1
- package/dist/server/auth/jwt.d.ts +1 -1
- package/dist/server/authority-server.d.ts +1 -1
- package/dist/server/cache/index.d.ts +1 -1
- package/dist/server/cache/utils.d.ts +1 -1
- package/dist/server/config/bucket.d.ts +1 -1
- package/dist/server/config/defaults.d.ts +1 -1
- package/dist/server/config/index.d.ts +4 -4
- package/dist/server/config/logger.d.ts +1 -1
- package/dist/server/config/types.d.ts +6 -6
- package/dist/server/core.d.ts +3 -3
- package/dist/server/file-queue-protocol-plugin.d.ts +2 -2
- package/dist/server/help.d.ts +1 -1
- package/dist/server/index.d.ts +17 -17
- package/dist/server/operation-registry.d.ts +1 -1
- package/dist/server/protocol-plugin.d.ts +3 -3
- package/dist/server/rate-limit/index.d.ts +1 -1
- package/dist/server/rate-limit/utils.d.ts +1 -1
- package/dist/server/rpc-protocol-plugin.d.ts +1 -1
- package/dist/server/server.d.ts +2 -2
- package/dist/server/server.js +1 -1
- package/dist/server/token-limit/index.d.ts +1 -1
- package/dist/server/token-limit/utils.d.ts +1 -1
- package/dist/server/tools.d.ts +2 -2
- package/dist/server/transports.d.ts +1 -1
- package/dist/server/webrtc-plugin.d.ts +3 -3
- package/dist/server/websocket-plugin.d.ts +1 -1
- package/dist/shared/tools.d.ts +1 -1
- package/dist/spec/decorators.d.ts +3 -3
- package/dist/spec/index.d.ts +2 -2
- package/dist/spec/metadata.d.ts +1 -1
- package/dist/static/index.d.ts +5 -5
- package/dist/static/plat-static-folders.d.ts +1 -1
- package/dist/static/static-folder.d.ts +2 -2
- package/dist/types/client.d.ts +3 -3
- package/dist/types/endpoints.d.ts +2 -2
- package/dist/types/errors.d.ts +1 -1
- package/dist/types/index.d.ts +8 -8
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -484,6 +484,34 @@ plat serve
|
|
|
484
484
|
|
|
485
485
|
The CLI is available from both Node and Python packaging surfaces, with capability moving toward parity.
|
|
486
486
|
|
|
487
|
+
Method names are forgiving: `createOrder`, `create-order`, `create_order` and `create order` are the same command.
|
|
488
|
+
|
|
489
|
+
### Extending the CLI (don't write your own)
|
|
490
|
+
|
|
491
|
+
`runCli` / `runHttpCli` (and the engine under them, `runCliCore`) take options for everything an app might
|
|
492
|
+
want to do differently, so you never need to bypass plat's CLI:
|
|
493
|
+
|
|
494
|
+
```ts
|
|
495
|
+
import { runHttpCli } from '@modularizer/plat-cli' // zero dependencies; or runCli from '@modularizer/plat'
|
|
496
|
+
|
|
497
|
+
await runHttpCli({
|
|
498
|
+
baseUrl: () => discoverServer(), // or a string; spec defaults to GET /openapi.json
|
|
499
|
+
headers: () => ({ authorization: `Bearer ${token()}` }),
|
|
500
|
+
commands: { host: (ctx) => manageHosts(ctx.argv) }, // CLI-only commands; win over spec methods
|
|
501
|
+
overrides: { runSql: async (ctx, next) => confirmWrites(ctx) && next() }, // wrap/replace a method
|
|
502
|
+
positional: { runSql: ['datasource', 'query'] }, // `cli run sql shop "select 1"`
|
|
503
|
+
beforeCall: (ctx) => { ctx.input.limit ??= 100 }, // rewrite input
|
|
504
|
+
afterCall: (result) => unwrap(result), // rewrite output
|
|
505
|
+
onUnknown: ({ candidates }) => suggest(candidates), // fallback; return true if handled
|
|
506
|
+
onError: (err) => prettyPrint(err),
|
|
507
|
+
formatters: { md: toMarkdown }, defaultFormat: 'md',
|
|
508
|
+
help: (commands) => myHelp(commands),
|
|
509
|
+
})
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
Also replaceable: `parseArgs`, `resolveName`, `call` (the transport), `spec` (object or async function), `io`.
|
|
513
|
+
If you need something these don't cover, add an option to plat instead of forking the CLI.
|
|
514
|
+
|
|
487
515
|
## 🧩 Plugin architecture
|
|
488
516
|
|
|
489
517
|
The plugin architecture matters, but mostly as an implementation and extension story.
|
package/dist/args/index.d.ts
CHANGED
package/dist/args/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/args/index.ts"],"names":[],"mappings":"AACA,cAAc,MAAM,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/args/index.ts"],"names":[],"mappings":"AACA,cAAc,MAAM,CAAA;AACpB,cAAc,eAAe,CAAA"}
|
package/dist/args/index.js
CHANGED
package/dist/args/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/args/index.ts"],"names":[],"mappings":"AACA,cAAc,MAAM,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/args/index.ts"],"names":[],"mappings":"AACA,cAAc,MAAM,CAAA;AACpB,cAAc,eAAe,CAAA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forgiving method names for CLIs: `runCloneFeed`, `run-clone-feed`, `run_clone_feed` and
|
|
3
|
+
* `run clone feed` all name the same operation.
|
|
4
|
+
*
|
|
5
|
+
* Pure (no node/DOM imports) so the lightweight client package can ship it.
|
|
6
|
+
*/
|
|
7
|
+
/** Split a name into lowercase words on camelCase, acronym, `-`, `_`, `.` and whitespace boundaries. */
|
|
8
|
+
export declare function nameWords(name: string): string[];
|
|
9
|
+
/** The canonical comparison key: all words, lowercased, joined with no separator. */
|
|
10
|
+
export declare function normalizeName(name: string): string;
|
|
11
|
+
export type ResolvedCommand = {
|
|
12
|
+
ok: true;
|
|
13
|
+
name: string;
|
|
14
|
+
consumed: number;
|
|
15
|
+
} | {
|
|
16
|
+
ok: false;
|
|
17
|
+
reason: 'unknown' | 'ambiguous';
|
|
18
|
+
candidates: string[];
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Resolve the leading bare tokens of `argv` to one of `names`. The longest run of leading tokens
|
|
22
|
+
* whose normalized join matches wins (so `run clone feed` beats a shorter `run`); a lone token spelled
|
|
23
|
+
* exactly like a name wins over look-alikes. `consumed` is how many argv
|
|
24
|
+
* tokens the command used. Two names that normalize identically are `ambiguous`, never guessed.
|
|
25
|
+
*/
|
|
26
|
+
export declare function resolveCommand(names: readonly string[], argv: readonly string[]): ResolvedCommand;
|
|
27
|
+
//# sourceMappingURL=method_name.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"method_name.d.ts","sourceRoot":"","sources":["../../src/args/method_name.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,wGAAwG;AACxG,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAOhD;AAED,qFAAqF;AACrF,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,MAAM,MAAM,eAAe,GACrB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC5C;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,SAAS,GAAG,WAAW,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,CAAA;AAO1E;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,eAAe,CAmBjG"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forgiving method names for CLIs: `runCloneFeed`, `run-clone-feed`, `run_clone_feed` and
|
|
3
|
+
* `run clone feed` all name the same operation.
|
|
4
|
+
*
|
|
5
|
+
* Pure (no node/DOM imports) so the lightweight client package can ship it.
|
|
6
|
+
*/
|
|
7
|
+
/** Split a name into lowercase words on camelCase, acronym, `-`, `_`, `.` and whitespace boundaries. */
|
|
8
|
+
export function nameWords(name) {
|
|
9
|
+
return name
|
|
10
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
|
|
11
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')
|
|
12
|
+
.split(/[\s_\-.]+/)
|
|
13
|
+
.filter(Boolean)
|
|
14
|
+
.map((word) => word.toLowerCase());
|
|
15
|
+
}
|
|
16
|
+
/** The canonical comparison key: all words, lowercased, joined with no separator. */
|
|
17
|
+
export function normalizeName(name) {
|
|
18
|
+
return nameWords(name).join('');
|
|
19
|
+
}
|
|
20
|
+
/** True for tokens that can be part of a command name (not flags, `key=value` or JSON). */
|
|
21
|
+
function isNameToken(token) {
|
|
22
|
+
return !token.startsWith('-') && !token.startsWith('{') && !token.startsWith('[') && !token.includes('=');
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Resolve the leading bare tokens of `argv` to one of `names`. The longest run of leading tokens
|
|
26
|
+
* whose normalized join matches wins (so `run clone feed` beats a shorter `run`); a lone token spelled
|
|
27
|
+
* exactly like a name wins over look-alikes. `consumed` is how many argv
|
|
28
|
+
* tokens the command used. Two names that normalize identically are `ambiguous`, never guessed.
|
|
29
|
+
*/
|
|
30
|
+
export function resolveCommand(names, argv) {
|
|
31
|
+
const byKey = new Map();
|
|
32
|
+
for (const name of names) {
|
|
33
|
+
const key = normalizeName(name);
|
|
34
|
+
byKey.set(key, [...(byKey.get(key) ?? []), name]);
|
|
35
|
+
}
|
|
36
|
+
let run = 0;
|
|
37
|
+
while (run < argv.length && isNameToken(argv[run]))
|
|
38
|
+
run += 1;
|
|
39
|
+
for (let length = run; length >= 1; length -= 1) {
|
|
40
|
+
// A single token spelled exactly like a name is never ambiguous, even if siblings normalize alike.
|
|
41
|
+
if (length === 1 && names.includes(argv[0]))
|
|
42
|
+
return { ok: true, name: argv[0], consumed: 1 };
|
|
43
|
+
const matches = byKey.get(normalizeName(argv.slice(0, length).join(' ')));
|
|
44
|
+
if (matches === undefined)
|
|
45
|
+
continue;
|
|
46
|
+
if (matches.length === 1)
|
|
47
|
+
return { ok: true, name: matches[0], consumed: length };
|
|
48
|
+
return { ok: false, reason: 'ambiguous', candidates: matches };
|
|
49
|
+
}
|
|
50
|
+
return { ok: false, reason: 'unknown', candidates: [] };
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=method_name.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"method_name.js","sourceRoot":"","sources":["../../src/args/method_name.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,wGAAwG;AACxG,MAAM,UAAU,SAAS,CAAC,IAAY;IAClC,OAAO,IAAI;SACN,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC;SACtC,OAAO,CAAC,uBAAuB,EAAE,OAAO,CAAC;SACzC,KAAK,CAAC,WAAW,CAAC;SAClB,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAA;AAC1C,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,aAAa,CAAC,IAAY;IACtC,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;AACnC,CAAC;AAMD,2FAA2F;AAC3F,SAAS,WAAW,CAAC,KAAa;IAC9B,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA;AAC7G,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,KAAwB,EAAE,IAAuB;IAC5E,MAAM,KAAK,GAAG,IAAI,GAAG,EAAoB,CAAA;IACzC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,CAAC,CAAA;QAC/B,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,CAAA;IACrD,CAAC;IAED,IAAI,GAAG,GAAG,CAAC,CAAA;IACX,OAAO,GAAG,GAAG,IAAI,CAAC,MAAM,IAAI,WAAW,CAAC,IAAI,CAAC,GAAG,CAAE,CAAC;QAAE,GAAG,IAAI,CAAC,CAAA;IAE7D,KAAK,IAAI,MAAM,GAAG,GAAG,EAAE,MAAM,IAAI,CAAC,EAAE,MAAM,IAAI,CAAC,EAAE,CAAC;QAC9C,mGAAmG;QACnG,IAAI,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC;YAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAA;QAC9F,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;QACzE,IAAI,OAAO,KAAK,SAAS;YAAE,SAAQ;QACnC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAA;QAClF,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,EAAE,CAAA;IAClE,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,EAAE,EAAE,CAAA;AAC3D,CAAC"}
|
package/dist/args/validate.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Lean validator covering the JSON Schema subset that gen-schema.ts produces.
|
|
5
5
|
* Coerces before validating (string→number, string→date, trim, etc.)
|
|
6
6
|
*/
|
|
7
|
-
import { type JsonSchema } from './coerce';
|
|
7
|
+
import { type JsonSchema } from './coerce.js';
|
|
8
8
|
export declare class ValidationError extends Error {
|
|
9
9
|
issues: string[];
|
|
10
10
|
constructor(issues: string[]);
|
package/dist/args/z2.d.ts
CHANGED
|
@@ -19,9 +19,9 @@
|
|
|
19
19
|
* hex, digits, numeric, upper, lower, title, slug,
|
|
20
20
|
* num, int, posint, pos, percent, limit, offset
|
|
21
21
|
*/
|
|
22
|
-
export { parse, safeParse, ValidationError } from './validate';
|
|
22
|
+
export { parse, safeParse, ValidationError } from './validate.js';
|
|
23
23
|
export type { ParseResult } from './validate';
|
|
24
|
-
export { coerce, parseDateish, parseRelativeDate, registerCoerce, Coerce } from './coerce';
|
|
24
|
+
export { coerce, parseDateish, parseRelativeDate, registerCoerce, Coerce } from './coerce.js';
|
|
25
25
|
export type { JsonSchema } from './coerce';
|
|
26
26
|
export type { str, char, text, word, token, line, email, url, uuid, ip, ipv6, hostname, datestr, datetime, time, json, pattern, grep, like, ilike, hex, digits, numeric, upper, lower, alpha, alphanum, title, slug, semver, base64, base58, phone, color, locale, mimetype, filepath, cuid, ulid, nanoid, jwt, countrycode, currency, lang, cron, num, float, double, int, pos, neg, notneg, posint, percent, limit, offset, port, byte, timestamp, age, cents, lat, lng, flag, } from './scalars';
|
|
27
27
|
//# sourceMappingURL=z2.d.ts.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type ClientSideServerInstanceInfo } from '../client-side-server/protocol';
|
|
2
|
-
import type { ClientSideServerRequestHandler } from '../client-side-server/mqtt-webrtc';
|
|
1
|
+
import { type ClientSideServerInstanceInfo } from '../client-side-server/protocol.js';
|
|
2
|
+
import type { ClientSideServerRequestHandler } from '../client-side-server/mqtt-webrtc.js';
|
|
3
3
|
export interface HTTPForwarderOptions {
|
|
4
4
|
/** Base URL of the upstream HTTP server (e.g. "http://localhost:8080"). */
|
|
5
5
|
upstream?: string;
|
package/dist/bridge/index.d.ts
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
* HTTP server on the same LAN. Responses are shipped back as
|
|
7
7
|
* `PLAT_RESPONSE` messages on the same data channel.
|
|
8
8
|
*/
|
|
9
|
-
import { type ClientSideServerMQTTWebRTCOptions, type ClientSideServerWorkerInfo } from '../client-side-server/mqtt-webrtc';
|
|
10
|
-
import type { ClientSideServerInstanceInfo } from '../client-side-server/protocol';
|
|
11
|
-
export { createHTTPForwarder, type HTTPForwarderOptions } from './http-forwarder';
|
|
9
|
+
import { type ClientSideServerMQTTWebRTCOptions, type ClientSideServerWorkerInfo } from '../client-side-server/mqtt-webrtc.js';
|
|
10
|
+
import type { ClientSideServerInstanceInfo } from '../client-side-server/protocol.js';
|
|
11
|
+
export { createHTTPForwarder, type HTTPForwarderOptions } from './http-forwarder.js';
|
|
12
12
|
export interface PLATHTTPBridgeOptions extends ClientSideServerMQTTWebRTCOptions {
|
|
13
13
|
/** css:// name the bridge registers as (e.g. "my-api" or "authority.com/my-api"). */
|
|
14
14
|
name: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-proxy.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/api-proxy.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"api-proxy.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/api-proxy.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA8KH;;GAEG;AACH,wBAAsB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAkGzE"}
|
|
@@ -7,6 +7,7 @@ import path from 'path';
|
|
|
7
7
|
import { OpenAPIClient } from '../../client/openapi-client.js';
|
|
8
8
|
import { createClientSideServerMQTTWebRTCTransportPlugin } from '../../client-side-server/mqtt-webrtc.js';
|
|
9
9
|
import { PLAT_AUTHORITY_URL } from '../../client-side-server/authority-default.js';
|
|
10
|
+
import { resolveCommand } from '../../args/method_name.js';
|
|
10
11
|
/**
|
|
11
12
|
* Parse CLI arguments into params object and options
|
|
12
13
|
* Supports multiple formats:
|
|
@@ -113,6 +114,16 @@ function findOperation(spec, operationId) {
|
|
|
113
114
|
}
|
|
114
115
|
return null;
|
|
115
116
|
}
|
|
117
|
+
function operationIds(spec) {
|
|
118
|
+
const ids = [];
|
|
119
|
+
for (const methods of Object.values(spec.paths)) {
|
|
120
|
+
for (const operation of Object.values(methods)) {
|
|
121
|
+
if (operation.operationId)
|
|
122
|
+
ids.push(operation.operationId);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return ids;
|
|
126
|
+
}
|
|
116
127
|
/**
|
|
117
128
|
* Check if a string is an HTTP method
|
|
118
129
|
*/
|
|
@@ -145,13 +156,23 @@ export async function apiProxy(cwd, argv) {
|
|
|
145
156
|
let methodOverride;
|
|
146
157
|
let pathOverride;
|
|
147
158
|
let argsStartIndex = 1;
|
|
148
|
-
|
|
159
|
+
// Spec paths always start with `/`, so `get user` is the operation name, not `GET user`.
|
|
160
|
+
if (isHttpMethod(argv[0]) && argv[1]?.startsWith('/')) {
|
|
149
161
|
methodOverride = argv[0].toUpperCase();
|
|
150
162
|
pathOverride = argv[1];
|
|
151
163
|
argsStartIndex = 2;
|
|
152
164
|
}
|
|
153
165
|
else {
|
|
154
|
-
|
|
166
|
+
// Any spelling of the name works: runCloneFeed, run-clone-feed, run_clone_feed, `run clone feed`.
|
|
167
|
+
const resolved = resolveCommand(operationIds(spec), argv);
|
|
168
|
+
if (!resolved.ok) {
|
|
169
|
+
console.error(resolved.reason === 'ambiguous'
|
|
170
|
+
? `❌ Error: '${argv[0]}' is ambiguous. Could be: ${resolved.candidates.join(', ')}`
|
|
171
|
+
: `❌ Error: Operation '${argv[0]}' not found in OpenAPI spec`);
|
|
172
|
+
process.exit(1);
|
|
173
|
+
}
|
|
174
|
+
operationId = resolved.name;
|
|
175
|
+
argsStartIndex = resolved.consumed;
|
|
155
176
|
}
|
|
156
177
|
let operation = null;
|
|
157
178
|
// If we have method + path override, find the operation by those
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-proxy.js","sourceRoot":"","sources":["../../../src/cli/commands/api-proxy.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,EAAE,+CAA+C,EAAE,MAAM,sCAAsC,CAAA;AACtG,OAAO,EAAE,kBAAkB,EAAE,MAAM,4CAA4C,CAAA;
|
|
1
|
+
{"version":3,"file":"api-proxy.js","sourceRoot":"","sources":["../../../src/cli/commands/api-proxy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The extensible CLI engine behind `plat run`, generated CLIs and any app-specific CLI.
|
|
3
|
+
*
|
|
4
|
+
* Everything an application might want to do differently is an option here, so nobody has to
|
|
5
|
+
* bypass plat's CLI to get custom behaviour: add CLI-only commands, wrap or replace a method,
|
|
6
|
+
* map bare words to parameters, discover the server, rewrite input or output, handle unknown
|
|
7
|
+
* commands, format errors. Pure: no network, no node-only imports. The transport is `call`.
|
|
8
|
+
*/
|
|
9
|
+
import { type ResolvedCommand } from '../args/method_name.js';
|
|
10
|
+
import { type CliFormatter } from './format.js';
|
|
11
|
+
/** One operation from the OpenAPI spec. */
|
|
12
|
+
export interface CliCommandInfo {
|
|
13
|
+
name: string;
|
|
14
|
+
method: string;
|
|
15
|
+
path: string;
|
|
16
|
+
summary?: string;
|
|
17
|
+
params: {
|
|
18
|
+
name: string;
|
|
19
|
+
required: boolean;
|
|
20
|
+
}[];
|
|
21
|
+
}
|
|
22
|
+
/** Pull the callable operations out of an OpenAPI document. */
|
|
23
|
+
export declare function extractCommands(spec: any): CliCommandInfo[];
|
|
24
|
+
export interface CliParsed {
|
|
25
|
+
input: Record<string, any>;
|
|
26
|
+
format: string;
|
|
27
|
+
/** Bare words after the command, in order (for `positional`). */
|
|
28
|
+
words: string[];
|
|
29
|
+
}
|
|
30
|
+
export interface CliContext {
|
|
31
|
+
/** The tokens after the command name (flags, `--k=v`, bare words). */
|
|
32
|
+
argv: readonly string[];
|
|
33
|
+
/** The matched spec operation; null for a CLI-only command. */
|
|
34
|
+
command: CliCommandInfo | null;
|
|
35
|
+
/** The name that matched, canonical (`runCloneFeed`, or your custom command's key). */
|
|
36
|
+
name: string;
|
|
37
|
+
/** What will be sent. `beforeCall` and overrides may change it. */
|
|
38
|
+
input: Record<string, any>;
|
|
39
|
+
format: string;
|
|
40
|
+
spec: any;
|
|
41
|
+
options: CliOptions;
|
|
42
|
+
/** Print helpers that honour `options.io`. */
|
|
43
|
+
log: (text: string) => void;
|
|
44
|
+
error: (text: string) => void;
|
|
45
|
+
}
|
|
46
|
+
export type CliCall = (command: CliCommandInfo, input: Record<string, any>, ctx: CliContext) => Promise<unknown>;
|
|
47
|
+
/** A CLI-only command. Return a value to have it printed in the chosen format, or print yourself. */
|
|
48
|
+
export type CliCustomCommand = (ctx: CliContext) => unknown | Promise<unknown>;
|
|
49
|
+
/** Wrap or replace a spec method for the CLI. `next` performs the normal call (with the current input). */
|
|
50
|
+
export type CliOverride = (ctx: CliContext, next: (input?: Record<string, any>) => Promise<unknown>) => unknown | Promise<unknown>;
|
|
51
|
+
export interface CliUnknown {
|
|
52
|
+
argv: readonly string[];
|
|
53
|
+
reason: 'unknown' | 'ambiguous';
|
|
54
|
+
candidates: string[];
|
|
55
|
+
spec: any;
|
|
56
|
+
}
|
|
57
|
+
export interface CliOptions {
|
|
58
|
+
/** The OpenAPI document, or a function that gets it (fetch it, read a file, discover a server).
|
|
59
|
+
* Loaded lazily: only when a spec method, help or onUnknown needs it, never for a CLI-only command. */
|
|
60
|
+
spec: any | (() => any | Promise<any>);
|
|
61
|
+
/** The transport. Plat's runtime supplies one over `OpenAPIClient`; the light entry over `fetch`. */
|
|
62
|
+
call: CliCall;
|
|
63
|
+
/** CLI-only commands, matched before spec methods; they win on a name clash (a custom `describe` is
|
|
64
|
+
* never turned into a longer stitched method like `describeRelation`). A custom `help` replaces the
|
|
65
|
+
* built-in help for `help`, `--help` and `-h`. Multi-word keys work. */
|
|
66
|
+
commands?: Record<string, CliCustomCommand>;
|
|
67
|
+
/** Wraps EVERY spec call (outermost): confirmations, retries, logging. `next` does the rest of the chain. */
|
|
68
|
+
around?: (ctx: CliContext, next: (input?: Record<string, any>) => Promise<unknown>) => unknown | Promise<unknown>;
|
|
69
|
+
/** Per-method CLI behaviour layered on top of a spec method. */
|
|
70
|
+
overrides?: Record<string, CliOverride>;
|
|
71
|
+
/** `{ sql: ['datasource', 'query'] }` — bare words after the command fill these params, in order. */
|
|
72
|
+
positional?: Record<string, string[]>;
|
|
73
|
+
/** Replace argument parsing entirely. */
|
|
74
|
+
parseArgs?: (argv: readonly string[], command: CliCommandInfo | null) => CliParsed;
|
|
75
|
+
/** Replace how a typed name maps to a command (default: any spelling, longest match). */
|
|
76
|
+
resolveName?: (names: readonly string[], argv: readonly string[]) => ResolvedCommand;
|
|
77
|
+
/** Runs before every spec call; mutate `ctx.input`, throw to abort. */
|
|
78
|
+
beforeCall?: (ctx: CliContext) => void | Promise<void>;
|
|
79
|
+
/** Runs on every spec result; return what to print. */
|
|
80
|
+
afterCall?: (result: unknown, ctx: CliContext) => unknown | Promise<unknown>;
|
|
81
|
+
/** Fallback for an unknown or ambiguous command. Return true if you handled it. */
|
|
82
|
+
onUnknown?: (info: CliUnknown, ctx: Pick<CliContext, 'log' | 'error' | 'options'>) => boolean | void | Promise<boolean | void>;
|
|
83
|
+
/** Replace how errors are reported. Default: print the message and exit 1. */
|
|
84
|
+
onError?: (err: unknown, ctx: Pick<CliContext, 'log' | 'error' | 'options'>) => void;
|
|
85
|
+
/** Replace the help text (return the string to print, or print yourself and return undefined). */
|
|
86
|
+
help?: (commands: CliCommandInfo[], options: CliOptions, spec: any) => string | void;
|
|
87
|
+
/** Extra or replacement `--format` values. */
|
|
88
|
+
formatters?: Record<string, CliFormatter>;
|
|
89
|
+
defaultFormat?: string;
|
|
90
|
+
/** Title line in the default help. */
|
|
91
|
+
title?: string;
|
|
92
|
+
/** Override console/exit (tests, embedding). */
|
|
93
|
+
io?: {
|
|
94
|
+
log?: (t: string) => void;
|
|
95
|
+
error?: (t: string) => void;
|
|
96
|
+
exit?: (code: number) => never;
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
export declare function defaultParseArgs(argv: readonly string[]): CliParsed;
|
|
100
|
+
export declare function defaultHelp(commands: CliCommandInfo[], options: CliOptions, spec: any): string;
|
|
101
|
+
/** Run the CLI. Resolves when done; failures go through `onError` (default: exit 1). */
|
|
102
|
+
export declare function runCliCore(options: CliOptions, argv: readonly string[]): Promise<void>;
|
|
103
|
+
//# sourceMappingURL=core.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/cli/core.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/core.js
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The extensible CLI engine behind `plat run`, generated CLIs and any app-specific CLI.
|
|
3
|
+
*
|
|
4
|
+
* Everything an application might want to do differently is an option here, so nobody has to
|
|
5
|
+
* bypass plat's CLI to get custom behaviour: add CLI-only commands, wrap or replace a method,
|
|
6
|
+
* map bare words to parameters, discover the server, rewrite input or output, handle unknown
|
|
7
|
+
* commands, format errors. Pure: no network, no node-only imports. The transport is `call`.
|
|
8
|
+
*/
|
|
9
|
+
import { resolveCommand } from '../args/method_name.js';
|
|
10
|
+
import { defaultFormatters } from './format.js';
|
|
11
|
+
/** Pull the callable operations out of an OpenAPI document. */
|
|
12
|
+
export function extractCommands(spec) {
|
|
13
|
+
const commands = [];
|
|
14
|
+
for (const [urlPath, methods] of Object.entries(spec?.paths ?? {})) {
|
|
15
|
+
for (const [httpMethod, _op] of Object.entries(methods)) {
|
|
16
|
+
const op = _op;
|
|
17
|
+
if (!op?.operationId)
|
|
18
|
+
continue;
|
|
19
|
+
const params = [];
|
|
20
|
+
for (const p of op.parameters ?? [])
|
|
21
|
+
params.push({ name: p.name, required: p.required ?? false });
|
|
22
|
+
const schema = op.requestBody?.content?.['application/json']?.schema;
|
|
23
|
+
if (schema?.properties) {
|
|
24
|
+
const required = new Set(schema.required ?? []);
|
|
25
|
+
for (const name of Object.keys(schema.properties))
|
|
26
|
+
params.push({ name, required: required.has(name) });
|
|
27
|
+
}
|
|
28
|
+
commands.push({ name: op.operationId, method: httpMethod.toUpperCase(), path: urlPath, summary: op.summary, params });
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return commands;
|
|
32
|
+
}
|
|
33
|
+
export function defaultParseArgs(argv) {
|
|
34
|
+
const input = {};
|
|
35
|
+
const words = [];
|
|
36
|
+
let format = '';
|
|
37
|
+
for (const arg of argv) {
|
|
38
|
+
const m = arg.match(/^--([\w-]+)=(.*)$/) || arg.match(/^--([\w-]+)$/);
|
|
39
|
+
if (!m) {
|
|
40
|
+
words.push(arg);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (m[1] === 'format') {
|
|
44
|
+
format = m[2] ?? '';
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
const key = m[1].replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
48
|
+
let val = m[2] ?? true;
|
|
49
|
+
if (val === 'true')
|
|
50
|
+
val = true;
|
|
51
|
+
else if (val === 'false')
|
|
52
|
+
val = false;
|
|
53
|
+
else if (typeof val === 'string' && /^-?\d+(\.\d+)?$/.test(val))
|
|
54
|
+
val = Number(val);
|
|
55
|
+
else if (typeof val === 'string' && (val.startsWith('{') || val.startsWith('['))) {
|
|
56
|
+
try {
|
|
57
|
+
val = JSON.parse(val);
|
|
58
|
+
}
|
|
59
|
+
catch { }
|
|
60
|
+
}
|
|
61
|
+
input[key] = val;
|
|
62
|
+
}
|
|
63
|
+
return { input, format, words };
|
|
64
|
+
}
|
|
65
|
+
export function defaultHelp(commands, options, spec) {
|
|
66
|
+
const lines = [`${options.title ?? spec?.info?.title ?? 'API'} CLI\n`];
|
|
67
|
+
lines.push('Usage: <command> [--key=value ...] [--format=json|yaml|table|csv|human]\n');
|
|
68
|
+
lines.push('Commands:');
|
|
69
|
+
for (const name of Object.keys(options.commands ?? {}))
|
|
70
|
+
lines.push(` ${name}`);
|
|
71
|
+
for (const cmd of commands) {
|
|
72
|
+
const params = cmd.params.map(p => p.required ? `--${p.name}` : `[--${p.name}]`).join(' ');
|
|
73
|
+
const summary = cmd.summary ? ` — ${cmd.summary}` : '';
|
|
74
|
+
lines.push(` ${cmd.name.padEnd(30)} ${params}${summary}`);
|
|
75
|
+
}
|
|
76
|
+
return lines.join('\n');
|
|
77
|
+
}
|
|
78
|
+
/** Run the CLI. Resolves when done; failures go through `onError` (default: exit 1). */
|
|
79
|
+
export async function runCliCore(options, argv) {
|
|
80
|
+
const log = options.io?.log ?? ((t) => console.log(t));
|
|
81
|
+
const error = options.io?.error ?? ((t) => console.error(t));
|
|
82
|
+
const exit = options.io?.exit ?? ((code) => process.exit(code));
|
|
83
|
+
const base = { log, error, options };
|
|
84
|
+
const fail = (err) => {
|
|
85
|
+
if (options.onError)
|
|
86
|
+
return options.onError(err, base);
|
|
87
|
+
error(err instanceof Error ? err.message : String(err));
|
|
88
|
+
exit(1);
|
|
89
|
+
};
|
|
90
|
+
try {
|
|
91
|
+
const custom = options.commands ?? {};
|
|
92
|
+
const formatters = { ...defaultFormatters, ...options.formatters };
|
|
93
|
+
let loaded;
|
|
94
|
+
const load = async () => {
|
|
95
|
+
if (!loaded) {
|
|
96
|
+
const spec = typeof options.spec === 'function' ? await options.spec() : options.spec;
|
|
97
|
+
loaded = { spec, commands: extractCommands(spec) };
|
|
98
|
+
}
|
|
99
|
+
return loaded;
|
|
100
|
+
};
|
|
101
|
+
const resolver = options.resolveName ?? resolveCommand;
|
|
102
|
+
const [first] = argv;
|
|
103
|
+
const wantsHelp = first === undefined || first === 'help' || first === '--help' || first === '-h';
|
|
104
|
+
if (wantsHelp && !custom.help) {
|
|
105
|
+
const { spec, commands } = await load();
|
|
106
|
+
const text = (options.help ?? defaultHelp)(commands, options, spec);
|
|
107
|
+
if (text !== undefined)
|
|
108
|
+
log(text);
|
|
109
|
+
return exit(0);
|
|
110
|
+
}
|
|
111
|
+
// CLI-only commands first, so the spec (and the network) is only needed for spec methods.
|
|
112
|
+
let resolved = resolver(Object.keys(custom), wantsHelp ? ['help'] : argv);
|
|
113
|
+
// A replaced resolver may answer with a spec name it was never offered; only custom names count here.
|
|
114
|
+
if (resolved.ok && !custom[resolved.name])
|
|
115
|
+
resolved = { ok: false, reason: 'unknown', candidates: [] };
|
|
116
|
+
let spec = undefined;
|
|
117
|
+
let commands = [];
|
|
118
|
+
if (!resolved.ok && resolved.reason === 'unknown') {
|
|
119
|
+
;
|
|
120
|
+
({ spec, commands } = await load());
|
|
121
|
+
resolved = resolver(commands.map(c => c.name), argv);
|
|
122
|
+
}
|
|
123
|
+
if (!resolved.ok) {
|
|
124
|
+
const handled = await options.onUnknown?.({ argv, reason: resolved.reason, candidates: resolved.candidates, spec }, base);
|
|
125
|
+
if (handled === true)
|
|
126
|
+
return;
|
|
127
|
+
return fail(new Error(resolved.reason === 'ambiguous'
|
|
128
|
+
? `Ambiguous command: ${first}. Could be: ${resolved.candidates.join(', ')}.`
|
|
129
|
+
: `Unknown command: ${first}. Run with --help for available commands.`));
|
|
130
|
+
}
|
|
131
|
+
if (wantsHelp)
|
|
132
|
+
resolved = { ...resolved, consumed: first === undefined ? 0 : 1 };
|
|
133
|
+
const command = custom[resolved.name] ? null : commands.find(c => c.name === resolved.name) ?? null;
|
|
134
|
+
const rest = argv.slice(resolved.consumed);
|
|
135
|
+
const parsed = (options.parseArgs ?? defaultParseArgs)(rest, command);
|
|
136
|
+
const input = { ...parsed.input };
|
|
137
|
+
const positional = options.positional?.[resolved.name] ?? [];
|
|
138
|
+
positional.forEach((param, index) => {
|
|
139
|
+
const word = parsed.words[index];
|
|
140
|
+
if (word !== undefined && input[param] === undefined)
|
|
141
|
+
input[param] = word;
|
|
142
|
+
});
|
|
143
|
+
const format = parsed.format || options.defaultFormat || 'json';
|
|
144
|
+
const ctx = { ...base, argv: rest, command, name: resolved.name, input, format, spec };
|
|
145
|
+
const print = (value) => {
|
|
146
|
+
if (value === undefined)
|
|
147
|
+
return;
|
|
148
|
+
const formatter = formatters[format];
|
|
149
|
+
if (!formatter)
|
|
150
|
+
throw new Error(`Unknown format: ${format}. Available: ${Object.keys(formatters).join(', ')}`);
|
|
151
|
+
log(formatter(value));
|
|
152
|
+
};
|
|
153
|
+
const customRun = custom[resolved.name];
|
|
154
|
+
if (customRun)
|
|
155
|
+
return print(await customRun(ctx));
|
|
156
|
+
if (!command)
|
|
157
|
+
return;
|
|
158
|
+
const call = async (override) => {
|
|
159
|
+
if (override)
|
|
160
|
+
ctx.input = override;
|
|
161
|
+
await options.beforeCall?.(ctx);
|
|
162
|
+
const result = await options.call(command, ctx.input, ctx);
|
|
163
|
+
return options.afterCall ? options.afterCall(result, ctx) : result;
|
|
164
|
+
};
|
|
165
|
+
const override = options.overrides?.[resolved.name];
|
|
166
|
+
const inner = override ? () => override(ctx, call) : () => call();
|
|
167
|
+
print(options.around ? await options.around(ctx, async (input) => {
|
|
168
|
+
if (input)
|
|
169
|
+
ctx.input = input;
|
|
170
|
+
return inner();
|
|
171
|
+
}) : await inner());
|
|
172
|
+
}
|
|
173
|
+
catch (err) {
|
|
174
|
+
fail(err);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=core.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../../src/cli/core.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in CLI output formatters. Pure (no node-only imports besides the optional terminal width),
|
|
3
|
+
* so the lightweight client package can ship them.
|
|
4
|
+
*/
|
|
5
|
+
export declare function formatJson(data: any): string;
|
|
6
|
+
export declare function formatYaml(data: any, indent?: number): string;
|
|
7
|
+
export declare function formatHuman(data: any, indent?: number): string;
|
|
8
|
+
export declare function formatTable(data: any): string;
|
|
9
|
+
export declare function formatCsv(data: any): string;
|
|
10
|
+
export type CliFormatter = (data: any) => string;
|
|
11
|
+
/** Name → formatter. A CLI adds or replaces entries through `CliOptions.formatters`. */
|
|
12
|
+
export declare const defaultFormatters: Record<string, CliFormatter>;
|
|
13
|
+
//# sourceMappingURL=format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/cli/format.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,wBAAgB,UAAU,CAAC,IAAI,EAAE,GAAG,GAAG,MAAM,CAE5C;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,SAAI,GAAG,MAAM,CAyBxD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,SAAI,GAAG,MAAM,CAiBzD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,GAAG,GAAG,MAAM,CA0D7C;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,GAAG,GAAG,MAAM,CAoB3C;AAED,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,GAAG,KAAK,MAAM,CAAA;AAEhD,wFAAwF;AACxF,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAM1D,CAAA"}
|