@skillcdn/console 0.4.2 → 0.4.4
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 +4 -4
- package/dist/api.d.ts +3 -3
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +3 -3
- package/dist/api.js.map +1 -1
- package/dist/cli/cli.d.ts.map +1 -1
- package/dist/cli/cli.js +120 -33
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/format.d.ts +4 -2
- package/dist/cli/format.d.ts.map +1 -1
- package/dist/cli/format.js +38 -10
- package/dist/cli/format.js.map +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +22 -15
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/plugin-check.d.ts +10 -1
- package/dist/cli/plugin-check.d.ts.map +1 -1
- package/dist/cli/plugin-check.js +45 -4
- package/dist/cli/plugin-check.js.map +1 -1
- package/dist/cli/plugin-cli.d.ts +1 -1
- package/dist/cli/plugin-cli.d.ts.map +1 -1
- package/dist/cli/plugin-cli.js +80 -5
- package/dist/cli/plugin-cli.js.map +1 -1
- package/dist/cli/plugin-init.d.ts +19 -0
- package/dist/cli/plugin-init.d.ts.map +1 -1
- package/dist/cli/plugin-init.js +141 -3
- package/dist/cli/plugin-init.js.map +1 -1
- package/dist/client.d.ts +7 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +18 -5
- package/dist/client.js.map +1 -1
- package/dist/compat.js +1 -1
- package/dist/components/board.d.ts +8 -0
- package/dist/components/board.d.ts.map +1 -1
- package/dist/components/board.js +3 -3
- package/dist/components/board.js.map +1 -1
- package/dist/components/comments.d.ts.map +1 -1
- package/dist/components/comments.js +1 -1
- package/dist/components/comments.js.map +1 -1
- package/dist/components/decision-form.d.ts +8 -1
- package/dist/components/decision-form.d.ts.map +1 -1
- package/dist/components/decision-form.js +57 -7
- package/dist/components/decision-form.js.map +1 -1
- package/dist/components/decision-list.d.ts +9 -1
- package/dist/components/decision-list.d.ts.map +1 -1
- package/dist/components/decision-list.js +53 -7
- package/dist/components/decision-list.js.map +1 -1
- package/dist/components/event-feed.d.ts.map +1 -1
- package/dist/components/event-feed.js +7 -1
- package/dist/components/event-feed.js.map +1 -1
- package/dist/components/goals.d.ts.map +1 -1
- package/dist/components/goals.js +2 -2
- package/dist/components/goals.js.map +1 -1
- package/dist/components/home.d.ts +35 -0
- package/dist/components/home.d.ts.map +1 -0
- package/dist/components/home.js +326 -0
- package/dist/components/home.js.map +1 -0
- package/dist/components/my-decisions.d.ts +2 -0
- package/dist/components/my-decisions.d.ts.map +1 -1
- package/dist/components/my-decisions.js +2 -2
- package/dist/components/my-decisions.js.map +1 -1
- package/dist/components/pack-connect.d.ts.map +1 -1
- package/dist/components/pack-connect.js +5 -4
- package/dist/components/pack-connect.js.map +1 -1
- package/dist/components/people.d.ts +2 -0
- package/dist/components/people.d.ts.map +1 -1
- package/dist/components/people.js +15 -2
- package/dist/components/people.js.map +1 -1
- package/dist/components/plugin-frame.d.ts +3 -12
- package/dist/components/plugin-frame.d.ts.map +1 -1
- package/dist/components/plugin-frame.js +53 -20
- package/dist/components/plugin-frame.js.map +1 -1
- package/dist/components/plugin-settings.d.ts.map +1 -1
- package/dist/components/plugin-settings.js +151 -26
- package/dist/components/plugin-settings.js.map +1 -1
- package/dist/components/projects.d.ts +0 -8
- package/dist/components/projects.d.ts.map +1 -1
- package/dist/components/projects.js +1 -13
- package/dist/components/projects.js.map +1 -1
- package/dist/components/task-view.d.ts +2 -1
- package/dist/components/task-view.d.ts.map +1 -1
- package/dist/components/task-view.js +2 -1
- package/dist/components/task-view.js.map +1 -1
- package/dist/components/ui.d.ts.map +1 -1
- package/dist/components/ui.js +5 -2
- package/dist/components/ui.js.map +1 -1
- package/dist/connect-page.d.ts.map +1 -1
- package/dist/connect-page.js +5 -6
- package/dist/connect-page.js.map +1 -1
- package/dist/console.css +764 -192
- package/dist/console.d.ts +10 -3
- package/dist/console.d.ts.map +1 -1
- package/dist/console.js +49 -28
- package/dist/console.js.map +1 -1
- package/dist/data.d.ts +6 -3
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +31 -7
- package/dist/data.js.map +1 -1
- package/dist/docs-page.d.ts.map +1 -1
- package/dist/docs-page.js +6 -5
- package/dist/docs-page.js.map +1 -1
- package/dist/home-tiles.d.ts +92 -0
- package/dist/home-tiles.d.ts.map +1 -0
- package/dist/home-tiles.js +294 -0
- package/dist/home-tiles.js.map +1 -0
- package/dist/i18n/en.d.ts +180 -0
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +181 -1
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/index.d.ts +4 -2
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/i18n/index.js +10 -11
- package/dist/i18n/index.js.map +1 -1
- package/dist/i18n/ko.d.ts.map +1 -1
- package/dist/i18n/ko.js +176 -3
- package/dist/i18n/ko.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/limits.d.ts +8 -0
- package/dist/limits.d.ts.map +1 -1
- package/dist/limits.js +8 -0
- package/dist/limits.js.map +1 -1
- package/dist/plugin/bridge.d.ts +44 -3
- package/dist/plugin/bridge.d.ts.map +1 -1
- package/dist/plugin/bridge.js +26 -0
- package/dist/plugin/bridge.js.map +1 -1
- package/dist/plugin/capabilities.d.ts +7 -1
- package/dist/plugin/capabilities.d.ts.map +1 -1
- package/dist/plugin/capabilities.js +14 -1
- package/dist/plugin/capabilities.js.map +1 -1
- package/dist/plugin/context.d.ts +24 -1
- package/dist/plugin/context.d.ts.map +1 -1
- package/dist/plugin/define.d.ts +1 -0
- package/dist/plugin/define.d.ts.map +1 -1
- package/dist/plugin/define.js +1 -1
- package/dist/plugin/define.js.map +1 -1
- package/dist/plugin/limits.d.ts +5 -2
- package/dist/plugin/limits.d.ts.map +1 -1
- package/dist/plugin/limits.js +5 -2
- package/dist/plugin/limits.js.map +1 -1
- package/dist/plugin/manifest.d.ts +83 -6
- package/dist/plugin/manifest.d.ts.map +1 -1
- package/dist/plugin/manifest.js +111 -7
- package/dist/plugin/manifest.js.map +1 -1
- package/dist/plugin/rest-schemas.d.ts +76 -0
- package/dist/plugin/rest-schemas.d.ts.map +1 -1
- package/dist/plugin/rest-schemas.js +23 -2
- package/dist/plugin/rest-schemas.js.map +1 -1
- package/dist/plugin/sandbox.d.ts +4 -3
- package/dist/plugin/sandbox.d.ts.map +1 -1
- package/dist/plugin/sandbox.js +33 -6
- package/dist/plugin/sandbox.js.map +1 -1
- package/dist/plugin/semver.d.ts +26 -0
- package/dist/plugin/semver.d.ts.map +1 -0
- package/dist/plugin/semver.js +76 -0
- package/dist/plugin/semver.js.map +1 -0
- package/dist/plugin/testing.d.ts.map +1 -1
- package/dist/plugin/testing.js +2 -1
- package/dist/plugin/testing.js.map +1 -1
- package/dist/plugin/web.d.ts +10 -1
- package/dist/plugin/web.d.ts.map +1 -1
- package/dist/plugin/web.js +34 -0
- package/dist/plugin/web.js.map +1 -1
- package/dist/plugin.d.ts +3 -2
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +3 -2
- package/dist/plugin.js.map +1 -1
- package/dist/rules.d.ts +2 -2
- package/dist/rules.js +3 -3
- package/dist/schemas.d.ts +574 -11
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +154 -25
- package/dist/schemas.js.map +1 -1
- package/dist/use-action.d.ts +8 -2
- package/dist/use-action.d.ts.map +1 -1
- package/dist/use-action.js +13 -6
- package/dist/use-action.js.map +1 -1
- package/dist/vocabulary.d.ts +3 -1
- package/dist/vocabulary.d.ts.map +1 -1
- package/dist/vocabulary.js +3 -0
- package/dist/vocabulary.js.map +1 -1
- package/docs/specs/cli.md +4 -3
- package/docs/specs/plugins.md +49 -35
- package/docs/specs/rest.md +20 -18
- package/package.json +7 -7
- package/skills/building-a-plugin/SKILL.md +10 -9
- package/skills/planning-the-board/references/setting-up.md +2 -1
- package/skills/working-the-board/SKILL.md +3 -3
- package/src/api.ts +10 -0
- package/src/cli/cli.ts +162 -39
- package/src/cli/format.ts +54 -10
- package/src/cli/help.ts +23 -14
- package/src/cli/plugin-check.ts +68 -2
- package/src/cli/plugin-cli.ts +104 -6
- package/src/cli/plugin-init.ts +178 -3
- package/src/client.ts +36 -9
- package/src/compat.ts +1 -1
- package/src/components/board.tsx +3 -3
- package/src/components/comments.tsx +1 -0
- package/src/components/decision-form.tsx +166 -29
- package/src/components/decision-list.tsx +116 -15
- package/src/components/event-feed.tsx +7 -1
- package/src/components/goals.tsx +4 -1
- package/src/components/home.tsx +615 -0
- package/src/components/my-decisions.tsx +4 -1
- package/src/components/pack-connect.tsx +5 -4
- package/src/components/people.tsx +136 -54
- package/src/components/plugin-frame.tsx +62 -63
- package/src/components/plugin-settings.tsx +428 -87
- package/src/components/projects.tsx +0 -55
- package/src/components/task-view.tsx +9 -1
- package/src/components/ui.tsx +6 -2
- package/src/connect-page.tsx +5 -6
- package/src/console.tsx +98 -42
- package/src/data.ts +41 -11
- package/src/docs-page.tsx +6 -5
- package/src/home-tiles.ts +438 -0
- package/src/i18n/en.ts +185 -0
- package/src/i18n/index.ts +17 -14
- package/src/i18n/ko.ts +181 -3
- package/src/index.ts +7 -5
- package/src/limits.ts +8 -0
- package/src/plugin/bridge.ts +77 -1
- package/src/plugin/capabilities.ts +17 -1
- package/src/plugin/context.ts +24 -2
- package/src/plugin/define.ts +4 -1
- package/src/plugin/limits.ts +5 -2
- package/src/plugin/manifest.ts +154 -10
- package/src/plugin/rest-schemas.ts +27 -1
- package/src/plugin/sandbox.ts +36 -8
- package/src/plugin/semver.ts +89 -0
- package/src/plugin/testing.ts +2 -1
- package/src/plugin/web.ts +49 -0
- package/src/plugin.ts +18 -0
- package/src/rules.ts +3 -3
- package/src/schemas.ts +190 -28
- package/src/styles/console.css +764 -192
- package/src/use-action.ts +16 -7
- package/src/vocabulary.ts +4 -0
- package/template/plugin/console-plugin.json +3 -1
- package/template/plugin/package.json +3 -3
package/src/plugin/sandbox.ts
CHANGED
|
@@ -13,6 +13,15 @@ export const FORBIDDEN_BUILTINS: readonly string[] = [
|
|
|
13
13
|
"dgram",
|
|
14
14
|
"dns",
|
|
15
15
|
"dns/promises",
|
|
16
|
+
// The same network, under the names Node keeps for compatibility.
|
|
17
|
+
"_http_agent",
|
|
18
|
+
"_http_client",
|
|
19
|
+
"_http_common",
|
|
20
|
+
"_http_incoming",
|
|
21
|
+
"_http_outgoing",
|
|
22
|
+
"_http_server",
|
|
23
|
+
"_tls_common",
|
|
24
|
+
"_tls_wrap",
|
|
16
25
|
"child_process",
|
|
17
26
|
"cluster",
|
|
18
27
|
"worker_threads",
|
|
@@ -67,6 +76,15 @@ export interface HardenedThread {
|
|
|
67
76
|
readonly removed: readonly string[];
|
|
68
77
|
}
|
|
69
78
|
|
|
79
|
+
/** What a plugin is told of a built-in it may not have, by whichever way it asked. */
|
|
80
|
+
function refusedBuiltin(specifier: string): Error {
|
|
81
|
+
const error = new Error(
|
|
82
|
+
`the host refuses ${specifier}: a plugin reaches the console through ctx alone`,
|
|
83
|
+
);
|
|
84
|
+
(error as { code?: string }).code = "ERR_PLUGIN_FORBIDDEN_BUILTIN";
|
|
85
|
+
return error;
|
|
86
|
+
}
|
|
87
|
+
|
|
70
88
|
/** The module hook: refuses the forbidden built-ins and lets everything else resolve as it would. */
|
|
71
89
|
export function forbiddingResolve<C, R>(
|
|
72
90
|
specifier: string,
|
|
@@ -74,19 +92,16 @@ export function forbiddingResolve<C, R>(
|
|
|
74
92
|
nextResolve: (specifier: string, context: C) => R,
|
|
75
93
|
): R {
|
|
76
94
|
if (isForbiddenBuiltin(specifier)) {
|
|
77
|
-
|
|
78
|
-
`the host refuses ${specifier}: a plugin reaches the console through ctx alone`,
|
|
79
|
-
);
|
|
80
|
-
(error as { code?: string }).code = "ERR_PLUGIN_FORBIDDEN_BUILTIN";
|
|
81
|
-
throw error;
|
|
95
|
+
throw refusedBuiltin(specifier);
|
|
82
96
|
}
|
|
83
97
|
return nextResolve(specifier, context);
|
|
84
98
|
}
|
|
85
99
|
|
|
86
100
|
/**
|
|
87
|
-
* Hardens the current thread: refuses the forbidden built-ins through the module hooks
|
|
88
|
-
* the globals, empties the environment,
|
|
89
|
-
* before importing plugin code; it reaches
|
|
101
|
+
* Hardens the current thread: refuses the forbidden built-ins through the module hooks and through
|
|
102
|
+
* `process.getBuiltinModule`, which goes round them, removes the globals, empties the environment,
|
|
103
|
+
* and blocks `process.binding`. Call it in a worker thread before importing plugin code; it reaches
|
|
104
|
+
* nothing outside that thread.
|
|
90
105
|
*/
|
|
91
106
|
export function hardenThread(
|
|
92
107
|
moduleApi: Pick<typeof import("node:module"), "registerHooks">,
|
|
@@ -112,6 +127,19 @@ export function hardenThread(
|
|
|
112
127
|
for (const name of ["binding", "_linkedBinding", "dlopen"]) {
|
|
113
128
|
Object.defineProperty(proc, name, { value: refuse, writable: false, configurable: false });
|
|
114
129
|
}
|
|
130
|
+
const getBuiltinModule = proc.getBuiltinModule;
|
|
131
|
+
if (typeof getBuiltinModule === "function") {
|
|
132
|
+
Object.defineProperty(proc, "getBuiltinModule", {
|
|
133
|
+
value: (specifier: string): unknown => {
|
|
134
|
+
if (isForbiddenBuiltin(specifier)) {
|
|
135
|
+
throw refusedBuiltin(specifier);
|
|
136
|
+
}
|
|
137
|
+
return getBuiltinModule.call(proc, specifier);
|
|
138
|
+
},
|
|
139
|
+
writable: false,
|
|
140
|
+
configurable: false,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
115
143
|
const env = proc.env as Record<string, unknown> | undefined;
|
|
116
144
|
if (env !== undefined) {
|
|
117
145
|
for (const key of Object.keys(env)) {
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// Versions and ranges as a manifest spells them (docs/specs/plugins.md, "The manifest"): the
|
|
2
|
+
// range of another plugin's version in `requires`, and the range of the console's version in
|
|
3
|
+
// `console`. Read loosely, as npm spells the common ones, with no library: a plugin declares
|
|
4
|
+
// `>=0.4.3 <0.6`, and the console, the authoring command and the tests compare the same way.
|
|
5
|
+
|
|
6
|
+
export type Triple = readonly [number, number, number];
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A version read loosely: `0.4.3`, `v0.4.3`, `0.6` (as `0.6.0`), `1` (as `1.0.0`), a prerelease or
|
|
10
|
+
* a build after the numbers ignored; nothing for anything else.
|
|
11
|
+
*/
|
|
12
|
+
export function parseLooseVersion(text: string): Triple | undefined {
|
|
13
|
+
const match = /^v?(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:[-+].*)?$/.exec(text.trim());
|
|
14
|
+
return match === null
|
|
15
|
+
? undefined
|
|
16
|
+
: [Number(match[1]), Number(match[2] ?? "0"), Number(match[3] ?? "0")];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function compareTriples(a: Triple, b: Triple): number {
|
|
20
|
+
return a[0] - b[0] || a[1] - b[1] || a[2] - b[2];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Whether a version is within a range as npm spells the common ones: `*`, exact, `^`, `~`, `>=`,
|
|
25
|
+
* `>`, `<=`, `<`, several with spaces between (all must hold) and alternatives with `||` between
|
|
26
|
+
* (one must hold). A partial version in the range is read as `.0` filled in: `<0.6` is `<0.6.0`.
|
|
27
|
+
*/
|
|
28
|
+
export function satisfiesRange(version: string, range: string): boolean {
|
|
29
|
+
const have = parseLooseVersion(version);
|
|
30
|
+
const trimmed = range.trim();
|
|
31
|
+
if (trimmed === "*" || trimmed === "" || trimmed === "x" || trimmed === "latest") {
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
if (have === undefined) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
return trimmed.split(/\s*\|\|\s*/).some((alternative) =>
|
|
38
|
+
alternative.split(/\s+/).every((part) => {
|
|
39
|
+
const operator = /^(\^|~|>=|<=|>|<|=)?(.*)$/.exec(part);
|
|
40
|
+
const wanted = parseLooseVersion(operator?.[2] ?? "");
|
|
41
|
+
if (wanted === undefined) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
switch (operator?.[1]) {
|
|
45
|
+
case "^":
|
|
46
|
+
return (
|
|
47
|
+
compareTriples(have, wanted) >= 0 &&
|
|
48
|
+
(wanted[0] === 0 ? have[0] === 0 && have[1] === wanted[1] : have[0] === wanted[0])
|
|
49
|
+
);
|
|
50
|
+
case "~":
|
|
51
|
+
return (
|
|
52
|
+
compareTriples(have, wanted) >= 0 && have[0] === wanted[0] && have[1] === wanted[1]
|
|
53
|
+
);
|
|
54
|
+
case ">=":
|
|
55
|
+
return compareTriples(have, wanted) >= 0;
|
|
56
|
+
case ">":
|
|
57
|
+
return compareTriples(have, wanted) > 0;
|
|
58
|
+
case "<=":
|
|
59
|
+
return compareTriples(have, wanted) <= 0;
|
|
60
|
+
case "<":
|
|
61
|
+
return compareTriples(have, wanted) < 0;
|
|
62
|
+
default:
|
|
63
|
+
return compareTriples(have, wanted) === 0;
|
|
64
|
+
}
|
|
65
|
+
}),
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* The version a dependency spells, read loosely: `^0.4.3`, `~0.4.3`, `>=0.4.3` and `0.4.3` are
|
|
71
|
+
* all `0.4.3`; `workspace:*`, `*`, `latest` and a tag name none.
|
|
72
|
+
*/
|
|
73
|
+
export function versionOfDependency(spec: string): Triple | undefined {
|
|
74
|
+
return parseLooseVersion(spec.trim().replace(/^(?:\^|~|>=|=)\s*/, ""));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function formatTriple(version: Triple): string {
|
|
78
|
+
return `${version[0]}.${version[1]}.${version[2]}`;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* The range of consoles a plugin written against `version` runs on, as `console-plugin init`
|
|
83
|
+
* writes it: from that version on, within its line, since the plugin API moves with the console's
|
|
84
|
+
* line before 1.0 (`>=0.4.3 <0.5.0`), and within its major from 1.0 (`>=1.2.0 <2.0.0`).
|
|
85
|
+
*/
|
|
86
|
+
export function lineRangeFrom(version: Triple): string {
|
|
87
|
+
const below: Triple = version[0] === 0 ? [0, version[1] + 1, 0] : [version[0] + 1, 0, 0];
|
|
88
|
+
return `>=${formatTriple(version)} <${formatTriple(below)}`;
|
|
89
|
+
}
|
package/src/plugin/testing.ts
CHANGED
|
@@ -519,7 +519,7 @@ function refusingConsole(given: TestConsoleOptions | undefined): PluginConsole {
|
|
|
519
519
|
return {
|
|
520
520
|
workspace:
|
|
521
521
|
given?.workspace ?? (async () => forbidden("console.workspace", "console.workspace")),
|
|
522
|
-
people: fill("people", ["list", "get"], given?.people),
|
|
522
|
+
people: fill("people", ["list", "get", "granted"], given?.people),
|
|
523
523
|
projects: fill("projects", ["list", "get", "members"], given?.projects),
|
|
524
524
|
tasks: fill("tasks", ["list", "get", "create", "update", "comment"], given?.tasks),
|
|
525
525
|
decisions: fill("decisions", ["list", "get", "ask"], given?.decisions),
|
|
@@ -538,6 +538,7 @@ function build(store: Store, options: TestContextOptions, caller: PluginCaller):
|
|
|
538
538
|
version: "0.0.0",
|
|
539
539
|
dataVersion: 1,
|
|
540
540
|
settings: {},
|
|
541
|
+
capabilities: [],
|
|
541
542
|
board: null,
|
|
542
543
|
projects: "all",
|
|
543
544
|
...options.plugin,
|
package/src/plugin/web.ts
CHANGED
|
@@ -11,11 +11,13 @@ import {
|
|
|
11
11
|
type BridgeFile,
|
|
12
12
|
type BridgeInit,
|
|
13
13
|
type BridgeMethod,
|
|
14
|
+
type BridgePicture,
|
|
14
15
|
type BridgeToPage,
|
|
15
16
|
isBridgePath,
|
|
16
17
|
isBridgeToFrame,
|
|
17
18
|
MAX_BRIDGE_TITLE_LENGTH,
|
|
18
19
|
PLUGIN_BRIDGE_VERSION,
|
|
20
|
+
type PluginWidgetSizeName,
|
|
19
21
|
} from "./bridge.js";
|
|
20
22
|
import type { PluginRecord, RecordPage, RecordVersion } from "./context.js";
|
|
21
23
|
|
|
@@ -111,6 +113,13 @@ export interface PluginFrame {
|
|
|
111
113
|
type: string,
|
|
112
114
|
): Promise<{ readonly handle: string }>;
|
|
113
115
|
};
|
|
116
|
+
readonly people: {
|
|
117
|
+
/**
|
|
118
|
+
* An address to put in an image, of the person of that id (ADR-0063), with `people:read`; or
|
|
119
|
+
* `null` for a person with no picture to show. Kept for the life of the frame.
|
|
120
|
+
*/
|
|
121
|
+
picture(id: string): Promise<string | null>;
|
|
122
|
+
};
|
|
114
123
|
/** The console's page follows a path of the console's in place; a URL is refused. */
|
|
115
124
|
navigate(path: string): void;
|
|
116
125
|
/** The console's page downloads a file of this plugin. */
|
|
@@ -125,12 +134,21 @@ export interface PluginFrame {
|
|
|
125
134
|
onTheme(handler: (theme: Readonly<Record<string, string>>) => void): () => void;
|
|
126
135
|
/** The console navigated within this page's address. */
|
|
127
136
|
onPath(handler: (path: string) => void): () => void;
|
|
137
|
+
/** The person gave the widget another size (ADR-0059); `context.size` was the first. */
|
|
138
|
+
onSize(handler: (size: PluginWidgetSizeName) => void): () => void;
|
|
128
139
|
/** Stops listening to the console's page. */
|
|
129
140
|
close(): void;
|
|
130
141
|
}
|
|
131
142
|
|
|
132
143
|
const DEFAULT_CONNECT_MS = 10_000;
|
|
133
144
|
|
|
145
|
+
/** What a page is told for a person with no picture to show, which is no failure of the page's. */
|
|
146
|
+
const NO_PICTURE: ReadonlySet<string> = new Set([
|
|
147
|
+
"plugin.not_found",
|
|
148
|
+
"picture.refused",
|
|
149
|
+
"picture.unavailable",
|
|
150
|
+
]);
|
|
151
|
+
|
|
134
152
|
function globalWindow(): FrameWindow {
|
|
135
153
|
const candidate = (globalThis as { window?: FrameWindow }).window;
|
|
136
154
|
if (candidate === undefined) {
|
|
@@ -219,7 +237,9 @@ export function connect(options: ConnectOptions = {}): Promise<PluginFrame> {
|
|
|
219
237
|
const eventHandlers = new Set<(kind: BridgeEventKind, data: unknown) => void>();
|
|
220
238
|
const themeHandlers = new Set<(theme: Readonly<Record<string, string>>) => void>();
|
|
221
239
|
const pathHandlers = new Set<(path: string) => void>();
|
|
240
|
+
const sizeHandlers = new Set<(size: PluginWidgetSizeName) => void>();
|
|
222
241
|
const subscribed = new Set<BridgeEventKind>();
|
|
242
|
+
const pictures = new Map<string, Promise<string | null>>();
|
|
223
243
|
let counter = 0;
|
|
224
244
|
let stopHeight: (() => void) | undefined;
|
|
225
245
|
|
|
@@ -301,6 +321,26 @@ export function connect(options: ConnectOptions = {}): Promise<PluginFrame> {
|
|
|
301
321
|
}>;
|
|
302
322
|
},
|
|
303
323
|
},
|
|
324
|
+
people: {
|
|
325
|
+
picture: (id) => {
|
|
326
|
+
const kept = pictures.get(id);
|
|
327
|
+
if (kept !== undefined) {
|
|
328
|
+
return kept;
|
|
329
|
+
}
|
|
330
|
+
const asked = (call("people.picture", { id }) as Promise<BridgePicture>).then(
|
|
331
|
+
({ type, bytes }) => URL.createObjectURL(new Blob([bytes], { type })),
|
|
332
|
+
(error: unknown) => {
|
|
333
|
+
if (error instanceof PluginBridgeError && NO_PICTURE.has(error.code)) {
|
|
334
|
+
return null;
|
|
335
|
+
}
|
|
336
|
+
pictures.delete(id);
|
|
337
|
+
throw error;
|
|
338
|
+
},
|
|
339
|
+
);
|
|
340
|
+
pictures.set(id, asked);
|
|
341
|
+
return asked;
|
|
342
|
+
},
|
|
343
|
+
},
|
|
304
344
|
navigate: (path) => {
|
|
305
345
|
if (!isBridgePath(path)) {
|
|
306
346
|
throw new PluginBridgeError({
|
|
@@ -338,6 +378,10 @@ export function connect(options: ConnectOptions = {}): Promise<PluginFrame> {
|
|
|
338
378
|
pathHandlers.add(handler);
|
|
339
379
|
return () => pathHandlers.delete(handler);
|
|
340
380
|
},
|
|
381
|
+
onSize: (handler) => {
|
|
382
|
+
sizeHandlers.add(handler);
|
|
383
|
+
return () => sizeHandlers.delete(handler);
|
|
384
|
+
},
|
|
341
385
|
close: () => {
|
|
342
386
|
win.removeEventListener("message", listener);
|
|
343
387
|
stopHeight?.();
|
|
@@ -393,6 +437,11 @@ export function connect(options: ConnectOptions = {}): Promise<PluginFrame> {
|
|
|
393
437
|
handler(message.path);
|
|
394
438
|
}
|
|
395
439
|
return;
|
|
440
|
+
case "size":
|
|
441
|
+
for (const handler of sizeHandlers) {
|
|
442
|
+
handler(message.size);
|
|
443
|
+
}
|
|
444
|
+
return;
|
|
396
445
|
default:
|
|
397
446
|
return;
|
|
398
447
|
}
|
package/src/plugin.ts
CHANGED
|
@@ -29,6 +29,7 @@ export {
|
|
|
29
29
|
type CapabilityWords,
|
|
30
30
|
capabilityWords,
|
|
31
31
|
isPluginCapability,
|
|
32
|
+
OUTBOUND_WEBRTC,
|
|
32
33
|
outboundAllows,
|
|
33
34
|
PLUGIN_CAPABILITIES,
|
|
34
35
|
PLUGIN_CAPABILITY_PREFIXES,
|
|
@@ -72,8 +73,10 @@ export { PluginDefinitionError } from "./plugin/definition-error.js";
|
|
|
72
73
|
export * from "./plugin/limits.js";
|
|
73
74
|
export {
|
|
74
75
|
CURRENT_PLUGIN_API,
|
|
76
|
+
capabilitiesAsked,
|
|
75
77
|
isPluginKey,
|
|
76
78
|
type Localized,
|
|
79
|
+
legacyWidgetSize,
|
|
77
80
|
localizedText,
|
|
78
81
|
type ManifestParse,
|
|
79
82
|
PLUGIN_API_MAJORS,
|
|
@@ -83,6 +86,8 @@ export {
|
|
|
83
86
|
PLUGIN_PAGE_LEVELS,
|
|
84
87
|
PLUGIN_SETTING_TYPES,
|
|
85
88
|
PLUGIN_WIDGET_PLACES,
|
|
89
|
+
PLUGIN_WIDGET_SIZE_CELLS,
|
|
90
|
+
PLUGIN_WIDGET_SIZE_NAMES,
|
|
86
91
|
PLUGIN_WIDGET_SIZES,
|
|
87
92
|
type PluginBoard,
|
|
88
93
|
type PluginBoardNeeds,
|
|
@@ -93,16 +98,20 @@ export {
|
|
|
93
98
|
type PluginPageLevel,
|
|
94
99
|
type PluginRole,
|
|
95
100
|
type PluginSetting,
|
|
101
|
+
type PluginSettingGroup,
|
|
96
102
|
type PluginSettingType,
|
|
97
103
|
type PluginWidget,
|
|
98
104
|
type PluginWidgetPlace,
|
|
99
105
|
type PluginWidgetSize,
|
|
106
|
+
type PluginWidgetSizeName,
|
|
100
107
|
parsePluginManifest,
|
|
101
108
|
pluginManifestSchema,
|
|
102
109
|
RESERVED_COMMAND_NAMES,
|
|
103
110
|
RESERVED_PAGE_KEYS,
|
|
104
111
|
RESERVED_PLUGIN_KEYS,
|
|
105
112
|
SETTING_KEY_PATTERN,
|
|
113
|
+
TIME_OF_DAY,
|
|
114
|
+
widgetSizesOf,
|
|
106
115
|
} from "./plugin/manifest.js";
|
|
107
116
|
export {
|
|
108
117
|
isPluginError,
|
|
@@ -124,3 +133,12 @@ export {
|
|
|
124
133
|
REMOVED_GLOBALS,
|
|
125
134
|
removedGlobalsIn,
|
|
126
135
|
} from "./plugin/sandbox.js";
|
|
136
|
+
export {
|
|
137
|
+
compareTriples,
|
|
138
|
+
formatTriple,
|
|
139
|
+
lineRangeFrom,
|
|
140
|
+
parseLooseVersion,
|
|
141
|
+
satisfiesRange,
|
|
142
|
+
type Triple,
|
|
143
|
+
versionOfDependency,
|
|
144
|
+
} from "./plugin/semver.js";
|
package/src/rules.ts
CHANGED
|
@@ -83,7 +83,7 @@ export function isReferenceRules(body: string): boolean {
|
|
|
83
83
|
/** What stands in the rules for the language of the person the agent works for. */
|
|
84
84
|
export const RULES_LANGUAGE_PLACEHOLDER = "{language}";
|
|
85
85
|
|
|
86
|
-
/** What the rules say
|
|
86
|
+
/** What the rules say for a person with no language yet: the task's, as the people of the board wrote it. */
|
|
87
87
|
const TASKS_LANGUAGE = "the language the task is written in";
|
|
88
88
|
|
|
89
89
|
/** The name of a language in English, from its tag (`ko` is Korean); the tag itself when it is not one. */
|
|
@@ -101,8 +101,8 @@ export function languageNameOf(tag: string): string {
|
|
|
101
101
|
|
|
102
102
|
/**
|
|
103
103
|
* The rules as they read for a person: `{language}` filled with the name of the language they
|
|
104
|
-
*
|
|
105
|
-
*
|
|
104
|
+
* read in (ADR-0065), or with the task's language while they have none. The command fills them
|
|
105
|
+
* for the person whose token it holds; the pages for whoever reads them.
|
|
106
106
|
*/
|
|
107
107
|
export function fillRules(body: string, language: string | null | undefined): string {
|
|
108
108
|
const name = language == null ? TASKS_LANGUAGE : languageNameOf(language);
|