@faable/faable 4.21.1 → 4.22.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.
@@ -11,8 +11,11 @@ const assert_name_free = async (api, project, name) => {
11
11
  limit: 200,
12
12
  all: true
13
13
  });
14
- const wanted = name.toLowerCase();
15
- const clash = apps.data.find(a => a.name.toLowerCase() === wanted);
14
+ // Same comparison as the api (app_name_unique.plugin.ts): trimmed, NFC,
15
+ // case-insensitive.
16
+ const key = (s) => s.trim().normalize('NFC').toLowerCase();
17
+ const wanted = key(name);
18
+ const clash = apps.data.find(a => key(a.name) === wanted);
16
19
  if (clash) {
17
20
  throw new CliError('name_taken', `${project} already has an app named "${clash.name}" (${clash.id}). Deploy to it with --app ${clash.id}, or choose another name.`);
18
21
  }
@@ -31,6 +31,19 @@ const retry_of = (deployment) => {
31
31
  * was about to succeed (backlog §379).
32
32
  */
33
33
  const TAIL_CHARS = 200;
34
+ /**
35
+ * The build's warnings, after its log (api `deployment.build_warnings`). The
36
+ * same lines are in the log above, but scrolled away among hundreds of npm
37
+ * lines; a deploy that ends READY is exactly the one nobody scrolls back on.
38
+ */
39
+ const format_build_warnings = (warnings) => {
40
+ if (!warnings?.length)
41
+ return '';
42
+ const n = warnings.length;
43
+ return (`\n⚠️ ${n} build warning${n === 1 ? '' : 's'} — the build worked around ${n === 1 ? 'this' : 'these'}; fix ${n === 1 ? 'it' : 'them'} so it does not have to:\n` +
44
+ warnings.map(w => ` • ${w.message}\n`).join('') +
45
+ '\n');
46
+ };
34
47
  /**
35
48
  * The part of `content` not shown yet, given how much was `printed` and the
36
49
  * last characters of it (`seen_tail`).
@@ -111,11 +124,18 @@ out = process.stdout) => {
111
124
  // already live (READY) — the promotion poll takes over from here.
112
125
  if (phase === 'INITIALIZING' || phase === 'READY') {
113
126
  await tail_logs();
114
- return { id: deployment_id };
127
+ const build_warnings = deployment?.build_warnings;
128
+ const summary = format_build_warnings(build_warnings);
129
+ if (summary)
130
+ out.write(summary);
131
+ return {
132
+ id: deployment_id,
133
+ ...(build_warnings?.length ? { build_warnings } : {})
134
+ };
115
135
  }
116
136
  await wait(POLL_INTERVAL_MS);
117
137
  }
118
138
  throw new Error('Timed out waiting for the remote build. Check the dashboard for its status.');
119
139
  };
120
140
 
121
- export { follow_remote_build, unseen };
141
+ export { follow_remote_build, format_build_warnings, unseen };
@@ -21,8 +21,11 @@ in_project) => {
21
21
  limit: 200,
22
22
  all: true
23
23
  });
24
- const wanted = ref.toLowerCase();
25
- const matches = apps.data.filter(a => a.name.toLowerCase() === wanted || a.slug?.toLowerCase() === wanted);
24
+ // NFC: an app name is free text, and a decomposed "é" (typed on macOS,
25
+ // pasted from a file) must match the composed one the api stores.
26
+ const key = (s) => s?.trim().normalize('NFC').toLowerCase();
27
+ const wanted = key(ref);
28
+ const matches = apps.data.filter(a => key(a.name) === wanted || key(a.slug) === wanted);
26
29
  if (matches.length === 1)
27
30
  return matches[0].id;
28
31
  if (matches.length === 0) {
package/dist/mcp/tools.js CHANGED
@@ -16,6 +16,12 @@ const target = (a) => ['--app', a.app, ...scope(a)];
16
16
  const opt = (flag, value) => value === undefined || value === null || value === ''
17
17
  ? []
18
18
  : [flag, String(value)];
19
+ // Free text that may start with "-" (an app name is any text): as a separate
20
+ // argument yargs reads "--no-deploy" as a flag of its own and the name comes
21
+ // out empty. Glued with "=" it can only be the value.
22
+ const optText = (flag, value) => value === undefined || value === null || value === ''
23
+ ? []
24
+ : [`${flag}=${String(value)}`];
19
25
  const READ = {
20
26
  readOnlyHint: true,
21
27
  destructiveHint: false,
@@ -711,7 +717,7 @@ const TOOLS = [
711
717
  flags: a => [
712
718
  '--repo',
713
719
  a.repo,
714
- ...opt('--name', a.name),
720
+ ...optText('--name', a.name),
715
721
  ...opt('--branch', a.branch),
716
722
  ...(a.deploy === false ? ['--no-deploy'] : []),
717
723
  ...(a.wait && a.deploy !== false ? ['--wait', '--timeout', '300'] : []),
@@ -898,7 +904,7 @@ const TOOLS = [
898
904
  '--workdir',
899
905
  a.workdir,
900
906
  ...opt('--app', a.app),
901
- ...opt('--create', a.create),
907
+ ...optText('--create', a.create),
902
908
  '--yes',
903
909
  ...scope(a)
904
910
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@faable/faable",
3
- "version": "4.21.1",
3
+ "version": "4.22.1",
4
4
  "main": "dist/index.js",
5
5
  "license": "MIT",
6
6
  "author": "Marc Pomar <marc@faable.com>",