@stigmer/plugin-package 3.15.3-dev.20260916211208
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/LICENSE +190 -0
- package/README.md +66 -0
- package/detect.d.ts +50 -0
- package/detect.d.ts.map +1 -0
- package/detect.js +164 -0
- package/detect.js.map +1 -0
- package/dialects/claude.d.ts +30 -0
- package/dialects/claude.d.ts.map +1 -0
- package/dialects/claude.js +71 -0
- package/dialects/claude.js.map +1 -0
- package/dialects/codex.d.ts +18 -0
- package/dialects/codex.d.ts.map +1 -0
- package/dialects/codex.js +19 -0
- package/dialects/codex.js.map +1 -0
- package/dialects/cursor.d.ts +23 -0
- package/dialects/cursor.d.ts.map +1 -0
- package/dialects/cursor.js +63 -0
- package/dialects/cursor.js.map +1 -0
- package/dialects/manifest.d.ts +109 -0
- package/dialects/manifest.d.ts.map +1 -0
- package/dialects/manifest.js +194 -0
- package/dialects/manifest.js.map +1 -0
- package/dialects/open.d.ts +18 -0
- package/dialects/open.d.ts.map +1 -0
- package/dialects/open.js +47 -0
- package/dialects/open.js.map +1 -0
- package/documents.d.ts +43 -0
- package/documents.d.ts.map +1 -0
- package/documents.js +111 -0
- package/documents.js.map +1 -0
- package/files.d.ts +114 -0
- package/files.d.ts.map +1 -0
- package/files.js +187 -0
- package/files.js.map +1 -0
- package/frontmatter.d.ts +51 -0
- package/frontmatter.d.ts.map +1 -0
- package/frontmatter.js +61 -0
- package/frontmatter.js.map +1 -0
- package/index.d.ts +19 -0
- package/index.d.ts.map +1 -0
- package/index.js +17 -0
- package/index.js.map +1 -0
- package/messages.d.ts +39 -0
- package/messages.d.ts.map +1 -0
- package/messages.js +135 -0
- package/messages.js.map +1 -0
- package/normalise/ignored.d.ts +24 -0
- package/normalise/ignored.d.ts.map +1 -0
- package/normalise/ignored.js +68 -0
- package/normalise/ignored.js.map +1 -0
- package/normalise/mcp-servers.d.ts +47 -0
- package/normalise/mcp-servers.d.ts.map +1 -0
- package/normalise/mcp-servers.js +397 -0
- package/normalise/mcp-servers.js.map +1 -0
- package/normalise/overlay.d.ts +27 -0
- package/normalise/overlay.d.ts.map +1 -0
- package/normalise/overlay.js +67 -0
- package/normalise/overlay.js.map +1 -0
- package/normalise/skills.d.ts +31 -0
- package/normalise/skills.d.ts.map +1 -0
- package/normalise/skills.js +116 -0
- package/normalise/skills.js.map +1 -0
- package/normalise/sub-agents.d.ts +44 -0
- package/normalise/sub-agents.d.ts.map +1 -0
- package/normalise/sub-agents.js +168 -0
- package/normalise/sub-agents.js.map +1 -0
- package/normalise/variables.d.ts +27 -0
- package/normalise/variables.d.ts.map +1 -0
- package/normalise/variables.js +155 -0
- package/normalise/variables.js.map +1 -0
- package/outcome.d.ts +46 -0
- package/outcome.d.ts.map +1 -0
- package/outcome.js +21 -0
- package/outcome.js.map +1 -0
- package/package.json +40 -0
- package/placeholders.d.ts +41 -0
- package/placeholders.d.ts.map +1 -0
- package/placeholders.js +68 -0
- package/placeholders.js.map +1 -0
- package/read-plugin-package.d.ts +19 -0
- package/read-plugin-package.d.ts.map +1 -0
- package/read-plugin-package.js +67 -0
- package/read-plugin-package.js.map +1 -0
- package/src/__test-utils__/directory-files.ts +29 -0
- package/src/__test-utils__/read.ts +55 -0
- package/src/__tests__/adversarial.test.ts +434 -0
- package/src/__tests__/detect.test.ts +133 -0
- package/src/__tests__/files.test.ts +119 -0
- package/src/__tests__/fixtures/cursor-plugins/NOTICE +22 -0
- package/src/__tests__/fixtures/cursor-plugins/advisor/.cursor-plugin/plugin.json +33 -0
- package/src/__tests__/fixtures/cursor-plugins/advisor/CHANGELOG.md +8 -0
- package/src/__tests__/fixtures/cursor-plugins/advisor/LICENSE +21 -0
- package/src/__tests__/fixtures/cursor-plugins/advisor/README.md +87 -0
- package/src/__tests__/fixtures/cursor-plugins/advisor/agents/advisor-subagent.md +48 -0
- package/src/__tests__/fixtures/cursor-plugins/advisor/assets/avatar.png +0 -0
- package/src/__tests__/fixtures/cursor-plugins/advisor/hooks/capture-response.sh +20 -0
- package/src/__tests__/fixtures/cursor-plugins/advisor/hooks/hooks.json +27 -0
- package/src/__tests__/fixtures/cursor-plugins/advisor/hooks/lib.sh +61 -0
- package/src/__tests__/fixtures/cursor-plugins/advisor/hooks/mark-pending.sh +27 -0
- package/src/__tests__/fixtures/cursor-plugins/advisor/hooks/record-consult.sh +41 -0
- package/src/__tests__/fixtures/cursor-plugins/advisor/hooks/stop-hook.sh +48 -0
- package/src/__tests__/fixtures/cursor-plugins/advisor/skills/advisor/SKILL.md +123 -0
- package/src/__tests__/fixtures/cursor-plugins/advisor/skills/advisor/references/briefing-template.md +44 -0
- package/src/__tests__/fixtures/cursor-plugins/github/.cursor-plugin/plugin.json +45 -0
- package/src/__tests__/fixtures/cursor-plugins/github/CHANGELOG.md +9 -0
- package/src/__tests__/fixtures/cursor-plugins/github/LICENSE +21 -0
- package/src/__tests__/fixtures/cursor-plugins/github/README.md +64 -0
- package/src/__tests__/fixtures/cursor-plugins/github/assets/logo.svg +0 -0
- package/src/__tests__/fixtures/cursor-plugins/github/mcp.json +11 -0
- package/src/__tests__/fixtures/cursor-plugins/playwright/.cursor-plugin/plugin.json +35 -0
- package/src/__tests__/fixtures/cursor-plugins/playwright/CHANGELOG.md +8 -0
- package/src/__tests__/fixtures/cursor-plugins/playwright/LICENSE +21 -0
- package/src/__tests__/fixtures/cursor-plugins/playwright/README.md +46 -0
- package/src/__tests__/fixtures/cursor-plugins/playwright/assets/logo.svg +0 -0
- package/src/__tests__/fixtures/cursor-plugins/playwright/mcp.json +8 -0
- package/src/__tests__/fixtures/cursor-plugins/salesforce/.cursor-plugin/plugin.json +48 -0
- package/src/__tests__/fixtures/cursor-plugins/salesforce/CHANGELOG.md +10 -0
- package/src/__tests__/fixtures/cursor-plugins/salesforce/LICENSE +21 -0
- package/src/__tests__/fixtures/cursor-plugins/salesforce/README.md +95 -0
- package/src/__tests__/fixtures/cursor-plugins/salesforce/assets/logo.svg +0 -0
- package/src/__tests__/fixtures/cursor-plugins/salesforce/mcp.json +12 -0
- package/src/__tests__/fixtures/cursor-plugins/thermos/.cursor-plugin/plugin.json +32 -0
- package/src/__tests__/fixtures/cursor-plugins/thermos/CHANGELOG.md +8 -0
- package/src/__tests__/fixtures/cursor-plugins/thermos/LICENSE +21 -0
- package/src/__tests__/fixtures/cursor-plugins/thermos/README.md +70 -0
- package/src/__tests__/fixtures/cursor-plugins/thermos/agents/thermo-nuclear-code-quality-review-subagent.md +23 -0
- package/src/__tests__/fixtures/cursor-plugins/thermos/agents/thermo-nuclear-review-subagent.md +28 -0
- package/src/__tests__/fixtures/cursor-plugins/thermos/assets/logo.png +0 -0
- package/src/__tests__/fixtures/cursor-plugins/thermos/skills/thermo-nuclear-code-quality-review/SKILL.md +192 -0
- package/src/__tests__/fixtures/cursor-plugins/thermos/skills/thermo-nuclear-review/SKILL.md +51 -0
- package/src/__tests__/fixtures/cursor-plugins/thermos/skills/thermos/SKILL.md +21 -0
- package/src/__tests__/fixtures/cursor-plugins/xero/.cursor-plugin/plugin.json +53 -0
- package/src/__tests__/fixtures/cursor-plugins/xero/CHANGELOG.md +9 -0
- package/src/__tests__/fixtures/cursor-plugins/xero/LICENSE +21 -0
- package/src/__tests__/fixtures/cursor-plugins/xero/README.md +79 -0
- package/src/__tests__/fixtures/cursor-plugins/xero/assets/logo.png +0 -0
- package/src/__tests__/fixtures/cursor-plugins/xero/mcp.json +16 -0
- package/src/__tests__/fixtures.test.ts +198 -0
- package/src/__tests__/mcp-servers.test.ts +120 -0
- package/src/__tests__/overlay-and-ignored.test.ts +65 -0
- package/src/__tests__/skills.test.ts +89 -0
- package/src/__tests__/sub-agents.test.ts +111 -0
- package/src/__tests__/variables.test.ts +94 -0
- package/src/detect.ts +189 -0
- package/src/dialects/claude.ts +90 -0
- package/src/dialects/codex.ts +24 -0
- package/src/dialects/cursor.ts +73 -0
- package/src/dialects/manifest.ts +237 -0
- package/src/dialects/open.ts +48 -0
- package/src/documents.ts +145 -0
- package/src/files.ts +213 -0
- package/src/frontmatter.ts +70 -0
- package/src/index.ts +59 -0
- package/src/messages.ts +206 -0
- package/src/normalise/ignored.ts +70 -0
- package/src/normalise/mcp-servers.ts +427 -0
- package/src/normalise/overlay.ts +71 -0
- package/src/normalise/skills.ts +126 -0
- package/src/normalise/sub-agents.ts +184 -0
- package/src/normalise/variables.ts +161 -0
- package/src/outcome.ts +122 -0
- package/src/placeholders.ts +74 -0
- package/src/read-plugin-package.ts +74 -0
- package/src/testing.ts +258 -0
- package/src/types.ts +189 -0
- package/testing.d.ts +106 -0
- package/testing.d.ts.map +1 -0
- package/testing.js +182 -0
- package/testing.js.map +1 -0
- package/types.d.ts +152 -0
- package/types.d.ts.map +1 -0
- package/types.js +19 -0
- package/types.js.map +1 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Cursor manifest (`.cursor-plugin/plugin.json`).
|
|
3
|
+
*
|
|
4
|
+
* Cursor publishes a draft-07 schema for this file (`additionalProperties:
|
|
5
|
+
* false`, only `name` required); the known-field set below is that schema's
|
|
6
|
+
* key list, and `author` there carries `name` and `email` only. Component
|
|
7
|
+
* fields `skills`, `agents`, `rules`, `commands` are a path or an array of
|
|
8
|
+
* paths (the schema says "glob pattern(s) or path(s)"; every published
|
|
9
|
+
* plugin uses a `./`-prefixed directory, and a glob is refused rather than
|
|
10
|
+
* expanded). `mcpServers` is a path, an inline object, or an array of
|
|
11
|
+
* either. `variables` is a JSON Schema object whose `properties` are the
|
|
12
|
+
* variables a user is prompted for and whose `required` list marks the
|
|
13
|
+
* mandatory ones; Cursor has no sensitivity flag, so Stigmer treats every
|
|
14
|
+
* Cursor variable as a secret. `rules`, `commands`, `hooks`, `logo` and
|
|
15
|
+
* `minClientVersions` are recorded as ignored; `displayName`, `publisher`,
|
|
16
|
+
* `category` and `tags` are marketplace metadata Stigmer neither carries
|
|
17
|
+
* nor warns about.
|
|
18
|
+
*/
|
|
19
|
+
import type { JsonObject } from "../documents.js";
|
|
20
|
+
import type { Findings } from "../messages.js";
|
|
21
|
+
import { type DialectManifest } from "./manifest.js";
|
|
22
|
+
export declare function readCursorManifest(object: JsonObject, path: string, findings: Findings): DialectManifest;
|
|
23
|
+
//# sourceMappingURL=cursor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../src/dialects/cursor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EACL,KAAK,eAAe,EAMrB,MAAM,eAAe,CAAC;AA0BvB,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,eAAe,CAkBxG"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Cursor manifest (`.cursor-plugin/plugin.json`).
|
|
3
|
+
*
|
|
4
|
+
* Cursor publishes a draft-07 schema for this file (`additionalProperties:
|
|
5
|
+
* false`, only `name` required); the known-field set below is that schema's
|
|
6
|
+
* key list, and `author` there carries `name` and `email` only. Component
|
|
7
|
+
* fields `skills`, `agents`, `rules`, `commands` are a path or an array of
|
|
8
|
+
* paths (the schema says "glob pattern(s) or path(s)"; every published
|
|
9
|
+
* plugin uses a `./`-prefixed directory, and a glob is refused rather than
|
|
10
|
+
* expanded). `mcpServers` is a path, an inline object, or an array of
|
|
11
|
+
* either. `variables` is a JSON Schema object whose `properties` are the
|
|
12
|
+
* variables a user is prompted for and whose `required` list marks the
|
|
13
|
+
* mandatory ones; Cursor has no sensitivity flag, so Stigmer treats every
|
|
14
|
+
* Cursor variable as a secret. `rules`, `commands`, `hooks`, `logo` and
|
|
15
|
+
* `minClientVersions` are recorded as ignored; `displayName`, `publisher`,
|
|
16
|
+
* `category` and `tags` are marketplace metadata Stigmer neither carries
|
|
17
|
+
* nor warns about.
|
|
18
|
+
*/
|
|
19
|
+
import { ignoredFieldComponents, readDeclaredPaths, readIdentity, readMcpSources, warnUnknownFields, } from "./manifest.js";
|
|
20
|
+
const KNOWN_FIELDS = new Set([
|
|
21
|
+
"name",
|
|
22
|
+
"displayName",
|
|
23
|
+
"description",
|
|
24
|
+
"version",
|
|
25
|
+
"minClientVersions",
|
|
26
|
+
"author",
|
|
27
|
+
"publisher",
|
|
28
|
+
"homepage",
|
|
29
|
+
"repository",
|
|
30
|
+
"license",
|
|
31
|
+
"logo",
|
|
32
|
+
"keywords",
|
|
33
|
+
"category",
|
|
34
|
+
"tags",
|
|
35
|
+
"commands",
|
|
36
|
+
"agents",
|
|
37
|
+
"skills",
|
|
38
|
+
"rules",
|
|
39
|
+
"hooks",
|
|
40
|
+
"variables",
|
|
41
|
+
"mcpServers",
|
|
42
|
+
]);
|
|
43
|
+
export function readCursorManifest(object, path, findings) {
|
|
44
|
+
warnUnknownFields(object, KNOWN_FIELDS, path, findings);
|
|
45
|
+
const identity = readIdentity(object, path, findings);
|
|
46
|
+
const skillPaths = readDeclaredPaths(object, "skills", path, findings) ?? [];
|
|
47
|
+
const agentPaths = readDeclaredPaths(object, "agents", path, findings);
|
|
48
|
+
const manifest = {
|
|
49
|
+
dialect: "cursor",
|
|
50
|
+
path,
|
|
51
|
+
identity,
|
|
52
|
+
skillPaths,
|
|
53
|
+
mcpConfigs: readMcpSources(object, "mcpServers", path, "cursor", findings),
|
|
54
|
+
ignored: ignoredFieldComponents(object, path),
|
|
55
|
+
};
|
|
56
|
+
if (agentPaths !== undefined)
|
|
57
|
+
manifest.agentPaths = agentPaths;
|
|
58
|
+
if (object["variables"] !== undefined) {
|
|
59
|
+
manifest.variables = { dialect: "cursor", value: object["variables"], manifest: path };
|
|
60
|
+
}
|
|
61
|
+
return manifest;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=cursor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../src/dialects/cursor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,EAEL,sBAAsB,EACtB,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAEvB,MAAM,YAAY,GAAwB,IAAI,GAAG,CAAC;IAChD,MAAM;IACN,aAAa;IACb,aAAa;IACb,SAAS;IACT,mBAAmB;IACnB,QAAQ;IACR,WAAW;IACX,UAAU;IACV,YAAY;IACZ,SAAS;IACT,MAAM;IACN,UAAU;IACV,UAAU;IACV,MAAM;IACN,UAAU;IACV,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,OAAO;IACP,WAAW;IACX,YAAY;CACb,CAAC,CAAC;AAEH,MAAM,UAAU,kBAAkB,CAAC,MAAkB,EAAE,IAAY,EAAE,QAAkB;IACrF,iBAAiB,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;IACxD,MAAM,QAAQ,GAAG,YAAY,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;IACtD,MAAM,UAAU,GAAG,iBAAiB,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC7E,MAAM,UAAU,GAAG,iBAAiB,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;IACvE,MAAM,QAAQ,GAAmE;QAC/E,OAAO,EAAE,QAAQ;QACjB,IAAI;QACJ,QAAQ;QACR,UAAU;QACV,UAAU,EAAE,cAAc,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC;QAC1E,OAAO,EAAE,sBAAsB,CAAC,MAAM,EAAE,IAAI,CAAC;KAC9C,CAAC;IACF,IAAI,UAAU,KAAK,SAAS;QAAE,QAAQ,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/D,IAAI,MAAM,CAAC,WAAW,CAAC,KAAK,SAAS,EAAE,CAAC;QACtC,QAAQ,CAAC,SAAS,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACzF,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The intermediate every dialect reader reduces its manifest to, and the
|
|
3
|
+
* field-reading helpers they share.
|
|
4
|
+
*
|
|
5
|
+
* A `DialectManifest` says what one manifest CONTRIBUTES: identity fields,
|
|
6
|
+
* declared component paths, MCP configuration sources, a variables block,
|
|
7
|
+
* and the fields it carries that Stigmer records as ignored. It does not
|
|
8
|
+
* decide anything across manifests: precedence, name conflicts and default
|
|
9
|
+
* locations are `detect.ts`'s, and turning declarations into skills,
|
|
10
|
+
* servers and variables is `normalise/`'s. Keeping the readers to "what
|
|
11
|
+
* does this file say" is what lets a plugin carry a root manifest and a
|
|
12
|
+
* vendor manifest at once and have both read.
|
|
13
|
+
*
|
|
14
|
+
* Unknown fields WARN in every dialect (the open format says report and
|
|
15
|
+
* ignore; Cursor's own validator would reject them, but a warning serves
|
|
16
|
+
* the author and the install still works). A known field of the wrong type
|
|
17
|
+
* is fatal (`manifest-field-type`), the open format's rule for any
|
|
18
|
+
* violation other than an unknown field.
|
|
19
|
+
*/
|
|
20
|
+
import { type JsonObject } from "../documents.js";
|
|
21
|
+
import type { Findings } from "../messages.js";
|
|
22
|
+
import type { IgnoredComponent, IgnoredComponentKind, PluginAuthor, PluginDialect } from "../types.js";
|
|
23
|
+
export interface PluginIdentity {
|
|
24
|
+
readonly name?: string;
|
|
25
|
+
readonly version?: string;
|
|
26
|
+
readonly description?: string;
|
|
27
|
+
readonly author?: PluginAuthor;
|
|
28
|
+
readonly homepage?: string;
|
|
29
|
+
readonly repository?: string;
|
|
30
|
+
readonly license?: string;
|
|
31
|
+
readonly keywords?: readonly string[];
|
|
32
|
+
}
|
|
33
|
+
/** A component path a manifest declared, normalised, with where it was declared. */
|
|
34
|
+
export interface DeclaredPath {
|
|
35
|
+
/** Plugin-relative, no leading `./`, no trailing slash; the root is `""`. */
|
|
36
|
+
readonly path: string;
|
|
37
|
+
/** The manifest that declared it, for messages. */
|
|
38
|
+
readonly manifest: string;
|
|
39
|
+
}
|
|
40
|
+
/** Where MCP server entries come from: a configuration file, or an object inline in a manifest. */
|
|
41
|
+
export type McpConfigSource = {
|
|
42
|
+
readonly kind: "file";
|
|
43
|
+
readonly path: string;
|
|
44
|
+
readonly dialect: PluginDialect;
|
|
45
|
+
readonly manifest: string;
|
|
46
|
+
} | {
|
|
47
|
+
readonly kind: "inline";
|
|
48
|
+
readonly manifest: string;
|
|
49
|
+
readonly servers: unknown;
|
|
50
|
+
readonly dialect: PluginDialect;
|
|
51
|
+
};
|
|
52
|
+
/** A variables block, raw, tagged with the dialect whose shape it takes. */
|
|
53
|
+
export type VariablesDeclaration = {
|
|
54
|
+
readonly dialect: "cursor";
|
|
55
|
+
readonly value: unknown;
|
|
56
|
+
readonly manifest: string;
|
|
57
|
+
} | {
|
|
58
|
+
readonly dialect: "claude";
|
|
59
|
+
readonly value: unknown;
|
|
60
|
+
readonly manifest: string;
|
|
61
|
+
};
|
|
62
|
+
export interface DialectManifest {
|
|
63
|
+
readonly dialect: PluginDialect;
|
|
64
|
+
readonly path: string;
|
|
65
|
+
readonly identity: PluginIdentity;
|
|
66
|
+
/** Declared skill paths; the default `skills/` is scanned regardless. */
|
|
67
|
+
readonly skillPaths: readonly DeclaredPath[];
|
|
68
|
+
/** Declared agent paths; `undefined` leaves the default `agents/` scan in force. */
|
|
69
|
+
readonly agentPaths?: readonly DeclaredPath[];
|
|
70
|
+
readonly mcpConfigs: readonly McpConfigSource[];
|
|
71
|
+
readonly variables?: VariablesDeclaration;
|
|
72
|
+
readonly ignored: readonly IgnoredComponent[];
|
|
73
|
+
}
|
|
74
|
+
/** Warn once per field the dialect does not define. */
|
|
75
|
+
export declare function warnUnknownFields(object: JsonObject, known: ReadonlySet<string>, path: string, findings: Findings): void;
|
|
76
|
+
/**
|
|
77
|
+
* The identity fields every dialect shares. `author` is an object in every
|
|
78
|
+
* dialect (Cursor's schema has no `url`; the extra key is a warning there,
|
|
79
|
+
* reported by the caller's known-field set for `author`).
|
|
80
|
+
*/
|
|
81
|
+
export declare function readIdentity(object: JsonObject, path: string, findings: Findings): PluginIdentity;
|
|
82
|
+
/**
|
|
83
|
+
* A path field (`skills`, `agents`, ...) as declared paths. A value that is
|
|
84
|
+
* not a path (wrong prefix, escape, glob) is reported and dropped; the
|
|
85
|
+
* rest are kept, so one bad entry does not hide the others.
|
|
86
|
+
*/
|
|
87
|
+
export declare function readDeclaredPaths(object: JsonObject, field: string, path: string, findings: Findings): readonly DeclaredPath[] | undefined;
|
|
88
|
+
/**
|
|
89
|
+
* A vendor `mcpServers` field: a path, an inline `mcpServers` object, or an
|
|
90
|
+
* array of either. Each becomes one source under the dialect's rules.
|
|
91
|
+
*/
|
|
92
|
+
export declare function readMcpSources(object: JsonObject, field: string, path: string, dialect: PluginDialect, findings: Findings): readonly McpConfigSource[];
|
|
93
|
+
/**
|
|
94
|
+
* Manifest fields Stigmer reads past, recorded as ignored components at
|
|
95
|
+
* `<manifest>#<field>` when present. Shared across dialects; each names the
|
|
96
|
+
* fields it knows through `known` so the same field is never also an
|
|
97
|
+
* unknown-field warning.
|
|
98
|
+
*/
|
|
99
|
+
export declare const IGNORED_FIELD_KINDS: Readonly<Record<string, IgnoredComponentKind>>;
|
|
100
|
+
export declare function ignoredFieldComponents(object: JsonObject, path: string): IgnoredComponent[];
|
|
101
|
+
/**
|
|
102
|
+
* `extensions` in a root manifest: every namespace with content is an
|
|
103
|
+
* ignored component (a client ignores namespaces it does not implement
|
|
104
|
+
* without validating them); an empty object, including Stigmer's own
|
|
105
|
+
* reserved `ai.stigmer`, is silent. A non-object `extensions` is the open
|
|
106
|
+
* format's one non-fatal type violation: reported and ignored.
|
|
107
|
+
*/
|
|
108
|
+
export declare function extensionComponents(object: JsonObject, path: string, findings: Findings): IgnoredComponent[];
|
|
109
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/dialects/manifest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The intermediate every dialect reader reduces its manifest to, and the
|
|
3
|
+
* field-reading helpers they share.
|
|
4
|
+
*
|
|
5
|
+
* A `DialectManifest` says what one manifest CONTRIBUTES: identity fields,
|
|
6
|
+
* declared component paths, MCP configuration sources, a variables block,
|
|
7
|
+
* and the fields it carries that Stigmer records as ignored. It does not
|
|
8
|
+
* decide anything across manifests: precedence, name conflicts and default
|
|
9
|
+
* locations are `detect.ts`'s, and turning declarations into skills,
|
|
10
|
+
* servers and variables is `normalise/`'s. Keeping the readers to "what
|
|
11
|
+
* does this file say" is what lets a plugin carry a root manifest and a
|
|
12
|
+
* vendor manifest at once and have both read.
|
|
13
|
+
*
|
|
14
|
+
* Unknown fields WARN in every dialect (the open format says report and
|
|
15
|
+
* ignore; Cursor's own validator would reject them, but a warning serves
|
|
16
|
+
* the author and the install still works). A known field of the wrong type
|
|
17
|
+
* is fatal (`manifest-field-type`), the open format's rule for any
|
|
18
|
+
* violation other than an unknown field.
|
|
19
|
+
*/
|
|
20
|
+
import { fields, isJsonObject, optionalString, optionalStringArray, stringOrStringArray } from "../documents.js";
|
|
21
|
+
import { resolveDeclaredPath } from "../files.js";
|
|
22
|
+
/** Warn once per field the dialect does not define. */
|
|
23
|
+
export function warnUnknownFields(object, known, path, findings) {
|
|
24
|
+
for (const [name] of fields(object)) {
|
|
25
|
+
if (!known.has(name))
|
|
26
|
+
findings.warn("manifest-field-unknown", { path, subject: name });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The identity fields every dialect shares. `author` is an object in every
|
|
31
|
+
* dialect (Cursor's schema has no `url`; the extra key is a warning there,
|
|
32
|
+
* reported by the caller's known-field set for `author`).
|
|
33
|
+
*/
|
|
34
|
+
export function readIdentity(object, path, findings) {
|
|
35
|
+
const identity = {};
|
|
36
|
+
const name = optionalString(object, "name", path, findings);
|
|
37
|
+
if (name !== undefined)
|
|
38
|
+
identity.name = name;
|
|
39
|
+
const version = optionalString(object, "version", path, findings);
|
|
40
|
+
if (version !== undefined)
|
|
41
|
+
identity.version = version;
|
|
42
|
+
const description = optionalString(object, "description", path, findings);
|
|
43
|
+
if (description !== undefined)
|
|
44
|
+
identity.description = description;
|
|
45
|
+
const homepage = optionalString(object, "homepage", path, findings);
|
|
46
|
+
if (homepage !== undefined)
|
|
47
|
+
identity.homepage = homepage;
|
|
48
|
+
const repository = optionalString(object, "repository", path, findings);
|
|
49
|
+
if (repository !== undefined)
|
|
50
|
+
identity.repository = repository;
|
|
51
|
+
const license = optionalString(object, "license", path, findings);
|
|
52
|
+
if (license !== undefined)
|
|
53
|
+
identity.license = license;
|
|
54
|
+
const keywords = optionalStringArray(object, "keywords", path, findings);
|
|
55
|
+
if (keywords !== undefined)
|
|
56
|
+
identity.keywords = keywords;
|
|
57
|
+
const author = readAuthor(object, path, findings);
|
|
58
|
+
if (author !== undefined)
|
|
59
|
+
identity.author = author;
|
|
60
|
+
return identity;
|
|
61
|
+
}
|
|
62
|
+
function readAuthor(object, path, findings) {
|
|
63
|
+
const value = object["author"];
|
|
64
|
+
if (value === undefined)
|
|
65
|
+
return undefined;
|
|
66
|
+
if (!isJsonObject(value)) {
|
|
67
|
+
findings.error("manifest-field-type", { path, subject: "author", detail: "an object" });
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
const author = {};
|
|
71
|
+
const name = optionalString(value, "name", path, findings);
|
|
72
|
+
if (name !== undefined)
|
|
73
|
+
author.name = name;
|
|
74
|
+
const email = optionalString(value, "email", path, findings);
|
|
75
|
+
if (email !== undefined)
|
|
76
|
+
author.email = email;
|
|
77
|
+
const url = optionalString(value, "url", path, findings);
|
|
78
|
+
if (url !== undefined)
|
|
79
|
+
author.url = url;
|
|
80
|
+
return author;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* A path field (`skills`, `agents`, ...) as declared paths. A value that is
|
|
84
|
+
* not a path (wrong prefix, escape, glob) is reported and dropped; the
|
|
85
|
+
* rest are kept, so one bad entry does not hide the others.
|
|
86
|
+
*/
|
|
87
|
+
export function readDeclaredPaths(object, field, path, findings) {
|
|
88
|
+
const values = stringOrStringArray(object, field, path, findings);
|
|
89
|
+
if (values === undefined)
|
|
90
|
+
return undefined;
|
|
91
|
+
const declared = [];
|
|
92
|
+
for (const value of values) {
|
|
93
|
+
const resolved = resolveDeclaredPath(value);
|
|
94
|
+
if (!resolved.ok) {
|
|
95
|
+
findings.error(resolved.kind, { path, subject: value });
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
declared.push({ path: resolved.path, manifest: path });
|
|
99
|
+
}
|
|
100
|
+
return declared;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* A vendor `mcpServers` field: a path, an inline `mcpServers` object, or an
|
|
104
|
+
* array of either. Each becomes one source under the dialect's rules.
|
|
105
|
+
*/
|
|
106
|
+
export function readMcpSources(object, field, path, dialect, findings) {
|
|
107
|
+
const value = object[field];
|
|
108
|
+
if (value === undefined)
|
|
109
|
+
return [];
|
|
110
|
+
const items = Array.isArray(value) ? value : [value];
|
|
111
|
+
const sources = [];
|
|
112
|
+
for (const item of items) {
|
|
113
|
+
if (typeof item === "string") {
|
|
114
|
+
const resolved = resolveDeclaredPath(item);
|
|
115
|
+
if (!resolved.ok) {
|
|
116
|
+
findings.error(resolved.kind, { path, subject: item });
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
sources.push({ kind: "file", path: resolved.path, dialect, manifest: path });
|
|
120
|
+
}
|
|
121
|
+
else if (isJsonObject(item)) {
|
|
122
|
+
sources.push({ kind: "inline", manifest: path, servers: item, dialect });
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
findings.error("manifest-field-type", { path, subject: field, detail: "a path, an object, or an array of either" });
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return sources;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Manifest fields Stigmer reads past, recorded as ignored components at
|
|
132
|
+
* `<manifest>#<field>` when present. Shared across dialects; each names the
|
|
133
|
+
* fields it knows through `known` so the same field is never also an
|
|
134
|
+
* unknown-field warning.
|
|
135
|
+
*/
|
|
136
|
+
export const IGNORED_FIELD_KINDS = {
|
|
137
|
+
hooks: "hooks",
|
|
138
|
+
rules: "rules",
|
|
139
|
+
commands: "commands",
|
|
140
|
+
workflows: "workflows",
|
|
141
|
+
outputStyles: "output-styles",
|
|
142
|
+
lspServers: "lsp-servers",
|
|
143
|
+
channels: "channels",
|
|
144
|
+
dependencies: "dependencies",
|
|
145
|
+
defaultEnabled: "default-enabled",
|
|
146
|
+
minClientVersions: "min-client-versions",
|
|
147
|
+
logo: "logo",
|
|
148
|
+
apps: "apps",
|
|
149
|
+
};
|
|
150
|
+
export function ignoredFieldComponents(object, path) {
|
|
151
|
+
const ignored = [];
|
|
152
|
+
for (const [name, value] of fields(object)) {
|
|
153
|
+
const kind = IGNORED_FIELD_KINDS[name];
|
|
154
|
+
if (kind !== undefined)
|
|
155
|
+
ignored.push({ kind, path: `${path}#${name}` });
|
|
156
|
+
if (name === "experimental" && isJsonObject(value)) {
|
|
157
|
+
for (const [sub] of fields(value)) {
|
|
158
|
+
const subKind = EXPERIMENTAL_KINDS[sub];
|
|
159
|
+
if (subKind !== undefined)
|
|
160
|
+
ignored.push({ kind: subKind, path: `${path}#experimental.${sub}` });
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return ignored;
|
|
165
|
+
}
|
|
166
|
+
const EXPERIMENTAL_KINDS = {
|
|
167
|
+
themes: "themes",
|
|
168
|
+
monitors: "monitors",
|
|
169
|
+
evals: "evals",
|
|
170
|
+
};
|
|
171
|
+
/**
|
|
172
|
+
* `extensions` in a root manifest: every namespace with content is an
|
|
173
|
+
* ignored component (a client ignores namespaces it does not implement
|
|
174
|
+
* without validating them); an empty object, including Stigmer's own
|
|
175
|
+
* reserved `ai.stigmer`, is silent. A non-object `extensions` is the open
|
|
176
|
+
* format's one non-fatal type violation: reported and ignored.
|
|
177
|
+
*/
|
|
178
|
+
export function extensionComponents(object, path, findings) {
|
|
179
|
+
const value = object["extensions"];
|
|
180
|
+
if (value === undefined)
|
|
181
|
+
return [];
|
|
182
|
+
if (!isJsonObject(value)) {
|
|
183
|
+
findings.warn("manifest-extensions-invalid", { path });
|
|
184
|
+
return [];
|
|
185
|
+
}
|
|
186
|
+
const ignored = [];
|
|
187
|
+
for (const [namespace, content] of fields(value)) {
|
|
188
|
+
if (isJsonObject(content) && fields(content).length === 0)
|
|
189
|
+
continue;
|
|
190
|
+
ignored.push({ kind: "extension", path: `${path}#extensions.${namespace}` });
|
|
191
|
+
}
|
|
192
|
+
return ignored;
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/dialects/manifest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Agent Plugins 1.0.0 root manifest (`plugin.json`).
|
|
3
|
+
*
|
|
4
|
+
* The open format's manifest is closed and versioned: `$schema` is required
|
|
5
|
+
* and must be the canonical 1.0.0 identifier, the ten permitted fields are
|
|
6
|
+
* fixed, an unknown field is reported and ignored, and any other violation
|
|
7
|
+
* is fatal. Components live at fixed locations only (`skills/`, `mcp.json`),
|
|
8
|
+
* so this manifest declares no paths and no inline servers; `mcp.json` is
|
|
9
|
+
* read under the open format's rules by `detect.ts` when it exists.
|
|
10
|
+
* Client-specific data belongs under `extensions`, which Stigmer records as
|
|
11
|
+
* ignored per namespace (its own `ai.stigmer` namespace is reserved and
|
|
12
|
+
* empty today).
|
|
13
|
+
*/
|
|
14
|
+
import { type JsonObject } from "../documents.js";
|
|
15
|
+
import { type Findings } from "../messages.js";
|
|
16
|
+
import { type DialectManifest } from "./manifest.js";
|
|
17
|
+
export declare function readOpenManifest(object: JsonObject, path: string, findings: Findings): DialectManifest;
|
|
18
|
+
//# sourceMappingURL=open.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"open.d.ts","sourceRoot":"","sources":["../../src/dialects/open.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,EAAiC,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC9E,OAAO,EAAE,KAAK,eAAe,EAAwD,MAAM,eAAe,CAAC;AAe3G,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,eAAe,CAgBtG"}
|
package/dialects/open.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Agent Plugins 1.0.0 root manifest (`plugin.json`).
|
|
3
|
+
*
|
|
4
|
+
* The open format's manifest is closed and versioned: `$schema` is required
|
|
5
|
+
* and must be the canonical 1.0.0 identifier, the ten permitted fields are
|
|
6
|
+
* fixed, an unknown field is reported and ignored, and any other violation
|
|
7
|
+
* is fatal. Components live at fixed locations only (`skills/`, `mcp.json`),
|
|
8
|
+
* so this manifest declares no paths and no inline servers; `mcp.json` is
|
|
9
|
+
* read under the open format's rules by `detect.ts` when it exists.
|
|
10
|
+
* Client-specific data belongs under `extensions`, which Stigmer records as
|
|
11
|
+
* ignored per namespace (its own `ai.stigmer` namespace is reserved and
|
|
12
|
+
* empty today).
|
|
13
|
+
*/
|
|
14
|
+
import { describeValue } from "../documents.js";
|
|
15
|
+
import { AGENT_PLUGINS_MANIFEST_SCHEMA } from "../messages.js";
|
|
16
|
+
import { extensionComponents, readIdentity, warnUnknownFields } from "./manifest.js";
|
|
17
|
+
const KNOWN_FIELDS = new Set([
|
|
18
|
+
"$schema",
|
|
19
|
+
"name",
|
|
20
|
+
"version",
|
|
21
|
+
"description",
|
|
22
|
+
"author",
|
|
23
|
+
"homepage",
|
|
24
|
+
"repository",
|
|
25
|
+
"license",
|
|
26
|
+
"keywords",
|
|
27
|
+
"extensions",
|
|
28
|
+
]);
|
|
29
|
+
export function readOpenManifest(object, path, findings) {
|
|
30
|
+
const schema = object["$schema"];
|
|
31
|
+
if (schema === undefined) {
|
|
32
|
+
findings.error("manifest-schema-missing", { path });
|
|
33
|
+
}
|
|
34
|
+
else if (schema !== AGENT_PLUGINS_MANIFEST_SCHEMA) {
|
|
35
|
+
findings.error("manifest-schema-unsupported", { path, detail: describeValue(schema) });
|
|
36
|
+
}
|
|
37
|
+
warnUnknownFields(object, KNOWN_FIELDS, path, findings);
|
|
38
|
+
return {
|
|
39
|
+
dialect: "agent-plugins",
|
|
40
|
+
path,
|
|
41
|
+
identity: readIdentity(object, path, findings),
|
|
42
|
+
skillPaths: [],
|
|
43
|
+
mcpConfigs: [],
|
|
44
|
+
ignored: extensionComponents(object, path, findings),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=open.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"open.js","sourceRoot":"","sources":["../../src/dialects/open.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,aAAa,EAAmB,MAAM,iBAAiB,CAAC;AACjE,OAAO,EAAE,6BAA6B,EAAiB,MAAM,gBAAgB,CAAC;AAC9E,OAAO,EAAwB,mBAAmB,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAE3G,MAAM,YAAY,GAAwB,IAAI,GAAG,CAAC;IAChD,SAAS;IACT,MAAM;IACN,SAAS;IACT,aAAa;IACb,QAAQ;IACR,UAAU;IACV,YAAY;IACZ,SAAS;IACT,UAAU;IACV,YAAY;CACb,CAAC,CAAC;AAEH,MAAM,UAAU,gBAAgB,CAAC,MAAkB,EAAE,IAAY,EAAE,QAAkB;IACnF,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;IACjC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,QAAQ,CAAC,KAAK,CAAC,yBAAyB,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC;SAAM,IAAI,MAAM,KAAK,6BAA6B,EAAE,CAAC;QACpD,QAAQ,CAAC,KAAK,CAAC,6BAA6B,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACzF,CAAC;IACD,iBAAiB,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;IACxD,OAAO;QACL,OAAO,EAAE,eAAe;QACxB,IAAI;QACJ,QAAQ,EAAE,YAAY,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC;QAC9C,UAAU,EAAE,EAAE;QACd,UAAU,EAAE,EAAE;QACd,OAAO,EAAE,mBAAmB,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC;KACrD,CAAC;AACJ,CAAC"}
|
package/documents.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading one document through its cap, and the JSON shape checks every
|
|
3
|
+
* dialect reader repeats.
|
|
4
|
+
*
|
|
5
|
+
* `readText` is the only place the library calls `PluginFiles.read`: the
|
|
6
|
+
* declared size is checked against the document class's cap first, the
|
|
7
|
+
* returned length second, and an over-cap document becomes a
|
|
8
|
+
* `document-too-large` finding instead of a read. The JSON helpers turn a
|
|
9
|
+
* parse failure into a finding of the caller's kind and leave the value
|
|
10
|
+
* `unknown`, so each reader narrows fields with the `expect*` helpers and
|
|
11
|
+
* reports a wrong type with the field's name rather than trusting a cast.
|
|
12
|
+
*/
|
|
13
|
+
import { type PluginDocumentClass, type PluginFileIndex } from "./files.js";
|
|
14
|
+
import type { Findings } from "./messages.js";
|
|
15
|
+
import type { PluginErrorKind } from "./outcome.js";
|
|
16
|
+
/** The document's text, or `undefined` after a `document-too-large` finding. */
|
|
17
|
+
export declare function readText(index: PluginFileIndex, path: string, cls: PluginDocumentClass, findings: Findings): string | undefined;
|
|
18
|
+
/** The document's bytes, or `undefined` after a `document-too-large` finding. */
|
|
19
|
+
export declare function readBytes(index: PluginFileIndex, path: string, cls: PluginDocumentClass, findings: Findings): Uint8Array | undefined;
|
|
20
|
+
/** A parsed JSON object (non-null, non-array), or `undefined` after a finding of `kind`. */
|
|
21
|
+
export declare function parseJsonObject(text: string, path: string, kind: Extract<PluginErrorKind, "manifest-unreadable" | "mcp-config-unreadable">, findings: Findings): JsonObject | undefined;
|
|
22
|
+
export type JsonObject = Readonly<Record<string, unknown>>;
|
|
23
|
+
export declare function isJsonObject(value: unknown): value is JsonObject;
|
|
24
|
+
export declare function isStringArray(value: unknown): value is readonly string[];
|
|
25
|
+
export declare function isStringRecord(value: unknown): value is Readonly<Record<string, string>>;
|
|
26
|
+
/** A JSON value as a sentence can quote it: a string as itself, anything else serialised. */
|
|
27
|
+
export declare function describeValue(value: unknown): string;
|
|
28
|
+
/**
|
|
29
|
+
* The fields of `object`, in the document's own order. `Object.entries`
|
|
30
|
+
* reads own enumerable properties only, so a `__proto__` key in the JSON is
|
|
31
|
+
* just another entry here and never reaches a prototype.
|
|
32
|
+
*/
|
|
33
|
+
export declare function fields(object: JsonObject): readonly (readonly [string, unknown])[];
|
|
34
|
+
/** A string field or `undefined`; a present non-string reports `manifest-field-type`. */
|
|
35
|
+
export declare function optionalString(object: JsonObject, field: string, path: string, findings: Findings): string | undefined;
|
|
36
|
+
/** A string-array field or `undefined`; a present non-array-of-strings reports `manifest-field-type`. */
|
|
37
|
+
export declare function optionalStringArray(object: JsonObject, field: string, path: string, findings: Findings): readonly string[] | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* A field that may be one string or an array of strings (the vendor
|
|
40
|
+
* dialects' path fields), normalised to an array; `undefined` when absent.
|
|
41
|
+
*/
|
|
42
|
+
export declare function stringOrStringArray(object: JsonObject, field: string, path: string, findings: Findings): readonly string[] | undefined;
|
|
43
|
+
//# sourceMappingURL=documents.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documents.d.ts","sourceRoot":"","sources":["../src/documents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAsC,KAAK,mBAAmB,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAChH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,gFAAgF;AAChF,wBAAgB,QAAQ,CACtB,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,mBAAmB,EACxB,QAAQ,EAAE,QAAQ,GACjB,MAAM,GAAG,SAAS,CAGpB;AAED,iFAAiF;AACjF,wBAAgB,SAAS,CACvB,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,mBAAmB,EACxB,QAAQ,EAAE,QAAQ,GACjB,UAAU,GAAG,SAAS,CAgBxB;AAED,4FAA4F;AAC5F,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,OAAO,CAAC,eAAe,EAAE,qBAAqB,GAAG,uBAAuB,CAAC,EAC/E,QAAQ,EAAE,QAAQ,GACjB,UAAU,GAAG,SAAS,CAaxB;AAED,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAE3D,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAEhE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,MAAM,EAAE,CAExE;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAExF;AAED,6FAA6F;AAC7F,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEpD;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,CAElF;AAED,yFAAyF;AACzF,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS,CAQtH;AAED,yGAAyG;AACzG,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,QAAQ,GACjB,SAAS,MAAM,EAAE,GAAG,SAAS,CAQ/B;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,QAAQ,GACjB,SAAS,MAAM,EAAE,GAAG,SAAS,CAO/B"}
|
package/documents.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading one document through its cap, and the JSON shape checks every
|
|
3
|
+
* dialect reader repeats.
|
|
4
|
+
*
|
|
5
|
+
* `readText` is the only place the library calls `PluginFiles.read`: the
|
|
6
|
+
* declared size is checked against the document class's cap first, the
|
|
7
|
+
* returned length second, and an over-cap document becomes a
|
|
8
|
+
* `document-too-large` finding instead of a read. The JSON helpers turn a
|
|
9
|
+
* parse failure into a finding of the caller's kind and leave the value
|
|
10
|
+
* `unknown`, so each reader narrows fields with the `expect*` helpers and
|
|
11
|
+
* reports a wrong type with the field's name rather than trusting a cast.
|
|
12
|
+
*/
|
|
13
|
+
import { decodeUtf8, PLUGIN_DOCUMENT_LIMITS } from "./files.js";
|
|
14
|
+
/** The document's text, or `undefined` after a `document-too-large` finding. */
|
|
15
|
+
export function readText(index, path, cls, findings) {
|
|
16
|
+
const bytes = readBytes(index, path, cls, findings);
|
|
17
|
+
return bytes === undefined ? undefined : decodeUtf8(bytes);
|
|
18
|
+
}
|
|
19
|
+
/** The document's bytes, or `undefined` after a `document-too-large` finding. */
|
|
20
|
+
export function readBytes(index, path, cls, findings) {
|
|
21
|
+
const limit = PLUGIN_DOCUMENT_LIMITS[cls];
|
|
22
|
+
const entry = index.entry(path);
|
|
23
|
+
if (entry === undefined) {
|
|
24
|
+
throw new Error(`plugin file '${path}' is not listed`);
|
|
25
|
+
}
|
|
26
|
+
if (entry.size > limit) {
|
|
27
|
+
findings.error("document-too-large", { path, subject: String(entry.size), detail: String(limit) });
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
const bytes = index.files.read(path);
|
|
31
|
+
if (bytes.length > limit) {
|
|
32
|
+
findings.error("document-too-large", { path, subject: String(bytes.length), detail: String(limit) });
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
return bytes;
|
|
36
|
+
}
|
|
37
|
+
/** A parsed JSON object (non-null, non-array), or `undefined` after a finding of `kind`. */
|
|
38
|
+
export function parseJsonObject(text, path, kind, findings) {
|
|
39
|
+
let value;
|
|
40
|
+
try {
|
|
41
|
+
value = JSON.parse(text);
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
findings.error(kind, { path, detail: error instanceof Error ? error.message : String(error) });
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
if (!isJsonObject(value)) {
|
|
48
|
+
findings.error(kind, { path, detail: "the document is not a JSON object" });
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
return value;
|
|
52
|
+
}
|
|
53
|
+
export function isJsonObject(value) {
|
|
54
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
55
|
+
}
|
|
56
|
+
export function isStringArray(value) {
|
|
57
|
+
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
58
|
+
}
|
|
59
|
+
export function isStringRecord(value) {
|
|
60
|
+
return isJsonObject(value) && Object.values(value).every((item) => typeof item === "string");
|
|
61
|
+
}
|
|
62
|
+
/** A JSON value as a sentence can quote it: a string as itself, anything else serialised. */
|
|
63
|
+
export function describeValue(value) {
|
|
64
|
+
return typeof value === "string" ? value : JSON.stringify(value);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* The fields of `object`, in the document's own order. `Object.entries`
|
|
68
|
+
* reads own enumerable properties only, so a `__proto__` key in the JSON is
|
|
69
|
+
* just another entry here and never reaches a prototype.
|
|
70
|
+
*/
|
|
71
|
+
export function fields(object) {
|
|
72
|
+
return Object.entries(object);
|
|
73
|
+
}
|
|
74
|
+
/** A string field or `undefined`; a present non-string reports `manifest-field-type`. */
|
|
75
|
+
export function optionalString(object, field, path, findings) {
|
|
76
|
+
const value = object[field];
|
|
77
|
+
if (value === undefined)
|
|
78
|
+
return undefined;
|
|
79
|
+
if (typeof value !== "string") {
|
|
80
|
+
findings.error("manifest-field-type", { path, subject: field, detail: "a string" });
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
return value;
|
|
84
|
+
}
|
|
85
|
+
/** A string-array field or `undefined`; a present non-array-of-strings reports `manifest-field-type`. */
|
|
86
|
+
export function optionalStringArray(object, field, path, findings) {
|
|
87
|
+
const value = object[field];
|
|
88
|
+
if (value === undefined)
|
|
89
|
+
return undefined;
|
|
90
|
+
if (!isStringArray(value)) {
|
|
91
|
+
findings.error("manifest-field-type", { path, subject: field, detail: "an array of strings" });
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
return value;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* A field that may be one string or an array of strings (the vendor
|
|
98
|
+
* dialects' path fields), normalised to an array; `undefined` when absent.
|
|
99
|
+
*/
|
|
100
|
+
export function stringOrStringArray(object, field, path, findings) {
|
|
101
|
+
const value = object[field];
|
|
102
|
+
if (value === undefined)
|
|
103
|
+
return undefined;
|
|
104
|
+
if (typeof value === "string")
|
|
105
|
+
return [value];
|
|
106
|
+
if (isStringArray(value))
|
|
107
|
+
return value;
|
|
108
|
+
findings.error("manifest-field-type", { path, subject: field, detail: "a string or an array of strings" });
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=documents.js.map
|