@wuapidev/cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +84 -0
- package/dist/args.d.ts +17 -0
- package/dist/args.d.ts.map +1 -0
- package/dist/args.js +96 -0
- package/dist/args.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +7 -0
- package/dist/cli.js.map +1 -0
- package/dist/context.d.ts +45 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +120 -0
- package/dist/context.js.map +1 -0
- package/dist/credentials.d.ts +31 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +90 -0
- package/dist/credentials.js.map +1 -0
- package/dist/dialcodes.d.ts +5 -0
- package/dist/dialcodes.d.ts.map +1 -0
- package/dist/dialcodes.js +51 -0
- package/dist/dialcodes.js.map +1 -0
- package/dist/dispatch.d.ts +37 -0
- package/dist/dispatch.d.ts.map +1 -0
- package/dist/dispatch.js +225 -0
- package/dist/dispatch.js.map +1 -0
- package/dist/dotenv.d.ts +7 -0
- package/dist/dotenv.d.ts.map +1 -0
- package/dist/dotenv.js +67 -0
- package/dist/dotenv.js.map +1 -0
- package/dist/errors.d.ts +24 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +41 -0
- package/dist/errors.js.map +1 -0
- package/dist/files.d.ts +4 -0
- package/dist/files.d.ts.map +1 -0
- package/dist/files.js +35 -0
- package/dist/files.js.map +1 -0
- package/dist/generated/operations.d.ts +3 -0
- package/dist/generated/operations.d.ts.map +1 -0
- package/dist/generated/operations.js +4462 -0
- package/dist/generated/operations.js.map +1 -0
- package/dist/help.d.ts +13 -0
- package/dist/help.d.ts.map +1 -0
- package/dist/help.js +176 -0
- package/dist/help.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/io.d.ts +35 -0
- package/dist/io.d.ts.map +1 -0
- package/dist/io.js +103 -0
- package/dist/io.js.map +1 -0
- package/dist/link.d.ts +26 -0
- package/dist/link.d.ts.map +1 -0
- package/dist/link.js +226 -0
- package/dist/link.js.map +1 -0
- package/dist/login.d.ts +30 -0
- package/dist/login.d.ts.map +1 -0
- package/dist/login.js +224 -0
- package/dist/login.js.map +1 -0
- package/dist/main.d.ts +3 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +88 -0
- package/dist/main.js.map +1 -0
- package/dist/mcp.d.ts +3 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +127 -0
- package/dist/mcp.js.map +1 -0
- package/dist/operation.d.ts +32 -0
- package/dist/operation.d.ts.map +1 -0
- package/dist/operation.js +3 -0
- package/dist/operation.js.map +1 -0
- package/dist/paths.d.ts +12 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +27 -0
- package/dist/paths.js.map +1 -0
- package/dist/profiles.d.ts +6 -0
- package/dist/profiles.d.ts.map +1 -0
- package/dist/profiles.js +119 -0
- package/dist/profiles.js.map +1 -0
- package/dist/qr.d.ts +19 -0
- package/dist/qr.d.ts.map +1 -0
- package/dist/qr.js +198 -0
- package/dist/qr.js.map +1 -0
- package/dist/send.d.ts +3 -0
- package/dist/send.d.ts.map +1 -0
- package/dist/send.js +73 -0
- package/dist/send.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- package/package.json +61 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 wuapi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# wuapi CLI
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@wuapidev/cli)
|
|
4
|
+
[](https://github.com/wuapidev/wuapi-cli/actions/workflows/ci.yml)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
|
|
7
|
+
The command line for [wuapi](https://wuapi.dev), the WhatsApp API for developers. Log in from the browser, link a number by QR code or pairing code, send a message, set up the MCP server, and call every endpoint of the API, from your terminal or from an AI agent.
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npx @wuapidev/cli login # opens the browser, stores a key
|
|
11
|
+
npx @wuapidev/cli link --country VE # shows a QR code, waits until the number is linked
|
|
12
|
+
npx @wuapidev/cli send +584121234567 "Hola" # sends from your linked number
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Node 20 or later. Using it often? Install it once and the command is just `wuapi`:
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
npm install -g @wuapidev/cli
|
|
19
|
+
wuapi login
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Docs: [wuapi.dev/docs#cli](https://wuapi.dev/docs#cli).
|
|
23
|
+
|
|
24
|
+
> wuapi links your own numbers as devices, the same way WhatsApp Web works. It does not use the WhatsApp Business Platform. WhatsApp can restrict numbers that behave like spam: send only to people who expect your messages.
|
|
25
|
+
|
|
26
|
+
## Commands
|
|
27
|
+
|
|
28
|
+
| Command | |
|
|
29
|
+
|---|---|
|
|
30
|
+
| `wuapi login [--env] [--no-browser] [--profile <name>]` | Log in in the browser. The CLI shows a code, you approve it at wuapi.dev, and it stores a new API key. `--env` also writes `WUAPI_API_KEY` to `./.env` and adds `.env` to `./.gitignore`. |
|
|
31
|
+
| `wuapi login --start` / `--finish` | The same in two steps (see [Agents](#agents)). |
|
|
32
|
+
| `wuapi profiles` | Your stored logins, `*` on the current one. |
|
|
33
|
+
| `wuapi switch [<profile>]` | Change the current profile (a picker when you leave out the name). |
|
|
34
|
+
| `wuapi logout [<profile>] [--all]` | Forget a login. The key stays valid until you revoke it at [wuapi.dev/app/api-keys](https://wuapi.dev/app/api-keys). |
|
|
35
|
+
| `wuapi whoami` | The organization, project and key in use. |
|
|
36
|
+
| `wuapi link [--phone +E164] [--country XX] [--city name] [--name label] [--open] [--no-wait] [--timeout 300]` | Create an account and link it. Without `--phone`: a QR code in the terminal (`--open` also opens it in the browser; it refreshes as the code rotates). With `--phone`: an 8-character pairing code to type in WhatsApp > Settings > Linked devices > Link a device > Link with phone number instead. The proxy location is the number's country (from `--phone`, or `--country`) and its biggest city, or the best match for `--city`. |
|
|
37
|
+
| `wuapi wait <accountId> [--timeout 300]` | Wait until an account is linked and ready. |
|
|
38
|
+
| `wuapi send <to> <text> [--account <id>] [--wait]` | Send a text. `--account` can be left out when one account is ready. `--wait` waits until it is sent or failed. |
|
|
39
|
+
| `wuapi mcp add [--client claude\|cursor\|vscode] [--scope project\|user]` | Register the local MCP server (`npx -y @wuapidev/mcp`) with your client. No key goes into the client's config: the server uses your `wuapi login`. |
|
|
40
|
+
|
|
41
|
+
### Every API endpoint
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
wuapi <resource> <method> [ids...] [--field value ...] [--data '<json>'|@file.json] [--all]
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
```sh
|
|
48
|
+
wuapi accounts list
|
|
49
|
+
wuapi messages list --accountId acc_1 --limit 5
|
|
50
|
+
wuapi groups get acc_1 120363012345678901@g.us
|
|
51
|
+
wuapi messages send --accountId acc_1 --to +584121234567 --type image --media.url https://example.com/a.jpg
|
|
52
|
+
wuapi webhook-endpoints create --url https://example.com/hook --events '["message.received"]'
|
|
53
|
+
wuapi projects api-keys list prj_1 --all
|
|
54
|
+
wuapi me
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Ids are positional, in the order the path takes them (or `--accountId acc_1`). Other flags are the query parameters or body fields of the operation: values are JSON when they parse (`5`, `true`, `["a"]`), text otherwise, and always text where the API expects a string. `--a.b value` sets a nested field. `--data` takes a JSON body, `@file.json` or `@-` (stdin); flags override it. List methods print one page (with `nextCursor`); `--all` fetches every page.
|
|
58
|
+
|
|
59
|
+
`wuapi help` lists the resources, `wuapi help <resource>` its methods, and `wuapi <resource> <method> --help` the fields, from the OpenAPI spec.
|
|
60
|
+
|
|
61
|
+
## Keys and profiles
|
|
62
|
+
|
|
63
|
+
The key comes from, in order: `--api-key`, `WUAPI_API_KEY`, `WUAPI_API_KEY` in `./.env`, the profile `--profile` or `WUAPI_PROFILE` names, the current profile. `--project <id or ext:externalId>` (or `WUAPI_PROJECT`) acts inside one project; a profile made from a project key uses its project. `--base-url` / `WUAPI_BASE_URL` point at another API host (https only, or http on localhost).
|
|
64
|
+
|
|
65
|
+
Each `wuapi login` adds a profile, named after the organization (`acme`) or organization and project (`acme/store-1`), and makes it current. Profiles live in `~/.config/wuapi/credentials.json` (`$XDG_CONFIG_HOME/wuapi`, or `%APPDATA%\wuapi` on Windows), readable only by you. The CLI never prints a key.
|
|
66
|
+
|
|
67
|
+
## Agents
|
|
68
|
+
|
|
69
|
+
Every command takes `--json`: the result is JSON on stdout, logs and progress go to stderr, and a failure exits non-zero with `{"error": {"code", "message"}}` on stdout. With `--json`, or when stdin is not a terminal, the CLI never asks anything.
|
|
70
|
+
|
|
71
|
+
An agent whose shell only shows output after a command ends logs in in two steps:
|
|
72
|
+
|
|
73
|
+
```sh
|
|
74
|
+
npx @wuapidev/cli login --start --json # {"url": "...", "code": "ABCD-EFGH", "expiresIn": 600}; show both to the person
|
|
75
|
+
npx @wuapidev/cli login --finish --json # waits until they approve, then {"profile", "organization", "project", ...}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Linking works the same way: `wuapi link --phone +584121234567 --no-wait --json` returns the account id and the pairing code at once (without `--phone`, `qrCodeUrl` and `qrCodeFile`, a PNG to show), and `wuapi wait <accountId> --json` returns when the number is ready.
|
|
79
|
+
|
|
80
|
+
`wuapi send` uses one idempotency key per command and reuses it on every retry, so a request cut off midway is never sent twice. Every wait is bounded (`--timeout`), and a dropped connection during a login, link or wait is retried until then.
|
|
81
|
+
|
|
82
|
+
## License
|
|
83
|
+
|
|
84
|
+
MIT
|
package/dist/args.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Flags that never take a value: `--json`, `--all`, ... */
|
|
2
|
+
export declare const BOOLEAN_FLAGS: Set<string>;
|
|
3
|
+
export interface Parsed {
|
|
4
|
+
positionals: string[];
|
|
5
|
+
/** Flag name -> raw value (`true` for a flag given without one). Repeats: the last wins. */
|
|
6
|
+
flags: Map<string, string | true>;
|
|
7
|
+
}
|
|
8
|
+
export declare function parseArgs(argv: string[]): Parsed;
|
|
9
|
+
/** A string flag: undefined when absent; a usage error when given without a value. */
|
|
10
|
+
export declare function stringFlag(p: Parsed, name: string): string | undefined;
|
|
11
|
+
export declare function boolFlag(p: Parsed, name: string): boolean;
|
|
12
|
+
export declare function numberFlag(p: Parsed, name: string, fallback: number, min?: number): number;
|
|
13
|
+
/** Fails on flags a command does not take. */
|
|
14
|
+
export declare function allowOnly(p: Parsed, allowed: string[]): void;
|
|
15
|
+
/** Flags every command accepts. */
|
|
16
|
+
export declare const GLOBAL_FLAGS: string[];
|
|
17
|
+
//# sourceMappingURL=args.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAOA,4DAA4D;AAC5D,eAAO,MAAM,aAAa,aAYxB,CAAC;AAIH,MAAM,WAAW,MAAM;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,4FAA4F;IAC5F,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;CACnC;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAqChD;AAED,sFAAsF;AACtF,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKtE;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAKzD;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,SAAI,GAAG,MAAM,CAMrF;AAED,8CAA8C;AAC9C,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAG5D;AAED,mCAAmC;AACnC,eAAO,MAAM,YAAY,UAAgE,CAAC"}
|
package/dist/args.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// Argument parsing. Commands take positionals and `--flag value` /
|
|
2
|
+
// `--flag=value` pairs; the generic `<resource> <method>` commands accept any
|
|
3
|
+
// flag (they become API fields), so this parser knows only which flags never
|
|
4
|
+
// take a value.
|
|
5
|
+
import { usage } from "./errors.js";
|
|
6
|
+
/** Flags that never take a value: `--json`, `--all`, ... */
|
|
7
|
+
export const BOOLEAN_FLAGS = new Set([
|
|
8
|
+
"json",
|
|
9
|
+
"help",
|
|
10
|
+
"version",
|
|
11
|
+
"all",
|
|
12
|
+
"wait",
|
|
13
|
+
"no-wait",
|
|
14
|
+
"open",
|
|
15
|
+
"no-browser",
|
|
16
|
+
"env",
|
|
17
|
+
"start",
|
|
18
|
+
"finish",
|
|
19
|
+
]);
|
|
20
|
+
const SHORT = { h: "help", v: "version" };
|
|
21
|
+
export function parseArgs(argv) {
|
|
22
|
+
const positionals = [];
|
|
23
|
+
const flags = new Map();
|
|
24
|
+
for (let i = 0; i < argv.length; i++) {
|
|
25
|
+
const a = argv[i];
|
|
26
|
+
if (a === "--") {
|
|
27
|
+
positionals.push(...argv.slice(i + 1));
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
if (a.startsWith("--") && a.length > 2) {
|
|
31
|
+
const eq = a.indexOf("=");
|
|
32
|
+
const name = eq === -1 ? a.slice(2) : a.slice(2, eq);
|
|
33
|
+
if (!name)
|
|
34
|
+
throw usage(`Bad flag: ${a}`);
|
|
35
|
+
if (eq !== -1) {
|
|
36
|
+
flags.set(name, a.slice(eq + 1));
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (BOOLEAN_FLAGS.has(name)) {
|
|
40
|
+
flags.set(name, true);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
const next = argv[i + 1];
|
|
44
|
+
if (next !== undefined && (!next.startsWith("-") || /^-\d/.test(next) || next === "-")) {
|
|
45
|
+
flags.set(name, next);
|
|
46
|
+
i++;
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
flags.set(name, true);
|
|
50
|
+
}
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (/^-[a-z]$/i.test(a) && SHORT[a.slice(1)]) {
|
|
54
|
+
flags.set(SHORT[a.slice(1)], true);
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
positionals.push(a);
|
|
58
|
+
}
|
|
59
|
+
return { positionals, flags };
|
|
60
|
+
}
|
|
61
|
+
/** A string flag: undefined when absent; a usage error when given without a value. */
|
|
62
|
+
export function stringFlag(p, name) {
|
|
63
|
+
const v = p.flags.get(name);
|
|
64
|
+
if (v === undefined)
|
|
65
|
+
return undefined;
|
|
66
|
+
if (v === true)
|
|
67
|
+
throw usage(`--${name} needs a value.`);
|
|
68
|
+
return v;
|
|
69
|
+
}
|
|
70
|
+
export function boolFlag(p, name) {
|
|
71
|
+
const v = p.flags.get(name);
|
|
72
|
+
if (v === undefined)
|
|
73
|
+
return false;
|
|
74
|
+
if (v === true)
|
|
75
|
+
return true;
|
|
76
|
+
return !/^(false|0|no|off)$/i.test(v);
|
|
77
|
+
}
|
|
78
|
+
export function numberFlag(p, name, fallback, min = 1) {
|
|
79
|
+
const v = stringFlag(p, name);
|
|
80
|
+
if (v === undefined)
|
|
81
|
+
return fallback;
|
|
82
|
+
const n = Number(v);
|
|
83
|
+
if (!Number.isFinite(n) || n < min)
|
|
84
|
+
throw usage(`--${name} must be a number of at least ${min}.`);
|
|
85
|
+
return n;
|
|
86
|
+
}
|
|
87
|
+
/** Fails on flags a command does not take. */
|
|
88
|
+
export function allowOnly(p, allowed) {
|
|
89
|
+
const ok = new Set([...allowed, ...GLOBAL_FLAGS]);
|
|
90
|
+
for (const name of p.flags.keys())
|
|
91
|
+
if (!ok.has(name))
|
|
92
|
+
throw usage(`Unknown flag --${name}.`);
|
|
93
|
+
}
|
|
94
|
+
/** Flags every command accepts. */
|
|
95
|
+
export const GLOBAL_FLAGS = ["json", "help", "api-key", "base-url", "project", "profile"];
|
|
96
|
+
//# sourceMappingURL=args.js.map
|
package/dist/args.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// The `wuapi` command. See `wuapi help` and https://wuapi.dev/docs#cli.
|
|
3
|
+
import { nodeIo } from "./io.js";
|
|
4
|
+
import { main } from "./main.js";
|
|
5
|
+
const code = await main(process.argv.slice(2), nodeIo());
|
|
6
|
+
process.exitCode = code;
|
|
7
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,wEAAwE;AACxE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;AACzD,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Wuapi } from "@wuapidev/sdk";
|
|
2
|
+
import type { Parsed } from "./args.js";
|
|
3
|
+
import { type Credentials, type Profile } from "./credentials.js";
|
|
4
|
+
import type { Io } from "./io.js";
|
|
5
|
+
export interface Ctx {
|
|
6
|
+
io: Io;
|
|
7
|
+
args: Parsed;
|
|
8
|
+
/** --json: results as JSON on stdout, everything else on stderr. */
|
|
9
|
+
json: boolean;
|
|
10
|
+
/** A person at a terminal: no --json and stdin is a TTY. Only then may a command ask. */
|
|
11
|
+
interactive: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare function makeCtx(io: Io, args: Parsed): Ctx;
|
|
14
|
+
export declare const log: (ctx: Ctx, text: string) => void;
|
|
15
|
+
/** Prints a result: JSON with --json, else the human text. */
|
|
16
|
+
export declare function emit(ctx: Ctx, value: unknown, human: () => string): void;
|
|
17
|
+
export declare const credsPath: (ctx: Ctx) => string;
|
|
18
|
+
export declare const pendingPath: (ctx: Ctx) => string;
|
|
19
|
+
export declare function readCreds(ctx: Ctx): Credentials;
|
|
20
|
+
/** Plain https, or http on this machine only: the key must never travel in clear text. */
|
|
21
|
+
export declare function isSafeBaseUrl(value: string): boolean;
|
|
22
|
+
/** --base-url > WUAPI_BASE_URL > the profile's > https://api.wuapi.dev. */
|
|
23
|
+
export declare function resolveBaseUrl(ctx: Ctx, profile?: Profile): string;
|
|
24
|
+
export type KeySource = "flag" | "env" | "dotenv" | "profile";
|
|
25
|
+
export interface Auth {
|
|
26
|
+
apiKey: string;
|
|
27
|
+
baseUrl: string;
|
|
28
|
+
project?: string;
|
|
29
|
+
source: KeySource;
|
|
30
|
+
/** The stored profile the key came from. */
|
|
31
|
+
profileName?: string;
|
|
32
|
+
profile?: Profile;
|
|
33
|
+
}
|
|
34
|
+
/** The profile named by --profile or WUAPI_PROFILE, else the current one. */
|
|
35
|
+
export declare function selectedProfile(ctx: Ctx, creds: Credentials): {
|
|
36
|
+
name: string;
|
|
37
|
+
profile: Profile;
|
|
38
|
+
} | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* The key: --api-key > WUAPI_API_KEY > WUAPI_API_KEY in ./.env >
|
|
41
|
+
* --profile / WUAPI_PROFILE > the current profile.
|
|
42
|
+
*/
|
|
43
|
+
export declare function resolveAuth(ctx: Ctx): Auth;
|
|
44
|
+
export declare function makeClient(ctx: Ctx, auth?: Auth): Wuapi;
|
|
45
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAIA,OAAO,EAAoB,KAAK,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAExC,OAAO,EAAmB,KAAK,WAAW,EAAE,KAAK,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAGnF,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAGlC,MAAM,WAAW,GAAG;IAClB,EAAE,EAAE,EAAE,CAAC;IACP,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,IAAI,EAAE,OAAO,CAAC;IACd,yFAAyF;IACzF,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,wBAAgB,OAAO,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,GAAG,CAGjD;AAED,eAAO,MAAM,GAAG,GAAI,KAAK,GAAG,EAAE,MAAM,MAAM,SAA4B,CAAC;AAEvE,8DAA8D;AAC9D,wBAAgB,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,MAAM,GAAG,IAAI,CAMxE;AAED,eAAO,MAAM,SAAS,GAAI,KAAK,GAAG,WAA8D,CAAC;AACjG,eAAO,MAAM,WAAW,GAAI,KAAK,GAAG,WAA+D,CAAC;AAEpG,wBAAgB,SAAS,CAAC,GAAG,EAAE,GAAG,GAAG,WAAW,CAM/C;AAED,0FAA0F;AAC1F,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAUpD;AAED,2EAA2E;AAC3E,wBAAgB,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,CAIlE;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE9D,MAAM,WAAW,IAAI;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,SAAS,CAAC;IAClB,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAID,6EAA6E;AAC7E,wBAAgB,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,WAAW,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,CAc5G;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,CA+B1C;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,GAAE,IAAuB,GAAG,KAAK,CAOzE"}
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
// What every command gets: the IO, the parsed arguments, the output mode, and
|
|
2
|
+
// the API key / base URL / project resolved from flags, environment, ./.env
|
|
3
|
+
// and the stored profiles.
|
|
4
|
+
import { DEFAULT_BASE_URL, Wuapi } from "@wuapidev/sdk";
|
|
5
|
+
import { stringFlag } from "./args.js";
|
|
6
|
+
import { loadCredentials } from "./credentials.js";
|
|
7
|
+
import { readDotenvKey } from "./dotenv.js";
|
|
8
|
+
import { CliError, usage } from "./errors.js";
|
|
9
|
+
import { credentialsPath, pendingLoginPath } from "./paths.js";
|
|
10
|
+
export function makeCtx(io, args) {
|
|
11
|
+
const json = args.flags.get("json") !== undefined;
|
|
12
|
+
return { io, args, json, interactive: !json && io.stdinIsTTY };
|
|
13
|
+
}
|
|
14
|
+
export const log = (ctx, text) => ctx.io.err(`${text}\n`);
|
|
15
|
+
/** Prints a result: JSON with --json, else the human text. */
|
|
16
|
+
export function emit(ctx, value, human) {
|
|
17
|
+
if (ctx.json)
|
|
18
|
+
ctx.io.out(`${JSON.stringify(value ?? { ok: true }, null, 2)}\n`);
|
|
19
|
+
else {
|
|
20
|
+
const text = human();
|
|
21
|
+
if (text)
|
|
22
|
+
ctx.io.out(text.endsWith("\n") ? text : `${text}\n`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export const credsPath = (ctx) => credentialsPath(ctx.io.env, ctx.io.platform, ctx.io.home);
|
|
26
|
+
export const pendingPath = (ctx) => pendingLoginPath(ctx.io.env, ctx.io.platform, ctx.io.home);
|
|
27
|
+
export function readCreds(ctx) {
|
|
28
|
+
try {
|
|
29
|
+
return loadCredentials(credsPath(ctx));
|
|
30
|
+
}
|
|
31
|
+
catch (e) {
|
|
32
|
+
throw new CliError("invalid_credentials", e.message);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/** Plain https, or http on this machine only: the key must never travel in clear text. */
|
|
36
|
+
export function isSafeBaseUrl(value) {
|
|
37
|
+
let url;
|
|
38
|
+
try {
|
|
39
|
+
url = new URL(value);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
if (url.username || url.password)
|
|
45
|
+
return false;
|
|
46
|
+
if (url.protocol === "https:")
|
|
47
|
+
return true;
|
|
48
|
+
return url.protocol === "http:" && (url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "[::1]");
|
|
49
|
+
}
|
|
50
|
+
/** --base-url > WUAPI_BASE_URL > the profile's > https://api.wuapi.dev. */
|
|
51
|
+
export function resolveBaseUrl(ctx, profile) {
|
|
52
|
+
const value = stringFlag(ctx.args, "base-url") ?? (ctx.io.env.WUAPI_BASE_URL?.trim() || undefined) ?? profile?.baseUrl ?? DEFAULT_BASE_URL;
|
|
53
|
+
if (!isSafeBaseUrl(value))
|
|
54
|
+
throw usage("The base URL must be https (or http://localhost for development).");
|
|
55
|
+
return value.replace(/\/+$/, "");
|
|
56
|
+
}
|
|
57
|
+
const KEY_RE = /^wu_(live|test)_[A-Za-z0-9]{16,128}$/;
|
|
58
|
+
/** The profile named by --profile or WUAPI_PROFILE, else the current one. */
|
|
59
|
+
export function selectedProfile(ctx, creds) {
|
|
60
|
+
const wanted = stringFlag(ctx.args, "profile") ?? (ctx.io.env.WUAPI_PROFILE?.trim() || undefined);
|
|
61
|
+
if (wanted !== undefined) {
|
|
62
|
+
const profile = creds.profiles[wanted];
|
|
63
|
+
if (!profile) {
|
|
64
|
+
const names = Object.keys(creds.profiles);
|
|
65
|
+
throw new CliError("profile_not_found", `No profile named "${wanted}".${names.length ? ` Profiles: ${names.join(", ")}.` : " Run `npx @wuapidev/cli login`."}`, {
|
|
66
|
+
details: { profiles: names },
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
return { name: wanted, profile };
|
|
70
|
+
}
|
|
71
|
+
if (creds.current && creds.profiles[creds.current])
|
|
72
|
+
return { name: creds.current, profile: creds.profiles[creds.current] };
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* The key: --api-key > WUAPI_API_KEY > WUAPI_API_KEY in ./.env >
|
|
77
|
+
* --profile / WUAPI_PROFILE > the current profile.
|
|
78
|
+
*/
|
|
79
|
+
export function resolveAuth(ctx) {
|
|
80
|
+
const flag = stringFlag(ctx.args, "api-key");
|
|
81
|
+
const env = ctx.io.env.WUAPI_API_KEY?.trim() || undefined;
|
|
82
|
+
const dotenv = flag || env ? undefined : readDotenvKey(ctx.io.cwd);
|
|
83
|
+
let apiKey = flag ?? env ?? dotenv;
|
|
84
|
+
let source = flag ? "flag" : env ? "env" : "dotenv";
|
|
85
|
+
let chosen;
|
|
86
|
+
if (!apiKey) {
|
|
87
|
+
chosen = selectedProfile(ctx, readCreds(ctx));
|
|
88
|
+
if (chosen) {
|
|
89
|
+
apiKey = chosen.profile.apiKey;
|
|
90
|
+
source = "profile";
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else if (stringFlag(ctx.args, "profile") !== undefined) {
|
|
94
|
+
log(ctx, `wuapi: --profile ignored: the key comes from ${source === "flag" ? "--api-key" : source === "env" ? "WUAPI_API_KEY" : "./.env"}.`);
|
|
95
|
+
}
|
|
96
|
+
if (!apiKey) {
|
|
97
|
+
throw new CliError("not_logged_in", "No API key. Run `npx @wuapidev/cli login`, or set WUAPI_API_KEY (create a key at https://wuapi.dev/app/api-keys).");
|
|
98
|
+
}
|
|
99
|
+
if (!KEY_RE.test(apiKey)) {
|
|
100
|
+
const where = source === "flag" ? "--api-key" : source === "env" ? "WUAPI_API_KEY" : source === "dotenv" ? "WUAPI_API_KEY in ./.env" : `profile ${chosen?.name}`;
|
|
101
|
+
throw new CliError("invalid_api_key", `${where} does not look like a wuapi API key (wu_live_...).`);
|
|
102
|
+
}
|
|
103
|
+
const project = stringFlag(ctx.args, "project") ?? (ctx.io.env.WUAPI_PROJECT?.trim() || undefined) ?? (source === "profile" ? chosen?.profile.project?.id : undefined);
|
|
104
|
+
return {
|
|
105
|
+
apiKey,
|
|
106
|
+
baseUrl: resolveBaseUrl(ctx, chosen?.profile),
|
|
107
|
+
...(project ? { project } : {}),
|
|
108
|
+
source,
|
|
109
|
+
...(chosen ? { profileName: chosen.name, profile: chosen.profile } : {}),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
export function makeClient(ctx, auth = resolveAuth(ctx)) {
|
|
113
|
+
return new Wuapi({
|
|
114
|
+
apiKey: auth.apiKey,
|
|
115
|
+
baseUrl: auth.baseUrl,
|
|
116
|
+
...(auth.project ? { project: auth.project } : {}),
|
|
117
|
+
fetch: ctx.io.fetch,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface Named {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
}
|
|
5
|
+
export interface Profile {
|
|
6
|
+
apiKey: string;
|
|
7
|
+
baseUrl?: string;
|
|
8
|
+
organization: Named;
|
|
9
|
+
project: Named | null;
|
|
10
|
+
keyPrefix?: string;
|
|
11
|
+
createdAt: string;
|
|
12
|
+
}
|
|
13
|
+
export interface Credentials {
|
|
14
|
+
version: 2;
|
|
15
|
+
current: string | null;
|
|
16
|
+
profiles: Record<string, Profile>;
|
|
17
|
+
}
|
|
18
|
+
export declare const EMPTY: Credentials;
|
|
19
|
+
/** `Acme Corp` -> `acme-corp`. Accents dropped; never empty. */
|
|
20
|
+
export declare function slug(text: string): string;
|
|
21
|
+
/** `acme`, or `acme/store-1` for a login scoped to a project. */
|
|
22
|
+
export declare function defaultProfileName(organization: Named, project: Named | null): string;
|
|
23
|
+
/**
|
|
24
|
+
* The name a new login gets: `wanted` when free or when it holds the same
|
|
25
|
+
* organization and project (a re-login replaces it), else `wanted-2`, `-3`...
|
|
26
|
+
*/
|
|
27
|
+
export declare function uniqueProfileName(creds: Credentials, wanted: string, profile: Profile): string;
|
|
28
|
+
/** Reads the file, migrating a version-1 file in place. Missing file: no profiles. */
|
|
29
|
+
export declare function loadCredentials(path?: string): Credentials;
|
|
30
|
+
export declare function saveCredentials(creds: Credentials, path?: string): void;
|
|
31
|
+
//# sourceMappingURL=credentials.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,KAAK,CAAC;IACpB,OAAO,EAAE,KAAK,GAAG,IAAI,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,CAAC,CAAC;IACX,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,eAAO,MAAM,KAAK,EAAE,WAAyD,CAAC;AAE9E,gEAAgE;AAChE,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAUzC;AAED,iEAAiE;AACjE,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,GAAG,IAAI,GAAG,MAAM,CAErF;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAQ9F;AAOD,sFAAsF;AACtF,wBAAgB,eAAe,CAAC,IAAI,GAAE,MAA0B,GAAG,WAAW,CAmC7E;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,GAAE,MAA0B,GAAG,IAAI,CAE1F"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// The stored logins: several profiles (an organization, or one project of it),
|
|
2
|
+
// one of them current. `wuapi login` adds one; `--profile` / WUAPI_PROFILE pick
|
|
3
|
+
// one for a command; `wuapi switch` changes the current one.
|
|
4
|
+
//
|
|
5
|
+
// File (0600): { version: 2, current, profiles: { <name>: Profile } }. A
|
|
6
|
+
// version-1 file (one login, written by 0.0.x previews) is read and migrated
|
|
7
|
+
// in place.
|
|
8
|
+
import { credentialsPath } from "./paths.js";
|
|
9
|
+
import { readJson, writePrivateJson } from "./files.js";
|
|
10
|
+
export const EMPTY = { version: 2, current: null, profiles: {} };
|
|
11
|
+
/** `Acme Corp` -> `acme-corp`. Accents dropped; never empty. */
|
|
12
|
+
export function slug(text) {
|
|
13
|
+
const s = text
|
|
14
|
+
.normalize("NFKD")
|
|
15
|
+
.replace(/[̀-ͯ]/g, "")
|
|
16
|
+
.toLowerCase()
|
|
17
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
18
|
+
.replace(/^-+|-+$/g, "")
|
|
19
|
+
.slice(0, 40)
|
|
20
|
+
.replace(/-+$/g, "");
|
|
21
|
+
return s || "default";
|
|
22
|
+
}
|
|
23
|
+
/** `acme`, or `acme/store-1` for a login scoped to a project. */
|
|
24
|
+
export function defaultProfileName(organization, project) {
|
|
25
|
+
return project ? `${slug(organization.name)}/${slug(project.name)}` : slug(organization.name);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The name a new login gets: `wanted` when free or when it holds the same
|
|
29
|
+
* organization and project (a re-login replaces it), else `wanted-2`, `-3`...
|
|
30
|
+
*/
|
|
31
|
+
export function uniqueProfileName(creds, wanted, profile) {
|
|
32
|
+
const same = (p) => p !== undefined && p.organization.id === profile.organization.id && (p.project?.id ?? null) === (profile.project?.id ?? null);
|
|
33
|
+
if (!creds.profiles[wanted] || same(creds.profiles[wanted]))
|
|
34
|
+
return wanted;
|
|
35
|
+
for (let i = 2;; i++) {
|
|
36
|
+
const name = `${wanted}-${i}`;
|
|
37
|
+
if (!creds.profiles[name] || same(creds.profiles[name]))
|
|
38
|
+
return name;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function isProfile(v) {
|
|
42
|
+
const p = v;
|
|
43
|
+
return typeof p === "object" && p !== null && typeof p.apiKey === "string" && typeof p.organization?.id === "string";
|
|
44
|
+
}
|
|
45
|
+
/** Reads the file, migrating a version-1 file in place. Missing file: no profiles. */
|
|
46
|
+
export function loadCredentials(path = credentialsPath()) {
|
|
47
|
+
let raw;
|
|
48
|
+
try {
|
|
49
|
+
raw = readJson(path);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
throw Object.assign(new Error(`${path} is not valid JSON. Delete it and run \`npx @wuapidev/cli login\` again.`), { code: "invalid_credentials" });
|
|
53
|
+
}
|
|
54
|
+
if (raw === undefined)
|
|
55
|
+
return { ...EMPTY, profiles: {} };
|
|
56
|
+
const r = raw;
|
|
57
|
+
if (r.version === 2 && typeof r.profiles === "object" && r.profiles !== null) {
|
|
58
|
+
const profiles = {};
|
|
59
|
+
for (const [name, p] of Object.entries(r.profiles))
|
|
60
|
+
if (isProfile(p))
|
|
61
|
+
profiles[name] = p;
|
|
62
|
+
const current = typeof r.current === "string" && profiles[r.current] ? r.current : (Object.keys(profiles)[0] ?? null);
|
|
63
|
+
return { version: 2, current, profiles };
|
|
64
|
+
}
|
|
65
|
+
if (r.version === 1 && isProfile(raw)) {
|
|
66
|
+
const v1 = raw;
|
|
67
|
+
const profile = {
|
|
68
|
+
apiKey: v1.apiKey,
|
|
69
|
+
...(v1.baseUrl ? { baseUrl: v1.baseUrl } : {}),
|
|
70
|
+
organization: v1.organization,
|
|
71
|
+
project: v1.project ?? null,
|
|
72
|
+
...(v1.keyPrefix ? { keyPrefix: v1.keyPrefix } : {}),
|
|
73
|
+
createdAt: v1.createdAt ?? new Date().toISOString(),
|
|
74
|
+
};
|
|
75
|
+
const name = defaultProfileName(profile.organization, profile.project);
|
|
76
|
+
const migrated = { version: 2, current: name, profiles: { [name]: profile } };
|
|
77
|
+
try {
|
|
78
|
+
writePrivateJson(path, migrated);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// Read-only config: use the migrated form in memory.
|
|
82
|
+
}
|
|
83
|
+
return migrated;
|
|
84
|
+
}
|
|
85
|
+
throw Object.assign(new Error(`${path} has an unknown format. Delete it and run \`npx @wuapidev/cli login\` again.`), { code: "invalid_credentials" });
|
|
86
|
+
}
|
|
87
|
+
export function saveCredentials(creds, path = credentialsPath()) {
|
|
88
|
+
writePrivateJson(path, creds);
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** `+584121234567` -> `VE`. Undefined when the number does not start with a known code. */
|
|
2
|
+
export declare function countryFromPhone(phone: string): string | undefined;
|
|
3
|
+
/** `+58 412-123 4567` -> `+584121234567`; undefined when it is not a phone number. */
|
|
4
|
+
export declare function normalizePhone(input: string): string | undefined;
|
|
5
|
+
//# sourceMappingURL=dialcodes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dialcodes.d.ts","sourceRoot":"","sources":["../src/dialcodes.ts"],"names":[],"mappings":"AAmCA,2FAA2F;AAC3F,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAOlE;AAED,sFAAsF;AACtF,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKhE"}
|