@codeworksh/cli 0.0.1-dev.20260918042316 → 0.0.1-dev.20260922183613
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/README.md +94 -0
- package/add--i7mPR73.mjs +81 -0
- package/add--i7mPR73.mjs.map +1 -0
- package/{catalog-Cv1zoZ5S.mjs → catalog-DJxy_lne.mjs} +2 -2
- package/{catalog-Cv1zoZ5S.mjs.map → catalog-DJxy_lne.mjs.map} +1 -1
- package/check-Dq2WOgap.mjs +47 -0
- package/check-Dq2WOgap.mjs.map +1 -0
- package/commonjs-BDiLMfFF.mjs +160 -0
- package/commonjs-BDiLMfFF.mjs.map +1 -0
- package/definitions-Dfwyyv_K.mjs +3348 -0
- package/definitions-Dfwyyv_K.mjs.map +1 -0
- package/entries-Gfsq7U4P.mjs +48 -0
- package/entries-Gfsq7U4P.mjs.map +1 -0
- package/{error-zJGKAF4a.mjs → error-BrbT9_4g.mjs} +2470 -1853
- package/error-BrbT9_4g.mjs.map +1 -0
- package/{generate-DdscbX3w.mjs → generate-DrGYpD3l.mjs} +3 -3
- package/{generate-DdscbX3w.mjs.map → generate-DrGYpD3l.mjs.map} +1 -1
- package/{harness-BBTdWdhx.mjs → harness-Bgvrr0ZB.mjs} +2 -2
- package/{harness-BBTdWdhx.mjs.map → harness-Bgvrr0ZB.mjs.map} +1 -1
- package/index.d.mts +6 -1
- package/index.mjs +22 -6
- package/index.mjs.map +1 -1
- package/install-DoO4D3fk.mjs +53 -0
- package/install-DoO4D3fk.mjs.map +1 -0
- package/lib-BkWR53Bz.mjs +37659 -0
- package/lib-BkWR53Bz.mjs.map +1 -0
- package/lib-CyynPpjH.mjs +846 -0
- package/lib-CyynPpjH.mjs.map +1 -0
- package/lib-Dw7R2suc.mjs +16078 -0
- package/lib-Dw7R2suc.mjs.map +1 -0
- package/lib-JQygPqgO.mjs +10868 -0
- package/lib-JQygPqgO.mjs.map +1 -0
- package/link-B1zfETsS.mjs +40 -0
- package/link-B1zfETsS.mjs.map +1 -0
- package/list-3OR68HpY.mjs +76 -0
- package/list-3OR68HpY.mjs.map +1 -0
- package/{list-C6BrwuV-.mjs → list-CfPfmfe0.mjs} +4 -4
- package/{list-C6BrwuV-.mjs.map → list-CfPfmfe0.mjs.map} +1 -1
- package/login-GFV3Z9f2.mjs +45 -0
- package/login-GFV3Z9f2.mjs.map +1 -0
- package/logout-D17TQUfo.mjs +29 -0
- package/logout-D17TQUfo.mjs.map +1 -0
- package/p-map-C2WSUhyP.mjs +116 -0
- package/p-map-C2WSUhyP.mjs.map +1 -0
- package/package.json +12 -9
- package/{providers-fO-GJuXn.mjs → providers-DLXs9aWZ.mjs} +4 -4
- package/{providers-fO-GJuXn.mjs.map → providers-DLXs9aWZ.mjs.map} +1 -1
- package/refresh-BTNuP1zL.mjs +35 -0
- package/refresh-BTNuP1zL.mjs.map +1 -0
- package/reload-BzwsCBQq.mjs +26 -0
- package/reload-BzwsCBQq.mjs.map +1 -0
- package/remove-DgB3l5JL.mjs +36 -0
- package/remove-DgB3l5JL.mjs.map +1 -0
- package/{run-CgPOJ-wJ.mjs → run-BVo4XsL6.mjs} +11 -8
- package/run-BVo4XsL6.mjs.map +1 -0
- package/runtime-Dl621FOp.mjs +345 -0
- package/runtime-Dl621FOp.mjs.map +1 -0
- package/{serve-Du6luqoi.mjs → serve-Dpep18-A.mjs} +93 -17
- package/serve-Dpep18-A.mjs.map +1 -0
- package/settings-C52IrA72.mjs +215 -0
- package/settings-C52IrA72.mjs.map +1 -0
- package/shared-Uwjcofff.mjs +115 -0
- package/shared-Uwjcofff.mjs.map +1 -0
- package/status-DPYq2Sx4.mjs +31 -0
- package/status-DPYq2Sx4.mjs.map +1 -0
- package/type-defs-BZxrtlVD.mjs +538 -0
- package/type-defs-BZxrtlVD.mjs.map +1 -0
- package/update-CJrBbHwq.mjs +44 -0
- package/update-CJrBbHwq.mjs.map +1 -0
- package/valid-BWgW_TUl.mjs +354 -0
- package/valid-BWgW_TUl.mjs.map +1 -0
- package/error-zJGKAF4a.mjs.map +0 -1
- package/run-CgPOJ-wJ.mjs.map +0 -1
- package/runtime-DuL-GGrx.mjs +0 -163
- package/runtime-DuL-GGrx.mjs.map +0 -1
- package/serve-Du6luqoi.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -82,6 +82,49 @@ The v0 endpoint has no authentication; its default binding is loopback. Plugins
|
|
|
82
82
|
|
|
83
83
|
---
|
|
84
84
|
|
|
85
|
+
### `codework auth login|status|refresh|logout`
|
|
86
|
+
|
|
87
|
+
Sign in to OpenAI Codex with your ChatGPT account, or to GitHub Copilot with your GitHub account. Credentials are
|
|
88
|
+
stored under the selected Codework home and are loaded automatically when a run uses an `openai-codex` or
|
|
89
|
+
`github-copilot` model.
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# Sign in
|
|
93
|
+
codework auth login --openai-codex
|
|
94
|
+
codework auth login --github-copilot
|
|
95
|
+
|
|
96
|
+
# Codex without a local callback port (SSH, containers, port 1455 in use)
|
|
97
|
+
codework auth login --openai-codex --device
|
|
98
|
+
|
|
99
|
+
# Inspect credential metadata without printing tokens
|
|
100
|
+
codework auth status --openai-codex
|
|
101
|
+
codework auth status --github-copilot
|
|
102
|
+
|
|
103
|
+
# Renew an expired login, or clear one
|
|
104
|
+
codework auth refresh --openai-codex
|
|
105
|
+
codework auth logout --github-copilot
|
|
106
|
+
|
|
107
|
+
# Authenticate the home owned by a running RPC server
|
|
108
|
+
codework auth login --openai-codex --server ws://127.0.0.1:7433/rpc
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
`--home` keeps authentication alongside the rest of that Codework installation; `--auth-file` overrides the credential
|
|
112
|
+
file directly. Both providers share one `auth.json`, keyed by provider, so signing out of one leaves the other alone.
|
|
113
|
+
With `--server`, the CLI runs the interactive login locally -- a browser callback and a device prompt both need this
|
|
114
|
+
terminal -- and sends only the resulting credentials to the RPC server for storage.
|
|
115
|
+
|
|
116
|
+
**OpenAI Codex** has two flows. The default keeps Aikit's registered `http://localhost:1455/auth/callback` redirect,
|
|
117
|
+
and falls back to asking for the redirect URL if the callback never arrives. `--device` instead prints a code to enter
|
|
118
|
+
at `auth.openai.com/codex/device` and needs no local port at all — use it over SSH, inside a container, or when another
|
|
119
|
+
sign-in already holds 1455. That port is fixed by the redirect registered against the OAuth client, so it cannot move.
|
|
120
|
+
|
|
121
|
+
**GitHub Copilot** uses the GitHub device flow: the CLI prints a user code, opens `github.com/login/device`, and waits.
|
|
122
|
+
The token does not expire, so there is no `--refresh` -- sign in again on persistent 401s. `--enterprise <domain>`
|
|
123
|
+
logs into a GitHub Enterprise host, and `--enable-models` turns on catalog models the account has left unconfigured.
|
|
124
|
+
Login records the plan-specific Copilot API host, which later runs use in place of the catalog default.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
85
128
|
### `codework models`
|
|
86
129
|
|
|
87
130
|
List catalog models as `provider/model`, one per line.
|
|
@@ -116,6 +159,57 @@ codework models generate ./path/to/custom-models.json
|
|
|
116
159
|
|
|
117
160
|
---
|
|
118
161
|
|
|
162
|
+
### `codework plugin add` / `codework plugin remove`
|
|
163
|
+
|
|
164
|
+
Install a plugin and record it in a settings file, or take it back out. Scoping follows npm: the
|
|
165
|
+
project is the default, `-g` is user-wide.
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
# This project: edits .codework/settings.jsonc, creating .codework/ here if no ancestor has one
|
|
169
|
+
codework plugin add @acme/codework-tool-proc@1.2.0
|
|
170
|
+
|
|
171
|
+
# Every project this user runs: writes ~/.codework/settings.jsonc
|
|
172
|
+
codework plugin add @acme/codework-tool-proc@1.2.0 -g
|
|
173
|
+
|
|
174
|
+
# Remove it, along with any configuration written against it
|
|
175
|
+
codework plugin remove @acme/codework-tool-proc
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
The project is found the way the harness finds it, and the way git finds a repository: the
|
|
179
|
+
nearest ancestor holding a `.codework` directory. Run from `packages/app`, the command edits the
|
|
180
|
+
repository's own `.codework/settings.jsonc` rather than starting a second project beside it. An
|
|
181
|
+
empty `.codework/` is enough — the marker is the directory, so creating it is how you say a
|
|
182
|
+
project begins here. When no ancestor has one, `add` creates `.codework/` in the directory you are
|
|
183
|
+
in and prints the path, because that decides where every later plugin entry lands.
|
|
184
|
+
|
|
185
|
+
`add` installs and imports the module before writing anything, so a spec that is not a plugin
|
|
186
|
+
fails with its own error and leaves the file untouched; the line it prints names the plugin ID the
|
|
187
|
+
module actually declared. Adding a plugin that is already configured under another spelling — a
|
|
188
|
+
different version, or the path instead of the package — rewrites that entry in place rather than
|
|
189
|
+
leaving a second loader behind, the way `npm install pkg@2` updates the spec already recorded.
|
|
190
|
+
Configuration written against the plugin is left where it is. Edits preserve comments, key order and formatting, and are written
|
|
191
|
+
through a temp file so an interrupted run cannot truncate your settings.
|
|
192
|
+
|
|
193
|
+
`remove` drops the module entry and any configuration object naming the same plugin, whichever
|
|
194
|
+
spelling each was written with: the version it was added with is not part of its identity, and the
|
|
195
|
+
ID a module declares removes the entry that loads it. Resolving an ID reads what is installed and
|
|
196
|
+
never fetches anything. A plugin can also be kept but switched off without removing it, with
|
|
197
|
+
`{ "plugin": "acme.tool.proc", "enabled": false }`.
|
|
198
|
+
|
|
199
|
+
#### Flags:
|
|
200
|
+
|
|
201
|
+
| Flag | Description |
|
|
202
|
+
| :------------------ | :--------------------------------------------------------------------------------- |
|
|
203
|
+
| `-g`, `--global` | Edit the user-wide settings file instead of this project's |
|
|
204
|
+
| `--home` | Where that user-wide file lives (default: `CODEWORK_HOME_DIR`, else `~/.codework`) |
|
|
205
|
+
| `--user-config-dir` | Edit `<dir>/settings.jsonc`; outranks both of the above |
|
|
206
|
+
|
|
207
|
+
Plugin entries accumulate across settings layers, so a user-wide plugin still applies inside a
|
|
208
|
+
project that declares its own. A project that wants an inherited plugin gone says so in its own
|
|
209
|
+
file, with `{ "plugin": "<id>", "enabled": false }`.
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
119
213
|
## Environment Variables
|
|
120
214
|
|
|
121
215
|
| Variable | Description |
|
package/add--i7mPR73.mjs
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { B as inspect, _t as path, a as reportFailure, at as SessionNotLinkedError, bt as resolve, f as writeOut, gt as layer$2, it as SessionNotFoundError, lt as layer$1, ot as layer, rt as Service, xt as ID } from "./error-BrbT9_4g.mjs";
|
|
2
|
+
import { i as Cmd, t as handler } from "./runtime-Dl621FOp.mjs";
|
|
3
|
+
import { a as resolveTarget, c as writePlugins, i as readPlugins, l as written, n as matches, o as spellings, s as withPluginsLock, t as identify } from "./settings-C52IrA72.mjs";
|
|
4
|
+
import { Effect, Layer, Option, Path } from "effect";
|
|
5
|
+
//#region src/cli/cmd/handlers/plugin/session.ts
|
|
6
|
+
/**
|
|
7
|
+
* The host directory a session is linked to.
|
|
8
|
+
*
|
|
9
|
+
* **A session ID can answer this and a project ID cannot**, which is why the flag takes one. A
|
|
10
|
+
* `Project` is env-independent by design -- its identity is a repo marker, a remote hash or a root
|
|
11
|
+
* commit, never a path -- and its spaces hold `location`s *inside* an env, which may be a container
|
|
12
|
+
* on another machine. Deriving a host settings file from one would mean walking the host
|
|
13
|
+
* filesystem from a path that means something somewhere else, which is the exact failure the
|
|
14
|
+
* `hostDir` split exists to prevent: it does not error, it finds a stranger's project.
|
|
15
|
+
*
|
|
16
|
+
* A session, by contrast, carries a `hostDir` that was *declared* on the host. Absent is a normal
|
|
17
|
+
* state rather than corruption, and it is the one this refuses.
|
|
18
|
+
*/
|
|
19
|
+
const linkedDirectory = Effect.fn("CLI.plugin.linkedDirectory")(function* (sessionId, home) {
|
|
20
|
+
const paths = yield* resolve(Option.isNone(home) ? {} : { home: home.value });
|
|
21
|
+
const id = ID.ascending(sessionId);
|
|
22
|
+
return yield* Effect.gen(function* () {
|
|
23
|
+
const found = yield* (yield* Service).get(id);
|
|
24
|
+
if (Option.isNone(found)) return yield* new SessionNotFoundError({ sessionId: id });
|
|
25
|
+
const hostDir = Option.getOrUndefined(found.value.hostDir);
|
|
26
|
+
if (hostDir === void 0) return yield* new SessionNotLinkedError({ sessionId: id });
|
|
27
|
+
return hostDir;
|
|
28
|
+
}).pipe(Effect.provide(layer.pipe(Layer.provide(layer$1), Layer.provide(layer$2(yield* path(paths.data))))));
|
|
29
|
+
});
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region src/cli/cmd/handlers/plugin/add.ts
|
|
32
|
+
var add_default = handler(Cmd.commands.plugin.commands.add, Effect.fn("CLI.plugin.add")(function* ({ package: reference, global: userWide, session }) {
|
|
33
|
+
return yield* Effect.gen(function* () {
|
|
34
|
+
const shared = yield* Cmd.spec;
|
|
35
|
+
const path = yield* Path.Path;
|
|
36
|
+
const paths = yield* resolve(Option.isNone(shared.home) ? {} : { home: shared.home.value });
|
|
37
|
+
const linked = Option.isNone(session) ? void 0 : yield* linkedDirectory(session.value, shared.home);
|
|
38
|
+
const from = linked ?? path.resolve(".");
|
|
39
|
+
const target = yield* resolveTarget(shared, userWide, linked, false);
|
|
40
|
+
const plugin = yield* inspect(reference, {
|
|
41
|
+
cache: paths.cache,
|
|
42
|
+
hostDir: from,
|
|
43
|
+
file: target.path
|
|
44
|
+
});
|
|
45
|
+
const entry = yield* written(reference, {
|
|
46
|
+
cwd: from,
|
|
47
|
+
file: target.path,
|
|
48
|
+
root: target.root
|
|
49
|
+
});
|
|
50
|
+
const spelled = yield* spellings(reference, from);
|
|
51
|
+
const version = plugin.version === void 0 ? "" : `@${plugin.version}`;
|
|
52
|
+
yield* withPluginsLock(target.path, Effect.gen(function* () {
|
|
53
|
+
const { source, plugins } = yield* readPlugins(target.path);
|
|
54
|
+
const entries = yield* identify(plugins, target.path, paths.cache);
|
|
55
|
+
const names = (candidate) => matches(candidate, spelled) || candidate.answers.has(plugin.id);
|
|
56
|
+
const existing = entries.findIndex((candidate) => candidate.loads && names(candidate));
|
|
57
|
+
if (existing >= 0) {
|
|
58
|
+
const current = entries[existing]?.value;
|
|
59
|
+
if (current === entry) {
|
|
60
|
+
yield* writeOut(`Plugin "${reference}" is already configured in ${target.path}\n`);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const replaced = [...plugins];
|
|
64
|
+
replaced[existing] = entry;
|
|
65
|
+
yield* writePlugins(target.path, source, replaced);
|
|
66
|
+
yield* writeOut(`Updated ${plugin.id} (${String(current)} -> ${entry}${version}) in ${target.path}\n`);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const configured = entries.findIndex((candidate) => !candidate.loads && names(candidate));
|
|
70
|
+
const updated = [...plugins];
|
|
71
|
+
updated.splice(configured < 0 ? updated.length : configured, 0, entry);
|
|
72
|
+
yield* writePlugins(target.path, source, updated);
|
|
73
|
+
yield* writeOut(`Added ${plugin.id} (${entry}${version}) to ${target.path}\n`);
|
|
74
|
+
}));
|
|
75
|
+
if (target.created !== void 0) yield* writeOut(`Created ${target.created}/\n`);
|
|
76
|
+
}).pipe(Effect.catch(reportFailure));
|
|
77
|
+
}));
|
|
78
|
+
//#endregion
|
|
79
|
+
export { add_default as default };
|
|
80
|
+
|
|
81
|
+
//# sourceMappingURL=add--i7mPR73.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add--i7mPR73.mjs","names":["Global.resolve","SessionStore.Service","SessionStore.SessionNotFoundError","SessionStore.SessionNotLinkedError","Event.layer","Database.layer","Database.path","Runtime.handler","Global.resolve","Plugin.inspect"],"sources":["../../src/cli/cmd/handlers/plugin/session.ts","../../src/cli/cmd/handlers/plugin/add.ts"],"sourcesContent":["import { Database, Event, Global, Session, SessionStore } from \"@codeworksh/harness/effect\";\nimport { Effect, Layer, Option } from \"effect\";\n\n/**\n * The host directory a session is linked to.\n *\n * **A session ID can answer this and a project ID cannot**, which is why the flag takes one. A\n * `Project` is env-independent by design -- its identity is a repo marker, a remote hash or a root\n * commit, never a path -- and its spaces hold `location`s *inside* an env, which may be a container\n * on another machine. Deriving a host settings file from one would mean walking the host\n * filesystem from a path that means something somewhere else, which is the exact failure the\n * `hostDir` split exists to prevent: it does not error, it finds a stranger's project.\n *\n * A session, by contrast, carries a `hostDir` that was *declared* on the host. Absent is a normal\n * state rather than corruption, and it is the one this refuses.\n */\nexport const linkedDirectory = Effect.fn(\"CLI.plugin.linkedDirectory\")(function* (\n\tsessionId: string,\n\thome: Option.Option<string>,\n) {\n\tconst paths = yield* Global.resolve(Option.isNone(home) ? {} : { home: home.value });\n\tconst id = Session.SessionSchema.ID.ascending(sessionId);\n\n\treturn yield* Effect.gen(function* () {\n\t\tconst sessions = yield* SessionStore.Service;\n\t\tconst found = yield* sessions.get(id);\n\t\tif (Option.isNone(found)) return yield* new SessionStore.SessionNotFoundError({ sessionId: id });\n\t\tconst hostDir = Option.getOrUndefined(found.value.hostDir);\n\t\tif (hostDir === undefined) return yield* new SessionStore.SessionNotLinkedError({ sessionId: id });\n\t\treturn hostDir;\n\t}).pipe(\n\t\t// Only the session row is read, so this needs the database and the event log the store is\n\t\t// built on -- no sandboxes, no control plane, no plugin machinery.\n\t\tEffect.provide(\n\t\t\tSessionStore.layer.pipe(\n\t\t\t\tLayer.provide(Event.layer),\n\t\t\t\tLayer.provide(Database.layer(yield* Database.path(paths.data))),\n\t\t\t),\n\t\t),\n\t);\n});\n","import { Global, Plugin } from \"@codeworksh/harness/effect\";\nimport { Effect, Option, Path } from \"effect\";\nimport { Runtime } from \"../../../../framework/runtime.ts\";\nimport { reportFailure } from \"../../../error.ts\";\nimport { writeOut } from \"../../../output.ts\";\nimport { Cmd } from \"../../cmd.ts\";\nimport { linkedDirectory } from \"./session.ts\";\nimport {\n\tidentify,\n\tmatches,\n\treadPlugins,\n\tresolveTarget,\n\tspellings,\n\twithPluginsLock,\n\twritePlugins,\n\twritten,\n} from \"./settings.ts\";\n\nexport default Runtime.handler(\n\tCmd.commands.plugin.commands.add,\n\tEffect.fn(\"CLI.plugin.add\")(function* ({ package: reference, global: userWide, session }) {\n\t\tconst program = Effect.gen(function* () {\n\t\t\tconst shared = yield* Cmd.spec;\n\t\t\tconst path = yield* Path.Path;\n\t\t\tconst paths = yield* Global.resolve(Option.isNone(shared.home) ? {} : { home: shared.home.value });\n\n\t\t\t// A session names the project to write into when the shell's directory is not it --\n\t\t\t// a server or a UI acting on a session's behalf, rather than a person standing in the\n\t\t\t// repository. It fails when that session has no project, which is a state `session\n\t\t\t// link` exists to fix.\n\t\t\tconst linked = Option.isNone(session) ? undefined : yield* linkedDirectory(session.value, shared.home);\n\t\t\t/*\n\t\t\t * One directory answers every question this command asks about the reference, and it\n\t\t\t * is resolved before any of them.\n\t\t\t *\n\t\t\t * A relative spec anchors here, the `.npmrc` chain governing the install is read from\n\t\t\t * here, and the entry is written anchored here. Splitting them is not a cosmetic\n\t\t\t * inconsistency: under `--session` the shell's directory is a server's, so validating\n\t\t\t * `./plugins/x.ts` against it imports one file and writes a reference to another, and\n\t\t\t * reading the `.npmrc` chain from it installs from the wrong registry -- a private\n\t\t\t * scope's token lives in the project being written to, not wherever the server runs.\n\t\t\t */\n\t\t\tconst from = linked ?? path.resolve(\".\");\n\n\t\t\t// The file the entry will land in decides the install's registry identity: it is named\n\t\t\t// here -- without creating the marker -- so the store keys the artifact under the same\n\t\t\t// `.npmrc` chain every later resolve of this entry re-derives, and a bad reference\n\t\t\t// still leaves nothing behind.\n\t\t\tconst target = yield* resolveTarget(shared, userWide, linked, false);\n\n\t\t\t// Install and import before touching the file: a spec that turns out not to be a plugin\n\t\t\t// should fail here, with its own error, rather than at the next run from a file the user\n\t\t\t// then has to repair by hand.\n\t\t\tconst plugin = yield* Plugin.inspect(reference, { cache: paths.cache, hostDir: from, file: target.path });\n\t\t\t// What goes in the file, which is not always what was typed: a relative path anchors to\n\t\t\t// the settings file being written, not to the directory the command ran in.\n\t\t\tconst entry = yield* written(reference, {\n\t\t\t\tcwd: from,\n\t\t\t\tfile: target.path,\n\t\t\t\troot: target.root,\n\t\t\t});\n\t\t\tconst spelled = yield* spellings(reference, from);\n\t\t\tconst version = plugin.version === undefined ? \"\" : `@${plugin.version}`;\n\t\t\tyield* withPluginsLock(\n\t\t\t\ttarget.path,\n\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\tconst { source, plugins } = yield* readPlugins(target.path);\n\t\t\t\t\tconst entries = yield* identify(plugins, target.path, paths.cache);\n\t\t\t\t\t// Configured already if any spelling of an existing entry names this plugin -- the same\n\t\t\t\t\t// package under a different version, the path it was added by, or the ID it declares.\n\t\t\t\t\tconst names = (candidate: (typeof entries)[number]) =>\n\t\t\t\t\t\tmatches(candidate, spelled) || candidate.answers.has(plugin.id);\n\t\t\t\t\tconst existing = entries.findIndex((candidate) => candidate.loads && names(candidate));\n\t\t\t\t\tif (existing >= 0) {\n\t\t\t\t\t\tconst current = entries[existing]?.value;\n\t\t\t\t\t\tif (current === entry) {\n\t\t\t\t\t\t\tyield* writeOut(`Plugin \"${reference}\" is already configured in ${target.path}\\n`);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst replaced = [...plugins];\n\t\t\t\t\t\treplaced[existing] = entry;\n\t\t\t\t\t\tyield* writePlugins(target.path, source, replaced);\n\t\t\t\t\t\tyield* writeOut(\n\t\t\t\t\t\t\t`Updated ${plugin.id} (${String(current)} -> ${entry}${version}) in ${target.path}\\n`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Put the loader before existing configuration so its options apply to the module.\n\t\t\t\t\tconst configured = entries.findIndex((candidate) => !candidate.loads && names(candidate));\n\t\t\t\t\tconst updated = [...plugins];\n\t\t\t\t\tupdated.splice(configured < 0 ? updated.length : configured, 0, entry);\n\t\t\t\t\tyield* writePlugins(target.path, source, updated);\n\t\t\t\t\tyield* writeOut(`Added ${plugin.id} (${entry}${version}) to ${target.path}\\n`);\n\t\t\t\t}),\n\t\t\t);\n\t\t\t// Said after the write, because `resolveTarget` only named the marker: the lock's\n\t\t\t// write is what made it, and \"created\" should be true by the time it is printed.\n\t\t\tif (target.created !== undefined) yield* writeOut(`Created ${target.created}/\\n`);\n\t\t});\n\n\t\treturn yield* program.pipe(Effect.catch(reportFailure));\n\t}),\n);\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { et as ModelCatalogError } from "./error-BrbT9_4g.mjs";
|
|
2
2
|
import { Effect } from "effect";
|
|
3
3
|
import { Model } from "@codeworksh/aikit";
|
|
4
4
|
//#region src/cli/cmd/handlers/models/catalog.ts
|
|
@@ -28,4 +28,4 @@ const loadProviders = Effect.tryPromise({
|
|
|
28
28
|
//#endregion
|
|
29
29
|
export { loadProviders as n, loadCatalog as t };
|
|
30
30
|
|
|
31
|
-
//# sourceMappingURL=catalog-
|
|
31
|
+
//# sourceMappingURL=catalog-DJxy_lne.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog-
|
|
1
|
+
{"version":3,"file":"catalog-DJxy_lne.mjs","names":["Runner.ModelCatalogError"],"sources":["../../src/cli/cmd/handlers/models/catalog.ts"],"sourcesContent":["import { Model } from \"@codeworksh/aikit\";\nimport { Runner } from \"@codeworksh/harness/effect\";\nimport { Effect } from \"effect\";\n\nconst catalogError = (cause: unknown): Runner.ModelCatalogError => {\n\tif (\n\t\ttypeof cause === \"object\" &&\n\t\tcause !== null &&\n\t\t\"name\" in cause &&\n\t\tcause.name === \"ModelCatalogLoadError\" &&\n\t\t\"data\" in cause &&\n\t\ttypeof cause.data === \"object\" &&\n\t\tcause.data !== null\n\t) {\n\t\tconst data = cause.data;\n\t\tif (\n\t\t\t\"path\" in data &&\n\t\t\ttypeof data.path === \"string\" &&\n\t\t\t\"message\" in data &&\n\t\t\ttypeof data.message === \"string\" &&\n\t\t\t\"reason\" in data &&\n\t\t\t(data.reason === \"missing\" ||\n\t\t\t\tdata.reason === \"unreadable\" ||\n\t\t\t\tdata.reason === \"empty\" ||\n\t\t\t\tdata.reason === \"invalid\")\n\t\t) {\n\t\t\treturn new Runner.ModelCatalogError({\n\t\t\t\tpath: data.path,\n\t\t\t\treason: data.reason,\n\t\t\t\tdetail: data.message,\n\t\t\t});\n\t\t}\n\t}\n\treturn new Runner.ModelCatalogError({\n\t\tpath: \"\",\n\t\treason: \"unreadable\",\n\t\tdetail: cause instanceof Error ? cause.message : \"failed to load the model catalog\",\n\t});\n};\n\nexport const loadCatalog = Effect.tryPromise({\n\ttry: () => Model.getBuiltInModels(),\n\tcatch: catalogError,\n});\n\nexport const loadProviders = Effect.tryPromise({\n\ttry: () => Model.getProviders(),\n\tcatch: catalogError,\n});\n"],"mappings":";;;;AAIA,MAAM,gBAAgB,UAA6C;CAClE,IACC,OAAO,UAAU,YACjB,UAAU,QACV,UAAU,SACV,MAAM,SAAS,2BACf,UAAU,SACV,OAAO,MAAM,SAAS,YACtB,MAAM,SAAS,MACd;EACD,MAAM,OAAO,MAAM;EACnB,IACC,UAAU,QACV,OAAO,KAAK,SAAS,YACrB,aAAa,QACb,OAAO,KAAK,YAAY,YACxB,YAAY,SACX,KAAK,WAAW,aAChB,KAAK,WAAW,gBAChB,KAAK,WAAW,WAChB,KAAK,WAAW,YAEjB,OAAO,IAAIA,kBAAyB;GACnC,MAAM,KAAK;GACX,QAAQ,KAAK;GACb,QAAQ,KAAK;EACd,CAAC;CAEH;CACA,OAAO,IAAIA,kBAAyB;EACnC,MAAM;EACN,QAAQ;EACR,QAAQ,iBAAiB,QAAQ,MAAM,UAAU;CAClD,CAAC;AACF;AAEA,MAAa,cAAc,OAAO,WAAW;CAC5C,WAAW,MAAM,iBAAiB;CAClC,OAAO;AACR,CAAC;AAED,MAAa,gBAAgB,OAAO,WAAW;CAC9C,WAAW,MAAM,aAAa;CAC9B,OAAO;AACR,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { V as check, a as reportFailure, f as writeOut } from "./error-BrbT9_4g.mjs";
|
|
2
|
+
import { i as Cmd, t as handler } from "./runtime-Dl621FOp.mjs";
|
|
3
|
+
import { n as probe, r as read, t as fetchable } from "./entries-Gfsq7U4P.mjs";
|
|
4
|
+
import { Effect } from "effect";
|
|
5
|
+
//#region src/cli/cmd/handlers/plugin/check.ts
|
|
6
|
+
/**
|
|
7
|
+
* Which configured plugins have a newer revision available.
|
|
8
|
+
*
|
|
9
|
+
* A probe failure -- offline, registry down, a remote that refuses -- is **not** an update. It is
|
|
10
|
+
* reported per target and the command exits non-zero, rather than being swallowed into "you are up
|
|
11
|
+
* to date": an outage that reads as currency is the one answer this command must never give.
|
|
12
|
+
*/
|
|
13
|
+
var check_default = handler(Cmd.commands.plugin.commands.check, Effect.fn("CLI.plugin.check")(function* ({ refresh }) {
|
|
14
|
+
return yield* Effect.gen(function* () {
|
|
15
|
+
const shared = yield* Cmd.spec;
|
|
16
|
+
const { entries, cache } = yield* read(shared);
|
|
17
|
+
let outdated = 0;
|
|
18
|
+
let failed = 0;
|
|
19
|
+
for (const entry of entries) {
|
|
20
|
+
const target = fetchable(entry.target);
|
|
21
|
+
if (target === void 0) continue;
|
|
22
|
+
const state = yield* check(target, cache, {
|
|
23
|
+
refresh,
|
|
24
|
+
probe: probe(cache, entry.from),
|
|
25
|
+
from: entry.from
|
|
26
|
+
}).pipe(Effect.result);
|
|
27
|
+
if (state._tag === "Failure") {
|
|
28
|
+
failed += 1;
|
|
29
|
+
yield* writeOut(`${entry.reference} error[${state.failure.reason}]: ${state.failure.message}\n`);
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
switch (state.success._tag) {
|
|
33
|
+
case "outdated":
|
|
34
|
+
outdated += 1;
|
|
35
|
+
yield* writeOut(`${entry.reference} ${state.success.filed ?? "?"} -> ${state.success.available}\n`);
|
|
36
|
+
break;
|
|
37
|
+
case "not-installed": yield* writeOut(`${entry.reference} plugin-not-installed\n`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
yield* writeOut(outdated === 0 && failed === 0 ? "Everything is up to date.\n" : `${outdated} update${outdated === 1 ? "" : "s"} available.\n`);
|
|
41
|
+
if (failed > 0) process.exitCode = 1;
|
|
42
|
+
}).pipe(Effect.catch(reportFailure));
|
|
43
|
+
}));
|
|
44
|
+
//#endregion
|
|
45
|
+
export { check_default as default };
|
|
46
|
+
|
|
47
|
+
//# sourceMappingURL=check-Dq2WOgap.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-Dq2WOgap.mjs","names":["Runtime.handler","Plugin.check"],"sources":["../../src/cli/cmd/handlers/plugin/check.ts"],"sourcesContent":["import { Plugin } from \"@codeworksh/harness/effect\";\nimport { Effect } from \"effect\";\nimport { Runtime } from \"../../../../framework/runtime.ts\";\nimport { reportFailure } from \"../../../error.ts\";\nimport { writeOut } from \"../../../output.ts\";\nimport { Cmd } from \"../../cmd.ts\";\nimport { fetchable, probe, read } from \"./entries.ts\";\n\n/**\n * Which configured plugins have a newer revision available.\n *\n * A probe failure -- offline, registry down, a remote that refuses -- is **not** an update. It is\n * reported per target and the command exits non-zero, rather than being swallowed into \"you are up\n * to date\": an outage that reads as currency is the one answer this command must never give.\n */\nexport default Runtime.handler(\n\tCmd.commands.plugin.commands.check,\n\tEffect.fn(\"CLI.plugin.check\")(function* ({ refresh }) {\n\t\tconst program = Effect.gen(function* () {\n\t\t\tconst shared = yield* Cmd.spec;\n\t\t\tconst { entries, cache } = yield* read(shared);\n\n\t\t\tlet outdated = 0;\n\t\t\tlet failed = 0;\n\t\t\tfor (const entry of entries) {\n\t\t\t\tconst target = fetchable(entry.target);\n\t\t\t\t// Nothing to compare: a local path has no revision, and `check` skips it rather\n\t\t\t\t// than reporting it as current.\n\t\t\t\tif (target === undefined) continue;\n\n\t\t\t\tconst state = yield* Plugin.check(target, cache, {\n\t\t\t\t\trefresh,\n\t\t\t\t\tprobe: probe(cache, entry.from),\n\t\t\t\t\tfrom: entry.from,\n\t\t\t\t}).pipe(Effect.result);\n\t\t\t\tif (state._tag === \"Failure\") {\n\t\t\t\t\tfailed += 1;\n\t\t\t\t\tyield* writeOut(`${entry.reference} error[${state.failure.reason}]: ${state.failure.message}\\n`);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tswitch (state.success._tag) {\n\t\t\t\t\tcase \"outdated\":\n\t\t\t\t\t\toutdated += 1;\n\t\t\t\t\t\tyield* writeOut(`${entry.reference} ${state.success.filed ?? \"?\"} -> ${state.success.available}\\n`);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"not-installed\":\n\t\t\t\t\t\tyield* writeOut(`${entry.reference} plugin-not-installed\\n`);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t// An exact version and a commit SHA cannot move, so neither is worth a line.\n\t\t\t\t\tcase \"immutable\":\n\t\t\t\t\tcase \"current\":\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tyield* writeOut(\n\t\t\t\toutdated === 0 && failed === 0\n\t\t\t\t\t? \"Everything is up to date.\\n\"\n\t\t\t\t\t: `${outdated} update${outdated === 1 ? \"\" : \"s\"} available.\\n`,\n\t\t\t);\n\t\t\tif (failed > 0) process.exitCode = 1;\n\t\t});\n\n\t\treturn yield* program.pipe(Effect.catch(reportFailure));\n\t}),\n);\n"],"mappings":";;;;;;;;;;;;AAeA,IAAA,gBAAeA,QACd,IAAI,SAAS,OAAO,SAAS,OAC7B,OAAO,GAAG,kBAAkB,CAAC,CAAC,WAAW,EAAE,WAAW;CA8CrD,OAAO,OA7CS,OAAO,IAAI,aAAa;EACvC,MAAM,SAAS,OAAO,IAAI;EAC1B,MAAM,EAAE,SAAS,UAAU,OAAO,KAAK,MAAM;EAE7C,IAAI,WAAW;EACf,IAAI,SAAS;EACb,KAAK,MAAM,SAAS,SAAS;GAC5B,MAAM,SAAS,UAAU,MAAM,MAAM;GAGrC,IAAI,WAAW,KAAA,GAAW;GAE1B,MAAM,QAAQ,OAAOC,MAAa,QAAQ,OAAO;IAChD;IACA,OAAO,MAAM,OAAO,MAAM,IAAI;IAC9B,MAAM,MAAM;GACb,CAAC,CAAC,CAAC,KAAK,OAAO,MAAM;GACrB,IAAI,MAAM,SAAS,WAAW;IAC7B,UAAU;IACV,OAAO,SAAS,GAAG,MAAM,UAAU,UAAU,MAAM,QAAQ,OAAO,KAAK,MAAM,QAAQ,QAAQ,GAAG;IAChG;GACD;GACA,QAAQ,MAAM,QAAQ,MAAtB;IACC,KAAK;KACJ,YAAY;KACZ,OAAO,SAAS,GAAG,MAAM,UAAU,IAAI,MAAM,QAAQ,SAAS,IAAI,MAAM,MAAM,QAAQ,UAAU,GAAG;KACnG;IACD,KAAK,iBACJ,OAAO,SAAS,GAAG,MAAM,UAAU,yBAAyB;GAM9D;EACD;EAEA,OAAO,SACN,aAAa,KAAK,WAAW,IAC1B,gCACA,GAAG,SAAS,SAAS,aAAa,IAAI,KAAK,IAAI,cACnD;EACA,IAAI,SAAS,GAAG,QAAQ,WAAW;CACpC,CAEoB,CAAC,CAAC,KAAK,OAAO,MAAM,aAAa,CAAC;AACvD,CAAC,CACF"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { Ct as __commonJSMin, Et as __require } from "./error-BrbT9_4g.mjs";
|
|
2
|
+
import { h as require_commonjs$1, t as require_lib$2, u as require_index_min } from "./lib-JQygPqgO.mjs";
|
|
3
|
+
//#region ../../node_modules/.pnpm/@npmcli+name-from-folder@5.0.0/node_modules/@npmcli/name-from-folder/lib/index.js
|
|
4
|
+
var require_lib$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
5
|
+
const { basename, dirname } = __require("path");
|
|
6
|
+
const getName = (parent, base) => parent.charAt(0) === "@" ? `${parent}/${base}` : base;
|
|
7
|
+
module.exports = (dir) => dir ? getName(basename(dirname(dir)), basename(dir)) : false;
|
|
8
|
+
}));
|
|
9
|
+
//#endregion
|
|
10
|
+
//#region ../../node_modules/.pnpm/@npmcli+map-workspaces@6.0.0/node_modules/@npmcli/map-workspaces/lib/index.js
|
|
11
|
+
var require_lib = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
12
|
+
const path = __require("path");
|
|
13
|
+
const getName = require_lib$1();
|
|
14
|
+
const { minimatch } = require_commonjs$1();
|
|
15
|
+
const pkgJson = require_lib$2();
|
|
16
|
+
const { glob } = require_index_min();
|
|
17
|
+
function appendNegatedPatterns(allPatterns) {
|
|
18
|
+
const patterns = [];
|
|
19
|
+
const negatedPatterns = [];
|
|
20
|
+
for (let pattern of allPatterns) {
|
|
21
|
+
const excl = pattern.match(/^!+/);
|
|
22
|
+
if (excl) pattern = pattern.slice(excl[0].length);
|
|
23
|
+
pattern = pattern.replace(/^\.?\/+/, "");
|
|
24
|
+
if (excl && excl[0].length % 2 === 1) negatedPatterns.push(pattern);
|
|
25
|
+
else {
|
|
26
|
+
for (let i = 0; i < negatedPatterns.length; ++i) {
|
|
27
|
+
const negatedPattern = negatedPatterns[i];
|
|
28
|
+
if (minimatch(pattern, negatedPattern)) negatedPatterns.splice(i, 1);
|
|
29
|
+
}
|
|
30
|
+
patterns.push(pattern);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
for (const negated of negatedPatterns) for (const pattern of minimatch.match(patterns, negated)) patterns.splice(patterns.indexOf(pattern), 1);
|
|
34
|
+
return {
|
|
35
|
+
patterns,
|
|
36
|
+
negatedPatterns
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function getPatterns(workspaces) {
|
|
40
|
+
const workspacesDeclaration = Array.isArray(workspaces.packages) ? workspaces.packages : workspaces;
|
|
41
|
+
if (!Array.isArray(workspacesDeclaration)) throw getError({
|
|
42
|
+
message: "workspaces config expects an Array",
|
|
43
|
+
code: "EWORKSPACESCONFIG"
|
|
44
|
+
});
|
|
45
|
+
return appendNegatedPatterns(workspacesDeclaration);
|
|
46
|
+
}
|
|
47
|
+
function getPackageName(pkg, pathname) {
|
|
48
|
+
return pkg.name || getName(pathname);
|
|
49
|
+
}
|
|
50
|
+
function getGlobPattern(pattern) {
|
|
51
|
+
pattern = pattern.replace(/\\/g, "/");
|
|
52
|
+
return pattern.endsWith("/") ? pattern : `${pattern}/`;
|
|
53
|
+
}
|
|
54
|
+
function getError({ Type = TypeError, message, code }) {
|
|
55
|
+
return Object.assign(new Type(message), { code });
|
|
56
|
+
}
|
|
57
|
+
function reverseResultMap(map) {
|
|
58
|
+
return new Map(Array.from(map, (item) => item.reverse()));
|
|
59
|
+
}
|
|
60
|
+
async function mapWorkspaces(opts = {}) {
|
|
61
|
+
if (!opts || !opts.pkg) throw getError({
|
|
62
|
+
message: "mapWorkspaces missing pkg info",
|
|
63
|
+
code: "EMAPWORKSPACESPKG"
|
|
64
|
+
});
|
|
65
|
+
if (!opts.cwd) opts.cwd = process.cwd();
|
|
66
|
+
const { workspaces = [] } = opts.pkg;
|
|
67
|
+
const { patterns, negatedPatterns } = getPatterns(workspaces);
|
|
68
|
+
const results = /* @__PURE__ */ new Map();
|
|
69
|
+
if (!patterns.length && !negatedPatterns.length) return results;
|
|
70
|
+
const seen = /* @__PURE__ */ new Map();
|
|
71
|
+
const getGlobOpts = () => ({
|
|
72
|
+
...opts,
|
|
73
|
+
ignore: [
|
|
74
|
+
...opts.ignore || [],
|
|
75
|
+
"**/node_modules/**",
|
|
76
|
+
...negatedPatterns
|
|
77
|
+
]
|
|
78
|
+
});
|
|
79
|
+
let matches = await glob(patterns.map((p) => getGlobPattern(p)), getGlobOpts());
|
|
80
|
+
matches = matches.sort((a, b) => a.localeCompare(b, "en"));
|
|
81
|
+
const orderedMatches = [];
|
|
82
|
+
for (const pattern of patterns) orderedMatches.push(...matches.filter((m) => {
|
|
83
|
+
return minimatch(m, pattern, {
|
|
84
|
+
partial: true,
|
|
85
|
+
windowsPathsNoEscape: true
|
|
86
|
+
});
|
|
87
|
+
}));
|
|
88
|
+
for (const match of orderedMatches) {
|
|
89
|
+
let pkg;
|
|
90
|
+
try {
|
|
91
|
+
pkg = await pkgJson.normalize(path.join(opts.cwd, match));
|
|
92
|
+
} catch (err) {
|
|
93
|
+
if (err.code === "ENOENT" || err.code === "ENOTDIR") continue;
|
|
94
|
+
else throw err;
|
|
95
|
+
}
|
|
96
|
+
const name = getPackageName(pkg.content, pkg.path);
|
|
97
|
+
let seenPackagePathnames = seen.get(name);
|
|
98
|
+
if (!seenPackagePathnames) {
|
|
99
|
+
seenPackagePathnames = /* @__PURE__ */ new Set();
|
|
100
|
+
seen.set(name, seenPackagePathnames);
|
|
101
|
+
}
|
|
102
|
+
seenPackagePathnames.add(pkg.path);
|
|
103
|
+
}
|
|
104
|
+
const errorMessageArray = ["must not have multiple workspaces with the same name"];
|
|
105
|
+
for (const [packageName, seenPackagePathnames] of seen) if (seenPackagePathnames.size > 1) addDuplicateErrorMessages(errorMessageArray, packageName, seenPackagePathnames);
|
|
106
|
+
else results.set(packageName, seenPackagePathnames.values().next().value);
|
|
107
|
+
if (errorMessageArray.length > 1) throw getError({
|
|
108
|
+
Type: Error,
|
|
109
|
+
message: errorMessageArray.join("\n"),
|
|
110
|
+
code: "EDUPLICATEWORKSPACE"
|
|
111
|
+
});
|
|
112
|
+
return results;
|
|
113
|
+
}
|
|
114
|
+
function addDuplicateErrorMessages(messageArray, packageName, packagePathnames) {
|
|
115
|
+
messageArray.push(`package '${packageName}' has conflicts in the following paths:`);
|
|
116
|
+
for (const packagePathname of packagePathnames) messageArray.push(" " + packagePathname);
|
|
117
|
+
}
|
|
118
|
+
mapWorkspaces.virtual = function(opts = {}) {
|
|
119
|
+
if (!opts || !opts.lockfile) throw getError({
|
|
120
|
+
message: "mapWorkspaces.virtual missing lockfile info",
|
|
121
|
+
code: "EMAPWORKSPACESLOCKFILE"
|
|
122
|
+
});
|
|
123
|
+
if (!opts.cwd) opts.cwd = process.cwd();
|
|
124
|
+
const { packages = {} } = opts.lockfile;
|
|
125
|
+
const { workspaces = [] } = packages[""] || {};
|
|
126
|
+
const results = /* @__PURE__ */ new Map();
|
|
127
|
+
const { patterns, negatedPatterns } = getPatterns(workspaces);
|
|
128
|
+
if (!patterns.length && !negatedPatterns.length) return results;
|
|
129
|
+
negatedPatterns.push("**/node_modules/**");
|
|
130
|
+
const packageKeys = Object.keys(packages);
|
|
131
|
+
for (const pattern of negatedPatterns) for (const packageKey of minimatch.match(packageKeys, pattern)) packageKeys.splice(packageKeys.indexOf(packageKey), 1);
|
|
132
|
+
for (const pattern of patterns) for (const packageKey of minimatch.match(packageKeys, pattern)) {
|
|
133
|
+
const packagePathname = path.join(opts.cwd, packageKey);
|
|
134
|
+
const name = getPackageName(packages[packageKey], packagePathname);
|
|
135
|
+
results.set(packagePathname, name);
|
|
136
|
+
}
|
|
137
|
+
return reverseResultMap(results);
|
|
138
|
+
};
|
|
139
|
+
module.exports = mapWorkspaces;
|
|
140
|
+
}));
|
|
141
|
+
//#endregion
|
|
142
|
+
//#region ../../node_modules/.pnpm/walk-up-path@4.0.0/node_modules/walk-up-path/dist/commonjs/index.js
|
|
143
|
+
var require_commonjs = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
144
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
145
|
+
exports.walkUp = void 0;
|
|
146
|
+
const path_1 = __require("path");
|
|
147
|
+
const walkUp = function* (path) {
|
|
148
|
+
for (path = (0, path_1.resolve)(path); path;) {
|
|
149
|
+
yield path;
|
|
150
|
+
const pp = (0, path_1.dirname)(path);
|
|
151
|
+
if (pp === path) break;
|
|
152
|
+
else path = pp;
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
exports.walkUp = walkUp;
|
|
156
|
+
}));
|
|
157
|
+
//#endregion
|
|
158
|
+
export { require_lib as n, require_lib$1 as r, require_commonjs as t };
|
|
159
|
+
|
|
160
|
+
//# sourceMappingURL=commonjs-BDiLMfFF.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commonjs-BDiLMfFF.mjs","names":[],"sources":["../../../../node_modules/.pnpm/@npmcli+name-from-folder@5.0.0/node_modules/@npmcli/name-from-folder/lib/index.js","../../../../node_modules/.pnpm/@npmcli+map-workspaces@6.0.0/node_modules/@npmcli/map-workspaces/lib/index.js","../../../../node_modules/.pnpm/walk-up-path@4.0.0/node_modules/walk-up-path/dist/commonjs/index.js"],"sourcesContent":["const { basename, dirname } = require('path')\n\nconst getName = (parent, base) =>\n parent.charAt(0) === '@' ? `${parent}/${base}` : base\n\nmodule.exports = dir => dir ? getName(basename(dirname(dir)), basename(dir))\n : false\n","const path = require('path')\n\nconst getName = require('@npmcli/name-from-folder')\nconst { minimatch } = require('minimatch')\nconst pkgJson = require('@npmcli/package-json')\nconst { glob } = require('glob')\n\nfunction appendNegatedPatterns (allPatterns) {\n const patterns = []\n const negatedPatterns = []\n for (let pattern of allPatterns) {\n const excl = pattern.match(/^!+/)\n if (excl) {\n pattern = pattern.slice(excl[0].length)\n }\n\n // strip off any / or ./ from the start of the pattern. /foo => foo\n pattern = pattern.replace(/^\\.?\\/+/, '')\n\n // an odd number of ! means a negated pattern. !!foo ==> foo\n const negate = excl && excl[0].length % 2 === 1\n if (negate) {\n negatedPatterns.push(pattern)\n } else {\n // remove negated patterns that appeared before this pattern to avoid\n // ignoring paths that were matched afterwards\n // e.g: ['packages/**', '!packages/b/**', 'packages/b/a']\n // in the above list, the last pattern overrides the negated pattern\n // right before it. In effect, the above list would become:\n // ['packages/**', 'packages/b/a']\n // The order matters here which is why we must do it inside the loop\n // as opposed to doing it all together at the end.\n for (let i = 0; i < negatedPatterns.length; ++i) {\n const negatedPattern = negatedPatterns[i]\n if (minimatch(pattern, negatedPattern)) {\n negatedPatterns.splice(i, 1)\n }\n }\n patterns.push(pattern)\n }\n }\n\n // use the negated patterns to eagerly remove all the patterns that\n // can be removed to avoid unnecessary crawling\n for (const negated of negatedPatterns) {\n for (const pattern of minimatch.match(patterns, negated)) {\n patterns.splice(patterns.indexOf(pattern), 1)\n }\n }\n return { patterns, negatedPatterns }\n}\n\nfunction getPatterns (workspaces) {\n const workspacesDeclaration =\n Array.isArray(workspaces.packages)\n ? workspaces.packages\n : workspaces\n\n if (!Array.isArray(workspacesDeclaration)) {\n throw getError({\n message: 'workspaces config expects an Array',\n code: 'EWORKSPACESCONFIG',\n })\n }\n\n return appendNegatedPatterns(workspacesDeclaration)\n}\n\nfunction getPackageName (pkg, pathname) {\n return pkg.name || getName(pathname)\n}\n\n// make sure glob pattern only matches folders\nfunction getGlobPattern (pattern) {\n pattern = pattern.replace(/\\\\/g, '/')\n return pattern.endsWith('/')\n ? pattern\n : `${pattern}/`\n}\n\nfunction getError ({ Type = TypeError, message, code }) {\n return Object.assign(new Type(message), { code })\n}\n\nfunction reverseResultMap (map) {\n return new Map(Array.from(map, item => item.reverse()))\n}\n\nasync function mapWorkspaces (opts = {}) {\n if (!opts || !opts.pkg) {\n throw getError({\n message: 'mapWorkspaces missing pkg info',\n code: 'EMAPWORKSPACESPKG',\n })\n }\n if (!opts.cwd) {\n opts.cwd = process.cwd()\n }\n\n const { workspaces = [] } = opts.pkg\n const { patterns, negatedPatterns } = getPatterns(workspaces)\n const results = new Map()\n\n if (!patterns.length && !negatedPatterns.length) {\n return results\n }\n\n const seen = new Map()\n const getGlobOpts = () => ({\n ...opts,\n ignore: [\n ...opts.ignore || [],\n '**/node_modules/**',\n // just ignore the negated patterns to avoid unnecessary crawling\n ...negatedPatterns,\n ],\n })\n\n let matches = await glob(patterns.map((p) => getGlobPattern(p)), getGlobOpts())\n // preserves glob@8 behavior\n matches = matches.sort((a, b) => a.localeCompare(b, 'en'))\n\n // we must preserve the order of results according to the given list of\n // workspace patterns\n const orderedMatches = []\n for (const pattern of patterns) {\n orderedMatches.push(...matches.filter((m) => {\n return minimatch(m, pattern, { partial: true, windowsPathsNoEscape: true })\n }))\n }\n\n for (const match of orderedMatches) {\n let pkg\n try {\n pkg = await pkgJson.normalize(path.join(opts.cwd, match))\n } catch (err) {\n if (err.code === 'ENOENT' || err.code === 'ENOTDIR') {\n continue\n } else {\n throw err\n }\n }\n\n const name = getPackageName(pkg.content, pkg.path)\n\n let seenPackagePathnames = seen.get(name)\n if (!seenPackagePathnames) {\n seenPackagePathnames = new Set()\n seen.set(name, seenPackagePathnames)\n }\n seenPackagePathnames.add(pkg.path)\n }\n\n const errorMessageArray = ['must not have multiple workspaces with the same name']\n for (const [packageName, seenPackagePathnames] of seen) {\n if (seenPackagePathnames.size > 1) {\n addDuplicateErrorMessages(errorMessageArray, packageName, seenPackagePathnames)\n } else {\n results.set(packageName, seenPackagePathnames.values().next().value)\n }\n }\n\n if (errorMessageArray.length > 1) {\n throw getError({\n Type: Error,\n message: errorMessageArray.join('\\n'),\n code: 'EDUPLICATEWORKSPACE',\n })\n }\n\n return results\n}\n\nfunction addDuplicateErrorMessages (messageArray, packageName, packagePathnames) {\n messageArray.push(\n `package '${packageName}' has conflicts in the following paths:`\n )\n\n for (const packagePathname of packagePathnames) {\n messageArray.push(\n ' ' + packagePathname\n )\n }\n}\n\nmapWorkspaces.virtual = function (opts = {}) {\n if (!opts || !opts.lockfile) {\n throw getError({\n message: 'mapWorkspaces.virtual missing lockfile info',\n code: 'EMAPWORKSPACESLOCKFILE',\n })\n }\n if (!opts.cwd) {\n opts.cwd = process.cwd()\n }\n\n const { packages = {} } = opts.lockfile\n const { workspaces = [] } = packages[''] || {}\n // uses a pathname-keyed map in order to negate the exact items\n const results = new Map()\n const { patterns, negatedPatterns } = getPatterns(workspaces)\n if (!patterns.length && !negatedPatterns.length) {\n return results\n }\n negatedPatterns.push('**/node_modules/**')\n\n const packageKeys = Object.keys(packages)\n for (const pattern of negatedPatterns) {\n for (const packageKey of minimatch.match(packageKeys, pattern)) {\n packageKeys.splice(packageKeys.indexOf(packageKey), 1)\n }\n }\n\n for (const pattern of patterns) {\n for (const packageKey of minimatch.match(packageKeys, pattern)) {\n const packagePathname = path.join(opts.cwd, packageKey)\n const name = getPackageName(packages[packageKey], packagePathname)\n results.set(packagePathname, name)\n }\n }\n\n // Invert pathname-keyed to a proper name-to-pathnames Map\n return reverseResultMap(results)\n}\n\nmodule.exports = mapWorkspaces\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.walkUp = void 0;\nconst path_1 = require(\"path\");\nconst walkUp = function* (path) {\n for (path = (0, path_1.resolve)(path); path;) {\n yield path;\n const pp = (0, path_1.dirname)(path);\n if (pp === path) {\n break;\n }\n else {\n path = pp;\n }\n }\n};\nexports.walkUp = walkUp;\n//# sourceMappingURL=index.js.map"],"x_google_ignoreList":[0,1,2],"mappings":"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"}
|