@openemail/cli 0.0.1 → 0.0.2
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/openemail.js +36 -26
- package/package.json +1 -1
package/openemail.js
CHANGED
|
@@ -344,7 +344,8 @@ const CLI_CALLBACK = {
|
|
|
344
344
|
APP_PATH: '/cli/callback',
|
|
345
345
|
LOOPBACK_PATH: '/callback',
|
|
346
346
|
LOOPBACK_HOST: '127.0.0.1',
|
|
347
|
-
PASTE_SEPARATOR: '.'
|
|
347
|
+
PASTE_SEPARATOR: '.'
|
|
348
|
+
};
|
|
348
349
|
const OAUTH_PARAMS = {
|
|
349
350
|
RESPONSE_TYPE: 'response_type',
|
|
350
351
|
CLIENT_ID: 'client_id',
|
|
@@ -672,7 +673,7 @@ const AUTH_MESSAGES = {
|
|
|
672
673
|
: `OpenEmail could not refresh your sign-in (status ${status}). Try again shortly.`,
|
|
673
674
|
SESSION_EXPIRED_PROFILE_NEXT: (name) => `Run \`openemail login --profile ${name}\` again.`,
|
|
674
675
|
SERVER_SAID: (reason) => `The server said: ${reason}`,
|
|
675
|
-
CLIENT_NAME: (host) =>
|
|
676
|
+
CLIENT_NAME: (host) => `${OAUTH_CLIENT.NAME_PREFIX}${host}`,
|
|
676
677
|
WHO_WORKSPACE: (workspace) => `workspace ${workspace}`,
|
|
677
678
|
WHO_KEY: (keyId) => `key ${keyId}`,
|
|
678
679
|
KEY_STAYS_VALID: (keyId) => `The key itself still works. Revoke it with \`openemail keys revoke ${keyId}\` if you no longer need it.`,
|
|
@@ -818,7 +819,6 @@ const DOCS_CHAT = {
|
|
|
818
819
|
};
|
|
819
820
|
const DOCS_PATHS = {
|
|
820
821
|
DOCS: '/docs',
|
|
821
|
-
DOCS_PREFIX: 'docs/',
|
|
822
822
|
MARKDOWN_EXTENSION: '.md',
|
|
823
823
|
INDEX: '/llms.txt',
|
|
824
824
|
ANCHOR: '#',
|
|
@@ -829,7 +829,8 @@ const DOCS_PATTERNS = {
|
|
|
829
829
|
LEADING_SLASHES: /^\/+/,
|
|
830
830
|
TRAILING_SLASHES: /\/+$/,
|
|
831
831
|
LINE_BREAK: /\r?\n/,
|
|
832
|
-
DOT_SEGMENT: /^\.{1,2}
|
|
832
|
+
DOT_SEGMENT: /^\.{1,2}$/,
|
|
833
|
+
DOCS_PREFIX: /^(?:[a-z]{2}\/)?docs(?:\/|$)/i
|
|
833
834
|
};
|
|
834
835
|
const DOCS_FETCH = {
|
|
835
836
|
ACCEPT: 'text/markdown, text/plain;q=0.9',
|
|
@@ -1111,7 +1112,7 @@ const BOOLEAN_TRUE_WORDS = new Set(['true', '1', 'yes', 'on']);
|
|
|
1111
1112
|
const BOOLEAN_FALSE_WORDS = new Set(['false', '0', 'no', 'off']);
|
|
1112
1113
|
const NEGATIVE_NUMBER_PATTERN = /^-\d+(\.\d+)?$/;
|
|
1113
1114
|
|
|
1114
|
-
var version$1 = "0.0.
|
|
1115
|
+
var version$1 = "0.0.2";
|
|
1115
1116
|
|
|
1116
1117
|
const VERSION$1 = version$1;
|
|
1117
1118
|
const CLI_NAME = 'openemail';
|
|
@@ -1244,7 +1245,7 @@ const SCRIPTING_ROWS = [
|
|
|
1244
1245
|
const HELP_JSON_SCHEMA_VERSION = 1;
|
|
1245
1246
|
const CLI_NAME_WORD_PATTERN = new RegExp(`(^|[^\\w-])${CLI_NAME}($|[^\\w-])`);
|
|
1246
1247
|
|
|
1247
|
-
var version = "0.0.
|
|
1248
|
+
var version = "0.0.6";
|
|
1248
1249
|
|
|
1249
1250
|
const BUILD_BASE_URL = 'https://api.openemail.uk';
|
|
1250
1251
|
|
|
@@ -3495,7 +3496,7 @@ const DomainsCreateAddressMethod = {
|
|
|
3495
3496
|
scopes: ['domains:write'],
|
|
3496
3497
|
parameters: [
|
|
3497
3498
|
{ name: 'id', type: 'string', required: true, description: 'Domain id from `list` or `create`, a UUID.' },
|
|
3498
|
-
{ name: 'body.localPart', type: 'string', required: true, description: 'The part in front of the @, 1 to 64 characters once trimmed, lower cased. Letters, digits and ! # $ % & \' * + / = ? ^ _
|
|
3499
|
+
{ name: 'body.localPart', type: 'string', required: true, description: 'The part in front of the @, 1 to 64 characters once trimmed, lower cased. Letters, digits, the backtick and ! # $ % & \' * + / = ? ^ _ { | } ~ - are allowed, and so are dots between them. `*` on its own is how the catch-all is written and is refused.' },
|
|
3499
3500
|
{ name: 'body.label', type: 'string | null', required: false, description: 'A name for the address shown in the app, trimmed, up to 120 characters. Leave it out, or send null or an empty string, for none.' },
|
|
3500
3501
|
{ name: 'options.signal', type: 'AbortSignal', required: false, description: 'Cancels the request.' },
|
|
3501
3502
|
{ name: 'options.apiKey', type: 'string', required: false, description: 'Overrides the client\'s API key for this call only.' }
|
|
@@ -13921,6 +13922,7 @@ const RESOURCE_ID_LIST_KEY = 'ids';
|
|
|
13921
13922
|
const RESOURCE_ID_LIST_SUFFIX = 'Ids';
|
|
13922
13923
|
const RESOURCE_MAX_SAMPLE = '100';
|
|
13923
13924
|
const RESOURCE_READ_METHOD = 'GET';
|
|
13925
|
+
const RESOURCE_PATCH_METHOD = 'PATCH';
|
|
13924
13926
|
const RESOURCE_EXAMPLE_LIMIT = 5;
|
|
13925
13927
|
const RESOURCE_EXAMPLE_OPTIONAL_FLAGS = 3;
|
|
13926
13928
|
const RESOURCE_CONFIRM_TARGET_LIMIT = 5;
|
|
@@ -13941,6 +13943,7 @@ const RESOURCE_UNSUPPORTED_ESCAPE = /\\[^'\\]/;
|
|
|
13941
13943
|
const RESOURCE_SECRET_FLAG = /(key|token|secret|password)$/;
|
|
13942
13944
|
const RESOURCE_SENTENCE_BREAK = /(?<=[.!?])\s+(?=[A-Z`])/;
|
|
13943
13945
|
const RESOURCE_CAMEL_PATH = /^[a-z]+[A-Z][A-Za-z]*$/;
|
|
13946
|
+
const RESOURCE_EMPTY_STRING_CLEAR = /(\b[Nn]ull\b|`null`) or an empty string/g;
|
|
13944
13947
|
const RESOURCE_EXAMPLE_PATTERNS = {
|
|
13945
13948
|
STRING: /(\w+):\s*'((?:[^'\\\n]|\\.)*)'/g,
|
|
13946
13949
|
NUMBER: /(\w+):\s*(-?\d+(?:\.\d+)?)(?=\s*[,}\n])/g,
|
|
@@ -13979,6 +13982,7 @@ const RESOURCE_HELP = {
|
|
|
13979
13982
|
REQUIRED: 'Required.',
|
|
13980
13983
|
REQUIRED_WITH_DATA: 'Required, here or in `--data`.',
|
|
13981
13984
|
PAGING: 'Add `--all` to walk every page: a table on a terminal, one JSON object per line when piped or with `--ndjson`, and one `{ items, hasMore, nextCursor }` document with `--json`. `--max <n>` stops after that many items.',
|
|
13985
|
+
PAGING_OWN_SHAPE: 'Add `--all` to walk every page: a table on a terminal, one JSON object per line when piped or with `--ndjson`, and one JSON document with `--json`, shaped as Returns describes. `--max <n>` stops after that many items.',
|
|
13982
13986
|
DATA_USAGE: '--data <json|@file|->',
|
|
13983
13987
|
JSON_TYPE: (type) => `JSON shaped as \`${type}\`, inline or from a file with @path.`
|
|
13984
13988
|
};
|
|
@@ -14268,6 +14272,7 @@ const TERMINAL = {
|
|
|
14268
14272
|
MIN_WRAP_WIDTH: 16
|
|
14269
14273
|
};
|
|
14270
14274
|
const CODE_SPAN_DELIMITER = '`';
|
|
14275
|
+
const CODE_SPAN_PATTERN = /`([^`\s](?:[^`]*[^`\s])?)`/g;
|
|
14271
14276
|
const BANNER_LINES = [
|
|
14272
14277
|
' _ _',
|
|
14273
14278
|
' ___ _ __ ___ _ _ ___ _ __ __ _ (_)| |',
|
|
@@ -15535,13 +15540,7 @@ const Config$1 = {
|
|
|
15535
15540
|
Update: Update$1
|
|
15536
15541
|
};
|
|
15537
15542
|
|
|
15538
|
-
const FormatCode = (text, paint) =>
|
|
15539
|
-
const parts = text.split(CODE_SPAN_DELIMITER);
|
|
15540
|
-
if (parts.length < 3)
|
|
15541
|
-
return text;
|
|
15542
|
-
const balanced = parts.length % 2 === 1 ? parts : [...parts.slice(0, -2), `${parts[parts.length - 2]}${CODE_SPAN_DELIMITER}${parts[parts.length - 1]}`];
|
|
15543
|
-
return balanced.map((part, index) => index % 2 === 1 ? paint(part) : part).join('');
|
|
15544
|
-
};
|
|
15543
|
+
const FormatCode = (text, paint) => text.replace(CODE_SPAN_PATTERN, (_span, code) => paint(code));
|
|
15545
15544
|
|
|
15546
15545
|
const KNOWN_KINDS = new Set(Object.values(PROFILE_KINDS));
|
|
15547
15546
|
const IsUsable = (value) => IsRecord$2(value) && KNOWN_KINDS.has(value.kind) && typeof value.baseUrl === 'string';
|
|
@@ -17622,6 +17621,17 @@ const NonEmptyEnv = (name) => {
|
|
|
17622
17621
|
return value === undefined || value.length === 0 ? null : value;
|
|
17623
17622
|
};
|
|
17624
17623
|
|
|
17624
|
+
const LOCAL_NETWORK = /^(localhost|127\.\d+\.\d+\.\d+|0\.0\.0\.0|\[::1\]|10\.\d+\.\d+\.\d+|192\.168\.\d+\.\d+|172\.(1[6-9]|2\d|3[01])\.\d+\.\d+|[^/:]+\.local)(:|\/|$)/i;
|
|
17625
|
+
|
|
17626
|
+
const withScheme = (value) => {
|
|
17627
|
+
const trimmed = value.trim();
|
|
17628
|
+
if (trimmed === '' || /^https?:\/\//i.test(trimmed))
|
|
17629
|
+
return trimmed;
|
|
17630
|
+
const bare = trimmed.replace(/^\/+/, '');
|
|
17631
|
+
return `${LOCAL_NETWORK.test(bare) ? 'http' : 'https'}://${bare}`;
|
|
17632
|
+
};
|
|
17633
|
+
const publicUrl = (value) => withScheme(value).replace(/\/+$/, '');
|
|
17634
|
+
|
|
17625
17635
|
const Invalid = (value) => new UsageError(MESSAGES.INVALID_BASE_URL(Color.Sanitize(value)), { code: CLI_ERROR_CODES.INVALID_VALUE });
|
|
17626
17636
|
const Parse$3 = (url) => {
|
|
17627
17637
|
try {
|
|
@@ -17641,8 +17651,8 @@ const Unspecified = (normalised, url) => new UsageError(MESSAGES.UNSPECIFIED_HOS
|
|
|
17641
17651
|
next: MESSAGES.UNSPECIFIED_HOST_NEXT(Color.Sanitize(LoopbackInstead(url)))
|
|
17642
17652
|
});
|
|
17643
17653
|
const NormaliseUrl = (value) => {
|
|
17644
|
-
const normalised =
|
|
17645
|
-
if (normalised ===
|
|
17654
|
+
const normalised = publicUrl(value);
|
|
17655
|
+
if (normalised.length === 0)
|
|
17646
17656
|
throw Invalid(value);
|
|
17647
17657
|
const url = Parse$3(normalised);
|
|
17648
17658
|
if (url === null || (url.protocol !== URL_PROTOCOLS.HTTP && url.protocol !== URL_PROTOCOLS.HTTPS))
|
|
@@ -19257,11 +19267,7 @@ const PathOf = (raw) => {
|
|
|
19257
19267
|
return raw;
|
|
19258
19268
|
}
|
|
19259
19269
|
};
|
|
19260
|
-
const WithoutDocsPrefix = (path) =>
|
|
19261
|
-
if (path === DOCS_PATHS.DOCS_PREFIX.slice(0, -1))
|
|
19262
|
-
return '';
|
|
19263
|
-
return path.startsWith(DOCS_PATHS.DOCS_PREFIX) ? path.slice(DOCS_PATHS.DOCS_PREFIX.length) : path;
|
|
19264
|
-
};
|
|
19270
|
+
const WithoutDocsPrefix = (path) => path.replace(DOCS_PATTERNS.DOCS_PREFIX, '');
|
|
19265
19271
|
const Decoded = (segment) => {
|
|
19266
19272
|
try {
|
|
19267
19273
|
return decodeURIComponent(segment);
|
|
@@ -26578,7 +26584,7 @@ const RunVerb = (namespace, verb) => async (context) => {
|
|
|
26578
26584
|
|
|
26579
26585
|
const Code = (text) => `${CODE_SPAN_DELIMITER}${text}${CODE_SPAN_DELIMITER}`;
|
|
26580
26586
|
const VerbProse = (verb, text) => {
|
|
26581
|
-
let prose = text;
|
|
26587
|
+
let prose = text.replace(RESOURCE_EMPTY_STRING_CLEAR, '$1');
|
|
26582
26588
|
for (const flag of verb.flags) {
|
|
26583
26589
|
if (flag.parameter === null)
|
|
26584
26590
|
continue;
|
|
@@ -26609,7 +26615,10 @@ const VerbArguments = (verb) => verb.positionals.map(positional => ({
|
|
|
26609
26615
|
|
|
26610
26616
|
const VerbDescription = (verb) => {
|
|
26611
26617
|
const prose = VerbProse(verb, verb.entry.description).trim();
|
|
26612
|
-
|
|
26618
|
+
if (!verb.paginates)
|
|
26619
|
+
return prose;
|
|
26620
|
+
const paging = verb.returns.layout === MANIFEST_DEFAULT_PAGE_LAYOUT ? RESOURCE_HELP.PAGING : RESOURCE_HELP.PAGING_OWN_SHAPE;
|
|
26621
|
+
return `${prose}\n\n${paging}`;
|
|
26613
26622
|
};
|
|
26614
26623
|
|
|
26615
26624
|
const Collect = (fields, example, pattern, value) => {
|
|
@@ -26706,9 +26715,10 @@ const VerbExamples = (namespace, verb, known) => {
|
|
|
26706
26715
|
})
|
|
26707
26716
|
.slice(0, RESOURCE_EXAMPLE_OPTIONAL_FLAGS)
|
|
26708
26717
|
.flat();
|
|
26709
|
-
const
|
|
26718
|
+
const emptyPatch = verb.entry.method.toUpperCase() === RESOURCE_PATCH_METHOD && required.length === 0 && optional.length > 0;
|
|
26719
|
+
const examples = emptyPatch ? [] : [{ command: Join(essential) }];
|
|
26710
26720
|
if (optional.length > 0) {
|
|
26711
|
-
if (required.length > 0 || verb.positionals.some(positional => positional.required))
|
|
26721
|
+
if (!emptyPatch && (required.length > 0 || verb.positionals.some(positional => positional.required)))
|
|
26712
26722
|
examples[0].note = RESOURCE_EXAMPLE_NOTES.REQUIRED;
|
|
26713
26723
|
examples.push({ command: Join([...essential, ...optional]), note: RESOURCE_EXAMPLE_NOTES.FULL });
|
|
26714
26724
|
}
|
|
@@ -26729,7 +26739,7 @@ const VerbExamples = (namespace, verb, known) => {
|
|
|
26729
26739
|
}
|
|
26730
26740
|
const reads = verb.entry.method.toUpperCase() === RESOURCE_READ_METHOD && verb.returns.shape === MANIFEST_RETURN_SHAPES.OBJECT;
|
|
26731
26741
|
if (examples.length < 2 || reads) {
|
|
26732
|
-
examples.push({ command: Join([...essential, `--${GLOBAL_FLAG_NAMES.JSON}`]), note: RESOURCE_EXAMPLE_NOTES.JSON });
|
|
26742
|
+
examples.push({ command: Join([...essential, ...(emptyPatch ? optional : []), `--${GLOBAL_FLAG_NAMES.JSON}`]), note: RESOURCE_EXAMPLE_NOTES.JSON });
|
|
26733
26743
|
}
|
|
26734
26744
|
return examples.slice(0, RESOURCE_EXAMPLE_LIMIT);
|
|
26735
26745
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openemail/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"author": "OpenEmail",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"description": "The official OpenEmail command line. Sign in once, then send and read mail, manage domains, addresses, keys, webhooks, templates, contacts, audiences and every other OpenEmail resource, use the AI tools and connect MCP clients from your terminal.",
|