@jarel/myskills 0.1.0-alpha.2 → 0.1.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -4
- package/dist/index.js +238 -7
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Command-line client for MySkills.
|
|
4
4
|
|
|
5
|
+
Supported runtime: Node.js `>=22.13 <23 || >=24 <25`.
|
|
6
|
+
|
|
5
7
|
Package:
|
|
6
8
|
|
|
7
9
|
```text
|
|
@@ -49,7 +51,14 @@ myskills config reset api-url
|
|
|
49
51
|
myskills config list
|
|
50
52
|
myskills submit --path <file-directory-or-zip> [--api-url <url>] [--token <token>]
|
|
51
53
|
myskills review submissions [--api-url <url>] [--token <token>]
|
|
52
|
-
myskills review
|
|
54
|
+
myskills review bundle <submission-id> [--platform <name>] [--output <file>] [--api-url <url>] [--token <token>]
|
|
55
|
+
myskills review action <submission-id> --action <approve|request-changes|reject|publish> [--artifact-sha256 <hash>] [--reason <text>] [--api-url <url>] [--token <token>]
|
|
56
|
+
myskills submissions list [--api-url <url>] [--token <token>]
|
|
57
|
+
myskills submissions withdraw <submission-id> [--reason <text>] [--api-url <url>] [--token <token>]
|
|
58
|
+
myskills skills edit <skill-slug> [--title <text>] [--summary <text>] [--visibility <scope>] [--tag <tag>] [--reason <text>] [--api-url <url>] [--token <token>]
|
|
59
|
+
myskills skills archive|restore|delete <skill-slug> [--reason <text>] [--api-url <url>] [--token <token>]
|
|
60
|
+
myskills releases list <skill-slug> [--api-url <url>] [--token <token>]
|
|
61
|
+
myskills releases deprecate|unpublish|revoke|restore|delete <skill-slug>@<version> [--reason <text>] [--replacement <version>] [--api-url <url>] [--token <token>]
|
|
53
62
|
myskills teams list|skills [--api-url <url>] [--token <token>]
|
|
54
63
|
myskills teams create <team-name> [--name <team-name>] [--api-url <url>] [--token <token>]
|
|
55
64
|
myskills teams invite <team-id> --email <email> [--api-url <url>] [--token <token>]
|
|
@@ -68,9 +77,9 @@ myskills token list
|
|
|
68
77
|
myskills token revoke <token-id>
|
|
69
78
|
```
|
|
70
79
|
|
|
71
|
-
##
|
|
80
|
+
## Published And Candidate Channels
|
|
72
81
|
|
|
73
|
-
The
|
|
82
|
+
The currently published package remains available under npm's `alpha` tag:
|
|
74
83
|
|
|
75
84
|
```bash
|
|
76
85
|
npm install -g @jarel/myskills@alpha
|
|
@@ -84,13 +93,17 @@ Update the CLI with:
|
|
|
84
93
|
npm install -g @jarel/myskills@alpha
|
|
85
94
|
```
|
|
86
95
|
|
|
96
|
+
The `0.1.0-beta.2` source manifest is configured for the `beta` dist-tag, but package publication is a separate maintainer approval step. The release-verification workflow packs and installs the candidate without publishing it.
|
|
97
|
+
|
|
87
98
|
`validate`, `scan`, and `submit` accept a manifest file, package directory, or local `.zip` package. `login` prompts for the API URL when one is not supplied; the default is the local API at `http://localhost:3001`, and custom hosted URLs can be entered manually. Successful login stores the selected API URL in local CLI config so later commands can omit `--api-url`. API URL resolution is `--api-url`, then `MYSKILLS_API_URL`, then saved config, then `http://localhost:3001`.
|
|
88
99
|
|
|
89
100
|
`login` supports an email/password session flow and an API-key flow. The email/password flow handles MFA challenges with a TOTP or recovery code prompt and stores only the verified session token. The API-key flow validates the key with `/v1/me` before storing it. Token resolution is `--token`, then `MYSKILLS_TOKEN`, then the stored login token. The default token store uses the platform credential store through `@napi-rs/keyring` and falls back to `tokens.json` with user-only file permissions when keyring storage is unavailable or `MYSKILLS_TOKEN_STORE=file`/`MYSKILLS_TOKEN_FILE` is set. `auth status` validates the current token without printing it. `logout` revokes stored session tokens and clears the local entry; stored API tokens are removed locally and must be revoked with `token revoke`.
|
|
90
101
|
|
|
91
102
|
`config get api-url`, `config set api-url <url>`, `config reset api-url`, and `config list` manage the saved API URL. `doctor` checks the CLI version, Node version, resolved API URL, `/health`, auth status, token-store backend, install-directory writability, and `/v1/capabilities`. If the CLI is pointed at the web app instead of the API, or a newer command is sent to an older server, command errors include concrete next steps and `--json` returns structured error codes.
|
|
92
103
|
|
|
93
|
-
`submit` validates and scans locally before sending package directories as normalized text entries or `.zip` packages as base64 archive uploads for server-side extraction.
|
|
104
|
+
`submit` validates and scans locally before sending package directories as normalized text entries or `.zip` packages as base64 archive uploads for server-side extraction. Authors can inspect their submitted versions with `submissions list` and withdraw unreviewed or changes-requested submissions with `submissions withdraw`. Maintainers can fetch the reviewed artifact and approval hash with `review bundle`, then approve, request changes, reject, and publish submitted versions through `review action`.
|
|
105
|
+
|
|
106
|
+
Published artifacts remain immutable. `skills edit` changes mutable skill metadata only, while `releases deprecate`, `releases unpublish`, `releases revoke`, `releases restore`, and `releases delete` update server-owned lifecycle state for a specific version. Deprecated releases remain visible and installable; unpublished, revoked, archived, and deleted releases are hidden from install/export queries. `export` downloads server-authorized bundle content, verifies byte size and SHA-256 against release metadata, and writes normalized package paths under the requested output directory. `install` uses the same verified bundle path, writes into `--dir`, `MYSKILLS_INSTALL_DIR`, or the user data directory, and records local state in `.myskills-app/installed.json`; `update` preserves a rollback snapshot before replacing files, and `rollback` restores the most recent snapshot. `token create` prints the plaintext API token only once and does not overwrite the stored login session. Browser/device login, platform-specific install adapters, and archive creation are still planned.
|
|
94
107
|
|
|
95
108
|
Common scopes:
|
|
96
109
|
|
package/dist/index.js
CHANGED
|
@@ -16321,7 +16321,7 @@ function decodePackageText(buffer, relativePath) {
|
|
|
16321
16321
|
|
|
16322
16322
|
// src/cli.ts
|
|
16323
16323
|
var DEFAULT_API_URL = "http://localhost:3001";
|
|
16324
|
-
var CLI_VERSION = "0.1.0-
|
|
16324
|
+
var CLI_VERSION = "0.1.0-beta.2";
|
|
16325
16325
|
var CLI_VISIBILITY_SCOPES = ["public", "authenticated", "organization", "team", "private", "explicit-users"];
|
|
16326
16326
|
var LOGIN_AUTH_METHODS = ["password", "api-key"];
|
|
16327
16327
|
async function runCli(argv, runtime) {
|
|
@@ -16363,6 +16363,12 @@ async function runCli(argv, runtime) {
|
|
|
16363
16363
|
return await submitCommand(parsed, runtime);
|
|
16364
16364
|
case "review":
|
|
16365
16365
|
return await reviewCommand(parsed, runtime);
|
|
16366
|
+
case "submissions":
|
|
16367
|
+
return await submissionsCommand(parsed, runtime);
|
|
16368
|
+
case "skills":
|
|
16369
|
+
return await skillsCommand(parsed, runtime);
|
|
16370
|
+
case "releases":
|
|
16371
|
+
return await releasesCommand(parsed, runtime);
|
|
16366
16372
|
case "teams":
|
|
16367
16373
|
return await teamsCommand(parsed, runtime);
|
|
16368
16374
|
case "sharing":
|
|
@@ -16774,16 +16780,21 @@ async function reviewCommand(parsed, runtime) {
|
|
|
16774
16780
|
if (subcommand === "action") {
|
|
16775
16781
|
const submissionId = parsed.args[1];
|
|
16776
16782
|
if (!submissionId) {
|
|
16777
|
-
throw new CliError("Usage: myskills review action <submission-id> --action <approve|publish>", 2);
|
|
16783
|
+
throw new CliError("Usage: myskills review action <submission-id> --action <approve|request-changes|reject|publish> [--artifact-sha256 <hash>] [--reason <text>] [--api-url <url>] [--token <token>]", 2);
|
|
16778
16784
|
}
|
|
16779
16785
|
const action = stringOption(parsed, "action");
|
|
16780
|
-
if (action !== "approve" && action !== "publish") {
|
|
16781
|
-
throw new CliError("--action must be approve or publish.", 2);
|
|
16786
|
+
if (action !== "approve" && action !== "request-changes" && action !== "reject" && action !== "publish") {
|
|
16787
|
+
throw new CliError("--action must be approve, request-changes, reject, or publish.", 2);
|
|
16782
16788
|
}
|
|
16783
16789
|
const reason = optionalStringOption(parsed, "reason");
|
|
16790
|
+
const artifactSha256 = optionalStringOption(parsed, "artifact-sha256")?.toLowerCase();
|
|
16791
|
+
if (action === "approve" && !isArtifactSha256(artifactSha256)) {
|
|
16792
|
+
throw new CliError("--artifact-sha256 is required when approving a submission and must be a 64-character SHA-256 hex digest.", 2);
|
|
16793
|
+
}
|
|
16784
16794
|
const response = await apiPost(`/v1/review/submissions/${encodeURIComponent(submissionId)}/actions`, {
|
|
16785
16795
|
action,
|
|
16786
|
-
...reason ? { reason } : {}
|
|
16796
|
+
...reason ? { reason } : {},
|
|
16797
|
+
...action === "approve" ? { artifactSha256 } : {}
|
|
16787
16798
|
}, parsed, runtime, token);
|
|
16788
16799
|
if (parsed.options.json) {
|
|
16789
16800
|
runtime.io.stdout(JSON.stringify(response, null, 2));
|
|
@@ -16793,7 +16804,172 @@ async function reviewCommand(parsed, runtime) {
|
|
|
16793
16804
|
}
|
|
16794
16805
|
return 0;
|
|
16795
16806
|
}
|
|
16796
|
-
|
|
16807
|
+
if (subcommand === "bundle") {
|
|
16808
|
+
const submissionId = parsed.args[1];
|
|
16809
|
+
if (!submissionId) {
|
|
16810
|
+
throw new CliError("Usage: myskills review bundle <submission-id> [--platform <name>] [--output <file>] [--api-url <url>] [--token <token>]", 2);
|
|
16811
|
+
}
|
|
16812
|
+
const platform = optionalStringOption(parsed, "platform");
|
|
16813
|
+
const query = platform ? `?platform=${encodeURIComponent(platform)}` : "";
|
|
16814
|
+
const response = await apiGetWithHeaders(`/v1/review/submissions/${encodeURIComponent(submissionId)}/bundle${query}`, parsed, runtime, token);
|
|
16815
|
+
const artifactSha256 = response.headers["x-myskills-artifact-sha256"] ?? "";
|
|
16816
|
+
if (!isArtifactSha256(artifactSha256)) {
|
|
16817
|
+
throw new CliError("Review bundle response is missing artifact hash.", 1);
|
|
16818
|
+
}
|
|
16819
|
+
const outputPath = optionalStringOption(parsed, "output");
|
|
16820
|
+
if (outputPath) {
|
|
16821
|
+
await mkdir(path2.dirname(path2.resolve(outputPath)), { recursive: true });
|
|
16822
|
+
await writeFile(path2.resolve(outputPath), response.text, { encoding: "utf8", mode: 384 });
|
|
16823
|
+
}
|
|
16824
|
+
if (parsed.options.json) {
|
|
16825
|
+
runtime.io.stdout(JSON.stringify({
|
|
16826
|
+
artifactSha256,
|
|
16827
|
+
...outputPath ? { output: path2.resolve(outputPath) } : {},
|
|
16828
|
+
payload: parseJsonResponse(`/v1/review/submissions/${submissionId}/bundle`, apiBaseUrl(parsed, runtime), response.text)
|
|
16829
|
+
}, null, 2));
|
|
16830
|
+
} else {
|
|
16831
|
+
runtime.io.stdout(`artifactSha256=${artifactSha256}${outputPath ? ` output=${path2.resolve(outputPath)}` : ""}`);
|
|
16832
|
+
}
|
|
16833
|
+
return 0;
|
|
16834
|
+
}
|
|
16835
|
+
throw new CliError("Usage: myskills review submissions | review bundle <submission-id> | review action <submission-id> --action <approve|request-changes|reject|publish> [--artifact-sha256 <hash>] [--reason <text>]", 2);
|
|
16836
|
+
}
|
|
16837
|
+
async function submissionsCommand(parsed, runtime) {
|
|
16838
|
+
const token = await requireToken(parsed, runtime);
|
|
16839
|
+
const subcommand = parsed.args[0];
|
|
16840
|
+
if (subcommand === "list" || subcommand === "mine") {
|
|
16841
|
+
const response = await apiGet("/v1/submissions/mine", parsed, runtime, token);
|
|
16842
|
+
if (parsed.options.json) {
|
|
16843
|
+
runtime.io.stdout(JSON.stringify(response, null, 2));
|
|
16844
|
+
} else {
|
|
16845
|
+
const submissions = arrayField(response, "submissions");
|
|
16846
|
+
if (submissions.length === 0) {
|
|
16847
|
+
runtime.io.stdout("No submissions.");
|
|
16848
|
+
} else {
|
|
16849
|
+
for (const value of submissions) {
|
|
16850
|
+
const submission = recordField(value, "submission");
|
|
16851
|
+
runtime.io.stdout([
|
|
16852
|
+
requiredRecordString(submission, "id", "Submission response is missing id."),
|
|
16853
|
+
`${requiredRecordString(submission, "slug", "Submission response is missing slug.")}@${requiredRecordString(submission, "version", "Submission response is missing version.")}`,
|
|
16854
|
+
optionalRecordString(submission, "reviewStatus") ?? "-",
|
|
16855
|
+
optionalRecordString(submission, "lifecycleStatus") ?? "-",
|
|
16856
|
+
optionalRecordString(submission, "securityStatus") ?? "-"
|
|
16857
|
+
].join(" "));
|
|
16858
|
+
}
|
|
16859
|
+
}
|
|
16860
|
+
}
|
|
16861
|
+
return 0;
|
|
16862
|
+
}
|
|
16863
|
+
if (subcommand === "withdraw") {
|
|
16864
|
+
const submissionId = parsed.args[1];
|
|
16865
|
+
if (!submissionId) {
|
|
16866
|
+
throw new CliError("Usage: myskills submissions withdraw <submission-id> [--reason <text>] [--api-url <url>] [--token <token>]", 2);
|
|
16867
|
+
}
|
|
16868
|
+
const response = await apiPost(`/v1/submissions/${encodeURIComponent(submissionId)}/actions`, {
|
|
16869
|
+
action: "withdraw",
|
|
16870
|
+
...reasonPayload(parsed)
|
|
16871
|
+
}, parsed, runtime, token);
|
|
16872
|
+
printNamedRecord(response, "submission", runtime.io, ["id", "slug", "version", "reviewStatus", "lifecycleStatus"]);
|
|
16873
|
+
return 0;
|
|
16874
|
+
}
|
|
16875
|
+
throw new CliError("Usage: myskills submissions list | submissions withdraw <submission-id> [--reason <text>] [--api-url <url>] [--token <token>]", 2);
|
|
16876
|
+
}
|
|
16877
|
+
async function skillsCommand(parsed, runtime) {
|
|
16878
|
+
const token = await requireToken(parsed, runtime);
|
|
16879
|
+
const subcommand = parsed.args[0];
|
|
16880
|
+
const slug = parsed.args[1];
|
|
16881
|
+
if (subcommand === "edit") {
|
|
16882
|
+
if (!slug) {
|
|
16883
|
+
throw new CliError("Usage: myskills skills edit <skill-slug> [--title <text>] [--summary <text>] [--visibility <scope>] [--tag <tag>] [--reason <text>] [--api-url <url>] [--token <token>]", 2);
|
|
16884
|
+
}
|
|
16885
|
+
const payload = {
|
|
16886
|
+
...reasonPayload(parsed)
|
|
16887
|
+
};
|
|
16888
|
+
const title = optionalStringOption(parsed, "title");
|
|
16889
|
+
const summary = optionalStringOption(parsed, "summary");
|
|
16890
|
+
const visibility = optionalStringOption(parsed, "visibility");
|
|
16891
|
+
const tags = stringListOption(parsed, "tag");
|
|
16892
|
+
if (title !== void 0) {
|
|
16893
|
+
payload.title = title;
|
|
16894
|
+
}
|
|
16895
|
+
if (summary !== void 0) {
|
|
16896
|
+
payload.summary = summary;
|
|
16897
|
+
}
|
|
16898
|
+
if (visibility !== void 0) {
|
|
16899
|
+
if (!CLI_VISIBILITY_SCOPES.includes(visibility)) {
|
|
16900
|
+
throw new CliError(`--visibility must be one of: ${CLI_VISIBILITY_SCOPES.join(", ")}.`, 2);
|
|
16901
|
+
}
|
|
16902
|
+
payload.visibility = visibility;
|
|
16903
|
+
}
|
|
16904
|
+
if (tags.length > 0) {
|
|
16905
|
+
payload.tags = tags;
|
|
16906
|
+
}
|
|
16907
|
+
if (Object.keys(payload).every((key) => key === "reason")) {
|
|
16908
|
+
throw new CliError("At least one metadata option is required.", 2);
|
|
16909
|
+
}
|
|
16910
|
+
const response = await apiPut(`/v1/skills/${encodeURIComponent(parseInstallSlug(slug))}`, payload, parsed, runtime, token);
|
|
16911
|
+
printNamedRecord(response, "skill", runtime.io, ["slug", "title", "lifecycleStatus", "visibility"]);
|
|
16912
|
+
return 0;
|
|
16913
|
+
}
|
|
16914
|
+
if (subcommand === "archive" || subcommand === "restore" || subcommand === "delete") {
|
|
16915
|
+
if (!slug) {
|
|
16916
|
+
throw new CliError("Usage: myskills skills archive|restore|delete <skill-slug> [--reason <text>] [--api-url <url>] [--token <token>]", 2);
|
|
16917
|
+
}
|
|
16918
|
+
const response = await apiPost(`/v1/skills/${encodeURIComponent(parseInstallSlug(slug))}/actions`, {
|
|
16919
|
+
action: subcommand,
|
|
16920
|
+
...reasonPayload(parsed)
|
|
16921
|
+
}, parsed, runtime, token);
|
|
16922
|
+
printNamedRecord(response, "skill", runtime.io, ["slug", "title", "lifecycleStatus", "visibility"]);
|
|
16923
|
+
return 0;
|
|
16924
|
+
}
|
|
16925
|
+
throw new CliError("Usage: myskills skills edit|archive|restore|delete <skill-slug> [--api-url <url>] [--token <token>]", 2);
|
|
16926
|
+
}
|
|
16927
|
+
async function releasesCommand(parsed, runtime) {
|
|
16928
|
+
const subcommand = parsed.args[0];
|
|
16929
|
+
if (subcommand === "list") {
|
|
16930
|
+
const slug = parsed.args[1];
|
|
16931
|
+
if (!slug) {
|
|
16932
|
+
throw new CliError("Usage: myskills releases list <skill-slug>", 2);
|
|
16933
|
+
}
|
|
16934
|
+
const token = await tokenOption(parsed, runtime) ?? void 0;
|
|
16935
|
+
const response = await apiGet(`/v1/skills/${encodeURIComponent(parseInstallSlug(slug))}/releases`, parsed, runtime, token);
|
|
16936
|
+
if (parsed.options.json) {
|
|
16937
|
+
runtime.io.stdout(JSON.stringify(response, null, 2));
|
|
16938
|
+
} else {
|
|
16939
|
+
const releases = arrayField(response, "releases");
|
|
16940
|
+
if (releases.length === 0) {
|
|
16941
|
+
runtime.io.stdout("No releases.");
|
|
16942
|
+
} else {
|
|
16943
|
+
for (const value of releases) {
|
|
16944
|
+
const release = recordField(value, "release");
|
|
16945
|
+
runtime.io.stdout([
|
|
16946
|
+
`${requiredRecordString(release, "slug", "Release response is missing slug.")}@${requiredRecordString(release, "version", "Release response is missing version.")}`,
|
|
16947
|
+
optionalRecordString(release, "lifecycleStatus") ?? "-",
|
|
16948
|
+
optionalRecordString(release, "reviewStatus") ?? "-",
|
|
16949
|
+
optionalRecordString(release, "securityStatus") ?? "-",
|
|
16950
|
+
`published=${optionalRecordString(release, "publishedAt") ?? "-"}`
|
|
16951
|
+
].join(" "));
|
|
16952
|
+
}
|
|
16953
|
+
}
|
|
16954
|
+
}
|
|
16955
|
+
return 0;
|
|
16956
|
+
}
|
|
16957
|
+
if (["deprecate", "unpublish", "revoke", "restore", "delete"].includes(subcommand ?? "")) {
|
|
16958
|
+
const target = parsed.args[1];
|
|
16959
|
+
if (!target) {
|
|
16960
|
+
throw new CliError("Usage: myskills releases deprecate|unpublish|revoke|restore|delete <skill-slug>@<version> [--reason <text>] [--replacement <version>] [--api-url <url>] [--token <token>]", 2);
|
|
16961
|
+
}
|
|
16962
|
+
const { slug, version: version2 } = parseReleaseTarget(target);
|
|
16963
|
+
const token = await requireToken(parsed, runtime);
|
|
16964
|
+
const response = await apiPost(`/v1/skills/${encodeURIComponent(slug)}/releases/${encodeURIComponent(version2)}/actions`, {
|
|
16965
|
+
action: subcommand,
|
|
16966
|
+
...reasonPayload(parsed),
|
|
16967
|
+
...optionalStringOption(parsed, "replacement") ? { replacement: optionalStringOption(parsed, "replacement") } : {}
|
|
16968
|
+
}, parsed, runtime, token);
|
|
16969
|
+
printNamedRecord(response, "release", runtime.io, ["slug", "version", "lifecycleStatus", "reviewStatus", "securityStatus"]);
|
|
16970
|
+
return 0;
|
|
16971
|
+
}
|
|
16972
|
+
throw new CliError("Usage: myskills releases list <skill-slug> | releases deprecate|unpublish|revoke|restore|delete <skill-slug>@<version> [--api-url <url>] [--token <token>]", 2);
|
|
16797
16973
|
}
|
|
16798
16974
|
async function teamsCommand(parsed, runtime) {
|
|
16799
16975
|
const token = await requireToken(parsed, runtime);
|
|
@@ -17508,6 +17684,26 @@ function recordField(input, label) {
|
|
|
17508
17684
|
}
|
|
17509
17685
|
return input;
|
|
17510
17686
|
}
|
|
17687
|
+
function printNamedRecord(response, key, io, fields) {
|
|
17688
|
+
const record2 = recordField(response[key], key);
|
|
17689
|
+
io.stdout(fields.map((field) => optionalRecordString(record2, field) ?? "-").join(" "));
|
|
17690
|
+
}
|
|
17691
|
+
function reasonPayload(parsed) {
|
|
17692
|
+
const reason = optionalStringOption(parsed, "reason");
|
|
17693
|
+
return reason ? { reason } : {};
|
|
17694
|
+
}
|
|
17695
|
+
function parseReleaseTarget(target) {
|
|
17696
|
+
const separator = target.lastIndexOf("@");
|
|
17697
|
+
if (separator <= 0 || separator === target.length - 1) {
|
|
17698
|
+
throw new CliError("Release target must be <skill-slug>@<version>.", 2);
|
|
17699
|
+
}
|
|
17700
|
+
const slug = parseInstallSlug(target.slice(0, separator));
|
|
17701
|
+
const version2 = target.slice(separator + 1);
|
|
17702
|
+
if (!/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(version2)) {
|
|
17703
|
+
throw new CliError("Release version is invalid.", 2);
|
|
17704
|
+
}
|
|
17705
|
+
return { slug, version: version2 };
|
|
17706
|
+
}
|
|
17511
17707
|
function arrayField(record2, key) {
|
|
17512
17708
|
const value = record2[key];
|
|
17513
17709
|
return Array.isArray(value) ? value : [];
|
|
@@ -17570,6 +17766,21 @@ async function apiGet(pathname, parsed, runtime, token) {
|
|
|
17570
17766
|
}
|
|
17571
17767
|
return await apiJsonRequest(pathname, parsed, runtime, { headers });
|
|
17572
17768
|
}
|
|
17769
|
+
async function apiGetWithHeaders(pathname, parsed, runtime, token) {
|
|
17770
|
+
const headers = {};
|
|
17771
|
+
if (token) {
|
|
17772
|
+
headers.authorization = `Bearer ${token}`;
|
|
17773
|
+
}
|
|
17774
|
+
const response = await apiFetch(pathname, parsed, runtime, { headers });
|
|
17775
|
+
if (!response.ok) {
|
|
17776
|
+
const body = parseJsonResponse(pathname, apiBaseUrl(parsed, runtime), response.text);
|
|
17777
|
+
throw apiErrorFromBody(pathname, apiBaseUrl(parsed, runtime), response.status, body, response.text);
|
|
17778
|
+
}
|
|
17779
|
+
return {
|
|
17780
|
+
headers: response.headers,
|
|
17781
|
+
text: response.text
|
|
17782
|
+
};
|
|
17783
|
+
}
|
|
17573
17784
|
async function apiGetText(pathname, parsed, runtime, token) {
|
|
17574
17785
|
const headers = {};
|
|
17575
17786
|
if (token) {
|
|
@@ -17639,11 +17850,21 @@ async function apiFetch(pathname, parsed, runtime, init) {
|
|
|
17639
17850
|
].join("\n"), 1, "API_UNREACHABLE");
|
|
17640
17851
|
}
|
|
17641
17852
|
return {
|
|
17853
|
+
headers: responseHeaders(response.headers),
|
|
17642
17854
|
ok: response.ok,
|
|
17643
17855
|
status: response.status,
|
|
17644
17856
|
text: await response.text()
|
|
17645
17857
|
};
|
|
17646
17858
|
}
|
|
17859
|
+
function responseHeaders(input) {
|
|
17860
|
+
if (!input) {
|
|
17861
|
+
return {};
|
|
17862
|
+
}
|
|
17863
|
+
if (input instanceof Headers) {
|
|
17864
|
+
return Object.fromEntries([...input.entries()].map(([key, value]) => [key.toLowerCase(), value]));
|
|
17865
|
+
}
|
|
17866
|
+
return Object.fromEntries(Object.entries(input).map(([key, value]) => [key.toLowerCase(), value]));
|
|
17867
|
+
}
|
|
17647
17868
|
function parseJsonResponse(pathname, baseUrl, text) {
|
|
17648
17869
|
if (!text) {
|
|
17649
17870
|
return {};
|
|
@@ -18028,6 +18249,9 @@ function optionalStringOption(parsed, key) {
|
|
|
18028
18249
|
const value = parsed.options[key];
|
|
18029
18250
|
return typeof value === "string" && value ? value : void 0;
|
|
18030
18251
|
}
|
|
18252
|
+
function isArtifactSha256(value) {
|
|
18253
|
+
return typeof value === "string" && /^[a-f0-9]{64}$/.test(value);
|
|
18254
|
+
}
|
|
18031
18255
|
function stringListOption(parsed, key) {
|
|
18032
18256
|
const value = parsed.options[key];
|
|
18033
18257
|
if (typeof value === "string") {
|
|
@@ -18147,7 +18371,14 @@ function helpText() {
|
|
|
18147
18371
|
" config list",
|
|
18148
18372
|
" submit --path <file-directory-or-zip> [--api-url <url>] [--token <token>]",
|
|
18149
18373
|
" review submissions [--api-url <url>] [--token <token>]",
|
|
18150
|
-
" review
|
|
18374
|
+
" review bundle <submission-id> [--platform <name>] [--output <file>] [--api-url <url>] [--token <token>]",
|
|
18375
|
+
" review action <submission-id> --action <approve|request-changes|reject|publish> [--artifact-sha256 <hash>] [--reason <text>] [--api-url <url>] [--token <token>]",
|
|
18376
|
+
" submissions list [--api-url <url>] [--token <token>]",
|
|
18377
|
+
" submissions withdraw <submission-id> [--reason <text>] [--api-url <url>] [--token <token>]",
|
|
18378
|
+
" skills edit <skill-slug> [--title <text>] [--summary <text>] [--visibility <scope>] [--tag <tag>] [--reason <text>] [--api-url <url>] [--token <token>]",
|
|
18379
|
+
" skills archive|restore|delete <skill-slug> [--reason <text>] [--api-url <url>] [--token <token>]",
|
|
18380
|
+
" releases list <skill-slug> [--api-url <url>] [--token <token>]",
|
|
18381
|
+
" releases deprecate|unpublish|revoke|restore|delete <skill-slug>@<version> [--reason <text>] [--replacement <version>] [--api-url <url>] [--token <token>]",
|
|
18151
18382
|
" teams list|skills [--api-url <url>] [--token <token>]",
|
|
18152
18383
|
" teams create <team-name> [--name <team-name>] [--api-url <url>] [--token <token>]",
|
|
18153
18384
|
" teams invite <team-id> --email <email> [--api-url <url>] [--token <token>]",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jarel/myskills",
|
|
3
|
-
"version": "0.1.0-
|
|
3
|
+
"version": "0.1.0-beta.2",
|
|
4
4
|
"description": "Command-line client for publishing, discovering, installing, updating, and rolling back MySkills packages.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"private": false,
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"README.md"
|
|
14
14
|
],
|
|
15
15
|
"engines": {
|
|
16
|
-
"node": ">=
|
|
16
|
+
"node": ">=22.13 <23 || >=24 <25"
|
|
17
17
|
},
|
|
18
18
|
"repository": {
|
|
19
19
|
"type": "git",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
],
|
|
34
34
|
"publishConfig": {
|
|
35
35
|
"access": "public",
|
|
36
|
-
"tag": "
|
|
36
|
+
"tag": "beta",
|
|
37
37
|
"provenance": true
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"test": "node ../../scripts/run-node-tests.mjs --import tsx --extensions .test.ts"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@myskills-app/skill-package": "0.1.0-
|
|
44
|
+
"@myskills-app/skill-package": "0.1.0-beta.2",
|
|
45
45
|
"esbuild": "^0.28.1",
|
|
46
46
|
"tsx": "^4.20.6"
|
|
47
47
|
},
|