@outerlayer/cli 0.6.0 → 0.7.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 (80) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +10 -0
  3. package/dist/{agent-setup-USZ2SAXC.js → agent-setup-TXLDY5RV.js} +7 -6
  4. package/dist/{build-PAEKVYVK.js → build-JF5UOWKJ.js} +2 -1
  5. package/dist/build-info.json +1 -1
  6. package/dist/{check-CCVPBN7A.js → check-ASZL5BEO.js} +29 -23
  7. package/dist/{chunk-ZILGTTY6.js → chunk-2VO25HHO.js} +3 -3
  8. package/dist/{chunk-OIRNH6UO.js → chunk-5FWNEQNZ.js} +3 -3
  9. package/dist/{chunk-MXB5VB4Y.js → chunk-6IYLDODX.js} +6 -6
  10. package/dist/{chunk-4NLKY4WR.js → chunk-6QWV3YDJ.js} +2 -2
  11. package/dist/{chunk-UMFWVGJO.js → chunk-6ZZHWY2Z.js} +4 -3
  12. package/dist/{chunk-NQXFAGHU.js → chunk-7FTNIAHS.js} +1 -1
  13. package/dist/{chunk-EMY4I27X.js → chunk-7ZR5UPMB.js} +555 -5
  14. package/dist/{chunk-43J3M6KB.js → chunk-AII7CKTH.js} +45 -31
  15. package/dist/{chunk-VMJ3MMBX.js → chunk-AJKEHABI.js} +312 -18
  16. package/dist/{chunk-RBOMWNOG.js → chunk-AQ54MKSQ.js} +2 -2
  17. package/dist/{chunk-Z62HNKEJ.js → chunk-CEBIA5FD.js} +31 -5
  18. package/dist/{chunk-ANK2B36Y.js → chunk-D6FXM5OW.js} +6182 -28607
  19. package/dist/{chunk-BNMCXPG7.js → chunk-DGAIVMMN.js} +12 -3
  20. package/dist/{chunk-3DD6AOWC.js → chunk-DTXOJDEH.js} +26 -2
  21. package/dist/{chunk-RZSF5B46.js → chunk-E4PIFIC3.js} +100 -15
  22. package/dist/{chunk-H5NCNVDA.js → chunk-EV3M3EH7.js} +2 -2
  23. package/dist/chunk-HKMPVPO7.js +55 -0
  24. package/dist/{chunk-FA2BOX4O.js → chunk-JPR2WHHF.js} +1 -1
  25. package/dist/{chunk-ZMYPLFG3.js → chunk-M3SQ4YGD.js} +1 -1
  26. package/dist/{chunk-MIGEDH5P.js → chunk-MQPRB5K7.js} +9 -9
  27. package/dist/{chunk-AUFG23AA.js → chunk-OD2VTIHN.js} +19 -47
  28. package/dist/chunk-PUN7LMNS.js +39 -0
  29. package/dist/{chunk-JWOQNNN2.js → chunk-Q5G2ODUZ.js} +1 -1
  30. package/dist/{chunk-B2G7JHHB.js → chunk-R7STSBLC.js} +1 -1
  31. package/dist/{chunk-PMAMOSTP.js → chunk-SSU747O6.js} +85 -25
  32. package/dist/{chunk-YYYXRJUW.js → chunk-TI7B7UEO.js} +1 -1
  33. package/dist/{chunk-WO2BXCTQ.js → chunk-VXLJORHL.js} +1 -1
  34. package/dist/{chunk-CBPPJSAR.js → chunk-WVGSB3Z2.js} +2 -2
  35. package/dist/{chunk-IASWYRVG.js → chunk-X2FSFU4C.js} +4 -1
  36. package/dist/chunk-YNJEOGDL.js +22434 -0
  37. package/dist/{chunk-W4SQCOZU.js → chunk-ZOAEPWGL.js} +1 -1
  38. package/dist/{chunk-3DEVYTNQ.js → chunk-ZYHKJKSU.js} +1 -1
  39. package/dist/{chunk-WIOZAJ2W.js → chunk-ZZXLM64C.js} +1 -1
  40. package/dist/{cli-7WCNPBYC.js → cli-LEVCGAQV.js} +73 -71
  41. package/dist/{command-ARFK3OYF.js → command-FLSYCGIB.js} +47 -22
  42. package/dist/config-I3TVFYLH.js +10 -0
  43. package/dist/{connect-cmd-PCESZLTR.js → connect-cmd-MJMUONDY.js} +4 -4
  44. package/dist/{context-adopt-G5JAELE7.js → context-adopt-CE4KDXS3.js} +5 -4
  45. package/dist/{context-materialize-3HLPZAF6.js → context-materialize-QL33HDJN.js} +5 -4
  46. package/dist/{dist-RDLP4GGJ.js → dist-PXBSA7QX.js} +2 -1
  47. package/dist/{doctor-VOMYOHQU.js → doctor-FVDT3KJZ.js} +23 -16
  48. package/dist/{emit-artifact-cmd-TBF46VXZ.js → emit-artifact-cmd-7RPMRSVP.js} +11 -4
  49. package/dist/{emit-cmd-DCERAU27.js → emit-cmd-2QRMYPYO.js} +4 -3
  50. package/dist/{emit-criteria-cmd-3427XKFW.js → emit-criteria-cmd-MKI7WETO.js} +10 -1
  51. package/dist/{emit-finding-cmd-GSI75K36.js → emit-finding-cmd-RMLGZASB.js} +12 -1
  52. package/dist/{emit-result-cmd-3PRQKB55.js → emit-result-cmd-MTXAZ2GV.js} +13 -6
  53. package/dist/{exec-client-4XGXV3XN.js → exec-client-NPYNUAF3.js} +4 -3
  54. package/dist/{guest-init-GENRHNP7.js → guest-init-JWNNAH2H.js} +4 -3
  55. package/dist/{hook-fast-NJBBZQ5Q.js → hook-fast-XBOZ3N6L.js} +1 -1
  56. package/dist/{import-capture-cmd-AVZ4VIVJ.js → import-capture-cmd-T4556ELW.js} +3 -2
  57. package/dist/{import-ruler-cmd-GUHL6IY5.js → import-ruler-cmd-SG3UVGI7.js} +2 -1
  58. package/dist/index.js +3 -3
  59. package/dist/{init-WVR4BZQ4.js → init-BACXESVV.js} +21 -14
  60. package/dist/{init-OHYFIKZD.js → init-VLW7H6RW.js} +22 -15
  61. package/dist/{init-cmd-HMFNIFPI.js → init-cmd-VJFB5L7X.js} +10 -9
  62. package/dist/{install-DSUZE2TJ.js → install-NMAPLLBQ.js} +4 -3
  63. package/dist/{install-cmd-453C7IZT.js → install-cmd-B5SEU3G7.js} +2 -2
  64. package/dist/{logs-7RYUH5A6.js → logs-H55NWW4H.js} +1 -0
  65. package/dist/{loop-UAJB34KA.js → loop-D3243JKT.js} +29 -23
  66. package/dist/{machine-2JOWGRSZ.js → machine-EB3GEVI4.js} +20 -13
  67. package/dist/{session-sender-ED26V45B.js → session-sender-LMACEJJS.js} +6 -5
  68. package/dist/{starter-pack-LIZYMKYQ.js → starter-pack-MUXMAU4S.js} +4 -3
  69. package/dist/{status-6WNXX2O7.js → status-F4THTJJK.js} +24 -18
  70. package/dist/{sync-cmd-YONVGUYS.js → sync-cmd-M6JA3OEE.js} +5 -4
  71. package/dist/{watch-HHKAF26L.js → watch-NB5TGPEZ.js} +5 -4
  72. package/dist/{work-claim-cmd-LXBZTMJA.js → work-claim-cmd-UHMWOS3G.js} +13 -6
  73. package/dist/{work-cmd-OVNF44FY.js → work-cmd-6UMCFTAW.js} +9 -3
  74. package/dist/{work-comment-cmd-6DGQNTAH.js → work-comment-cmd-E4LEUIXZ.js} +9 -3
  75. package/dist/{work-open-pr-cmd-FCZHFHZS.js → work-open-pr-cmd-OPZWGSEQ.js} +10 -4
  76. package/dist/{work-pr-cmd-QJJVHZDC.js → work-pr-cmd-IDIAFFRU.js} +9 -2
  77. package/package.json +1 -1
  78. package/skill-pack/template/build/scripts/record-criteria.mjs +2 -1
  79. package/dist/chunk-7DBI6SNT.js +0 -55
  80. package/dist/config-HL2AIR3K.js +0 -9
@@ -1,13 +1,62 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { dashboardBase, isRepositoryLinked, workPageUrl, notLinkedText } from './chunk-7DBI6SNT.js';
4
- import { sanitizeTerminal } from './chunk-3DEVYTNQ.js';
5
- import { remoteLookupFailed } from './chunk-ANK2B36Y.js';
3
+ import { sanitizeTerminal } from './chunk-ZYHKJKSU.js';
4
+ import { remoteLookupFailed } from './chunk-D6FXM5OW.js';
5
+ import { DEFAULT_DASHBOARD } from './chunk-USO2DKBD.js';
6
6
  import { resolveGatewayCredentials } from './chunk-BOLTI6LR.js';
7
- import { findGitDirs, readRepoConnection, writeRepoConnection } from './chunk-BJ3KTMDH.js';
7
+ import { readCloudConfig } from './chunk-EABW6AJQ.js';
8
+ import { writeRepoConnection, findGitDirs, readRepoConnection } from './chunk-BJ3KTMDH.js';
8
9
  import { createInterface } from 'readline/promises';
9
10
 
10
11
  createRequire(import.meta.url);
12
+
13
+ // src/repository-link.ts
14
+ var LINKS_TIMEOUT_MS = 15e3;
15
+ var GITHUB_PREFIX = "github.com/";
16
+ function isLinkedRepository(local, linked) {
17
+ if (linked.provider !== "github" || typeof linked.repository !== "string") return false;
18
+ return local.toLowerCase() === `${GITHUB_PREFIX}${linked.repository.toLowerCase()}`;
19
+ }
20
+ function ownerAndName(repository) {
21
+ return repository.toLowerCase().startsWith(GITHUB_PREFIX) ? repository.slice(GITHUB_PREFIX.length) : repository;
22
+ }
23
+ async function isRepositoryLinked(fetchImpl, gatewayUrl, token, appId, repository) {
24
+ if (!repository.toLowerCase().startsWith(GITHUB_PREFIX)) return null;
25
+ let res;
26
+ try {
27
+ res = await fetchImpl(`${gatewayUrl.replace(/\/+$/, "")}/v1/apps/${encodeURIComponent(appId)}/git/links`, {
28
+ method: "GET",
29
+ headers: { authorization: `Bearer ${token}`, "x-outerlayer-app-id": appId },
30
+ signal: AbortSignal.timeout(LINKS_TIMEOUT_MS)
31
+ });
32
+ } catch {
33
+ return null;
34
+ }
35
+ if (!res.ok) return null;
36
+ const listed = (await res.json().catch(() => void 0))?.data;
37
+ if (!Array.isArray(listed)) return null;
38
+ return listed.some((entry) => isLinkedRepository(repository, entry ?? {}));
39
+ }
40
+ function dashboardBase(home) {
41
+ const saved = readCloudConfig(home).dashboard;
42
+ const base = typeof saved === "string" && saved.trim() !== "" ? saved : DEFAULT_DASHBOARD;
43
+ return base.replace(/\/+$/, "");
44
+ }
45
+ function workPageUrl(home, organization, factory) {
46
+ return `${dashboardBase(home)}/orgs/${encodeURIComponent(organization)}/factories/${encodeURIComponent(factory)}/work`;
47
+ }
48
+ function notLinkedText(factoryName, repository, url) {
49
+ const shown = sanitizeTerminal(repository);
50
+ const name = sanitizeTerminal(ownerAndName(repository));
51
+ return `${factoryName} has no link to ${shown} yet, so work from this repository cannot reach it.
52
+ Link it on the factory's Work page: ${url}
53
+ 1. Connect GitHub repository, and grant the App access to ${name}.
54
+ 2. Link repository, and pick ${name} and its default branch.
55
+ Then run \`outerlayer connect\` again.
56
+ `;
57
+ }
58
+
59
+ // src/connect-cmd.ts
11
60
  var REQUEST_TIMEOUT_MS = 15e3;
12
61
  var EXIT_NOT_LINKED = 2;
13
62
  var REASON_TEXT = {
@@ -72,10 +121,10 @@ function parseFactories(body) {
72
121
  function listText(factories, repository) {
73
122
  return factories.map((f) => ` ${slug(f)} ${f.displayName}${f.linked === true ? ` (linked to ${repository})` : ""}`).join("\n");
74
123
  }
75
- async function fetchFactories(deps, url, token, repository) {
124
+ async function fetchFactories(fetchImpl, url, token, repository) {
76
125
  let res;
77
126
  try {
78
- res = await deps.fetchImpl(`${url.replace(/\/+$/, "")}/v1/me/factories?${new URLSearchParams({ repository }).toString()}`, {
127
+ res = await fetchImpl(`${url.replace(/\/+$/, "")}/v1/me/factories?${new URLSearchParams({ repository }).toString()}`, {
79
128
  method: "GET",
80
129
  headers: { authorization: `Bearer ${token}` },
81
130
  signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
@@ -99,6 +148,26 @@ async function fetchFactories(deps, url, token, repository) {
99
148
  }
100
149
  return { ok: true, factories };
101
150
  }
151
+ function selectFactory(factories, saved, repository) {
152
+ const remembered = saved && factories.find((f) => f.id === saved.appId);
153
+ if (remembered) return { factory: remembered, reason: "saved" };
154
+ const linked = factories.filter((f) => f.linked === true);
155
+ if (linked.length === 1) return { factory: linked[0], reason: "linked" };
156
+ if (factories.length === 1) return { factory: factories[0], reason: "only" };
157
+ return { factory: void 0, values: factories.map(slug), text: listText(factories, repository) };
158
+ }
159
+ function saveFactoryConnection(gitCommonDir, saved, factory, now) {
160
+ if (saved?.appId === factory.id) return;
161
+ writeRepoConnection(gitCommonDir, {
162
+ appId: factory.id,
163
+ organization: { name: factory.organization.name, displayName: factory.organization.displayName },
164
+ factory: { name: factory.name, displayName: factory.displayName },
165
+ savedAt: now.toISOString()
166
+ });
167
+ }
168
+ function connectedLine(repository, factory, reason) {
169
+ return `Connected ${repository} to factory "${factory.displayName}" in ${factory.organization.displayName} (${REASON_TEXT[reason]}).`;
170
+ }
102
171
  async function choose(flags, deps, factories, saved, repository) {
103
172
  if (flags.factory !== void 0) {
104
173
  const wanted = flags.factory.toLowerCase();
@@ -108,11 +177,9 @@ async function choose(flags, deps, factories, saved, repository) {
108
177
  ${listText(factories, repository)}`;
109
178
  return result(1, "failed", `--factory ${flags.factory} names no factory you can use`, message);
110
179
  }
111
- const remembered = saved && factories.find((f) => f.id === saved.appId);
112
- if (remembered) return { factory: remembered, reason: "saved" };
180
+ const decided = selectFactory(factories, saved, repository);
181
+ if (decided.factory) return { factory: decided.factory, reason: decided.reason };
113
182
  const linked = factories.filter((f) => f.linked === true);
114
- if (linked.length === 1) return { factory: linked[0], reason: "linked" };
115
- if (factories.length === 1) return { factory: factories[0], reason: "only" };
116
183
  if (!deps.isTerminal) {
117
184
  const why = linked.length > 1 ? `${repository} is linked to more than one factory you can use` : `you can use more than one factory, and none is the only one ${repository} is linked to`;
118
185
  const message = `${why}, and there is no terminal to ask on.
@@ -169,7 +236,7 @@ async function runConnect(flags, deps) {
169
236
  const message = "no gateway address is saved. Run `outerlayer login` to sign in.";
170
237
  return result(1, "failed", message, message);
171
238
  }
172
- const listed = await fetchFactories(deps, creds.url, creds.credential, repository);
239
+ const listed = await fetchFactories(deps.fetchImpl, creds.url, creds.credential, repository);
173
240
  if (!listed.ok) return listed.result;
174
241
  const { factories } = listed;
175
242
  if (factories.length === 0) {
@@ -181,20 +248,13 @@ async function runConnect(flags, deps) {
181
248
  const choice = await choose(flags, deps, factories, saved, repository);
182
249
  if ("code" in choice) return choice;
183
250
  const { factory, reason } = choice;
184
- if (saved?.appId !== factory.id) {
185
- try {
186
- writeRepoConnection(dirs.gitCommonDir, {
187
- appId: factory.id,
188
- organization: { name: factory.organization.name, displayName: factory.organization.displayName },
189
- factory: { name: factory.name, displayName: factory.displayName },
190
- savedAt: deps.now().toISOString()
191
- });
192
- } catch (err) {
193
- const message = `could not save the connection under ${dirs.gitCommonDir}: ${err instanceof Error ? err.message : String(err)}`;
194
- return result(1, "failed", "could not save the connection", message);
195
- }
251
+ try {
252
+ saveFactoryConnection(dirs.gitCommonDir, saved, factory, deps.now());
253
+ } catch (err) {
254
+ const message = `could not save the connection under ${dirs.gitCommonDir}: ${err instanceof Error ? err.message : String(err)}`;
255
+ return result(1, "failed", "could not save the connection", message);
196
256
  }
197
- const connected = `Connected ${repository} to factory "${factory.displayName}" in ${factory.organization.displayName} (${REASON_TEXT[reason]}).
257
+ const connected = `${connectedLine(repository, factory, reason)}
198
258
  `;
199
259
  const why = `connected to ${slug(factory)}: ${REASON_TEXT[reason]}`;
200
260
  const linked = await isRepositoryLinked(deps.fetchImpl, creds.url, creds.credential, factory.id, repository);
@@ -229,4 +289,4 @@ async function runConnectCommand(flags, deps, out) {
229
289
  return r.code;
230
290
  }
231
291
 
232
- export { promptOnTerminal, realConnectDeps, runConnect, runConnectCommand };
292
+ export { connectedLine, fetchFactories, isLinkedRepository, promptOnTerminal, realConnectDeps, runConnect, runConnectCommand, saveFactoryConnection, selectFactory };
@@ -98,4 +98,4 @@ function execStartLine(configPath, nodePath) {
98
98
  return `ExecStart=${execStartCommand(configPath, nodePath)}`;
99
99
  }
100
100
 
101
- export { cleanVersions, currentVersion, entryIn, execStartCommand, execStartLine, isInLayout, packageRootIn, readMarker, removeMarker, stagingDir, startedThroughCurrent, switchCurrent, versionDir, writeMarker };
101
+ export { cleanVersions, currentLink, currentVersion, entryIn, execStartCommand, execStartLine, isInLayout, packageRootIn, readMarker, removeMarker, stagingDir, startedThroughCurrent, switchCurrent, versionDir, writeMarker };
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { splitRawFile } from './chunk-EMY4I27X.js';
3
+ import { splitRawFile } from './chunk-7ZR5UPMB.js';
4
4
  import { resolvePackageVersion } from './chunk-RA3O54FC.js';
5
5
  import { existsSync, readFileSync, mkdirSync, writeFileSync, readdirSync } from 'fs';
6
6
  import { join, dirname } from 'path';
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { EXEC_PORT } from './chunk-B2G7JHHB.js';
4
- import { RELAY_PORT } from './chunk-AUFG23AA.js';
3
+ import { EXEC_PORT } from './chunk-R7STSBLC.js';
4
+ import { RELAY_PORT } from './chunk-OD2VTIHN.js';
5
5
  import { spawn, spawnSync } from 'child_process';
6
6
  import { writeFileSync, chmodSync, mkdirSync } from 'fs';
7
7
 
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
+ import { autoConnect } from './chunk-PUN7LMNS.js';
3
4
  import { detectActiveSession } from './chunk-BFESLKPP.js';
4
- import { resolveRepoIdentity } from './chunk-ANK2B36Y.js';
5
+ import { resolveRepoIdentity } from './chunk-D6FXM5OW.js';
5
6
  import { parseTrackerNumber, trackerNumberError } from './chunk-WZBHBH3J.js';
6
7
  import { defaultFetch } from './chunk-BCLJSQCV.js';
7
8
  import { unauthorizedMessage, resolveGatewayCredentials } from './chunk-BOLTI6LR.js';
@@ -37,6 +38,8 @@ async function runWorkPr(opts) {
37
38
  const cwd = opts.cwd ?? process.cwd();
38
39
  const env = opts.env ?? process.env;
39
40
  const home = opts.home ?? homeFromEnv(env);
41
+ const refusal = await autoConnect(opts);
42
+ if (refusal !== void 0) throw new WorkPrCommandError(refusal);
40
43
  const creds = resolveCredentials(opts);
41
44
  const prNumber = resolvePrNumber(opts.number);
42
45
  const repository = resolveRepository(opts.repo, cwd);