@stigmer/plugin-package 3.15.3-dev.20260916211208 → 3.16.1-dev.20260917224426
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/client/archive.d.ts +27 -0
- package/client/archive.d.ts.map +1 -0
- package/client/archive.js +38 -0
- package/client/archive.js.map +1 -0
- package/client/ignore/defaults.d.ts +2 -0
- package/client/ignore/defaults.d.ts.map +1 -0
- package/client/ignore/defaults.js +140 -0
- package/client/ignore/defaults.js.map +1 -0
- package/client/ignore/match.d.ts +3 -0
- package/client/ignore/match.d.ts.map +1 -0
- package/client/ignore/match.js +166 -0
- package/client/ignore/match.js.map +1 -0
- package/client/ignore/matcher.d.ts +50 -0
- package/client/ignore/matcher.d.ts.map +1 -0
- package/client/ignore/matcher.js +116 -0
- package/client/ignore/matcher.js.map +1 -0
- package/client/ignore/pattern.d.ts +13 -0
- package/client/ignore/pattern.d.ts.map +1 -0
- package/client/ignore/pattern.js +118 -0
- package/client/ignore/pattern.js.map +1 -0
- package/client/refs.d.ts +76 -0
- package/client/refs.d.ts.map +1 -0
- package/client/refs.js +123 -0
- package/client/refs.js.map +1 -0
- package/client/select.d.ts +74 -0
- package/client/select.d.ts.map +1 -0
- package/client/select.js +121 -0
- package/client/select.js.map +1 -0
- package/client/vocabulary.d.ts +13 -0
- package/client/vocabulary.d.ts.map +1 -0
- package/client/vocabulary.js +17 -0
- package/client/vocabulary.js.map +1 -0
- package/client.d.ts +34 -0
- package/client.d.ts.map +1 -0
- package/client.js +34 -0
- package/client.js.map +1 -0
- package/files.d.ts +6 -0
- package/files.d.ts.map +1 -1
- package/files.js +6 -0
- package/files.js.map +1 -1
- package/index.d.ts +11 -6
- package/index.d.ts.map +1 -1
- package/index.js +9 -5
- package/index.js.map +1 -1
- package/marketplace/messages.d.ts +20 -0
- package/marketplace/messages.d.ts.map +1 -0
- package/marketplace/messages.js +50 -0
- package/marketplace/messages.js.map +1 -0
- package/marketplace/outcome.d.ts +72 -0
- package/marketplace/outcome.d.ts.map +1 -0
- package/marketplace/outcome.js +29 -0
- package/marketplace/outcome.js.map +1 -0
- package/marketplace/read-marketplace.d.ts +34 -0
- package/marketplace/read-marketplace.d.ts.map +1 -0
- package/marketplace/read-marketplace.js +359 -0
- package/marketplace/read-marketplace.js.map +1 -0
- package/messages.d.ts +25 -9
- package/messages.d.ts.map +1 -1
- package/messages.js +24 -8
- package/messages.js.map +1 -1
- package/outcome.d.ts +13 -6
- package/outcome.d.ts.map +1 -1
- package/package.json +8 -2
- package/src/__test-utils__/read.ts +4 -4
- package/src/__tests__/client-ignore.test.ts +133 -0
- package/src/__tests__/client-refs.test.ts +101 -0
- package/src/__tests__/client-select-archive.test.ts +152 -0
- package/src/__tests__/fixtures/cursor-plugins/.cursor-plugin/marketplace.json +412 -0
- package/src/__tests__/fixtures/cursor-plugins/NOTICE +5 -0
- package/src/__tests__/marketplace.test.ts +373 -0
- package/src/client/archive.ts +44 -0
- package/src/client/ignore/defaults.ts +155 -0
- package/src/client/ignore/match.ts +158 -0
- package/src/client/ignore/matcher.ts +156 -0
- package/src/client/ignore/pattern.ts +131 -0
- package/src/client/refs.ts +170 -0
- package/src/client/select.ts +161 -0
- package/src/client/vocabulary.ts +19 -0
- package/src/client.ts +67 -0
- package/src/files.ts +6 -0
- package/src/index.ts +21 -5
- package/src/marketplace/messages.ts +62 -0
- package/src/marketplace/outcome.ts +95 -0
- package/src/marketplace/read-marketplace.ts +402 -0
- package/src/messages.ts +34 -21
- package/src/outcome.ts +14 -6
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// Faithful port of go-git's plumbing/format/gitignore Pattern (ParsePattern +
|
|
2
|
+
// Match). This is what gives `push` its exact gitignore semantics: domain
|
|
3
|
+
// scoping, directory-only patterns, single-name vs glob matching, and the
|
|
4
|
+
// `**` zero-to-many-directories wildcard.
|
|
5
|
+
import { matchName } from "./match.js";
|
|
6
|
+
export var MatchResult;
|
|
7
|
+
(function (MatchResult) {
|
|
8
|
+
MatchResult[MatchResult["NoMatch"] = 0] = "NoMatch";
|
|
9
|
+
MatchResult[MatchResult["Exclude"] = 1] = "Exclude";
|
|
10
|
+
MatchResult[MatchResult["Include"] = 2] = "Include";
|
|
11
|
+
})(MatchResult || (MatchResult = {}));
|
|
12
|
+
const INCLUSION_PREFIX = "!";
|
|
13
|
+
const ZERO_TO_MANY = "**";
|
|
14
|
+
const DIR_SEP = "/";
|
|
15
|
+
class GitignorePattern {
|
|
16
|
+
inclusion;
|
|
17
|
+
domain;
|
|
18
|
+
parts;
|
|
19
|
+
dirOnly;
|
|
20
|
+
isGlob;
|
|
21
|
+
constructor(domain, parts, inclusion, dirOnly, isGlob) {
|
|
22
|
+
this.domain = domain;
|
|
23
|
+
this.parts = parts;
|
|
24
|
+
this.inclusion = inclusion;
|
|
25
|
+
this.dirOnly = dirOnly;
|
|
26
|
+
this.isGlob = isGlob;
|
|
27
|
+
}
|
|
28
|
+
match(path, isDir) {
|
|
29
|
+
const matchResult = this.inclusion ? MatchResult.Include : MatchResult.Exclude;
|
|
30
|
+
if (path.length <= this.domain.length)
|
|
31
|
+
return MatchResult.NoMatch;
|
|
32
|
+
for (let i = 0; i < this.domain.length; i++) {
|
|
33
|
+
if (path[i] !== this.domain[i])
|
|
34
|
+
return MatchResult.NoMatch;
|
|
35
|
+
}
|
|
36
|
+
const scoped = path.slice(this.domain.length);
|
|
37
|
+
const matched = this.isGlob ? this.globMatch(scoped, isDir) : this.simpleNameMatch(scoped, isDir);
|
|
38
|
+
return matched ? matchResult : MatchResult.NoMatch;
|
|
39
|
+
}
|
|
40
|
+
simpleNameMatch(path, isDir) {
|
|
41
|
+
for (let i = 0; i < path.length; i++) {
|
|
42
|
+
if (!matchName(this.parts[0] ?? "", path[i] ?? ""))
|
|
43
|
+
continue;
|
|
44
|
+
if (this.dirOnly && !isDir && i === path.length - 1)
|
|
45
|
+
return false;
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
globMatch(path, isDir) {
|
|
51
|
+
let matched = false;
|
|
52
|
+
let canTraverse = false;
|
|
53
|
+
let remaining = path;
|
|
54
|
+
for (let i = 0; i < this.parts.length; i++) {
|
|
55
|
+
const part = this.parts[i] ?? "";
|
|
56
|
+
if (part === "") {
|
|
57
|
+
canTraverse = false;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (part === ZERO_TO_MANY) {
|
|
61
|
+
if (i === this.parts.length - 1)
|
|
62
|
+
break;
|
|
63
|
+
canTraverse = true;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (part.includes(ZERO_TO_MANY))
|
|
67
|
+
return false;
|
|
68
|
+
if (remaining.length === 0)
|
|
69
|
+
return false;
|
|
70
|
+
if (canTraverse) {
|
|
71
|
+
canTraverse = false;
|
|
72
|
+
for (;;) {
|
|
73
|
+
if (remaining.length === 0) {
|
|
74
|
+
matched = false;
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
const e = remaining[0] ?? "";
|
|
78
|
+
remaining = remaining.slice(1);
|
|
79
|
+
if (matchName(part, e)) {
|
|
80
|
+
matched = true;
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
if (!matchName(part, remaining[0] ?? ""))
|
|
87
|
+
return false;
|
|
88
|
+
matched = true;
|
|
89
|
+
remaining = remaining.slice(1);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (matched && this.dirOnly && !isDir && remaining.length === 0) {
|
|
93
|
+
matched = false;
|
|
94
|
+
}
|
|
95
|
+
return matched;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/** Parse a gitignore pattern string into a matchable Pattern (go-git parity). */
|
|
99
|
+
export function parsePattern(raw, domain) {
|
|
100
|
+
let p = raw;
|
|
101
|
+
let inclusion = false;
|
|
102
|
+
if (p.startsWith(INCLUSION_PREFIX)) {
|
|
103
|
+
inclusion = true;
|
|
104
|
+
p = p.slice(1);
|
|
105
|
+
}
|
|
106
|
+
if (!p.endsWith("\\ ")) {
|
|
107
|
+
p = p.replace(/ +$/, "");
|
|
108
|
+
}
|
|
109
|
+
let dirOnly = false;
|
|
110
|
+
if (p.endsWith(DIR_SEP)) {
|
|
111
|
+
dirOnly = true;
|
|
112
|
+
p = p.slice(0, -1);
|
|
113
|
+
}
|
|
114
|
+
const isGlob = p.includes(DIR_SEP);
|
|
115
|
+
const parts = p.split(DIR_SEP);
|
|
116
|
+
return new GitignorePattern(domain, parts, inclusion, dirOnly, isGlob);
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=pattern.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pattern.js","sourceRoot":"","sources":["../../../src/client/ignore/pattern.ts"],"names":[],"mappings":"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"}
|
package/client/refs.d.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The two grammars a user types at any marketplace surface, and the words
|
|
3
|
+
* every client uses for what they name.
|
|
4
|
+
*
|
|
5
|
+
* `install [marketplace/]name[@version]`: the plugin's name in its
|
|
6
|
+
* marketplace, optionally qualified by the marketplace's name and pinned to
|
|
7
|
+
* the version the entry's manifest must carry. Both names obey the plugin
|
|
8
|
+
* name rule (`isValidPluginName`: lowercase letters, digits, `.` and `-`,
|
|
9
|
+
* never `/` or `@`), which is what makes the grammar unambiguous: the first
|
|
10
|
+
* `/` splits the marketplace off, the first `@` splits the version off, and
|
|
11
|
+
* anything else is not a ref. A path (`./thermos`, `/tmp/x`, `..`) is the
|
|
12
|
+
* one likely mistake and gets its own sentence, so a client can point at
|
|
13
|
+
* the command that installs a folder.
|
|
14
|
+
*
|
|
15
|
+
* A GitHub marketplace source: `owner/repo[@ref]`, or the URL a browser
|
|
16
|
+
* shows for that repository (`https://github.com/owner/repo[/tree/<ref>]`),
|
|
17
|
+
* normalised to one record. Every vendor keeps its marketplace file at the
|
|
18
|
+
* repository root, so a subdirectory grammar is not offered.
|
|
19
|
+
*
|
|
20
|
+
* Refusals are returned, not thrown: the CLI wraps one in its `UsageError`
|
|
21
|
+
* and the console renders it, and the sentence is the same in both. A
|
|
22
|
+
* client adds the second paragraph naming its own command.
|
|
23
|
+
*/
|
|
24
|
+
/** The built-in marketplace's name: the prefix in `install stigmer/<plugin>`; reserved in every client. */
|
|
25
|
+
export declare const OFFICIAL_MARKETPLACE_NAME = "stigmer";
|
|
26
|
+
export interface InstallRef {
|
|
27
|
+
/** The marketplace named before the `/`, or `undefined` when the name stands alone. */
|
|
28
|
+
readonly marketplace?: string;
|
|
29
|
+
readonly name: string;
|
|
30
|
+
/** The version named after the `@`, asserted against the entry's manifest. */
|
|
31
|
+
readonly version?: string;
|
|
32
|
+
}
|
|
33
|
+
export type InstallRefOutcome = {
|
|
34
|
+
readonly ok: true;
|
|
35
|
+
readonly ref: InstallRef;
|
|
36
|
+
} | {
|
|
37
|
+
readonly ok: false;
|
|
38
|
+
/** `path` when the text names a folder rather than a plugin; `shape` for every other refusal. */
|
|
39
|
+
readonly kind: "path" | "shape";
|
|
40
|
+
readonly message: string;
|
|
41
|
+
};
|
|
42
|
+
/** The grammar in the user's terms, quoted by every refusal. */
|
|
43
|
+
export declare const INSTALL_REF_SHAPE = "[marketplace/]name[@version], for example 'thermos', 'cursor-plugins/thermos' or 'thermos@1.0.0'";
|
|
44
|
+
export declare function parseInstallRef(text: string): InstallRefOutcome;
|
|
45
|
+
/** The grammar's own text for a ref, the inverse of `parseInstallRef`. */
|
|
46
|
+
export declare function formatInstallRef(ref: InstallRef): string;
|
|
47
|
+
/** Whether `text` reads as a filesystem path on any platform (relative, home, absolute, Windows). */
|
|
48
|
+
export declare function looksLikePath(text: string): boolean;
|
|
49
|
+
/** A public GitHub repository at a ref; the default branch when `ref` is absent. */
|
|
50
|
+
export interface GitHubMarketplaceSource {
|
|
51
|
+
readonly type: "github";
|
|
52
|
+
/** `owner/repo`. */
|
|
53
|
+
readonly repo: string;
|
|
54
|
+
/** Branch, tag or commit. */
|
|
55
|
+
readonly ref?: string;
|
|
56
|
+
}
|
|
57
|
+
export type GitHubSourceOutcome = {
|
|
58
|
+
readonly ok: true;
|
|
59
|
+
readonly source: GitHubMarketplaceSource;
|
|
60
|
+
} | {
|
|
61
|
+
readonly ok: false;
|
|
62
|
+
readonly message: string;
|
|
63
|
+
};
|
|
64
|
+
/** What a GitHub source may be typed as, quoted by every refusal. */
|
|
65
|
+
export declare const GITHUB_SOURCE_SHAPE = "a GitHub repository as 'owner/repo' or 'owner/repo@ref', or that repository's URL (https://github.com/owner/repo)";
|
|
66
|
+
/**
|
|
67
|
+
* `owner/repo[@ref]` or a github.com URL as one source. The URL form is
|
|
68
|
+
* tried first because it contains a `/` too; a text that is neither is
|
|
69
|
+
* refused with the shape.
|
|
70
|
+
*/
|
|
71
|
+
export declare function parseGitHubSource(text: string): GitHubSourceOutcome;
|
|
72
|
+
/** One phrase naming a GitHub source, for lists and sentences. */
|
|
73
|
+
export declare function describeGitHubSource(source: GitHubMarketplaceSource): string;
|
|
74
|
+
/** `owner/repo` as GitHub spells it: two segments, no `.git` suffix required or refused. */
|
|
75
|
+
export declare function isOwnerRepo(value: string): boolean;
|
|
76
|
+
//# sourceMappingURL=refs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refs.d.ts","sourceRoot":"","sources":["../../src/client/refs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,2GAA2G;AAC3G,eAAO,MAAM,yBAAyB,YAAY,CAAC;AAEnD,MAAM,WAAW,UAAU;IACzB,uFAAuF;IACvF,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,8EAA8E;IAC9E,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,MAAM,iBAAiB,GACzB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAA;CAAE,GAC/C;IACE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IACnB,iGAAiG;IACjG,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;AAKN,gEAAgE;AAChE,eAAO,MAAM,iBAAiB,qGACsE,CAAC;AAErG,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAsC/D;AAED,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,CAIxD;AAED,qGAAqG;AACrG,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAWnD;AAED,oFAAoF;AACpF,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,oBAAoB;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,6BAA6B;IAC7B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,MAAM,mBAAmB,GAC3B;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAA;CAAE,GAC/D;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAErD,qEAAqE;AACrE,eAAO,MAAM,mBAAmB,sHACqF,CAAC;AAItH;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,mBAAmB,CAkBnE;AAED,kEAAkE;AAClE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,uBAAuB,GAAG,MAAM,CAE5E;AAID,4FAA4F;AAC5F,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAGlD"}
|
package/client/refs.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The two grammars a user types at any marketplace surface, and the words
|
|
3
|
+
* every client uses for what they name.
|
|
4
|
+
*
|
|
5
|
+
* `install [marketplace/]name[@version]`: the plugin's name in its
|
|
6
|
+
* marketplace, optionally qualified by the marketplace's name and pinned to
|
|
7
|
+
* the version the entry's manifest must carry. Both names obey the plugin
|
|
8
|
+
* name rule (`isValidPluginName`: lowercase letters, digits, `.` and `-`,
|
|
9
|
+
* never `/` or `@`), which is what makes the grammar unambiguous: the first
|
|
10
|
+
* `/` splits the marketplace off, the first `@` splits the version off, and
|
|
11
|
+
* anything else is not a ref. A path (`./thermos`, `/tmp/x`, `..`) is the
|
|
12
|
+
* one likely mistake and gets its own sentence, so a client can point at
|
|
13
|
+
* the command that installs a folder.
|
|
14
|
+
*
|
|
15
|
+
* A GitHub marketplace source: `owner/repo[@ref]`, or the URL a browser
|
|
16
|
+
* shows for that repository (`https://github.com/owner/repo[/tree/<ref>]`),
|
|
17
|
+
* normalised to one record. Every vendor keeps its marketplace file at the
|
|
18
|
+
* repository root, so a subdirectory grammar is not offered.
|
|
19
|
+
*
|
|
20
|
+
* Refusals are returned, not thrown: the CLI wraps one in its `UsageError`
|
|
21
|
+
* and the console renders it, and the sentence is the same in both. A
|
|
22
|
+
* client adds the second paragraph naming its own command.
|
|
23
|
+
*/
|
|
24
|
+
import { isValidPluginName } from "../detect.js";
|
|
25
|
+
/** The built-in marketplace's name: the prefix in `install stigmer/<plugin>`; reserved in every client. */
|
|
26
|
+
export const OFFICIAL_MARKETPLACE_NAME = "stigmer";
|
|
27
|
+
/** The characters a `@version` may carry: the plugin's tag pattern, so what a ref pins is a tag the server can hold. */
|
|
28
|
+
const VERSION_PATTERN = /^[a-zA-Z0-9._-]+$/;
|
|
29
|
+
/** The grammar in the user's terms, quoted by every refusal. */
|
|
30
|
+
export const INSTALL_REF_SHAPE = "[marketplace/]name[@version], for example 'thermos', 'cursor-plugins/thermos' or 'thermos@1.0.0'";
|
|
31
|
+
export function parseInstallRef(text) {
|
|
32
|
+
if (looksLikePath(text)) {
|
|
33
|
+
return {
|
|
34
|
+
ok: false,
|
|
35
|
+
kind: "path",
|
|
36
|
+
message: `'${text}' is a path, and 'install' takes a plugin's name in a marketplace`,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
let rest = text;
|
|
40
|
+
let marketplace;
|
|
41
|
+
const slash = rest.indexOf("/");
|
|
42
|
+
if (slash !== -1) {
|
|
43
|
+
marketplace = rest.slice(0, slash);
|
|
44
|
+
rest = rest.slice(slash + 1);
|
|
45
|
+
if (!isValidPluginName(marketplace)) {
|
|
46
|
+
return { ok: false, kind: "shape", message: `'${marketplace}' is not a marketplace name` };
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
let version;
|
|
50
|
+
const at = rest.indexOf("@");
|
|
51
|
+
if (at !== -1) {
|
|
52
|
+
version = rest.slice(at + 1);
|
|
53
|
+
rest = rest.slice(0, at);
|
|
54
|
+
if (version === "" || !VERSION_PATTERN.test(version)) {
|
|
55
|
+
return { ok: false, kind: "shape", message: `'${version}' is not a version` };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (!isValidPluginName(rest)) {
|
|
59
|
+
return { ok: false, kind: "shape", message: `'${rest}' is not a plugin name` };
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
ok: true,
|
|
63
|
+
ref: {
|
|
64
|
+
...(marketplace !== undefined && { marketplace }),
|
|
65
|
+
name: rest,
|
|
66
|
+
...(version !== undefined && { version }),
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/** The grammar's own text for a ref, the inverse of `parseInstallRef`. */
|
|
71
|
+
export function formatInstallRef(ref) {
|
|
72
|
+
const prefix = ref.marketplace === undefined ? "" : `${ref.marketplace}/`;
|
|
73
|
+
const suffix = ref.version === undefined ? "" : `@${ref.version}`;
|
|
74
|
+
return `${prefix}${ref.name}${suffix}`;
|
|
75
|
+
}
|
|
76
|
+
/** Whether `text` reads as a filesystem path on any platform (relative, home, absolute, Windows). */
|
|
77
|
+
export function looksLikePath(text) {
|
|
78
|
+
return (text === "." ||
|
|
79
|
+
text === ".." ||
|
|
80
|
+
text.startsWith("./") ||
|
|
81
|
+
text.startsWith("../") ||
|
|
82
|
+
text.startsWith("~") ||
|
|
83
|
+
text.startsWith("/") ||
|
|
84
|
+
text.includes("\\") ||
|
|
85
|
+
/^[A-Za-z]:/.test(text));
|
|
86
|
+
}
|
|
87
|
+
/** What a GitHub source may be typed as, quoted by every refusal. */
|
|
88
|
+
export const GITHUB_SOURCE_SHAPE = "a GitHub repository as 'owner/repo' or 'owner/repo@ref', or that repository's URL (https://github.com/owner/repo)";
|
|
89
|
+
const GITHUB_URL = /^https?:\/\/(?:www\.)?github\.com\/([^/\s]+)\/([^/\s#?]+?)(?:\.git)?(?:\/tree\/([^\s#?]+))?\/?$/;
|
|
90
|
+
/**
|
|
91
|
+
* `owner/repo[@ref]` or a github.com URL as one source. The URL form is
|
|
92
|
+
* tried first because it contains a `/` too; a text that is neither is
|
|
93
|
+
* refused with the shape.
|
|
94
|
+
*/
|
|
95
|
+
export function parseGitHubSource(text) {
|
|
96
|
+
const url = GITHUB_URL.exec(text);
|
|
97
|
+
if (url !== null) {
|
|
98
|
+
const repo = `${url[1] ?? ""}/${url[2] ?? ""}`;
|
|
99
|
+
if (!isOwnerRepo(repo)) {
|
|
100
|
+
return { ok: false, message: `'${text}' does not name a GitHub repository` };
|
|
101
|
+
}
|
|
102
|
+
const ref = url[3];
|
|
103
|
+
return { ok: true, source: { type: "github", repo, ...(ref !== undefined && ref !== "" && { ref }) } };
|
|
104
|
+
}
|
|
105
|
+
const at = text.indexOf("@");
|
|
106
|
+
const repo = at === -1 ? text : text.slice(0, at);
|
|
107
|
+
const ref = at === -1 ? undefined : text.slice(at + 1);
|
|
108
|
+
if (isOwnerRepo(repo) && (ref === undefined || ref !== "")) {
|
|
109
|
+
return { ok: true, source: { type: "github", repo, ...(ref !== undefined && { ref }) } };
|
|
110
|
+
}
|
|
111
|
+
return { ok: false, message: `'${text}' is not a GitHub 'owner/repo'` };
|
|
112
|
+
}
|
|
113
|
+
/** One phrase naming a GitHub source, for lists and sentences. */
|
|
114
|
+
export function describeGitHubSource(source) {
|
|
115
|
+
return source.ref === undefined ? `github.com/${source.repo}` : `github.com/${source.repo}@${source.ref}`;
|
|
116
|
+
}
|
|
117
|
+
const OWNER_REPO_SEGMENT = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
118
|
+
/** `owner/repo` as GitHub spells it: two segments, no `.git` suffix required or refused. */
|
|
119
|
+
export function isOwnerRepo(value) {
|
|
120
|
+
const parts = value.split("/");
|
|
121
|
+
return parts.length === 2 && parts.every((part) => OWNER_REPO_SEGMENT.test(part) && part !== "." && part !== "..");
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=refs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refs.js","sourceRoot":"","sources":["../../src/client/refs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which files of a tree a plugin push carries, and in what order.
|
|
3
|
+
*
|
|
4
|
+
* A client that installs a plugin holds a tree: the CLI a directory on disk,
|
|
5
|
+
* the console the file list a marketplace host returned. Both must choose
|
|
6
|
+
* the same files in the same order, because the archive's bytes are the
|
|
7
|
+
* plugin's identity on the server (`status.digest` is the SHA-256 of what
|
|
8
|
+
* it received) and the order of the archive's entries is part of those
|
|
9
|
+
* bytes. This module is that choice, made once.
|
|
10
|
+
*
|
|
11
|
+
* The rule is the CLI's original walk (`stigmer push plugin <dir>`): at each
|
|
12
|
+
* directory the names are sorted by code point, files and directories
|
|
13
|
+
* interleaved by name, and a directory the matcher ignores is skipped whole,
|
|
14
|
+
* so no negation inside it can pull a file back. Symlinks never appear (the
|
|
15
|
+
* CLI walker skips them; a hosted tree has none the client asks for).
|
|
16
|
+
* `compareWalkOrder` states that order for a flat list of paths so a client
|
|
17
|
+
* with no directory to walk arrives at the same sequence; it is NOT the plain
|
|
18
|
+
* code-point order of full paths (`b/x.txt` sorts before `b.txt` here,
|
|
19
|
+
* because the directory `b` sorts before the file `b.txt` at their level).
|
|
20
|
+
* The reader in `read-plugin-package.ts` indexes entries by path and is
|
|
21
|
+
* indifferent to their order; only the archive cares.
|
|
22
|
+
*
|
|
23
|
+
* `.gitignore` and `.stigmerignore` are read from the root of the tree being
|
|
24
|
+
* selected, as the CLI does, never from an ancestor: a marketplace entry is
|
|
25
|
+
* its own plugin root.
|
|
26
|
+
*/
|
|
27
|
+
import type { PluginFiles } from "../files.js";
|
|
28
|
+
import { type Matcher } from "./ignore/matcher.js";
|
|
29
|
+
/** The tree a client holds before selection: every file it could offer, with its size. */
|
|
30
|
+
export interface CandidateFile {
|
|
31
|
+
/** Root-relative POSIX path, no leading `./`. */
|
|
32
|
+
readonly path: string;
|
|
33
|
+
readonly size: number;
|
|
34
|
+
}
|
|
35
|
+
/** What the selection included and left out, for the summary line every client prints. */
|
|
36
|
+
export interface SelectionStats {
|
|
37
|
+
filesIncluded: number;
|
|
38
|
+
filesIgnored: number;
|
|
39
|
+
/** Ignored directories that held at least one candidate; a tree lists no empty directories. */
|
|
40
|
+
dirsSkipped: number;
|
|
41
|
+
totalSize: number;
|
|
42
|
+
}
|
|
43
|
+
export interface SelectPluginFilesOptions {
|
|
44
|
+
/** Whether the tree's own root `.gitignore` applies (every push says yes unless asked otherwise). */
|
|
45
|
+
readonly respectGitignore: boolean;
|
|
46
|
+
readonly extraIgnore?: readonly string[];
|
|
47
|
+
readonly extraInclude?: readonly string[];
|
|
48
|
+
}
|
|
49
|
+
export interface PluginSelection {
|
|
50
|
+
readonly files: PluginFiles;
|
|
51
|
+
readonly stats: SelectionStats;
|
|
52
|
+
/** The matcher the selection ran, for diagnostics (`push --dry-run` lists its patterns). */
|
|
53
|
+
readonly matcher: Matcher;
|
|
54
|
+
}
|
|
55
|
+
/** The two files at a tree's root that shape its own selection. */
|
|
56
|
+
export declare const IGNORE_FILE_NAMES: {
|
|
57
|
+
readonly gitignore: ".gitignore";
|
|
58
|
+
readonly stigmerignore: ".stigmerignore";
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Select the files a push of `candidates` carries. `read` yields a listed
|
|
62
|
+
* candidate's bytes and is called here only for the two ignore files at the
|
|
63
|
+
* root, so a client may hand over a lazy reader and pay for the rest only
|
|
64
|
+
* when the archive is built.
|
|
65
|
+
*/
|
|
66
|
+
export declare function selectPluginFiles(candidates: readonly CandidateFile[], read: (path: string) => Uint8Array, options: SelectPluginFilesOptions): PluginSelection;
|
|
67
|
+
/**
|
|
68
|
+
* The order a sorted directory walk visits files: component by component,
|
|
69
|
+
* each compared by code point. Two paths never share a prefix that is a
|
|
70
|
+
* file in one and a directory in the other, so a shorter path is never a
|
|
71
|
+
* prefix of a longer one at the point they differ.
|
|
72
|
+
*/
|
|
73
|
+
export declare function compareWalkOrder(a: string, b: string): number;
|
|
74
|
+
//# sourceMappingURL=select.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../src/client/select.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAmB,WAAW,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAAsB,KAAK,OAAO,EAAwD,MAAM,qBAAqB,CAAC;AAE7H,0FAA0F;AAC1F,MAAM,WAAW,aAAa;IAC5B,iDAAiD;IACjD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,0FAA0F;AAC1F,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,+FAA+F;IAC/F,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,wBAAwB;IACvC,qGAAqG;IACrG,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;IACnC,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3C;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,4FAA4F;IAC5F,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED,mEAAmE;AACnE,eAAO,MAAM,iBAAiB;;;CAGpB,CAAC;AAEX;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,SAAS,aAAa,EAAE,EACpC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,UAAU,EAClC,OAAO,EAAE,wBAAwB,GAChC,eAAe,CAwCjB;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAU7D"}
|
package/client/select.js
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which files of a tree a plugin push carries, and in what order.
|
|
3
|
+
*
|
|
4
|
+
* A client that installs a plugin holds a tree: the CLI a directory on disk,
|
|
5
|
+
* the console the file list a marketplace host returned. Both must choose
|
|
6
|
+
* the same files in the same order, because the archive's bytes are the
|
|
7
|
+
* plugin's identity on the server (`status.digest` is the SHA-256 of what
|
|
8
|
+
* it received) and the order of the archive's entries is part of those
|
|
9
|
+
* bytes. This module is that choice, made once.
|
|
10
|
+
*
|
|
11
|
+
* The rule is the CLI's original walk (`stigmer push plugin <dir>`): at each
|
|
12
|
+
* directory the names are sorted by code point, files and directories
|
|
13
|
+
* interleaved by name, and a directory the matcher ignores is skipped whole,
|
|
14
|
+
* so no negation inside it can pull a file back. Symlinks never appear (the
|
|
15
|
+
* CLI walker skips them; a hosted tree has none the client asks for).
|
|
16
|
+
* `compareWalkOrder` states that order for a flat list of paths so a client
|
|
17
|
+
* with no directory to walk arrives at the same sequence; it is NOT the plain
|
|
18
|
+
* code-point order of full paths (`b/x.txt` sorts before `b.txt` here,
|
|
19
|
+
* because the directory `b` sorts before the file `b.txt` at their level).
|
|
20
|
+
* The reader in `read-plugin-package.ts` indexes entries by path and is
|
|
21
|
+
* indifferent to their order; only the archive cares.
|
|
22
|
+
*
|
|
23
|
+
* `.gitignore` and `.stigmerignore` are read from the root of the tree being
|
|
24
|
+
* selected, as the CLI does, never from an ancestor: a marketplace entry is
|
|
25
|
+
* its own plugin root.
|
|
26
|
+
*/
|
|
27
|
+
import { SOURCE_GITIGNORE, SOURCE_STIGMERIGNORE, buildMatcher } from "./ignore/matcher.js";
|
|
28
|
+
/** The two files at a tree's root that shape its own selection. */
|
|
29
|
+
export const IGNORE_FILE_NAMES = {
|
|
30
|
+
gitignore: SOURCE_GITIGNORE,
|
|
31
|
+
stigmerignore: SOURCE_STIGMERIGNORE,
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Select the files a push of `candidates` carries. `read` yields a listed
|
|
35
|
+
* candidate's bytes and is called here only for the two ignore files at the
|
|
36
|
+
* root, so a client may hand over a lazy reader and pay for the rest only
|
|
37
|
+
* when the archive is built.
|
|
38
|
+
*/
|
|
39
|
+
export function selectPluginFiles(candidates, read, options) {
|
|
40
|
+
const byPath = new Map(candidates.map((candidate) => [candidate.path, candidate]));
|
|
41
|
+
const sources = {
|
|
42
|
+
includeDefaults: true,
|
|
43
|
+
...(options.respectGitignore &&
|
|
44
|
+
byPath.has(IGNORE_FILE_NAMES.gitignore) && { gitignore: decode(read(IGNORE_FILE_NAMES.gitignore)) }),
|
|
45
|
+
...(byPath.has(IGNORE_FILE_NAMES.stigmerignore) && {
|
|
46
|
+
stigmerignore: decode(read(IGNORE_FILE_NAMES.stigmerignore)),
|
|
47
|
+
}),
|
|
48
|
+
...(options.extraIgnore !== undefined && { extraIgnore: options.extraIgnore }),
|
|
49
|
+
...(options.extraInclude !== undefined && { extraInclude: options.extraInclude }),
|
|
50
|
+
};
|
|
51
|
+
const matcher = buildMatcher(sources);
|
|
52
|
+
const stats = { filesIncluded: 0, filesIgnored: 0, dirsSkipped: 0, totalSize: 0 };
|
|
53
|
+
const skippedDirs = new Set();
|
|
54
|
+
const entries = [];
|
|
55
|
+
for (const candidate of [...candidates].sort((a, b) => compareWalkOrder(a.path, b.path))) {
|
|
56
|
+
if (underSkippedDir(candidate.path, matcher, skippedDirs, stats))
|
|
57
|
+
continue;
|
|
58
|
+
if (matcher.matchWithReason(candidate.path, false).ignored) {
|
|
59
|
+
stats.filesIgnored++;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
entries.push({ path: candidate.path, size: candidate.size });
|
|
63
|
+
stats.filesIncluded++;
|
|
64
|
+
stats.totalSize += candidate.size;
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
files: {
|
|
68
|
+
entries,
|
|
69
|
+
read(path) {
|
|
70
|
+
if (!byPath.has(path))
|
|
71
|
+
throw new Error(`plugin file '${path}' is not listed`);
|
|
72
|
+
return read(path);
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
stats,
|
|
76
|
+
matcher,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* The order a sorted directory walk visits files: component by component,
|
|
81
|
+
* each compared by code point. Two paths never share a prefix that is a
|
|
82
|
+
* file in one and a directory in the other, so a shorter path is never a
|
|
83
|
+
* prefix of a longer one at the point they differ.
|
|
84
|
+
*/
|
|
85
|
+
export function compareWalkOrder(a, b) {
|
|
86
|
+
const as = a.split("/");
|
|
87
|
+
const bs = b.split("/");
|
|
88
|
+
const depth = Math.min(as.length, bs.length);
|
|
89
|
+
for (let i = 0; i < depth; i++) {
|
|
90
|
+
const x = as[i] ?? "";
|
|
91
|
+
const y = bs[i] ?? "";
|
|
92
|
+
if (x !== y)
|
|
93
|
+
return x < y ? -1 : 1;
|
|
94
|
+
}
|
|
95
|
+
return as.length - bs.length;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* True when an ancestor directory of `path` is ignored as a directory. The
|
|
99
|
+
* walk checks a directory once and skips its subtree, so each ignored
|
|
100
|
+
* directory counts once whatever it holds.
|
|
101
|
+
*/
|
|
102
|
+
function underSkippedDir(path, matcher, skipped, stats) {
|
|
103
|
+
const parts = path.split("/");
|
|
104
|
+
let dir = "";
|
|
105
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
106
|
+
dir = dir === "" ? (parts[i] ?? "") : `${dir}/${parts[i] ?? ""}`;
|
|
107
|
+
if (skipped.has(dir))
|
|
108
|
+
return true;
|
|
109
|
+
if (matcher.matchWithReason(dir, true).ignored) {
|
|
110
|
+
skipped.add(dir);
|
|
111
|
+
stats.dirsSkipped++;
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
const decoder = new TextDecoder();
|
|
118
|
+
function decode(bytes) {
|
|
119
|
+
return decoder.decode(bytes);
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=select.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"select.js","sourceRoot":"","sources":["../../src/client/select.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,EAAoC,gBAAgB,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAgC7H,mEAAmE;AACnE,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,SAAS,EAAE,gBAAgB;IAC3B,aAAa,EAAE,oBAAoB;CAC3B,CAAC;AAEX;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAC/B,UAAoC,EACpC,IAAkC,EAClC,OAAiC;IAEjC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;IACnF,MAAM,OAAO,GAAkB;QAC7B,eAAe,EAAE,IAAI;QACrB,GAAG,CAAC,OAAO,CAAC,gBAAgB;YAC1B,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;QACtG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,aAAa,CAAC,IAAI;YACjD,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,aAAa,CAAC,CAAC;SAC7D,CAAC;QACF,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,SAAS,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC;QAC9E,GAAG,CAAC,OAAO,CAAC,YAAY,KAAK,SAAS,IAAI,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC;KAClF,CAAC;IACF,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IAEtC,MAAM,KAAK,GAAmB,EAAE,aAAa,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;IAClG,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IACtC,MAAM,OAAO,GAAsB,EAAE,CAAC;IAEtC,KAAK,MAAM,SAAS,IAAI,CAAC,GAAG,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;QACzF,IAAI,eAAe,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,CAAC;YAAE,SAAS;QAC3E,IAAI,OAAO,CAAC,eAAe,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;YAC3D,KAAK,CAAC,YAAY,EAAE,CAAC;YACrB,SAAS;QACX,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;QAC7D,KAAK,CAAC,aAAa,EAAE,CAAC;QACtB,KAAK,CAAC,SAAS,IAAI,SAAS,CAAC,IAAI,CAAC;IACpC,CAAC;IAED,OAAO;QACL,KAAK,EAAE;YACL,OAAO;YACP,IAAI,CAAC,IAAI;gBACP,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;oBAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,IAAI,iBAAiB,CAAC,CAAC;gBAC9E,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC;YACpB,CAAC;SACF;QACD,KAAK;QACL,OAAO;KACR,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,CAAS,EAAE,CAAS;IACnD,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACxB,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACxB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;IAC7C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/B,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACtB,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,EAAE,CAAC,MAAM,GAAG,EAAE,CAAC,MAAM,CAAC;AAC/B,CAAC;AAED;;;;GAIG;AACH,SAAS,eAAe,CAAC,IAAY,EAAE,OAAgB,EAAE,OAAoB,EAAE,KAAqB;IAClG,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,GAAG,GAAG,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACjE,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QAClC,IAAI,OAAO,CAAC,eAAe,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;YAC/C,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACjB,KAAK,CAAC,WAAW,EAAE,CAAC;YACpB,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;AAElC,SAAS,MAAM,CAAC,KAAiB;IAC/B,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The words every client prints for the same thing.
|
|
3
|
+
*
|
|
4
|
+
* The CLI's `validate -f`, `push plugin --dry-run` and `install`, and the
|
|
5
|
+
* console's install preview, all describe a package to the user; a
|
|
6
|
+
* platform where the same fact is named differently on two surfaces has
|
|
7
|
+
* two vocabularies. The labels here are the docs' words
|
|
8
|
+
* (`docs/vocabulary.md`), kept once.
|
|
9
|
+
*/
|
|
10
|
+
import type { PluginDialect } from "../types.js";
|
|
11
|
+
/** Human labels for the four dialects, in the vocabulary the docs use. */
|
|
12
|
+
export declare const DIALECT_LABELS: Readonly<Record<PluginDialect, string>>;
|
|
13
|
+
//# sourceMappingURL=vocabulary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vocabulary.d.ts","sourceRoot":"","sources":["../../src/client/vocabulary.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,0EAA0E;AAC1E,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAKlE,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The words every client prints for the same thing.
|
|
3
|
+
*
|
|
4
|
+
* The CLI's `validate -f`, `push plugin --dry-run` and `install`, and the
|
|
5
|
+
* console's install preview, all describe a package to the user; a
|
|
6
|
+
* platform where the same fact is named differently on two surfaces has
|
|
7
|
+
* two vocabularies. The labels here are the docs' words
|
|
8
|
+
* (`docs/vocabulary.md`), kept once.
|
|
9
|
+
*/
|
|
10
|
+
/** Human labels for the four dialects, in the vocabulary the docs use. */
|
|
11
|
+
export const DIALECT_LABELS = {
|
|
12
|
+
"agent-plugins": "Agent Plugins 1.0",
|
|
13
|
+
claude: "Claude Code plugin",
|
|
14
|
+
cursor: "Cursor plugin",
|
|
15
|
+
codex: "Codex plugin",
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=vocabulary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vocabulary.js","sourceRoot":"","sources":["../../src/client/vocabulary.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,0EAA0E;AAC1E,MAAM,CAAC,MAAM,cAAc,GAA4C;IACrE,eAAe,EAAE,mBAAmB;IACpC,MAAM,EAAE,oBAAoB;IAC5B,MAAM,EAAE,eAAe;IACvB,KAAK,EAAE,cAAc;CACtB,CAAC"}
|
package/client.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@stigmer/plugin-package/client`: what every client that installs a
|
|
3
|
+
* plugin does identically.
|
|
4
|
+
*
|
|
5
|
+
* The main entry reads a package; this entry is for the client that holds
|
|
6
|
+
* a tree and must turn it into the push the server expects. Two clients do
|
|
7
|
+
* that today, the CLI from a directory and the console from a marketplace
|
|
8
|
+
* host's file list, and a plugin installed from either must have one
|
|
9
|
+
* digest for one tree, be refused with one sentence for one mistake, and be
|
|
10
|
+
* described in one vocabulary. So the pieces live here, once:
|
|
11
|
+
*
|
|
12
|
+
* - the gitignore-compatible ignore engine and the security defaults
|
|
13
|
+
* (`ignore/`), pure over the text of the ignore files;
|
|
14
|
+
* - the selection rule (`select.ts`): which files a push carries, in the
|
|
15
|
+
* order the CLI's original walk produced them;
|
|
16
|
+
* - the archive and its digest (`archive.ts`): the deterministic zip and
|
|
17
|
+
* the SHA-256 the server records;
|
|
18
|
+
* - the grammars (`refs.ts`): an install ref and a GitHub marketplace
|
|
19
|
+
* source, with their refusal sentences;
|
|
20
|
+
* - the vocabulary (`vocabulary.ts`): the labels both surfaces print.
|
|
21
|
+
*
|
|
22
|
+
* Nothing here touches the filesystem, the network or any `node:*` module.
|
|
23
|
+
* A client's edge (a directory walk, a fetch) produces the candidates and
|
|
24
|
+
* the bytes; this entry decides what becomes of them.
|
|
25
|
+
*/
|
|
26
|
+
export { DEFAULT_PATTERNS } from "./client/ignore/defaults.js";
|
|
27
|
+
export { matchName } from "./client/ignore/match.js";
|
|
28
|
+
export { type IgnoreSources, type MatchReason, Matcher, Reason, REASON_TEXT, SOURCE_CLI, SOURCE_DEFAULTS, SOURCE_GITIGNORE, SOURCE_STIGMERIGNORE, buildMatcher, } from "./client/ignore/matcher.js";
|
|
29
|
+
export { MatchResult, type Pattern, parsePattern } from "./client/ignore/pattern.js";
|
|
30
|
+
export { type CandidateFile, type PluginSelection, type SelectPluginFilesOptions, type SelectionStats, IGNORE_FILE_NAMES, compareWalkOrder, selectPluginFiles, } from "./client/select.js";
|
|
31
|
+
export { DETERMINISTIC_ZIP_MTIME, archivePlugin, digestArchive } from "./client/archive.js";
|
|
32
|
+
export { type GitHubMarketplaceSource, type GitHubSourceOutcome, type InstallRef, type InstallRefOutcome, GITHUB_SOURCE_SHAPE, INSTALL_REF_SHAPE, OFFICIAL_MARKETPLACE_NAME, describeGitHubSource, formatInstallRef, isOwnerRepo, looksLikePath, parseGitHubSource, parseInstallRef, } from "./client/refs.js";
|
|
33
|
+
export { DIALECT_LABELS } from "./client/vocabulary.js";
|
|
34
|
+
//# sourceMappingURL=client.d.ts.map
|
package/client.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,OAAO,EACP,MAAM,EACN,WAAW,EACX,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,YAAY,GACb,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,KAAK,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AACrF,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,wBAAwB,EAC7B,KAAK,cAAc,EACnB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,uBAAuB,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAC5F,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,EACxB,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,mBAAmB,EACnB,iBAAiB,EACjB,yBAAyB,EACzB,oBAAoB,EACpB,gBAAgB,EAChB,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC"}
|