initiative-plugin-sdk 2.0.0
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 +21 -0
- package/README.md +656 -0
- package/dist/build.d.ts +52 -0
- package/dist/build.js +229 -0
- package/dist/build.js.map +1 -0
- package/dist/cli.d.ts +24 -0
- package/dist/cli.js +160 -0
- package/dist/cli.js.map +1 -0
- package/dist/client.d.ts +288 -0
- package/dist/client.js +539 -0
- package/dist/client.js.map +1 -0
- package/dist/contract.d.ts +1247 -0
- package/dist/contract.js +167 -0
- package/dist/contract.js.map +1 -0
- package/dist/define.d.ts +336 -0
- package/dist/define.js +120 -0
- package/dist/define.js.map +1 -0
- package/dist/dev.d.ts +28 -0
- package/dist/dev.js +147 -0
- package/dist/dev.js.map +1 -0
- package/dist/expression.d.ts +28 -0
- package/dist/expression.js +67 -0
- package/dist/expression.js.map +1 -0
- package/dist/init.d.ts +14 -0
- package/dist/init.js +52 -0
- package/dist/init.js.map +1 -0
- package/dist/keys.d.ts +85 -0
- package/dist/keys.js +109 -0
- package/dist/keys.js.map +1 -0
- package/dist/manifest.d.ts +8 -0
- package/dist/manifest.js +8 -0
- package/dist/manifest.js.map +1 -0
- package/dist/pack.d.ts +35 -0
- package/dist/pack.js +84 -0
- package/dist/pack.js.map +1 -0
- package/dist/plugin-api.generated.d.ts +4263 -0
- package/dist/plugin-api.generated.js +1019 -0
- package/dist/plugin-api.generated.js.map +1 -0
- package/dist/server.d.ts +75 -0
- package/dist/server.js +408 -0
- package/dist/server.js.map +1 -0
- package/dist/testing.d.ts +116 -0
- package/dist/testing.js +386 -0
- package/dist/testing.js.map +1 -0
- package/dist/tokens.d.ts +161 -0
- package/dist/tokens.js +215 -0
- package/dist/tokens.js.map +1 -0
- package/dist/validate.d.ts +86 -0
- package/dist/validate.js +997 -0
- package/dist/validate.js.map +1 -0
- package/dist/widget.d.ts +235 -0
- package/dist/widget.js +26 -0
- package/dist/widget.js.map +1 -0
- package/examples/minimal/README.md +48 -0
- package/examples/minimal/assets/avatar.png +0 -0
- package/examples/minimal/package.json +22 -0
- package/examples/minimal/src/plugin.ts +77 -0
- package/examples/minimal/src/widgets/open-issues.ts +11 -0
- package/examples/minimal/test/fixtures/issues-statistics.json +9 -0
- package/examples/minimal/test/issue-counts.test.ts +48 -0
- package/examples/minimal/tsconfig.json +14 -0
- package/manifest.contract.json +1886 -0
- package/package.json +92 -0
- package/schemas/plugin-manifest.json +1747 -0
package/dist/contract.js
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The plug-in contract, as TypeScript.
|
|
3
|
+
*
|
|
4
|
+
* GENERATED from `manifest.contract.json` by `scripts/generate.mjs`. Do not
|
|
5
|
+
* edit it: change the contract and run `npm run generate`.
|
|
6
|
+
*
|
|
7
|
+
* These are the enums, caps and character sets the bundled JSON Schema is built
|
|
8
|
+
* from, and the shape of every object it defines, so this package's types
|
|
9
|
+
* cannot describe a manifest the schema refuses, nor miss a term it allows.
|
|
10
|
+
*/
|
|
11
|
+
export const FEATURES = ["dashboards", "embeds", "endpoints", "widgets"];
|
|
12
|
+
export const PROTOCOLS = [1];
|
|
13
|
+
export const CONNECTION_SCOPES = ["interactive", "static"];
|
|
14
|
+
export const FLOW_TYPES = ["oauth2"];
|
|
15
|
+
export const TOKEN_TYPES = ["jwt_bearer"];
|
|
16
|
+
export const REVOKE_METHODS = ["github_grant", "hook", "rfc7009"];
|
|
17
|
+
export const JWT_ALGORITHMS = ["ES256", "RS256"];
|
|
18
|
+
export const FIELD_TYPES = ["bool", "int", "secret", "select", "string", "url"];
|
|
19
|
+
export const VENDOR_FIELD_TYPES = ["secret", "string", "url"];
|
|
20
|
+
export const GITHUB_PERMISSION_LEVELS = ["read", "write"];
|
|
21
|
+
export const GITHUB_APP_VALUES = ["client_id", "client_secret", "id", "pem", "slug", "webhook_secret"];
|
|
22
|
+
export const WEBHOOK_SCHEMES = ["hmac_sha1", "hmac_sha256"];
|
|
23
|
+
export const WEBHOOK_ENCODINGS = ["base64", "hex"];
|
|
24
|
+
export const PARAM_TYPES = ["bool", "datetime", "int", "select", "string", "url"];
|
|
25
|
+
export const RETURN_VALUE_TYPES = ["bool", "datetime", "int", "string", "url"];
|
|
26
|
+
export const DIRECTIONS = ["emit", "read", "write"];
|
|
27
|
+
export const ACTOR_KINDS = ["installation", "member"];
|
|
28
|
+
export const SCOPES = ["projects:read", "projects:write", "documents:read", "documents:write", "queues:read", "queues:write", "counter_groups:read", "counter_groups:write", "calendars:read", "calendars:write", "dashboards:read", "dashboards:write", "posts:read", "posts:write", "galleries:read", "galleries:write", "wikis:read", "wikis:write", "comments:read", "comments:write", "relationships:read", "relationships:write", "tags:read", "tags:write", "sharing:read", "sharing:write", "members:read", "initiatives:read", "initiatives:moderate", "community:admin"];
|
|
29
|
+
export const SURFACE_SCOPES = ["community", "initiative"];
|
|
30
|
+
export const EMBED_CAPABILITIES = ["camera", "clipboard-read", "clipboard-write", "display-capture", "fullscreen", "geolocation", "microphone"];
|
|
31
|
+
export const LISTING_KINDS = ["plugin", "dashboard"];
|
|
32
|
+
export const HTTP_METHODS = ["DELETE", "GET", "PATCH", "POST", "PUT"];
|
|
33
|
+
export const PAGE_LIMITS = ["refuse", "truncate"];
|
|
34
|
+
export const STATUS_RANGES = ["2xx", "3xx", "4xx", "5xx"];
|
|
35
|
+
export const CONNECTION_STATES = ["ok", "removed", "suspended", "unavailable"];
|
|
36
|
+
export const PLATFORM_CODES = ["invalid", "mapping-failed", "not-authorized", "not-found", "range-too-large"];
|
|
37
|
+
/** Every cap the platform enforces, by the name the contract gives it. */
|
|
38
|
+
export const CAPS = {
|
|
39
|
+
connections: 20,
|
|
40
|
+
fieldsPerConnection: 12,
|
|
41
|
+
vendorFields: 12,
|
|
42
|
+
githubAppPermissions: 100,
|
|
43
|
+
githubAppEvents: 100,
|
|
44
|
+
flowScopes: 24,
|
|
45
|
+
authorizeParams: 12,
|
|
46
|
+
tokenLifetimeSeconds: 600,
|
|
47
|
+
selectOptions: 24,
|
|
48
|
+
accessHintScopes: 24,
|
|
49
|
+
requiresTerms: 10,
|
|
50
|
+
widgets: 12,
|
|
51
|
+
widgetEndpoints: 8,
|
|
52
|
+
endpoints: 64,
|
|
53
|
+
paramsPerEndpoint: 12,
|
|
54
|
+
returnsPerEndpoint: 24,
|
|
55
|
+
embeds: 12,
|
|
56
|
+
embedCapabilities: 8,
|
|
57
|
+
bundledDashboards: 8,
|
|
58
|
+
dashboardWidgets: 50,
|
|
59
|
+
dashboardGridColumns: 12,
|
|
60
|
+
dashboardBindingParams: 12,
|
|
61
|
+
identifierLength: 64,
|
|
62
|
+
publicIdLength: 120,
|
|
63
|
+
pathLength: 200,
|
|
64
|
+
endpointIdLength: 200,
|
|
65
|
+
nameLength: 255,
|
|
66
|
+
labelLength: 120,
|
|
67
|
+
hintLength: 120,
|
|
68
|
+
descriptionLength: 500,
|
|
69
|
+
paramValueLength: 2000,
|
|
70
|
+
uidLength: 14,
|
|
71
|
+
textLength: 120,
|
|
72
|
+
locales: 40,
|
|
73
|
+
cacheTtlSeconds: 86400,
|
|
74
|
+
moduleSourceBytes: 65536,
|
|
75
|
+
sampleDataBytes: 32768,
|
|
76
|
+
serviceDefinitionBytes: 524288,
|
|
77
|
+
versionLength: 32,
|
|
78
|
+
publisherNameLength: 120,
|
|
79
|
+
urlLength: 300,
|
|
80
|
+
localeTagLength: 12,
|
|
81
|
+
widgetDescriptionLength: 400,
|
|
82
|
+
widgetOptions: 12,
|
|
83
|
+
valuesPerOption: 24,
|
|
84
|
+
identityKeyParts: 4,
|
|
85
|
+
pluginScopes: 24,
|
|
86
|
+
schedules: 8,
|
|
87
|
+
scheduleMinMinutes: 5,
|
|
88
|
+
scheduleMaxMinutes: 1440,
|
|
89
|
+
scheduleEveryLength: 5,
|
|
90
|
+
hosts: 8,
|
|
91
|
+
hostLength: 253,
|
|
92
|
+
steps: 3,
|
|
93
|
+
pages: 10,
|
|
94
|
+
perPage: 100,
|
|
95
|
+
requestQuery: 24,
|
|
96
|
+
requestHeaders: 12,
|
|
97
|
+
errorRules: 12,
|
|
98
|
+
unavailableCodes: 12,
|
|
99
|
+
webhookEvents: 32,
|
|
100
|
+
webhookStatuses: 12,
|
|
101
|
+
healthStates: 12,
|
|
102
|
+
statusCode: 599,
|
|
103
|
+
expressionLength: 16384,
|
|
104
|
+
graphqlLength: 16384,
|
|
105
|
+
expressionTimeMs: 1000,
|
|
106
|
+
expressionDepth: 500,
|
|
107
|
+
expressionOutputBytes: 1048576,
|
|
108
|
+
};
|
|
109
|
+
/** The character sets ids and paths are drawn from. */
|
|
110
|
+
export const CHARSETS = {
|
|
111
|
+
identifier: "-0123456789_abcdefghijklmnopqrstuvwxyz",
|
|
112
|
+
namespacedId: "-.0123456789_abcdefghijklmnopqrstuvwxyz",
|
|
113
|
+
publicId: "-.0123456789_abcdefghijklmnopqrstuvwxyz",
|
|
114
|
+
uid: "0123456789ABCDEFGHJKMNPQRSTVWXYZ",
|
|
115
|
+
path: "-./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz",
|
|
116
|
+
headerName: "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
|
|
117
|
+
fieldPath: "-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz",
|
|
118
|
+
localeTag: "-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
|
|
119
|
+
version: "0123456789.-+abcdefghijklmnopqrstuvwxyz",
|
|
120
|
+
artwork: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/._-",
|
|
121
|
+
queryName: "-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ[]_abcdefghijklmnopqrstuvwxyz~",
|
|
122
|
+
};
|
|
123
|
+
/**
|
|
124
|
+
* Every field the contract declares, by the object that owns it.
|
|
125
|
+
*
|
|
126
|
+
* The inventory the platform holds its normalizer to, exported so a consumer
|
|
127
|
+
* can enumerate what a manifest may carry without parsing the schema.
|
|
128
|
+
*/
|
|
129
|
+
export const FIELDS = {
|
|
130
|
+
requires: ["all_of", "any_of"],
|
|
131
|
+
accessHint: ["api", "scopes"],
|
|
132
|
+
connectionField: ["key", "type", "required", "label", "options", "managed"],
|
|
133
|
+
vendor: ["label", "fields", "setup"],
|
|
134
|
+
vendorField: ["key", "type", "required", "label"],
|
|
135
|
+
githubAppManifestSetup: ["kind", "app", "values"],
|
|
136
|
+
githubAppManifest: ["name", "url", "public", "default_permissions", "default_events"],
|
|
137
|
+
endpointParam: ["key", "type", "required", "label", "options", "options_from", "list"],
|
|
138
|
+
endpointReturn: ["key", "type", "label", "list"],
|
|
139
|
+
connection: ["id", "scope", "label", "fields", "flow", "token", "access_hint", "health"],
|
|
140
|
+
connectionFlow: ["type", "authorize_url", "token_url", "client_id", "client_secret", "scopes", "pkce", "authorize_params", "install_url", "after_connect", "revoke", "revoke_url"],
|
|
141
|
+
connectionToken: ["type", "exchange_url", "iss", "key", "alg", "lifetime"],
|
|
142
|
+
webhooks: ["verify", "dedup", "route", "events", "status"],
|
|
143
|
+
webhookVerify: ["scheme", "header", "prefix", "encoding", "secret"],
|
|
144
|
+
webhookRoute: ["path", "header", "connection", "field"],
|
|
145
|
+
schedule: ["id", "every"],
|
|
146
|
+
endpoint: ["id", "label", "description", "returns", "group", "needs_subject", "direction", "params", "actors", "admin_only", "public", "requires", "cache_ttl_seconds", "identity", "unavailable", "request", "steps", "map", "errors"],
|
|
147
|
+
widget: ["id", "meta", "module_source", "endpoints", "sample_data", "requires"],
|
|
148
|
+
embed: ["id", "path", "name", "scopes", "admin_only", "capabilities", "requires"],
|
|
149
|
+
bundledDashboard: ["uid", "public_id", "name", "description", "layout", "widgets"],
|
|
150
|
+
bundledDashboardWidget: ["id", "type", "title", "grid", "binding"],
|
|
151
|
+
endpointIdentity: ["kind", "key"],
|
|
152
|
+
vendorAuth: ["header", "prefix"],
|
|
153
|
+
vendorRequest: ["method", "url", "query", "headers", "body", "graphql", "connection", "paging"],
|
|
154
|
+
graphqlRequest: ["query", "variables"],
|
|
155
|
+
requestStep: ["name", "request"],
|
|
156
|
+
pageNumberPaging: ["kind", "page_param", "per_page_param", "per_page", "items", "max_pages", "on_limit"],
|
|
157
|
+
linkHeaderPaging: ["kind", "items", "max_pages", "on_limit"],
|
|
158
|
+
cursorPaging: ["kind", "next", "more", "param", "variable", "items", "max_pages", "on_limit"],
|
|
159
|
+
errorRule: ["status", "when", "code"],
|
|
160
|
+
afterConnect: ["request", "steps", "map", "refuse_when", "code"],
|
|
161
|
+
connectionHealth: ["request", "every", "states"],
|
|
162
|
+
healthState: ["status", "when", "state"],
|
|
163
|
+
webhookEvent: ["when", "emit", "map"],
|
|
164
|
+
webhookStatus: ["when", "connection", "state"],
|
|
165
|
+
manifest: ["plugin_kind", "service", "features", "default_name", "hosts", "auth", "vendor", "connections", "webhooks", "schedules", "endpoints", "community_summary", "widgets", "embeds", "dashboards"],
|
|
166
|
+
};
|
|
167
|
+
//# sourceMappingURL=contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,MAAM,CAAC,MAAM,QAAQ,GAAuB,CAAC,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;AAG7F,MAAM,CAAC,MAAM,SAAS,GAAwB,CAAC,CAAC,CAAC,CAAC;AAGlD,MAAM,CAAC,MAAM,iBAAiB,GAA+B,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;AAGvF,MAAM,CAAC,MAAM,UAAU,GAAwB,CAAC,QAAQ,CAAC,CAAC;AAG1D,MAAM,CAAC,MAAM,WAAW,GAAyB,CAAC,YAAY,CAAC,CAAC;AAGhE,MAAM,CAAC,MAAM,cAAc,GAA4B,CAAC,cAAc,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;AAG3F,MAAM,CAAC,MAAM,cAAc,GAA4B,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AAG1E,MAAM,CAAC,MAAM,WAAW,GAAyB,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;AAGtG,MAAM,CAAC,MAAM,kBAAkB,GAA+B,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;AAG1F,MAAM,CAAC,MAAM,wBAAwB,GAAqC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAG5F,MAAM,CAAC,MAAM,iBAAiB,GAA8B,CAAC,WAAW,EAAE,eAAe,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,CAAC,CAAC;AAGlI,MAAM,CAAC,MAAM,eAAe,GAA6B,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;AAGtF,MAAM,CAAC,MAAM,iBAAiB,GAA+B,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;AAG/E,MAAM,CAAC,MAAM,WAAW,GAAyB,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;AAGxG,MAAM,CAAC,MAAM,kBAAkB,GAA+B,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;AAG3G,MAAM,CAAC,MAAM,UAAU,GAAyB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AAG1E,MAAM,CAAC,MAAM,WAAW,GAAyB,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;AAG5E,MAAM,CAAC,MAAM,MAAM,GAAqB,CAAC,eAAe,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,aAAa,EAAE,cAAc,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,iBAAiB,CAAC,CAAC;AAGrkB,MAAM,CAAC,MAAM,cAAc,GAA4B,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;AAGnF,MAAM,CAAC,MAAM,kBAAkB,GAA+B,CAAC,QAAQ,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,CAAC,CAAC;AAG5K,MAAM,CAAC,MAAM,aAAa,GAA2B,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;AAG7E,MAAM,CAAC,MAAM,YAAY,GAA0B,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;AAG7F,MAAM,CAAC,MAAM,WAAW,GAAyB,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;AAGxE,MAAM,CAAC,MAAM,aAAa,GAA2B,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAGlF,MAAM,CAAC,MAAM,iBAAiB,GAA+B,CAAC,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC;AAG3G,MAAM,CAAC,MAAM,cAAc,GAA4B,CAAC,SAAS,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,WAAW,EAAE,iBAAiB,CAAC,CAAC;AAEvI,0EAA0E;AAC1E,MAAM,CAAC,MAAM,IAAI,GAAG;IAClB,WAAW,EAAE,EAAE;IACf,mBAAmB,EAAE,EAAE;IACvB,YAAY,EAAE,EAAE;IAChB,oBAAoB,EAAE,GAAG;IACzB,eAAe,EAAE,GAAG;IACpB,UAAU,EAAE,EAAE;IACd,eAAe,EAAE,EAAE;IACnB,oBAAoB,EAAE,GAAG;IACzB,aAAa,EAAE,EAAE;IACjB,gBAAgB,EAAE,EAAE;IACpB,aAAa,EAAE,EAAE;IACjB,OAAO,EAAE,EAAE;IACX,eAAe,EAAE,CAAC;IAClB,SAAS,EAAE,EAAE;IACb,iBAAiB,EAAE,EAAE;IACrB,kBAAkB,EAAE,EAAE;IACtB,MAAM,EAAE,EAAE;IACV,iBAAiB,EAAE,CAAC;IACpB,iBAAiB,EAAE,CAAC;IACpB,gBAAgB,EAAE,EAAE;IACpB,oBAAoB,EAAE,EAAE;IACxB,sBAAsB,EAAE,EAAE;IAC1B,gBAAgB,EAAE,EAAE;IACpB,cAAc,EAAE,GAAG;IACnB,UAAU,EAAE,GAAG;IACf,gBAAgB,EAAE,GAAG;IACrB,UAAU,EAAE,GAAG;IACf,WAAW,EAAE,GAAG;IAChB,UAAU,EAAE,GAAG;IACf,iBAAiB,EAAE,GAAG;IACtB,gBAAgB,EAAE,IAAI;IACtB,SAAS,EAAE,EAAE;IACb,UAAU,EAAE,GAAG;IACf,OAAO,EAAE,EAAE;IACX,eAAe,EAAE,KAAK;IACtB,iBAAiB,EAAE,KAAK;IACxB,eAAe,EAAE,KAAK;IACtB,sBAAsB,EAAE,MAAM;IAC9B,aAAa,EAAE,EAAE;IACjB,mBAAmB,EAAE,GAAG;IACxB,SAAS,EAAE,GAAG;IACd,eAAe,EAAE,EAAE;IACnB,uBAAuB,EAAE,GAAG;IAC5B,aAAa,EAAE,EAAE;IACjB,eAAe,EAAE,EAAE;IACnB,gBAAgB,EAAE,CAAC;IACnB,YAAY,EAAE,EAAE;IAChB,SAAS,EAAE,CAAC;IACZ,kBAAkB,EAAE,CAAC;IACrB,kBAAkB,EAAE,IAAI;IACxB,mBAAmB,EAAE,CAAC;IACtB,KAAK,EAAE,CAAC;IACR,UAAU,EAAE,GAAG;IACf,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,EAAE;IACT,OAAO,EAAE,GAAG;IACZ,YAAY,EAAE,EAAE;IAChB,cAAc,EAAE,EAAE;IAClB,UAAU,EAAE,EAAE;IACd,gBAAgB,EAAE,EAAE;IACpB,aAAa,EAAE,EAAE;IACjB,eAAe,EAAE,EAAE;IACnB,YAAY,EAAE,EAAE;IAChB,UAAU,EAAE,GAAG;IACf,gBAAgB,EAAE,KAAK;IACvB,aAAa,EAAE,KAAK;IACpB,gBAAgB,EAAE,IAAI;IACtB,eAAe,EAAE,GAAG;IACpB,qBAAqB,EAAE,OAAO;CACtB,CAAC;AAEX,uDAAuD;AACvD,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,UAAU,EAAE,wCAAwC;IACpD,YAAY,EAAE,yCAAyC;IACvD,QAAQ,EAAE,yCAAyC;IACnD,GAAG,EAAE,kCAAkC;IACvC,IAAI,EAAE,oEAAoE;IAC1E,UAAU,EAAE,iEAAiE;IAC7E,SAAS,EAAE,mEAAmE;IAC9E,SAAS,EAAE,uDAAuD;IAClE,OAAO,EAAE,yCAAyC;IAClD,OAAO,EAAE,oEAAoE;IAC7E,SAAS,EAAE,sEAAsE;CACzE,CAAC;AAEX;;;;;GAKG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,QAAQ,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC9B,UAAU,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC;IAC7B,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,CAAC;IAC3E,MAAM,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC;IACpC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC;IACjD,sBAAsB,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC;IACjD,iBAAiB,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,qBAAqB,EAAE,gBAAgB,CAAC;IACrF,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,CAAC;IACtF,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC;IAChD,UAAU,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,QAAQ,CAAC;IACxF,cAAc,EAAE,CAAC,MAAM,EAAE,eAAe,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,EAAE,kBAAkB,EAAE,aAAa,EAAE,eAAe,EAAE,QAAQ,EAAE,YAAY,CAAC;IAClL,eAAe,EAAE,CAAC,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,CAAC;IAC1E,QAAQ,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC;IAC1D,aAAa,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,CAAC;IACnE,YAAY,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,CAAC;IACvD,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC;IACzB,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,mBAAmB,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC;IACvO,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,WAAW,EAAE,aAAa,EAAE,UAAU,CAAC;IAC/E,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,CAAC;IACjF,gBAAgB,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,SAAS,CAAC;IAClF,sBAAsB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC;IAClE,gBAAgB,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC;IACjC,UAAU,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAChC,aAAa,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,CAAC;IAC/F,cAAc,EAAE,CAAC,OAAO,EAAE,WAAW,CAAC;IACtC,WAAW,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC;IAChC,gBAAgB,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,CAAC;IACxG,gBAAgB,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,CAAC;IAC5D,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,CAAC;IAC7F,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;IACrC,YAAY,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,CAAC;IAChE,gBAAgB,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC;IAChD,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC;IACxC,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC;IACrC,aAAa,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,CAAC;IAC9C,QAAQ,EAAE,CAAC,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,mBAAmB,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,CAAC;CAChM,CAAC"}
|
package/dist/define.d.ts
ADDED
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One typed definition of a plug-in.
|
|
3
|
+
*
|
|
4
|
+
* {@link definePlugin} takes everything a plug-in declares and does: its endpoints
|
|
5
|
+
* with their handlers, its hooks and schedules, its widgets and surfaces, and
|
|
6
|
+
* its listing. The same object routes Initiative's calls (`createPlugin`) and
|
|
7
|
+
* becomes the manifest (`initiative-plugin build`), so nothing is stated twice.
|
|
8
|
+
*
|
|
9
|
+
* {@link defineEndpoint} types one endpoint from its own declaration: its
|
|
10
|
+
* `params` type the handler's arguments and its `returns` type what the
|
|
11
|
+
* handler answers with.
|
|
12
|
+
*
|
|
13
|
+
* A declarative plug-in gives each endpoint a `request` (or `steps`) and a `map`
|
|
14
|
+
* in place of a handler, and names its `hosts`: Initiative then makes the
|
|
15
|
+
* calls and maps the answers itself, and there is no service to run. One plug-in
|
|
16
|
+
* is one kind or the other.
|
|
17
|
+
*
|
|
18
|
+
* Endpoints are named by their key. The manifest id is `plugin.<publicId>.<key>`,
|
|
19
|
+
* and everywhere a definition refers to an endpoint (a widget, a sample, a
|
|
20
|
+
* parameter's `options_from`, a bundled dashboard, `communitySummary`) it uses the
|
|
21
|
+
* key.
|
|
22
|
+
*/
|
|
23
|
+
import type { ActorKind, PluginScope, BundledDashboard, BundledDashboardWidget, Connection, Embed, Endpoint, EndpointParam, EndpointReturn, ErrorRule, Expression, Manifest, RequestStep, ReturnValueType, Scope, Vendor, VendorAuth, VendorRequest, WebhookEvent, Webhooks, Widget } from "./contract.js";
|
|
24
|
+
import type { Client } from "./client.js";
|
|
25
|
+
/**
|
|
26
|
+
* What every handler is handed as `context`: the value given to `createPlugin`.
|
|
27
|
+
*
|
|
28
|
+
* Empty until a plug-in says what it holds, by augmenting this interface:
|
|
29
|
+
*
|
|
30
|
+
* ```ts
|
|
31
|
+
* declare module "initiative-plugin-sdk/manifest" {
|
|
32
|
+
* interface PluginContext { tracker: TrackerClient }
|
|
33
|
+
* }
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export interface PluginContext {
|
|
37
|
+
}
|
|
38
|
+
/** One declared parameter, keyed by its name. */
|
|
39
|
+
export type ParamSpec = Omit<EndpointParam, "key">;
|
|
40
|
+
/** One declared return, keyed by its name: its type, or the whole declaration. */
|
|
41
|
+
export type ReturnSpec = ReturnValueType | Omit<EndpointReturn, "key">;
|
|
42
|
+
type Scalar<T> = T extends "int" ? number : T extends "bool" ? boolean : string;
|
|
43
|
+
type ReturnValue<S> = S extends ReturnValueType ? Scalar<S> : S extends {
|
|
44
|
+
type: infer T;
|
|
45
|
+
list: true;
|
|
46
|
+
} ? Array<Scalar<T>> : S extends {
|
|
47
|
+
type: infer T;
|
|
48
|
+
} ? Scalar<T> : never;
|
|
49
|
+
/**
|
|
50
|
+
* What an endpoint answers with: its declared returns, by name. A `list`
|
|
51
|
+
* return is an array. Each may be left out or null; a key the endpoint does
|
|
52
|
+
* not declare is refused.
|
|
53
|
+
*/
|
|
54
|
+
export type Result<R> = {
|
|
55
|
+
[K in keyof R]?: ReturnValue<R[K]> | null;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* A parameter as a caller sent it. Initiative sends strings; an automation
|
|
59
|
+
* may send numbers and booleans as they are.
|
|
60
|
+
*/
|
|
61
|
+
export type ParamValue = string | number | boolean;
|
|
62
|
+
/** The parameters a call carries, by their declared names. */
|
|
63
|
+
export type Params<P> = {
|
|
64
|
+
[K in keyof P]?: P[K] extends {
|
|
65
|
+
list: true;
|
|
66
|
+
} ? ParamValue[] : ParamValue;
|
|
67
|
+
};
|
|
68
|
+
/** Whose behalf a call is on: the community, or one of its members by this installation's reference for them. */
|
|
69
|
+
export type Actor = {
|
|
70
|
+
kind: "installation";
|
|
71
|
+
} | {
|
|
72
|
+
kind: "member";
|
|
73
|
+
member: string;
|
|
74
|
+
};
|
|
75
|
+
/** What every handler is handed. */
|
|
76
|
+
export interface Call {
|
|
77
|
+
/** The installation: the community, by the reference this plug-in's install knows it by. */
|
|
78
|
+
installation: string;
|
|
79
|
+
/** Initiative, acting as whoever the call is for. */
|
|
80
|
+
client: Client;
|
|
81
|
+
context: PluginContext;
|
|
82
|
+
}
|
|
83
|
+
export interface EndpointCall<P> extends Call {
|
|
84
|
+
/** The endpoint's manifest id. */
|
|
85
|
+
endpoint: string;
|
|
86
|
+
params: Params<P>;
|
|
87
|
+
/** Initiative's own calls, for a widget, are the community's. */
|
|
88
|
+
actor: Actor;
|
|
89
|
+
/** The plug-in that made this call through Initiative, by its public id, or null for Initiative's own. */
|
|
90
|
+
caller: string | null;
|
|
91
|
+
/** The initiative the call is confined to, when it is. */
|
|
92
|
+
initiative: number | null;
|
|
93
|
+
/** Connection id → the handle Initiative gives a token for, where the call depends on one. */
|
|
94
|
+
connections: Record<string, string>;
|
|
95
|
+
}
|
|
96
|
+
/** What a handler answers with. `actor` says whose credential ran it; absent, the call's actor. */
|
|
97
|
+
export interface Outcome<R> {
|
|
98
|
+
result: Result<R>;
|
|
99
|
+
actor?: ActorKind;
|
|
100
|
+
}
|
|
101
|
+
type Described = Omit<Endpoint, "id" | "direction" | "params" | "returns" | "request" | "steps" | "map" | "errors">;
|
|
102
|
+
/** An endpoint Initiative calls: a `read`, or a `write` another plug-in calls through it. */
|
|
103
|
+
export interface CallableEndpoint<P, R, D extends "read" | "write" = "read" | "write"> extends Described {
|
|
104
|
+
direction: D;
|
|
105
|
+
params?: P;
|
|
106
|
+
returns?: R;
|
|
107
|
+
handler: (call: EndpointCall<P>) => Promise<Outcome<R>>;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* An endpoint a declarative plug-in answers without code: Initiative makes the
|
|
111
|
+
* `request`, or each of the `steps` in order, and `map` turns the answer into
|
|
112
|
+
* the endpoint's returns.
|
|
113
|
+
*/
|
|
114
|
+
export type DeclarativeEndpoint<P, R, D extends "read" | "write" = "read" | "write"> = Described & {
|
|
115
|
+
direction: D;
|
|
116
|
+
params?: P;
|
|
117
|
+
returns?: R;
|
|
118
|
+
map: Expression;
|
|
119
|
+
errors?: ErrorRule[];
|
|
120
|
+
} & ({
|
|
121
|
+
request: VendorRequest;
|
|
122
|
+
steps?: never;
|
|
123
|
+
} | {
|
|
124
|
+
steps: RequestStep[];
|
|
125
|
+
request?: never;
|
|
126
|
+
});
|
|
127
|
+
/** An announcement the plug-in emits: declared, never called. */
|
|
128
|
+
export interface EmittedEndpoint<R> extends Described {
|
|
129
|
+
direction: "emit";
|
|
130
|
+
returns?: R;
|
|
131
|
+
}
|
|
132
|
+
export type EndpointDeclaration = CallableEndpoint<any, any> | DeclarativeEndpoint<any, any> | EmittedEndpoint<any>;
|
|
133
|
+
/** One endpoint, typed from its own `params` and `returns`. */
|
|
134
|
+
export declare function defineEndpoint<const R extends Record<string, ReturnSpec> = {}>(endpoint: EmittedEndpoint<R>): EmittedEndpoint<R>;
|
|
135
|
+
export declare function defineEndpoint<D extends "read" | "write", const P extends Record<string, ParamSpec> = {}, const R extends Record<string, ReturnSpec> = {}>(endpoint: CallableEndpoint<P, R, D>): CallableEndpoint<P, R, D>;
|
|
136
|
+
export declare function defineEndpoint<D extends "read" | "write", const P extends Record<string, ParamSpec> = {}, const R extends Record<string, ReturnSpec> = {}>(endpoint: DeclarativeEndpoint<P, R, D>): DeclarativeEndpoint<P, R, D>;
|
|
137
|
+
/** What `after_connect` is sent, once a connection's flow has exchanged its code. */
|
|
138
|
+
export interface AfterConnectCall extends Call {
|
|
139
|
+
/** The connection's manifest id. */
|
|
140
|
+
connection: string;
|
|
141
|
+
/** `member` for a member's own account, `installation` for the community's. */
|
|
142
|
+
actor: ActorKind;
|
|
143
|
+
/** The access token the flow just obtained, to look the account up with. */
|
|
144
|
+
access_token: string;
|
|
145
|
+
/** The flow's parameters, such as the `installation_id` an install page returned. */
|
|
146
|
+
params: Record<string, string>;
|
|
147
|
+
}
|
|
148
|
+
/** The connection's managed values and the account's label, or a refusal. */
|
|
149
|
+
export type AfterConnectAnswer = {
|
|
150
|
+
values?: Record<string, unknown>;
|
|
151
|
+
account_label?: string;
|
|
152
|
+
} | {
|
|
153
|
+
refuse: true;
|
|
154
|
+
};
|
|
155
|
+
/** What `revoke` is sent when a connection whose flow says `revoke: "hook"` ends. */
|
|
156
|
+
export interface RevokeCall extends Call {
|
|
157
|
+
connection: string;
|
|
158
|
+
access_token: string | null;
|
|
159
|
+
refresh_token: string | null;
|
|
160
|
+
}
|
|
161
|
+
/** One vendor webhook delivery, which Initiative checked and routed to this installation. */
|
|
162
|
+
export interface WebhookCall extends Call {
|
|
163
|
+
/** The static connection the delivery was routed by. */
|
|
164
|
+
connection: string;
|
|
165
|
+
/** The vendor's `x-` headers, lowercased. */
|
|
166
|
+
headers: Record<string, string>;
|
|
167
|
+
/** The body exactly as the vendor sent it. */
|
|
168
|
+
body: string;
|
|
169
|
+
}
|
|
170
|
+
/** One due schedule, for one installation. */
|
|
171
|
+
export interface ScheduleCall extends Call {
|
|
172
|
+
schedule: string;
|
|
173
|
+
/** When this schedule last succeeded for the installation (ISO 8601), or null the first time. */
|
|
174
|
+
since: string | null;
|
|
175
|
+
}
|
|
176
|
+
/** The hooks Initiative calls while it runs connections and receives the vendor's webhooks. */
|
|
177
|
+
export interface Hooks {
|
|
178
|
+
after_connect?: (call: AfterConnectCall) => Promise<AfterConnectAnswer>;
|
|
179
|
+
revoke?: (call: RevokeCall) => Promise<void>;
|
|
180
|
+
webhook?: (call: WebhookCall) => Promise<void>;
|
|
181
|
+
}
|
|
182
|
+
export interface ScheduleDeclaration {
|
|
183
|
+
/** A whole number of minutes (`15m`) or hours (`6h`). */
|
|
184
|
+
every: `${number}${"m" | "h"}`;
|
|
185
|
+
run: (call: ScheduleCall) => Promise<void>;
|
|
186
|
+
}
|
|
187
|
+
/** A member opening one of the plug-in's surfaces, as the handoff token names them. */
|
|
188
|
+
export interface Handoff extends Call {
|
|
189
|
+
surface: string;
|
|
190
|
+
/** The member, by this installation's reference for them. */
|
|
191
|
+
viewer: string;
|
|
192
|
+
/** Whether the viewer administers the community. For shaping screens; not a grant. */
|
|
193
|
+
admin: boolean;
|
|
194
|
+
/** The initiative the surface was opened in, or null for the whole community. */
|
|
195
|
+
initiative: number | null;
|
|
196
|
+
}
|
|
197
|
+
export interface SurfaceCall {
|
|
198
|
+
request: Request;
|
|
199
|
+
/** Null for a request that carries no handoff token, such as the page's own files. */
|
|
200
|
+
handoff: Handoff | null;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* A page of the plug-in that Initiative frames. The page is the plug-in's own; a
|
|
204
|
+
* request under its path that carries a handoff token reaches the handler with
|
|
205
|
+
* the handoff verified.
|
|
206
|
+
*/
|
|
207
|
+
export interface SurfaceDeclaration extends Omit<Embed, "id"> {
|
|
208
|
+
handler?: (call: SurfaceCall) => Promise<Response>;
|
|
209
|
+
}
|
|
210
|
+
type ReadName<E> = {
|
|
211
|
+
[K in keyof E]: E[K] extends {
|
|
212
|
+
direction: "read";
|
|
213
|
+
} ? K : never;
|
|
214
|
+
}[keyof E] & string;
|
|
215
|
+
type EmitName<E> = {
|
|
216
|
+
[K in keyof E]: E[K] extends {
|
|
217
|
+
direction: "emit";
|
|
218
|
+
} ? K : never;
|
|
219
|
+
}[keyof E] & string;
|
|
220
|
+
/** The vendor's webhooks. A declarative plug-in's events name the emit endpoint by its key. */
|
|
221
|
+
export type WebhooksDeclaration<E> = Omit<Webhooks, "events"> & {
|
|
222
|
+
events?: Array<Omit<WebhookEvent, "emit"> & {
|
|
223
|
+
emit: EmitName<E>;
|
|
224
|
+
}>;
|
|
225
|
+
};
|
|
226
|
+
type ReturnsOf<X> = X extends {
|
|
227
|
+
returns?: infer R;
|
|
228
|
+
} ? NonNullable<R> : {};
|
|
229
|
+
/** A dashboard tile the plug-in contributes. `module` is the widget's source file. */
|
|
230
|
+
export interface WidgetDeclaration<E> extends Omit<Widget, "id" | "module_source" | "endpoints" | "sample_data"> {
|
|
231
|
+
/** Read endpoints the widget may be bound to. */
|
|
232
|
+
endpoints?: readonly ReadName<E>[];
|
|
233
|
+
/**
|
|
234
|
+
* The widget's TypeScript module, relative to the plug-in's package: it exports
|
|
235
|
+
* `render(data)`. The build bundles it into the manifest's `module_source`.
|
|
236
|
+
*/
|
|
237
|
+
module: string;
|
|
238
|
+
/** What each endpoint would answer, for a preview with no network call. */
|
|
239
|
+
sample_data?: {
|
|
240
|
+
[K in ReadName<E>]?: Result<ReturnsOf<E[K]>>;
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
export interface DashboardDeclaration<E, W> extends Omit<BundledDashboard, "widgets"> {
|
|
244
|
+
widgets: Array<Omit<BundledDashboardWidget, "type" | "binding"> & {
|
|
245
|
+
type: keyof W & string;
|
|
246
|
+
binding: Omit<BundledDashboardWidget["binding"], "endpoint_id"> & {
|
|
247
|
+
endpoint_id: ReadName<E>;
|
|
248
|
+
};
|
|
249
|
+
}>;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* The plug-in's registry listing. `initiative-plugin build --registry <dir>` writes it
|
|
253
|
+
* while `version` is the package's own version.
|
|
254
|
+
*/
|
|
255
|
+
export interface ListingDeclaration {
|
|
256
|
+
/** The publisher's prefix, the part of the public id before the first dot. */
|
|
257
|
+
publisher: string;
|
|
258
|
+
/** One or two sentences for the listing's card. */
|
|
259
|
+
summary: string;
|
|
260
|
+
/** The listing page's longer text. Markdown. */
|
|
261
|
+
description?: string;
|
|
262
|
+
/** The listing's picture, relative to the plug-in's package. */
|
|
263
|
+
avatar: string;
|
|
264
|
+
version: string;
|
|
265
|
+
/** The oldest Initiative release this version runs on. */
|
|
266
|
+
minAppVersion?: string;
|
|
267
|
+
releaseNotes?: string;
|
|
268
|
+
/**
|
|
269
|
+
* A container plug-in's image for this version, pinned by digest. Every
|
|
270
|
+
* deployment runs its own copy and gives the key it signs with, so a listing
|
|
271
|
+
* names no keys. A declarative plug-in has none.
|
|
272
|
+
*/
|
|
273
|
+
image?: string;
|
|
274
|
+
/** The most the plug-in may ever be granted. Absent: its `scopes`. */
|
|
275
|
+
scopeCeiling?: Array<Scope | PluginScope>;
|
|
276
|
+
referenceSectors?: string[];
|
|
277
|
+
/**
|
|
278
|
+
* The Docker Compose service an operator copies to run the image beside
|
|
279
|
+
* Initiative. `service` is the fragment, YAML text of at most 4096
|
|
280
|
+
* characters. Initiative fills two placeholders when it shows it: `${IMAGE}`,
|
|
281
|
+
* `image` above, and `${INITIATIVE_URL}`, the deployment's public address;
|
|
282
|
+
* any other `${…}` is refused. `baseUrl` is where the service answers on the
|
|
283
|
+
* Compose network, such as `http://tracker:8080`: an http or https URL of at
|
|
284
|
+
* most 512 characters. A container plug-in's only.
|
|
285
|
+
*/
|
|
286
|
+
compose?: {
|
|
287
|
+
service: string;
|
|
288
|
+
baseUrl: string;
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
export interface PluginDefinition<E, W> {
|
|
292
|
+
/** `<publisher>.<slug>`. */
|
|
293
|
+
publicId: string;
|
|
294
|
+
/** The catalog id: 14 characters of Crockford base32, minted once (`initiative-plugin uid`). */
|
|
295
|
+
uid: string;
|
|
296
|
+
name: string;
|
|
297
|
+
scopes?: Array<Scope | PluginScope>;
|
|
298
|
+
/** A declarative plug-in's hosts: every host its requests may reach. Naming them makes the plug-in declarative. */
|
|
299
|
+
hosts?: string[];
|
|
300
|
+
/** How a declarative plug-in's requests carry their credential. Absent: `Authorization: Bearer <token>`. */
|
|
301
|
+
auth?: VendorAuth;
|
|
302
|
+
vendor?: Vendor;
|
|
303
|
+
/** Keyed by connection id. */
|
|
304
|
+
connections?: Record<string, Omit<Connection, "id">>;
|
|
305
|
+
webhooks?: WebhooksDeclaration<E>;
|
|
306
|
+
/** Keyed by schedule id. Each runs through the `schedule` hook. */
|
|
307
|
+
schedules?: Record<string, ScheduleDeclaration>;
|
|
308
|
+
endpoints?: E;
|
|
309
|
+
/** A read endpoint describing the community's standing with the plug-in's service. */
|
|
310
|
+
communitySummary?: ReadName<E>;
|
|
311
|
+
hooks?: Hooks;
|
|
312
|
+
widgets?: W;
|
|
313
|
+
/** Pages and panels, keyed by surface id. */
|
|
314
|
+
surfaces?: Record<string, SurfaceDeclaration>;
|
|
315
|
+
dashboards?: DashboardDeclaration<E, W>[];
|
|
316
|
+
listing?: ListingDeclaration;
|
|
317
|
+
}
|
|
318
|
+
/** Any plug-in's definition, as the server and the build read it. */
|
|
319
|
+
export type AnyPlugin = Omit<PluginDefinition<any, any>, "endpoints" | "widgets"> & {
|
|
320
|
+
endpoints?: Record<string, EndpointDeclaration>;
|
|
321
|
+
widgets?: Record<string, WidgetDeclaration<any>>;
|
|
322
|
+
};
|
|
323
|
+
/** The plug-in, declared once. */
|
|
324
|
+
export declare function definePlugin<const E extends Record<string, EndpointDeclaration> = {}, const W extends Record<string, WidgetDeclaration<E>> = {}>(definition: PluginDefinition<E, W>): PluginDefinition<E, W>;
|
|
325
|
+
/** An endpoint's manifest id. */
|
|
326
|
+
export declare function endpointId(plugin: {
|
|
327
|
+
publicId: string;
|
|
328
|
+
}, name: string): string;
|
|
329
|
+
/**
|
|
330
|
+
* The manifest a definition declares: its handlers left out, its keys made
|
|
331
|
+
* ids, in the contract's order. Each widget's `module_source` is taken from
|
|
332
|
+
* `modules` by widget id. A definition naming `hosts` is declarative, and its
|
|
333
|
+
* manifest has no `service` block.
|
|
334
|
+
*/
|
|
335
|
+
export declare function manifestOf(plugin: AnyPlugin, modules?: Record<string, string>): Manifest;
|
|
336
|
+
export {};
|
package/dist/define.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One typed definition of a plug-in.
|
|
3
|
+
*
|
|
4
|
+
* {@link definePlugin} takes everything a plug-in declares and does: its endpoints
|
|
5
|
+
* with their handlers, its hooks and schedules, its widgets and surfaces, and
|
|
6
|
+
* its listing. The same object routes Initiative's calls (`createPlugin`) and
|
|
7
|
+
* becomes the manifest (`initiative-plugin build`), so nothing is stated twice.
|
|
8
|
+
*
|
|
9
|
+
* {@link defineEndpoint} types one endpoint from its own declaration: its
|
|
10
|
+
* `params` type the handler's arguments and its `returns` type what the
|
|
11
|
+
* handler answers with.
|
|
12
|
+
*
|
|
13
|
+
* A declarative plug-in gives each endpoint a `request` (or `steps`) and a `map`
|
|
14
|
+
* in place of a handler, and names its `hosts`: Initiative then makes the
|
|
15
|
+
* calls and maps the answers itself, and there is no service to run. One plug-in
|
|
16
|
+
* is one kind or the other.
|
|
17
|
+
*
|
|
18
|
+
* Endpoints are named by their key. The manifest id is `plugin.<publicId>.<key>`,
|
|
19
|
+
* and everywhere a definition refers to an endpoint (a widget, a sample, a
|
|
20
|
+
* parameter's `options_from`, a bundled dashboard, `communitySummary`) it uses the
|
|
21
|
+
* key.
|
|
22
|
+
*/
|
|
23
|
+
import { FEATURES } from "./contract.js";
|
|
24
|
+
export function defineEndpoint(endpoint) {
|
|
25
|
+
return endpoint;
|
|
26
|
+
}
|
|
27
|
+
/** The plug-in, declared once. */
|
|
28
|
+
export function definePlugin(definition) {
|
|
29
|
+
return definition;
|
|
30
|
+
}
|
|
31
|
+
/** An endpoint's manifest id. */
|
|
32
|
+
export function endpointId(plugin, name) {
|
|
33
|
+
return `plugin.${plugin.publicId}.${name}`;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The manifest a definition declares: its handlers left out, its keys made
|
|
37
|
+
* ids, in the contract's order. Each widget's `module_source` is taken from
|
|
38
|
+
* `modules` by widget id. A definition naming `hosts` is declarative, and its
|
|
39
|
+
* manifest has no `service` block.
|
|
40
|
+
*/
|
|
41
|
+
export function manifestOf(plugin, modules = {}) {
|
|
42
|
+
const id = (name) => endpointId(plugin, name);
|
|
43
|
+
const blocks = {
|
|
44
|
+
vendor: plugin.vendor,
|
|
45
|
+
connections: listOf(plugin.connections, (key, connection) => ({ id: key, ...connection })),
|
|
46
|
+
webhooks: plugin.webhooks && {
|
|
47
|
+
...plugin.webhooks,
|
|
48
|
+
...(plugin.webhooks.events ? { events: plugin.webhooks.events.map((event) => ({ ...event, emit: id(event.emit) })) } : {}),
|
|
49
|
+
},
|
|
50
|
+
schedules: listOf(plugin.schedules, (key, schedule) => ({ id: key, every: schedule.every })),
|
|
51
|
+
endpoints: listOf(plugin.endpoints, (key, endpoint) => endpointOf(id(key), endpoint, id)),
|
|
52
|
+
community_summary: plugin.communitySummary === undefined ? undefined : id(plugin.communitySummary),
|
|
53
|
+
widgets: listOf(plugin.widgets, (key, widget) => widgetOf(key, widget, modules[key] ?? "", id)),
|
|
54
|
+
embeds: listOf(plugin.surfaces, (key, surface) => {
|
|
55
|
+
const { handler: _handler, ...embed } = surface;
|
|
56
|
+
return { id: key, ...embed };
|
|
57
|
+
}),
|
|
58
|
+
dashboards: plugin.dashboards?.map((dashboard) => ({
|
|
59
|
+
...dashboard,
|
|
60
|
+
widgets: dashboard.widgets.map((widget) => ({
|
|
61
|
+
...widget,
|
|
62
|
+
binding: { ...widget.binding, endpoint_id: id(widget.binding.endpoint_id) },
|
|
63
|
+
})),
|
|
64
|
+
})),
|
|
65
|
+
};
|
|
66
|
+
const present = Object.fromEntries(Object.entries(blocks).filter(([, value]) => value !== undefined));
|
|
67
|
+
return {
|
|
68
|
+
plugin_kind: "service",
|
|
69
|
+
...(plugin.hosts
|
|
70
|
+
? {}
|
|
71
|
+
: { service: { public_id: plugin.publicId, protocol: 1, ...(plugin.scopes ? { scopes: [...plugin.scopes] } : {}) } }),
|
|
72
|
+
features: FEATURES.filter((feature) => present[feature] !== undefined),
|
|
73
|
+
default_name: plugin.name,
|
|
74
|
+
...(plugin.hosts ? { hosts: [...plugin.hosts] } : {}),
|
|
75
|
+
...(plugin.auth ? { auth: plugin.auth } : {}),
|
|
76
|
+
...present,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/** A record's entries as a list, or undefined when it holds none. */
|
|
80
|
+
function listOf(record, build) {
|
|
81
|
+
const entries = Object.entries(record ?? {});
|
|
82
|
+
return entries.length ? entries.map(([key, value]) => build(key, value)) : undefined;
|
|
83
|
+
}
|
|
84
|
+
/** The declaration in the author's own order, with its keys made ids. */
|
|
85
|
+
function endpointOf(endpointIdValue, endpoint, id) {
|
|
86
|
+
const out = { id: endpointIdValue };
|
|
87
|
+
for (const [key, value] of Object.entries(endpoint)) {
|
|
88
|
+
if (key === "handler")
|
|
89
|
+
continue;
|
|
90
|
+
if (key === "params") {
|
|
91
|
+
out.params = Object.entries(value).map(([name, param]) => ({
|
|
92
|
+
key: name,
|
|
93
|
+
...param,
|
|
94
|
+
...(param.options_from ? { options_from: { ...param.options_from, endpoint: id(param.options_from.endpoint) } } : {}),
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
else if (key === "returns") {
|
|
98
|
+
out.returns = Object.entries(value).map(([name, spec]) => typeof spec === "string" ? { key: name, type: spec } : { key: name, ...spec });
|
|
99
|
+
}
|
|
100
|
+
else
|
|
101
|
+
out[key] = value;
|
|
102
|
+
}
|
|
103
|
+
return out;
|
|
104
|
+
}
|
|
105
|
+
function widgetOf(key, widget, source, id) {
|
|
106
|
+
const out = { id: key };
|
|
107
|
+
for (const [field, value] of Object.entries(widget)) {
|
|
108
|
+
if (field === "module")
|
|
109
|
+
out.module_source = source;
|
|
110
|
+
else if (field === "endpoints")
|
|
111
|
+
out.endpoints = value.map(id);
|
|
112
|
+
else if (field === "sample_data") {
|
|
113
|
+
out.sample_data = Object.fromEntries(Object.entries(value).map(([name, sample]) => [id(name), sample]));
|
|
114
|
+
}
|
|
115
|
+
else
|
|
116
|
+
out[field] = value;
|
|
117
|
+
}
|
|
118
|
+
return out;
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=define.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define.js","sourceRoot":"","sources":["../src/define.ts"],"names":[],"mappings":"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"}
|