@meilisearch/cli 0.0.0-stage → 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.
Files changed (165) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +97 -2
  3. package/bin/run.js +15 -0
  4. package/dist/commands/add/documents.js +54 -0
  5. package/dist/commands/add/documents.js.map +1 -0
  6. package/dist/commands/add/indexes.js +39 -0
  7. package/dist/commands/add/indexes.js.map +1 -0
  8. package/dist/commands/add/keys.js +63 -0
  9. package/dist/commands/add/keys.js.map +1 -0
  10. package/dist/commands/add/projects.js +96 -0
  11. package/dist/commands/add/projects.js.map +1 -0
  12. package/dist/commands/auth/login.js +26 -0
  13. package/dist/commands/auth/login.js.map +1 -0
  14. package/dist/commands/auth/logout.js +33 -0
  15. package/dist/commands/auth/logout.js.map +1 -0
  16. package/dist/commands/auth/refresh.js +22 -0
  17. package/dist/commands/auth/refresh.js.map +1 -0
  18. package/dist/commands/auth/status.js +34 -0
  19. package/dist/commands/auth/status.js.map +1 -0
  20. package/dist/commands/cancel/tasks.js +24 -0
  21. package/dist/commands/cancel/tasks.js.map +1 -0
  22. package/dist/commands/config/list.js +18 -0
  23. package/dist/commands/config/list.js.map +1 -0
  24. package/dist/commands/config/set.js +48 -0
  25. package/dist/commands/config/set.js.map +1 -0
  26. package/dist/commands/config/sync-with-cloud.js +144 -0
  27. package/dist/commands/config/sync-with-cloud.js.map +1 -0
  28. package/dist/commands/config/unset.js +28 -0
  29. package/dist/commands/config/unset.js.map +1 -0
  30. package/dist/commands/config/update.js +53 -0
  31. package/dist/commands/config/update.js.map +1 -0
  32. package/dist/commands/delete/documents.js +81 -0
  33. package/dist/commands/delete/documents.js.map +1 -0
  34. package/dist/commands/delete/indexes.js +28 -0
  35. package/dist/commands/delete/indexes.js.map +1 -0
  36. package/dist/commands/delete/keys.js +28 -0
  37. package/dist/commands/delete/keys.js.map +1 -0
  38. package/dist/commands/delete/projects.js +40 -0
  39. package/dist/commands/delete/projects.js.map +1 -0
  40. package/dist/commands/delete/settings.js +28 -0
  41. package/dist/commands/delete/settings.js.map +1 -0
  42. package/dist/commands/delete/tasks.js +34 -0
  43. package/dist/commands/delete/tasks.js.map +1 -0
  44. package/dist/commands/export.js +67 -0
  45. package/dist/commands/export.js.map +1 -0
  46. package/dist/commands/facet-search.js +87 -0
  47. package/dist/commands/facet-search.js.map +1 -0
  48. package/dist/commands/get/batches.js +35 -0
  49. package/dist/commands/get/batches.js.map +1 -0
  50. package/dist/commands/get/documents.js +74 -0
  51. package/dist/commands/get/documents.js.map +1 -0
  52. package/dist/commands/get/health.js +17 -0
  53. package/dist/commands/get/health.js.map +1 -0
  54. package/dist/commands/get/indexes.js +33 -0
  55. package/dist/commands/get/indexes.js.map +1 -0
  56. package/dist/commands/get/keys.js +36 -0
  57. package/dist/commands/get/keys.js.map +1 -0
  58. package/dist/commands/get/projects.js +40 -0
  59. package/dist/commands/get/projects.js.map +1 -0
  60. package/dist/commands/get/settings.js +25 -0
  61. package/dist/commands/get/settings.js.map +1 -0
  62. package/dist/commands/get/stats.js +37 -0
  63. package/dist/commands/get/stats.js.map +1 -0
  64. package/dist/commands/get/tasks.js +35 -0
  65. package/dist/commands/get/tasks.js.map +1 -0
  66. package/dist/commands/get/version.js +16 -0
  67. package/dist/commands/get/version.js.map +1 -0
  68. package/dist/commands/multi-search.js +39 -0
  69. package/dist/commands/multi-search.js.map +1 -0
  70. package/dist/commands/schema.js +95 -0
  71. package/dist/commands/schema.js.map +1 -0
  72. package/dist/commands/search.js +164 -0
  73. package/dist/commands/search.js.map +1 -0
  74. package/dist/commands/similar.js +86 -0
  75. package/dist/commands/similar.js.map +1 -0
  76. package/dist/commands/teleport.js +472 -0
  77. package/dist/commands/teleport.js.map +1 -0
  78. package/dist/commands/update/documents.js +56 -0
  79. package/dist/commands/update/documents.js.map +1 -0
  80. package/dist/commands/update/indexes.js +44 -0
  81. package/dist/commands/update/indexes.js.map +1 -0
  82. package/dist/commands/update/keys.js +42 -0
  83. package/dist/commands/update/keys.js.map +1 -0
  84. package/dist/commands/update/projects.js +62 -0
  85. package/dist/commands/update/projects.js.map +1 -0
  86. package/dist/commands/update/settings.js +145 -0
  87. package/dist/commands/update/settings.js.map +1 -0
  88. package/dist/lib/analytics.js +135 -0
  89. package/dist/lib/analytics.js.map +1 -0
  90. package/dist/lib/api-naming.js +435 -0
  91. package/dist/lib/api-naming.js.map +1 -0
  92. package/dist/lib/base-command.js +318 -0
  93. package/dist/lib/base-command.js.map +1 -0
  94. package/dist/lib/clients/analytics.js +24 -0
  95. package/dist/lib/clients/analytics.js.map +1 -0
  96. package/dist/lib/clients/management/generated/client/client.gen.js +217 -0
  97. package/dist/lib/clients/management/generated/client/client.gen.js.map +1 -0
  98. package/dist/lib/clients/management/generated/client/index.js +7 -0
  99. package/dist/lib/clients/management/generated/client/index.js.map +1 -0
  100. package/dist/lib/clients/management/generated/client/types.gen.js +3 -0
  101. package/dist/lib/clients/management/generated/client/types.gen.js.map +1 -0
  102. package/dist/lib/clients/management/generated/client/utils.gen.js +229 -0
  103. package/dist/lib/clients/management/generated/client/utils.gen.js.map +1 -0
  104. package/dist/lib/clients/management/generated/client.gen.js +4 -0
  105. package/dist/lib/clients/management/generated/client.gen.js.map +1 -0
  106. package/dist/lib/clients/management/generated/core/auth.gen.js +15 -0
  107. package/dist/lib/clients/management/generated/core/auth.gen.js.map +1 -0
  108. package/dist/lib/clients/management/generated/core/bodySerializer.gen.js +58 -0
  109. package/dist/lib/clients/management/generated/core/bodySerializer.gen.js.map +1 -0
  110. package/dist/lib/clients/management/generated/core/params.gen.js +110 -0
  111. package/dist/lib/clients/management/generated/core/params.gen.js.map +1 -0
  112. package/dist/lib/clients/management/generated/core/pathSerializer.gen.js +107 -0
  113. package/dist/lib/clients/management/generated/core/pathSerializer.gen.js.map +1 -0
  114. package/dist/lib/clients/management/generated/core/queryKeySerializer.gen.js +93 -0
  115. package/dist/lib/clients/management/generated/core/queryKeySerializer.gen.js.map +1 -0
  116. package/dist/lib/clients/management/generated/core/serverSentEvents.gen.js +133 -0
  117. package/dist/lib/clients/management/generated/core/serverSentEvents.gen.js.map +1 -0
  118. package/dist/lib/clients/management/generated/core/types.gen.js +3 -0
  119. package/dist/lib/clients/management/generated/core/types.gen.js.map +1 -0
  120. package/dist/lib/clients/management/generated/core/utils.gen.js +88 -0
  121. package/dist/lib/clients/management/generated/core/utils.gen.js.map +1 -0
  122. package/dist/lib/clients/management/generated/index.js +3 -0
  123. package/dist/lib/clients/management/generated/index.js.map +1 -0
  124. package/dist/lib/clients/management/generated/sdk.gen.js +398 -0
  125. package/dist/lib/clients/management/generated/sdk.gen.js.map +1 -0
  126. package/dist/lib/clients/management/generated/types.gen.js +3 -0
  127. package/dist/lib/clients/management/generated/types.gen.js.map +1 -0
  128. package/dist/lib/clients/management.js +21 -0
  129. package/dist/lib/clients/management.js.map +1 -0
  130. package/dist/lib/clients/meilisearch.js +69 -0
  131. package/dist/lib/clients/meilisearch.js.map +1 -0
  132. package/dist/lib/clients/oauth.js +225 -0
  133. package/dist/lib/clients/oauth.js.map +1 -0
  134. package/dist/lib/clients/ping.js +26 -0
  135. package/dist/lib/clients/ping.js.map +1 -0
  136. package/dist/lib/clients/trace.js +69 -0
  137. package/dist/lib/clients/trace.js.map +1 -0
  138. package/dist/lib/cloud-sync.js +113 -0
  139. package/dist/lib/cloud-sync.js.map +1 -0
  140. package/dist/lib/config.js +322 -0
  141. package/dist/lib/config.js.map +1 -0
  142. package/dist/lib/errors.js +302 -0
  143. package/dist/lib/errors.js.map +1 -0
  144. package/dist/lib/help.js +37 -0
  145. package/dist/lib/help.js.map +1 -0
  146. package/dist/lib/input.js +76 -0
  147. package/dist/lib/input.js.map +1 -0
  148. package/dist/lib/login.js +57 -0
  149. package/dist/lib/login.js.map +1 -0
  150. package/dist/lib/output.js +39 -0
  151. package/dist/lib/output.js.map +1 -0
  152. package/dist/lib/pagination.js +52 -0
  153. package/dist/lib/pagination.js.map +1 -0
  154. package/dist/lib/session.js +149 -0
  155. package/dist/lib/session.js.map +1 -0
  156. package/dist/lib/task-filters.js +118 -0
  157. package/dist/lib/task-filters.js.map +1 -0
  158. package/dist/lib/tasks.js +64 -0
  159. package/dist/lib/tasks.js.map +1 -0
  160. package/dist/lib/terminal.js +168 -0
  161. package/dist/lib/terminal.js.map +1 -0
  162. package/dist/lib/values.js +48 -0
  163. package/dist/lib/values.js.map +1 -0
  164. package/oclif.manifest.json +10470 -0
  165. package/package.json +81 -3
@@ -0,0 +1,322 @@
1
+ /**
2
+ * Configuration contract: projects, the config file, connection resolution,
3
+ * environment variables and secret redaction. See docs/contract/config.md.
4
+ *
5
+ * This file, output.ts and errors.ts implement the contract. They change only
6
+ * through a contract pull request.
7
+ */
8
+ import { randomBytes } from "node:crypto";
9
+ import { mkdirSync, readFileSync, renameSync, statSync, writeFileSync } from "node:fs";
10
+ import { homedir } from "node:os";
11
+ import { dirname, join } from "node:path";
12
+ import { isRecord, MeiliCliError } from "./errors.js";
13
+ /** Names of the environment variables the CLI reads. Nothing reads `process.env.MEILI_*` directly. */
14
+ export const ENV = {
15
+ CONFIG: "MEILI_CONFIG",
16
+ MANAGEMENT_TOKEN: "MEILI_MANAGEMENT_TOKEN",
17
+ MANAGEMENT_URL: "MEILI_MANAGEMENT_URL",
18
+ MANAGEMENT_CLIENT_ID: "MEILI_MANAGEMENT_CLIENT_ID",
19
+ MANAGEMENT_DASHBOARD_URL: "MEILI_MANAGEMENT_DASHBOARD_URL",
20
+ OUTPUT: "MEILI_OUTPUT",
21
+ TIMEOUT: "MEILI_TIMEOUT",
22
+ NO_ANALYTICS: "MEILI_NO_ANALYTICS",
23
+ };
24
+ export const DEFAULT_MANAGEMENT_URL = "https://api.meilisearch.com";
25
+ export const DEFAULT_MANAGEMENT_DASHBOARD_URL = "https://cloud.meilisearch.com";
26
+ /**
27
+ * The OAuth application of this CLI, which `auth login` identifies itself with.
28
+ * Every Cloud registers it with this id. A client id is public by definition: it
29
+ * names the application on the consent page, it is not a secret. See ADR 0014.
30
+ */
31
+ export const DEFAULT_MANAGEMENT_CLIENT_ID = "meilisearch-cli";
32
+ /**
33
+ * The table of docs/contract/config.md, in the same order. Rendered in `meili --help`.
34
+ * `flag` names the flag that carries the same setting: the two share their name,
35
+ * `MEILI_` plus the flag name in upper snake case (CLAUDE.md, rule 14).
36
+ */
37
+ export const ENV_VARS = [
38
+ {
39
+ name: ENV.CONFIG,
40
+ description: "Config file path. Default ~/.config/meili/config.json. Give each agent its own file, read-only.",
41
+ },
42
+ {
43
+ name: ENV.MANAGEMENT_TOKEN,
44
+ description: "Management API token, in place of the session of `auth login`. For development and tests.",
45
+ },
46
+ {
47
+ name: ENV.MANAGEMENT_URL,
48
+ description: `Management API base URL. Default ${DEFAULT_MANAGEMENT_URL}. For development and tests.`,
49
+ },
50
+ {
51
+ name: ENV.MANAGEMENT_CLIENT_ID,
52
+ description: "OAuth application the `auth login` command identifies itself with. Default: `meilisearch-cli`, the one of this CLI. For development and tests.",
53
+ },
54
+ {
55
+ name: ENV.MANAGEMENT_DASHBOARD_URL,
56
+ description: `Dashboard URL, which hosts the consent page of \`auth login\`. Default ${DEFAULT_MANAGEMENT_DASHBOARD_URL}. For development and tests.`,
57
+ },
58
+ { name: ENV.OUTPUT, description: "Default output mode: json or ndjson.", flag: "output" },
59
+ { name: ENV.TIMEOUT, description: "Default --timeout for --wait.", flag: "timeout" },
60
+ {
61
+ name: ENV.NO_ANALYTICS,
62
+ description: "`true` or `1` turns off the anonymous usage data the CLI sends. `DO_NOT_TRACK=1` and `CI` turn it off too.",
63
+ },
64
+ ];
65
+ /** `$MEILI_CONFIG`, else `$XDG_CONFIG_HOME/meili/config.json`, else `~/.config/meili/config.json`. */
66
+ export function configFilePath(env) {
67
+ return (nonEmpty(env[ENV.CONFIG]) ??
68
+ join(nonEmpty(env.XDG_CONFIG_HOME) ?? join(homedir(), ".config"), "meili", "config.json"));
69
+ }
70
+ /**
71
+ * The config file; no projects when it does not exist. A file readable by
72
+ * others holds API keys that others can read: `warn` receives it, and the
73
+ * file is read anyway. Windows has no file modes, so no check there.
74
+ */
75
+ export function readConfigFile(path, warn) {
76
+ const text = readOwnerOnly(path, "config", warn);
77
+ if (text === undefined)
78
+ return { path, projects: {} };
79
+ let parsed;
80
+ try {
81
+ parsed = JSON.parse(text);
82
+ }
83
+ catch (cause) {
84
+ throw new MeiliCliError("cli_config", `The config file ${path} is not valid JSON.`, { cause });
85
+ }
86
+ return { path, projects: parseProjects(parsed, path) };
87
+ }
88
+ function parseProjects(parsed, path) {
89
+ const shape = () => new MeiliCliError("cli_config", `The config file ${path} must be {"projects": {"<name>": {"url": "...", "apiKey": "...", "cloud": {"id": 1, "teamId": 2, "teamName": "..."}}}}, the key and cloud optional, and in cloud the team.`);
90
+ const projects = isRecord(parsed) ? parsed.projects : undefined;
91
+ if (!isRecord(projects))
92
+ throw shape();
93
+ const result = {};
94
+ for (const [name, entry] of Object.entries(projects)) {
95
+ if (!isRecord(entry) || typeof entry.url !== "string")
96
+ throw shape();
97
+ if (entry.apiKey !== undefined && typeof entry.apiKey !== "string")
98
+ throw shape();
99
+ const { cloud } = entry;
100
+ if (cloud !== undefined &&
101
+ (!isRecord(cloud) ||
102
+ !Number.isInteger(cloud.id) ||
103
+ (cloud.teamId !== undefined && !Number.isInteger(cloud.teamId)) ||
104
+ (cloud.teamName !== undefined && typeof cloud.teamName !== "string"))) {
105
+ throw shape();
106
+ }
107
+ result[name] = {
108
+ url: entry.url,
109
+ ...(entry.apiKey === undefined ? {} : { apiKey: entry.apiKey }),
110
+ ...(cloud === undefined
111
+ ? {}
112
+ : {
113
+ cloud: {
114
+ id: cloud.id,
115
+ ...(cloud.teamId === undefined ? {} : { teamId: cloud.teamId }),
116
+ ...(cloud.teamName === undefined ? {} : { teamName: cloud.teamName }),
117
+ },
118
+ }),
119
+ };
120
+ }
121
+ return result;
122
+ }
123
+ export function writeConfigFile(file) {
124
+ writeSecretFile(file.path, { projects: file.projects });
125
+ }
126
+ /**
127
+ * Writes a file of secrets owner-only and atomically: a command reading it
128
+ * meanwhile sees the previous file or the new one, never a half-written one.
129
+ * The temporary file is created exclusively, under an unpredictable name: a
130
+ * pre-existing file or symlink at that path, in a shared directory, would
131
+ * receive the secrets and keep its own permissions.
132
+ */
133
+ export function writeSecretFile(path, content) {
134
+ mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
135
+ const temporary = `${path}.${randomBytes(6).toString("hex")}.tmp`;
136
+ writeFileSync(temporary, `${JSON.stringify(content, null, 2)}\n`, { flag: "wx", mode: 0o600 });
137
+ renameSync(temporary, path);
138
+ }
139
+ /**
140
+ * The file, or undefined when it does not exist. A file readable by others
141
+ * holds secrets that others can read: `warn` receives it, and the file is read
142
+ * anyway. Windows has no file modes, so no check there.
143
+ */
144
+ export function readOwnerOnly(path, what, warn) {
145
+ const stat = statSync(path, { throwIfNoEntry: false });
146
+ if (stat === undefined)
147
+ return undefined;
148
+ if (process.platform !== "win32" && (stat.mode & 0o077) !== 0) {
149
+ warn(new MeiliCliError("cli_config", `The ${what} file ${path} is readable by others.`, {
150
+ hint: `Run \`chmod 600 ${path}\`.`,
151
+ }));
152
+ }
153
+ return readFileSync(path, "utf8");
154
+ }
155
+ /**
156
+ * The rules of docs/contract/config.md, "Resolution: the command line names
157
+ * the project". The file is read only for `--project`; nothing else is read.
158
+ * Never falls back to localhost.
159
+ */
160
+ export function resolveProjectConnection(flags, readFile) {
161
+ if (flags.url !== undefined) {
162
+ if (flags.project !== undefined) {
163
+ throw new MeiliCliError("cli_usage", "`--project` cannot be combined with `--project-url`: the name and the URL contradict each other.");
164
+ }
165
+ assertProjectUrl(flags.url);
166
+ return { url: flags.url, apiKey: flags.apiKey };
167
+ }
168
+ if (flags.project !== undefined) {
169
+ const entry = projectOf(readFile(), flags.project);
170
+ return { url: entry.url, apiKey: flags.apiKey ?? entry.apiKey };
171
+ }
172
+ throw new MeiliCliError("cli_usage", "Name the project with `--project <name>`, an entry of the config file, or with `--project-url <url>`.", { hint: "Run `meili config list` to see the projects of the config file." });
173
+ }
174
+ /**
175
+ * The Cloud project a management command acts on (config.md, "Cloud projects"):
176
+ * `--id` as given, or the `cloud.id` of the entry named by `--project`. Both
177
+ * together contradict each other; neither is a usage error.
178
+ */
179
+ export function resolveCloudProjectId(flags, readFile) {
180
+ if (flags.project !== undefined && flags.id !== undefined) {
181
+ throw new MeiliCliError("cli_usage", "`--project` cannot be combined with `--id`: the name and the id contradict each other.");
182
+ }
183
+ if (flags.project === undefined) {
184
+ if (flags.id === undefined) {
185
+ throw new MeiliCliError("cli_usage", "Name the project with `--id <id>` or `--project <name>`.");
186
+ }
187
+ return flags.id;
188
+ }
189
+ const file = readFile();
190
+ const { cloud } = projectOf(file, flags.project);
191
+ if (cloud === undefined) {
192
+ throw new MeiliCliError("cli_config", `Project \`${flags.project}\` has no cloud identifiers in ${file.path}: the management commands need the project's id.`, { hint: `Run \`meili config update --project ${flags.project} --sync-with-cloud\`.` });
193
+ }
194
+ return cloud.id;
195
+ }
196
+ /** `cli_config` when the file already has an entry named `name`; `detail` follows the path. */
197
+ export function assertNoProject(file, name, detail) {
198
+ if (file.projects[name] !== undefined) {
199
+ throw new MeiliCliError("cli_config", `Project \`${name}\` already exists in ${file.path}${detail}`, {
200
+ hint: `Run \`meili config update --project ${name}\` to change it, or \`meili config unset --project ${name}\` first.`,
201
+ });
202
+ }
203
+ }
204
+ /**
205
+ * The entry `--sync-config` changes for the Cloud project `id`: the one
206
+ * `--project` names, else the one whose `cloud.id` is `id`. None, or several,
207
+ * is `cli_config` before any call; `detail` follows the path.
208
+ */
209
+ export function cloudProjectEntry(file, project, id, detail) {
210
+ if (project !== undefined)
211
+ return project;
212
+ const names = entriesOfCloudId(file, id);
213
+ const [name] = names;
214
+ if (name !== undefined && names.length === 1)
215
+ return name;
216
+ throw new MeiliCliError("cli_config", names.length === 0
217
+ ? `No project of ${file.path} has the cloud id ${id}${detail}`
218
+ : `Projects ${names.map((each) => `\`${each}\``).join(", ")} of ${file.path} have the cloud id ${id}${detail}`, {
219
+ hint: names.length === 0
220
+ ? `Run \`meili config sync-with-cloud --project-url <url>\` first, with the project's URL.`
221
+ : "Name one with `--project` in place of `--id`.",
222
+ });
223
+ }
224
+ /** The names of the entries whose `cloud.id` is `id`. */
225
+ export function entriesOfCloudId(file, id) {
226
+ return Object.keys(file.projects).filter((name) => file.projects[name]?.cloud?.id === id);
227
+ }
228
+ /** `value` as a URL, or undefined. `URL.parse` would do, but only from Node 22.1. */
229
+ export function parseUrl(value) {
230
+ try {
231
+ return new URL(value);
232
+ }
233
+ catch {
234
+ return undefined;
235
+ }
236
+ }
237
+ /** True when `value` is an HTTP(S) URL: a Meilisearch instance answers over nothing else. */
238
+ export function isProjectUrl(value) {
239
+ const protocol = parseUrl(value)?.protocol;
240
+ return protocol === "http:" || protocol === "https:";
241
+ }
242
+ /**
243
+ * `cli_usage` unless `value` is an HTTP(S) URL: a Meilisearch instance answers
244
+ * over nothing else. The message leaves the value out, which may carry a password.
245
+ */
246
+ export function assertProjectUrl(value) {
247
+ if (!isProjectUrl(value)) {
248
+ throw new MeiliCliError("cli_usage", "Invalid project URL: `--project-url` takes an HTTP(S) URL.");
249
+ }
250
+ }
251
+ /** In the help of every command that writes the config file (config.md, "Config file"). */
252
+ export const CONFIG_FILE_WARNING = "The file holds API keys and decides where every later command goes, for every process that reads it: an agent runs this only when the human asked for it explicitly.";
253
+ /** The named entry, or `cli_config` with the path and the names the file has. */
254
+ export function projectOf(file, name) {
255
+ const entry = file.projects[name];
256
+ if (entry === undefined) {
257
+ throw new MeiliCliError("cli_config", `No project \`${name}\` in ${file.path}. Projects: ${Object.keys(file.projects).join(", ") || "none"}.`);
258
+ }
259
+ return entry;
260
+ }
261
+ // Secrets
262
+ /** `****1a2b`: the last four characters only. Shorter values are fully masked. */
263
+ export function maskSecret(value) {
264
+ return value.length > 4 ? `****${value.slice(-4)}` : "****";
265
+ }
266
+ /**
267
+ * Body fields whose value is a secret, as listed in config.md. `apikey` is the
268
+ * Management API's spelling, `masterKey` a Cloud project's key in the same API.
269
+ */
270
+ export const REDACTED_FIELDS = new Set([
271
+ "apiKey",
272
+ "apikey",
273
+ "masterKey",
274
+ "key",
275
+ "token",
276
+ "access_token",
277
+ "refresh_token",
278
+ ]);
279
+ const REDACTED_HEADERS = new Set([
280
+ "authorization",
281
+ "x-meili-api-key",
282
+ "cookie",
283
+ "set-cookie",
284
+ ]);
285
+ /** Masks the `Authorization` header (and the legacy `X-Meili-API-Key`) in a header map. */
286
+ export function redactHeaders(headers) {
287
+ const result = {};
288
+ for (const [name, value] of headers) {
289
+ if (REDACTED_HEADERS.has(name.toLowerCase())) {
290
+ const [scheme, ...rest] = value.split(" ");
291
+ result[name] =
292
+ rest.length > 0 && scheme !== undefined
293
+ ? `${scheme} ${maskSecret(rest.join(" "))}`
294
+ : maskSecret(value);
295
+ }
296
+ else {
297
+ result[name] = value;
298
+ }
299
+ }
300
+ return result;
301
+ }
302
+ /** Deep copy of a JSON value with every secret field masked. */
303
+ export function redactBody(value) {
304
+ if (Array.isArray(value))
305
+ return value.map(redactBody);
306
+ if (!isRecord(value))
307
+ return value;
308
+ const result = {};
309
+ for (const [field, fieldValue] of Object.entries(value)) {
310
+ if (REDACTED_FIELDS.has(field)) {
311
+ result[field] = typeof fieldValue === "string" ? maskSecret(fieldValue) : "****";
312
+ }
313
+ else {
314
+ result[field] = redactBody(fieldValue);
315
+ }
316
+ }
317
+ return result;
318
+ }
319
+ export function nonEmpty(value) {
320
+ return value === undefined || value === "" ? undefined : value;
321
+ }
322
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,302 @@
1
+ /**
2
+ * Error contract: codes, exit codes and rendering. See docs/contract/output.md.
3
+ *
4
+ * This file, output.ts and config.ts implement the contract. They change only
5
+ * through a contract pull request.
6
+ */
7
+ import { stripVTControlCharacters } from "node:util";
8
+ import { Errors } from "@oclif/core";
9
+ import { MeilisearchApiError, MeilisearchRequestError, MeilisearchRequestTimeOutError, } from "meilisearch";
10
+ /** Exit codes, as listed in the table of docs/contract/output.md. */
11
+ export const EXIT_CODES = {
12
+ success: 0,
13
+ error: 1,
14
+ usage: 2,
15
+ auth: 3,
16
+ notFound: 4,
17
+ timeout: 5,
18
+ network: 6,
19
+ taskFailed: 7,
20
+ };
21
+ /** Codes of errors raised by the CLI itself, with their default exit code. */
22
+ export const CLI_ERROR_CODES = {
23
+ cli_usage: EXIT_CODES.usage,
24
+ cli_config: EXIT_CODES.usage,
25
+ cli_auth_missing: EXIT_CODES.auth,
26
+ cli_auth_failed: EXIT_CODES.auth,
27
+ cli_timeout: EXIT_CODES.timeout,
28
+ cli_network: EXIT_CODES.network,
29
+ cli_task_failed: EXIT_CODES.taskFailed,
30
+ cli_input_invalid: EXIT_CODES.usage,
31
+ cli_internal: EXIT_CODES.error,
32
+ };
33
+ /** Exit code of an API error, from its HTTP status. Both APIs answer the same shape. */
34
+ export function apiExitCode(status) {
35
+ if (status === 401 || status === 403)
36
+ return EXIT_CODES.auth;
37
+ if (status === 404)
38
+ return EXIT_CODES.notFound;
39
+ return EXIT_CODES.error;
40
+ }
41
+ /**
42
+ * A non-2xx answer of the Management API. Its body is the error object of the
43
+ * document, the same shape as a Meilisearch one, and it is passed through
44
+ * (docs/contract/output.md, "Errors"); `body` is undefined when the answer
45
+ * carried none, which is not the API answering.
46
+ */
47
+ export class ManagementApiError extends Error {
48
+ status;
49
+ body;
50
+ url;
51
+ constructor(status, body, url) {
52
+ super(parseErrorBody(body)?.message ?? `The Management API answered HTTP ${status} to ${url}.`);
53
+ this.name = "ManagementApiError";
54
+ this.status = status;
55
+ this.body = body;
56
+ this.url = url;
57
+ }
58
+ }
59
+ /** The error object of either API, or undefined when the body is not one. */
60
+ export function parseErrorBody(body) {
61
+ if (!isRecord(body))
62
+ return undefined;
63
+ const { message, code, type, link } = body;
64
+ if (typeof message !== "string" || typeof code !== "string" || typeof type !== "string") {
65
+ return undefined;
66
+ }
67
+ return { code, type, message, ...(typeof link === "string" ? { link } : {}) };
68
+ }
69
+ /** The only error class commands may throw. */
70
+ export class MeiliCliError extends Error {
71
+ code;
72
+ exitCode;
73
+ hint;
74
+ constructor(code, message, options = {}) {
75
+ super(message, options.cause === undefined ? undefined : { cause: options.cause });
76
+ this.name = "MeiliCliError";
77
+ this.code = code;
78
+ this.exitCode = options.exitCode ?? CLI_ERROR_CODES[code];
79
+ this.hint = options.hint;
80
+ }
81
+ toBody() {
82
+ const body = { code: this.code, type: "cli", message: this.message };
83
+ if (this.hint !== undefined)
84
+ body.hint = this.hint;
85
+ return body;
86
+ }
87
+ }
88
+ const HELP_SUFFIX = /\n?See more help with --help\.?\s*$/;
89
+ /**
90
+ * Both APIs answer the same error object, so both are rendered the same way:
91
+ * the body passed through, the API's hint for that status, and the exit code
92
+ * of the status. No error body at all is a proxy or a wrong URL, not the API.
93
+ */
94
+ function renderApiError(error, status, url, sent, api) {
95
+ const body = parseErrorBody(sent);
96
+ if (body === undefined) {
97
+ return {
98
+ body: {
99
+ code: "cli_network",
100
+ type: "cli",
101
+ message: `${serverName(url)} answered HTTP ${status} without a ${api.name} error body.`,
102
+ },
103
+ exitCode: EXIT_CODES.network,
104
+ stack: error.stack,
105
+ };
106
+ }
107
+ const hint = api.hint(status);
108
+ if (hint !== undefined)
109
+ body.hint = hint;
110
+ return { body, exitCode: apiExitCode(status), stack: error.stack };
111
+ }
112
+ /**
113
+ * Converts anything thrown during a command into a contract error. `commandIds`
114
+ * are the commands of the manifest, `get indexes`, for the hint of an unknown command.
115
+ * `managementTokenFromEnv` says the Management API token came from
116
+ * `MEILI_MANAGEMENT_TOKEN`, which a new login would not replace.
117
+ */
118
+ export function toRenderedError(error, commandIds = [], managementTokenFromEnv = false) {
119
+ if (error instanceof MeiliCliError) {
120
+ return { body: error.toBody(), exitCode: error.exitCode, stack: error.stack };
121
+ }
122
+ if (error instanceof MeilisearchApiError) {
123
+ return renderApiError(error, error.response.status, error.response.url, error.cause, {
124
+ name: "Meilisearch",
125
+ hint: (status) => status === 401 || status === 403
126
+ ? "Provide an API key with `--project-api-key <key>`."
127
+ : undefined,
128
+ });
129
+ }
130
+ if (error instanceof ManagementApiError) {
131
+ return renderApiError(error, error.status, error.url, error.body, {
132
+ name: "Management API",
133
+ // A 403 is a right the account lacks: no new credential grants it.
134
+ hint: (status) => status !== 401
135
+ ? undefined
136
+ : managementTokenFromEnv
137
+ ? "Unset or replace `MEILI_MANAGEMENT_TOKEN`: it is used in place of the session of `meili auth login`."
138
+ : "Run `meili auth login` to log in again.",
139
+ });
140
+ }
141
+ if (error instanceof MeilisearchRequestTimeOutError) {
142
+ return {
143
+ body: {
144
+ code: "cli_timeout",
145
+ type: "cli",
146
+ message: `The HTTP request timed out after ${error.cause.timeout} ms.`,
147
+ },
148
+ exitCode: EXIT_CODES.timeout,
149
+ stack: error.stack,
150
+ };
151
+ }
152
+ if (error instanceof MeilisearchRequestError) {
153
+ return {
154
+ body: { code: "cli_network", type: "cli", message: networkMessage(error) },
155
+ exitCode: EXIT_CODES.network,
156
+ stack: error.stack,
157
+ };
158
+ }
159
+ if (error instanceof Errors.ExitError) {
160
+ // Already rendered upstream. Keep the exit code, print nothing.
161
+ return {
162
+ body: { code: "cli_internal", type: "cli", message: error.message },
163
+ exitCode: error.oclif.exit ?? EXIT_CODES.error,
164
+ stack: undefined,
165
+ };
166
+ }
167
+ if (error instanceof Errors.CLIError) {
168
+ // oclif parse errors and "command not found". Their exit code is 2 by default.
169
+ // oclif colors parts of its messages in a terminal: the JSON carries none of it.
170
+ const cleaned = stripVTControlCharacters(error.message).replace(HELP_SUFFIX, "");
171
+ const typed = cleaned.match(NOT_FOUND)?.[1]?.replaceAll(":", " ");
172
+ const closest = typed === undefined ? undefined : closestCommand(typed, commandIds);
173
+ return {
174
+ body: {
175
+ code: "cli_usage",
176
+ type: "cli",
177
+ message: typed === undefined ? cleaned : `Command \`${typed}\` not found.`,
178
+ hint: closest === undefined
179
+ ? "Run `meili --help` or `meili <command> --help` to see the usage."
180
+ : `Did you mean \`meili ${closest}\`?`,
181
+ },
182
+ exitCode: EXIT_CODES.usage,
183
+ stack: error.stack,
184
+ };
185
+ }
186
+ const message = error instanceof Error ? error.message : String(error);
187
+ return {
188
+ body: {
189
+ code: "cli_internal",
190
+ type: "cli",
191
+ message: `Unexpected error: ${message}`,
192
+ hint: "This is a bug in meili. Run the command again with `--debug` and report the trace.",
193
+ },
194
+ exitCode: EXIT_CODES.error,
195
+ stack: error instanceof Error ? error.stack : undefined,
196
+ };
197
+ }
198
+ /** oclif joins command ids with ":" in its messages; the CLI uses spaces. */
199
+ const NOT_FOUND = /^command (\S+) not found$/;
200
+ /** The command closest to what was typed, when it is close enough to be a typo. */
201
+ export function closestCommand(typed, commandIds) {
202
+ const tolerance = Math.max(2, Math.floor(typed.length / 3));
203
+ let best;
204
+ for (const id of commandIds) {
205
+ const distance = editDistance(typed, id);
206
+ if (distance <= tolerance && (best === undefined || distance < best.distance)) {
207
+ best = { id, distance };
208
+ }
209
+ }
210
+ return best?.id;
211
+ }
212
+ /** Levenshtein distance. */
213
+ function editDistance(a, b) {
214
+ const row = Array.from({ length: b.length + 1 }, (_, index) => index);
215
+ for (let i = 1; i <= a.length; i += 1) {
216
+ let diagonal = row[0] ?? 0;
217
+ row[0] = i;
218
+ for (let j = 1; j <= b.length; j += 1) {
219
+ const above = row[j] ?? 0;
220
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
221
+ row[j] = Math.min(above + 1, (row[j - 1] ?? 0) + 1, diagonal + cost);
222
+ diagonal = above;
223
+ }
224
+ }
225
+ return row[b.length] ?? 0;
226
+ }
227
+ function serverName(url) {
228
+ return url === "" ? "The server" : `The server at ${url}`;
229
+ }
230
+ function networkMessage(error) {
231
+ const target = error.message.match(/https?:\/\/\S+/)?.[0];
232
+ const where = target === undefined ? "the Meilisearch instance" : target.replace(/\/$/, "");
233
+ return cannotConnectMessage(where, error.cause);
234
+ }
235
+ /** The `cli_network` message: `Cannot connect to <where>`, with the deepest cause when there is one. */
236
+ export function cannotConnectMessage(where, cause) {
237
+ const reason = deepestCauseMessage(cause);
238
+ return reason === undefined
239
+ ? `Cannot connect to ${where}.`
240
+ : `Cannot connect to ${where}: ${reason}.`;
241
+ }
242
+ /** The innermost reason of a wrapped error: `fetch failed` hides `ECONNREFUSED`. */
243
+ export function deepestCauseMessage(cause) {
244
+ let current = cause;
245
+ let message;
246
+ for (let depth = 0; depth < 5 && current instanceof Error; depth += 1) {
247
+ if (current.message !== "")
248
+ message = current.message;
249
+ current = current.cause;
250
+ }
251
+ return message?.replace(/\.$/, "");
252
+ }
253
+ /** Formats an error for stderr: one JSON document, then the stack trace with --debug. */
254
+ export function formatError(rendered, options) {
255
+ const document = { error: rendered.body };
256
+ const lines = [options.pretty ? JSON.stringify(document, null, 2) : JSON.stringify(document)];
257
+ if (options.debug && rendered.stack !== undefined)
258
+ lines.push(rendered.stack);
259
+ return `${lines.join("\n")}\n`;
260
+ }
261
+ /** Writes a rendered error on stderr. Nothing ever goes to stdout from here. */
262
+ export function writeError(rendered, options) {
263
+ process.stderr.write(formatError(rendered, options));
264
+ }
265
+ /**
266
+ * One line for the human, on stderr, and only when a human is there to read it
267
+ * (docs/contract/output.md, "Streams"). Data never goes through here.
268
+ */
269
+ export function writeNotice(line) {
270
+ if (process.stderr.isTTY === true)
271
+ process.stderr.write(`${line}\n`);
272
+ }
273
+ /**
274
+ * Writes a warning on stderr, `{ "warning": ... }` in the shape of an error,
275
+ * and the command goes on. Indented when stderr is a TTY, like errors. An API
276
+ * error the command goes on through keeps the API's code.
277
+ */
278
+ export function writeWarning(warning) {
279
+ const document = { warning: warning instanceof MeiliCliError ? warning.toBody() : warning };
280
+ const pretty = process.stderr.isTTY === true;
281
+ process.stderr.write(`${pretty ? JSON.stringify(document, null, 2) : JSON.stringify(document)}\n`);
282
+ }
283
+ /**
284
+ * Last-resort handler for bin/run.js: errors thrown before a command exists
285
+ * (unknown command, bad global flags on a topic) or escaped from one.
286
+ * Errors already rendered by BaseCommand arrive as ExitError and print nothing.
287
+ */
288
+ export function handleFatalError(error, argv, commandIds) {
289
+ const rendered = toRenderedError(error, commandIds);
290
+ if (!(error instanceof Errors.ExitError)) {
291
+ writeError(rendered, {
292
+ pretty: process.stderr.isTTY === true,
293
+ debug: argv.includes("--debug"),
294
+ });
295
+ }
296
+ process.exitCode = rendered.exitCode;
297
+ }
298
+ /** A JSON object, as opposed to an array, a scalar or null. */
299
+ export function isRecord(value) {
300
+ return typeof value === "object" && value !== null && !Array.isArray(value);
301
+ }
302
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/lib/errors.ts"],"names":[],"mappings":"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"}