@geekity/cms 0.24.0 → 0.26.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/README.md +96 -160
- package/admin/pages/documents/editor.njk +48 -0
- package/admin/pages/federation/settings.njk +1 -59
- package/admin/pages/plugins/installed.njk +113 -0
- package/admin/pages/plugins/screen.njk +129 -0
- package/admin/static/admin.css +144 -4
- package/admin/static/editor-actions.js +202 -0
- package/dist/admin/accounts.d.ts +18 -39
- package/dist/admin/accounts.d.ts.map +1 -1
- package/dist/admin/accounts.js +19 -48
- package/dist/admin/accounts.js.map +1 -1
- package/dist/admin/documents.d.ts +5 -0
- package/dist/admin/documents.d.ts.map +1 -1
- package/dist/admin/documents.js +17 -8
- package/dist/admin/documents.js.map +1 -1
- package/dist/admin/editor-actions.d.ts +35 -0
- package/dist/admin/editor-actions.d.ts.map +1 -0
- package/dist/admin/editor-actions.js +187 -0
- package/dist/admin/editor-actions.js.map +1 -0
- package/dist/admin/federation.d.ts +4 -5
- package/dist/admin/federation.d.ts.map +1 -1
- package/dist/admin/federation.js +4 -5
- package/dist/admin/federation.js.map +1 -1
- package/dist/admin/index.d.ts +1 -1
- package/dist/admin/index.d.ts.map +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/menu.d.ts +1 -1
- package/dist/admin/menu.d.ts.map +1 -1
- package/dist/admin/menu.js +10 -3
- package/dist/admin/menu.js.map +1 -1
- package/dist/admin/plugins.d.ts +24 -0
- package/dist/admin/plugins.d.ts.map +1 -0
- package/dist/admin/plugins.js +312 -0
- package/dist/admin/plugins.js.map +1 -0
- package/dist/admin/routes.d.ts.map +1 -1
- package/dist/admin/routes.js +5 -1
- package/dist/admin/routes.js.map +1 -1
- package/dist/admin/settings-federation.d.ts +0 -25
- package/dist/admin/settings-federation.d.ts.map +1 -1
- package/dist/admin/settings-federation.js +1 -54
- package/dist/admin/settings-federation.js.map +1 -1
- package/dist/admin/settings.d.ts +2 -14
- package/dist/admin/settings.d.ts.map +1 -1
- package/dist/admin/settings.js +1 -21
- package/dist/admin/settings.js.map +1 -1
- package/dist/admin/store.d.ts +8 -1
- package/dist/admin/store.d.ts.map +1 -1
- package/dist/admin/store.js +7 -3
- package/dist/admin/store.js.map +1 -1
- package/dist/admin/templates.d.ts +2 -0
- package/dist/admin/templates.d.ts.map +1 -1
- package/dist/admin/templates.js +2 -0
- package/dist/admin/templates.js.map +1 -1
- package/dist/cli.d.ts +2 -3
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +278 -212
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +20 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +6 -0
- package/dist/config.js.map +1 -1
- package/dist/content/store.d.ts +6 -0
- package/dist/content/store.d.ts.map +1 -1
- package/dist/content/store.js +3 -0
- package/dist/content/store.js.map +1 -1
- package/dist/drain.d.ts +28 -0
- package/dist/drain.d.ts.map +1 -0
- package/dist/drain.js +106 -0
- package/dist/drain.js.map +1 -0
- package/dist/env.d.ts +11 -0
- package/dist/env.d.ts.map +1 -1
- package/dist/federation/federation.d.ts +4 -2
- package/dist/federation/federation.d.ts.map +1 -1
- package/dist/federation/federation.js +16 -21
- package/dist/federation/federation.js.map +1 -1
- package/dist/federation/inbox.d.ts +23 -3
- package/dist/federation/inbox.d.ts.map +1 -1
- package/dist/federation/inbox.js +63 -1
- package/dist/federation/inbox.js.map +1 -1
- package/dist/federation/index.d.ts +0 -4
- package/dist/federation/index.d.ts.map +1 -1
- package/dist/federation/index.js +0 -2
- package/dist/federation/index.js.map +1 -1
- package/dist/federation/mount.d.ts +6 -12
- package/dist/federation/mount.d.ts.map +1 -1
- package/dist/federation/mount.js +3 -50
- package/dist/federation/mount.js.map +1 -1
- package/dist/federation/queue.d.ts +22 -0
- package/dist/federation/queue.d.ts.map +1 -0
- package/dist/federation/queue.js +58 -0
- package/dist/federation/queue.js.map +1 -0
- package/dist/files/atomic.d.ts +13 -0
- package/dist/files/atomic.d.ts.map +1 -1
- package/dist/files/atomic.js +45 -0
- package/dist/files/atomic.js.map +1 -1
- package/dist/index.d.ts +30 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +156 -79
- package/dist/index.js.map +1 -1
- package/dist/plugin.d.ts +524 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +23 -0
- package/dist/plugin.js.map +1 -0
- package/dist/plugins/enabled.d.ts +23 -0
- package/dist/plugins/enabled.d.ts.map +1 -0
- package/dist/plugins/enabled.js +49 -0
- package/dist/plugins/enabled.js.map +1 -0
- package/dist/plugins/federation.d.ts +26 -0
- package/dist/plugins/federation.d.ts.map +1 -0
- package/dist/plugins/federation.js +114 -0
- package/dist/plugins/federation.js.map +1 -0
- package/dist/plugins/fetch.d.ts +15 -0
- package/dist/plugins/fetch.d.ts.map +1 -0
- package/dist/plugins/fetch.js +33 -0
- package/dist/plugins/fetch.js.map +1 -0
- package/dist/plugins/folder.d.ts +50 -0
- package/dist/plugins/folder.d.ts.map +1 -0
- package/dist/plugins/folder.js +171 -0
- package/dist/plugins/folder.js.map +1 -0
- package/dist/plugins/install.d.ts +45 -0
- package/dist/plugins/install.d.ts.map +1 -0
- package/dist/plugins/install.js +275 -0
- package/dist/plugins/install.js.map +1 -0
- package/dist/plugins/mount.d.ts +17 -0
- package/dist/plugins/mount.d.ts.map +1 -0
- package/dist/plugins/mount.js +44 -0
- package/dist/plugins/mount.js.map +1 -0
- package/dist/plugins/registry.d.ts +110 -0
- package/dist/plugins/registry.d.ts.map +1 -0
- package/dist/plugins/registry.js +447 -0
- package/dist/plugins/registry.js.map +1 -0
- package/dist/plugins/settings.d.ts +64 -0
- package/dist/plugins/settings.d.ts.map +1 -0
- package/dist/plugins/settings.js +219 -0
- package/dist/plugins/settings.js.map +1 -0
- package/dist/plugins/site.d.ts +17 -0
- package/dist/plugins/site.d.ts.map +1 -0
- package/dist/plugins/site.js +67 -0
- package/dist/plugins/site.js.map +1 -0
- package/dist/supervisor/primary.d.ts +47 -0
- package/dist/supervisor/primary.d.ts.map +1 -0
- package/dist/supervisor/primary.js +208 -0
- package/dist/supervisor/primary.js.map +1 -0
- package/dist/supervisor/protocol.d.ts +37 -0
- package/dist/supervisor/protocol.d.ts.map +1 -0
- package/dist/supervisor/protocol.js +29 -0
- package/dist/supervisor/protocol.js.map +1 -0
- package/dist/supervisor/supervision.d.ts +25 -0
- package/dist/supervisor/supervision.d.ts.map +1 -0
- package/dist/supervisor/supervision.js +7 -0
- package/dist/supervisor/supervision.js.map +1 -0
- package/dist/supervisor/worker.d.ts +29 -0
- package/dist/supervisor/worker.d.ts.map +1 -0
- package/dist/supervisor/worker.js +97 -0
- package/dist/supervisor/worker.js.map +1 -0
- package/dist/web/maintenance.d.ts +2 -2
- package/dist/web/maintenance.js +2 -2
- package/dist/web/negotiate.d.ts +4 -3
- package/dist/web/negotiate.d.ts.map +1 -1
- package/dist/web/negotiate.js +4 -3
- package/dist/web/negotiate.js.map +1 -1
- package/dist/web/routes.d.ts.map +1 -1
- package/dist/web/routes.js +33 -14
- package/dist/web/routes.js.map +1 -1
- package/package.json +10 -1
- package/dist/comments/conversation.d.ts +0 -29
- package/dist/comments/conversation.d.ts.map +0 -1
- package/dist/comments/conversation.js +0 -60
- package/dist/comments/conversation.js.map +0 -1
- package/dist/federation/import-wordpress.d.ts +0 -128
- package/dist/federation/import-wordpress.d.ts.map +0 -1
- package/dist/federation/import-wordpress.js +0 -426
- package/dist/federation/import-wordpress.js.map +0 -1
- package/dist/federation/wordpress.d.ts +0 -131
- package/dist/federation/wordpress.d.ts.map +0 -1
- package/dist/federation/wordpress.js +0 -342
- package/dist/federation/wordpress.js.map +0 -1
- package/dist/web/comments.d.ts +0 -60
- package/dist/web/comments.d.ts.map +0 -1
- package/dist/web/comments.js +0 -207
- package/dist/web/comments.js.map +0 -1
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `geekity plugin add` and `geekity plugin remove` (decision-33): a plugin
|
|
3
|
+
* package's bundle, fetched from the npm registry and unpacked into the
|
|
4
|
+
* plugins folder, with no npm and no `package.json` on the machine.
|
|
5
|
+
*
|
|
6
|
+
* Every check runs before the folder is touched. The new folder is written
|
|
7
|
+
* beside the live one under a dot-prefixed name, which a scan skips, and
|
|
8
|
+
* renamed into place, so a reload never sees a half-written folder.
|
|
9
|
+
*/
|
|
10
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
11
|
+
import { existsSync } from 'node:fs';
|
|
12
|
+
import { mkdir, rename, rm, writeFile } from 'node:fs/promises';
|
|
13
|
+
import path from 'node:path';
|
|
14
|
+
import { gunzipSync } from 'node:zlib';
|
|
15
|
+
import semver from 'semver';
|
|
16
|
+
import { HOST_API_VERSION } from '../plugin.js';
|
|
17
|
+
import { PLUGIN_ENTRY, PLUGIN_MANIFEST, readPluginManifest, scanPluginFolders } from './folder.js';
|
|
18
|
+
import { PACKAGE_NAME } from './registry.js';
|
|
19
|
+
export const DEFAULT_REGISTRY = 'https://registry.npmjs.org/';
|
|
20
|
+
/** The folder in a package that is the plugin's folder once installed. */
|
|
21
|
+
const BUNDLE_PREFIX = 'dist/bundle/';
|
|
22
|
+
/** `@scope/name@1.2.3`, `name@next` or a bare name. */
|
|
23
|
+
export function parsePackageSpec(spec) {
|
|
24
|
+
const at = spec.indexOf('@', 1);
|
|
25
|
+
const name = at === -1 ? spec : spec.slice(0, at);
|
|
26
|
+
const wanted = at === -1 ? 'latest' : spec.slice(at + 1);
|
|
27
|
+
if (!PACKAGE_NAME.test(name) || wanted === '') {
|
|
28
|
+
throw new Error(`${JSON.stringify(spec)} is not a package, such as @geekity/plugin-llm or @geekity/plugin-llm@0.1.0.`);
|
|
29
|
+
}
|
|
30
|
+
return { name, wanted };
|
|
31
|
+
}
|
|
32
|
+
/** Fetch, check and install one plugin package. Throws, leaving the folder alone, when it cannot. */
|
|
33
|
+
export async function addPlugin(spec, options) {
|
|
34
|
+
const { name } = spec;
|
|
35
|
+
const release = await resolveRelease(spec, options.registry);
|
|
36
|
+
const label = `${name} ${release.version}`;
|
|
37
|
+
const response = await fetch(release.tarball);
|
|
38
|
+
if (!response.ok) {
|
|
39
|
+
throw new Error(`Downloading ${label} failed: the registry answered ${String(response.status)}.`);
|
|
40
|
+
}
|
|
41
|
+
const tarball = Buffer.from(await response.arrayBuffer());
|
|
42
|
+
const integrityProblem = checkIntegrity(tarball, release);
|
|
43
|
+
if (integrityProblem !== undefined)
|
|
44
|
+
throw new Error(`${label} was refused: ${integrityProblem}`);
|
|
45
|
+
const files = bundleFiles(unpackTarball(tarball));
|
|
46
|
+
if (!files.has(PLUGIN_ENTRY) || !files.has(PLUGIN_MANIFEST)) {
|
|
47
|
+
throw new Error(`${label} has no plugin bundle (${BUNDLE_PREFIX}${PLUGIN_ENTRY} and ${BUNDLE_PREFIX}${PLUGIN_MANIFEST}). A plugin that is not bundled can only be installed with npm, by a site with its own server.`);
|
|
48
|
+
}
|
|
49
|
+
const directory = path.join(options.pluginsDir, ...name.split('/'));
|
|
50
|
+
const parent = path.dirname(directory);
|
|
51
|
+
await mkdir(parent, { recursive: true });
|
|
52
|
+
const staging = path.join(parent, hidden('adding', directory));
|
|
53
|
+
try {
|
|
54
|
+
for (const [file, bytes] of files) {
|
|
55
|
+
const target = path.join(staging, ...file.split('/'));
|
|
56
|
+
await mkdir(path.dirname(target), { recursive: true });
|
|
57
|
+
await writeFile(target, bytes);
|
|
58
|
+
}
|
|
59
|
+
const manifest = stagedManifest(staging, label, name);
|
|
60
|
+
const replaced = existsSync(directory) ? installedVersion(directory) : undefined;
|
|
61
|
+
await swapInto(staging, directory);
|
|
62
|
+
return { manifest, directory, replaced };
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
await rm(staging, { recursive: true, force: true });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/** Delete a plugin's folder. Throws when there is none. */
|
|
69
|
+
export async function removePlugin(name, pluginsDir) {
|
|
70
|
+
const directory = path.join(pluginsDir, ...name.split('/'));
|
|
71
|
+
if (!PACKAGE_NAME.test(name) || !existsSync(directory)) {
|
|
72
|
+
throw new Error(`${name} is not in the plugins folder, ${pluginsDir}.`);
|
|
73
|
+
}
|
|
74
|
+
const doomed = path.join(path.dirname(directory), hidden('removing', directory));
|
|
75
|
+
await rename(directory, doomed);
|
|
76
|
+
await rm(doomed, { recursive: true, force: true });
|
|
77
|
+
return directory;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* A line for each plugin the manifest requires that is not installed or not
|
|
81
|
+
* in range, and for a core out of range. `installed` maps each installed
|
|
82
|
+
* plugin to its version, or to `undefined` when that is not known.
|
|
83
|
+
*/
|
|
84
|
+
export function requirementNotes(manifest, installed, coreVersion) {
|
|
85
|
+
const notes = [];
|
|
86
|
+
for (const [dependency, range] of Object.entries(manifest.peerDependencies)) {
|
|
87
|
+
if (dependency === CORE_PACKAGE) {
|
|
88
|
+
if (!semver.satisfies(coreVersion, range)) {
|
|
89
|
+
notes.push(`It needs ${CORE_PACKAGE} ${range}, and this core is ${coreVersion}, so it will be unavailable.`);
|
|
90
|
+
}
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
if (!installed.has(dependency)) {
|
|
94
|
+
notes.push(`It requires ${dependency} ${range}, which is not installed. Add it with: geekity plugin add ${dependency}`);
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
const version = installed.get(dependency);
|
|
98
|
+
if (version !== undefined && !semver.satisfies(version, range)) {
|
|
99
|
+
notes.push(`It requires ${dependency} ${range}, and ${version} is installed.`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return notes;
|
|
103
|
+
}
|
|
104
|
+
const CORE_PACKAGE = '@geekity/cms';
|
|
105
|
+
async function resolveRelease(spec, registry) {
|
|
106
|
+
const url = new URL(spec.name.replace('/', '%2f'), registry.endsWith('/') ? registry : `${registry}/`);
|
|
107
|
+
const response = await fetch(url, {
|
|
108
|
+
headers: { accept: 'application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8' },
|
|
109
|
+
});
|
|
110
|
+
if (response.status === 404) {
|
|
111
|
+
throw new Error(`${spec.name} is not on the registry at ${registry}.`);
|
|
112
|
+
}
|
|
113
|
+
if (!response.ok) {
|
|
114
|
+
throw new Error(`The registry at ${registry} answered ${String(response.status)} for ${spec.name}.`);
|
|
115
|
+
}
|
|
116
|
+
const document = (await response.json());
|
|
117
|
+
const versions = Object.keys(document.versions ?? {});
|
|
118
|
+
const version = document['dist-tags']?.[spec.wanted] ??
|
|
119
|
+
(semver.valid(spec.wanted) !== null && versions.includes(spec.wanted)
|
|
120
|
+
? spec.wanted
|
|
121
|
+
: semver.validRange(spec.wanted) !== null
|
|
122
|
+
? semver.maxSatisfying(versions, spec.wanted)
|
|
123
|
+
: null);
|
|
124
|
+
const dist = version === null ? undefined : document.versions?.[version]?.dist;
|
|
125
|
+
if (version === null || dist?.tarball === undefined) {
|
|
126
|
+
throw new Error(`${spec.name} has no version matching ${spec.wanted}.`);
|
|
127
|
+
}
|
|
128
|
+
return { version, tarball: dist.tarball, integrity: dist.integrity, shasum: dist.shasum };
|
|
129
|
+
}
|
|
130
|
+
const HASHES = ['sha512', 'sha384', 'sha256', 'sha1'];
|
|
131
|
+
/** Why the tarball does not match what the registry published, or `undefined`. */
|
|
132
|
+
function checkIntegrity(tarball, release) {
|
|
133
|
+
const claims = (release.integrity ?? '').split(/\s+/).filter((claim) => claim !== '');
|
|
134
|
+
for (const algorithm of HASHES) {
|
|
135
|
+
const expected = claims
|
|
136
|
+
.filter((claim) => claim.startsWith(`${algorithm}-`))
|
|
137
|
+
.map((claim) => claim.slice(algorithm.length + 1).replace(/\?.*$/, ''));
|
|
138
|
+
if (expected.length === 0)
|
|
139
|
+
continue;
|
|
140
|
+
const actual = createHash(algorithm).update(tarball).digest('base64');
|
|
141
|
+
return expected.includes(actual)
|
|
142
|
+
? undefined
|
|
143
|
+
: `its ${algorithm} integrity hash does not match the one the registry published.`;
|
|
144
|
+
}
|
|
145
|
+
if (release.shasum !== undefined) {
|
|
146
|
+
return createHash('sha1').update(tarball).digest('hex') === release.shasum.toLowerCase()
|
|
147
|
+
? undefined
|
|
148
|
+
: 'its sha1 hash does not match the one the registry published.';
|
|
149
|
+
}
|
|
150
|
+
return 'the registry published no integrity hash to check it against.';
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* The regular files in a gzipped tar, by path with the archive's top folder
|
|
154
|
+
* (`package/` in an npm tarball) removed. Links and devices are skipped.
|
|
155
|
+
*/
|
|
156
|
+
export function unpackTarball(gzipped) {
|
|
157
|
+
const archive = gunzipSync(gzipped);
|
|
158
|
+
const files = new Map();
|
|
159
|
+
let longName;
|
|
160
|
+
let offset = 0;
|
|
161
|
+
while (offset + 512 <= archive.length) {
|
|
162
|
+
const header = archive.subarray(offset, offset + 512);
|
|
163
|
+
if (header.every((byte) => byte === 0))
|
|
164
|
+
break;
|
|
165
|
+
const size = Number.parseInt(field(header, 124, 12).trim() || '0', 8);
|
|
166
|
+
const type = String.fromCharCode(header[156] ?? 0);
|
|
167
|
+
const body = archive.subarray(offset + 512, offset + 512 + size);
|
|
168
|
+
offset += 512 + Math.ceil(size / 512) * 512;
|
|
169
|
+
if (type === 'x') {
|
|
170
|
+
longName = paxPath(body.toString('utf8')) ?? longName;
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
if (type === 'L') {
|
|
174
|
+
longName = body.toString('utf8').replace(/\0.*$/s, '');
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
const prefix = field(header, 345, 155);
|
|
178
|
+
const name = longName ?? (prefix === '' ? '' : `${prefix}/`) + field(header, 0, 100);
|
|
179
|
+
longName = undefined;
|
|
180
|
+
if (type !== '0' && type !== '\0')
|
|
181
|
+
continue;
|
|
182
|
+
const relative = name.split('/').slice(1).join('/');
|
|
183
|
+
if (relative !== '')
|
|
184
|
+
files.set(relative, Buffer.from(body));
|
|
185
|
+
}
|
|
186
|
+
return files;
|
|
187
|
+
}
|
|
188
|
+
function field(header, start, length) {
|
|
189
|
+
return header
|
|
190
|
+
.subarray(start, start + length)
|
|
191
|
+
.toString('utf8')
|
|
192
|
+
.replace(/\0.*$/s, '');
|
|
193
|
+
}
|
|
194
|
+
function paxPath(records) {
|
|
195
|
+
for (const record of records.split('\n')) {
|
|
196
|
+
const match = /^\d+ path=(.*)$/.exec(record);
|
|
197
|
+
if (match !== null)
|
|
198
|
+
return match[1];
|
|
199
|
+
}
|
|
200
|
+
return undefined;
|
|
201
|
+
}
|
|
202
|
+
/** The files under the package's `dist/bundle/`, by path inside it. Anything that would climb out is refused. */
|
|
203
|
+
function bundleFiles(files) {
|
|
204
|
+
const bundle = new Map();
|
|
205
|
+
for (const [file, bytes] of files) {
|
|
206
|
+
if (!file.startsWith(BUNDLE_PREFIX))
|
|
207
|
+
continue;
|
|
208
|
+
const inside = file.slice(BUNDLE_PREFIX.length);
|
|
209
|
+
const segments = inside.split('/');
|
|
210
|
+
if (segments.some((segment) => segment === '' || segment === '.' || segment === '..')) {
|
|
211
|
+
throw new Error(`The package holds a file the plugins folder cannot take: ${file}.`);
|
|
212
|
+
}
|
|
213
|
+
bundle.set(inside, bytes);
|
|
214
|
+
}
|
|
215
|
+
return bundle;
|
|
216
|
+
}
|
|
217
|
+
function stagedManifest(staging, label, name) {
|
|
218
|
+
let manifest;
|
|
219
|
+
try {
|
|
220
|
+
manifest = readPluginManifest(staging);
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
throw new Error(`${label} was refused: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
224
|
+
}
|
|
225
|
+
if (manifest === undefined)
|
|
226
|
+
throw new Error(`${label} has no ${PLUGIN_MANIFEST}.`);
|
|
227
|
+
if (manifest.name !== name) {
|
|
228
|
+
throw new Error(`${label} was refused: its ${PLUGIN_MANIFEST} names ${manifest.name}.`);
|
|
229
|
+
}
|
|
230
|
+
if (manifest.hostApi > HOST_API_VERSION) {
|
|
231
|
+
throw new Error(`${label} targets host API version ${String(manifest.hostApi)}, and this core provides version ${String(HOST_API_VERSION)}. Upgrade @geekity/cms, or add an older version of the plugin.`);
|
|
232
|
+
}
|
|
233
|
+
return manifest;
|
|
234
|
+
}
|
|
235
|
+
/** Each plugin folder by name, with the version its `plugin.json` names, when it has a usable one. */
|
|
236
|
+
export function installedFolders(pluginsDir) {
|
|
237
|
+
return new Map(scanPluginFolders(pluginsDir).map((folder) => [
|
|
238
|
+
folder.name,
|
|
239
|
+
installedVersion(folder.directory),
|
|
240
|
+
]));
|
|
241
|
+
}
|
|
242
|
+
function installedVersion(directory) {
|
|
243
|
+
try {
|
|
244
|
+
return readPluginManifest(directory)?.version;
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
return undefined;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Put the staged folder where the live one is. A directory cannot be renamed
|
|
252
|
+
* over a full one, so the old one is moved aside first, and back if the second
|
|
253
|
+
* rename fails.
|
|
254
|
+
*/
|
|
255
|
+
async function swapInto(staging, directory) {
|
|
256
|
+
if (!existsSync(directory)) {
|
|
257
|
+
await rename(staging, directory);
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
const old = path.join(path.dirname(directory), hidden('replaced', directory));
|
|
261
|
+
await rename(directory, old);
|
|
262
|
+
try {
|
|
263
|
+
await rename(staging, directory);
|
|
264
|
+
}
|
|
265
|
+
catch (error) {
|
|
266
|
+
await rename(old, directory);
|
|
267
|
+
throw error;
|
|
268
|
+
}
|
|
269
|
+
await rm(old, { recursive: true, force: true });
|
|
270
|
+
}
|
|
271
|
+
/** A dot-prefixed sibling name, which a scan of the plugins folder skips. */
|
|
272
|
+
function hidden(purpose, directory) {
|
|
273
|
+
return `.${purpose}-${path.basename(directory)}-${randomBytes(4).toString('hex')}`;
|
|
274
|
+
}
|
|
275
|
+
//# sourceMappingURL=install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/plugins/install.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Hono, MiddlewareHandler } from 'hono';
|
|
2
|
+
import type { GeekityEnv } from '../env.ts';
|
|
3
|
+
import type { PluginRegistry } from './registry.ts';
|
|
4
|
+
/**
|
|
5
|
+
* Read the enabled set for this request, bring the running plugins into line
|
|
6
|
+
* with it, and put the active set on the context. A site with no plugins
|
|
7
|
+
* reads nothing. A worker draining for a reload has stopped its plugins and
|
|
8
|
+
* leaves them stopped.
|
|
9
|
+
*/
|
|
10
|
+
export declare function pluginLifecycle(registry: PluginRegistry, draining: () => boolean): MiddlewareHandler<GeekityEnv>;
|
|
11
|
+
/**
|
|
12
|
+
* Every available plugin's public routes. A route whose plugin is not active
|
|
13
|
+
* for this request hands on to the next match, so it answers exactly what an
|
|
14
|
+
* absent route would.
|
|
15
|
+
*/
|
|
16
|
+
export declare function mountPluginRoutes(app: Hono<GeekityEnv>, registry: PluginRegistry): void;
|
|
17
|
+
//# sourceMappingURL=mount.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../../src/plugins/mount.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAEpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAIpD;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,MAAM,OAAO,GACtB,iBAAiB,CAAC,UAAU,CAAC,CAY/B;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,IAAI,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI,CAavF"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { readEnabledPlugins } from './enabled.js';
|
|
2
|
+
const NONE = new Set();
|
|
3
|
+
/**
|
|
4
|
+
* Read the enabled set for this request, bring the running plugins into line
|
|
5
|
+
* with it, and put the active set on the context. A site with no plugins
|
|
6
|
+
* reads nothing. A worker draining for a reload has stopped its plugins and
|
|
7
|
+
* leaves them stopped.
|
|
8
|
+
*/
|
|
9
|
+
export function pluginLifecycle(registry, draining) {
|
|
10
|
+
return async (c, next) => {
|
|
11
|
+
c.set('plugins', registry);
|
|
12
|
+
if (registry.plugins.length === 0) {
|
|
13
|
+
c.set('activePlugins', NONE);
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
const enabled = readEnabledPlugins(c.var.config.contentDir);
|
|
17
|
+
if (!draining())
|
|
18
|
+
await registry.reconcile(enabled);
|
|
19
|
+
c.set('activePlugins', registry.active(enabled));
|
|
20
|
+
}
|
|
21
|
+
await next();
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Every available plugin's public routes. A route whose plugin is not active
|
|
26
|
+
* for this request hands on to the next match, so it answers exactly what an
|
|
27
|
+
* absent route would.
|
|
28
|
+
*/
|
|
29
|
+
export function mountPluginRoutes(app, registry) {
|
|
30
|
+
for (const { plugin, problem, routes } of registry.plugins) {
|
|
31
|
+
if (problem !== undefined)
|
|
32
|
+
continue;
|
|
33
|
+
for (const route of routes) {
|
|
34
|
+
app.get(route.path, async (c, next) => {
|
|
35
|
+
if (!c.var.activePlugins.has(plugin.name)) {
|
|
36
|
+
await next();
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
return route.handler({ request: c.req.raw, params: c.req.param() });
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=mount.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mount.js","sourceRoot":"","sources":["../../src/plugins/mount.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAGlD,MAAM,IAAI,GAAwB,IAAI,GAAG,EAAE,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAwB,EACxB,QAAuB;IAEvB,OAAO,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;QACvB,CAAC,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAC3B,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAClC,CAAC,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;QAC/B,CAAC;aAAM,CAAC;YACN,MAAM,OAAO,GAAG,kBAAkB,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAC5D,IAAI,CAAC,QAAQ,EAAE;gBAAE,MAAM,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YACnD,CAAC,CAAC,GAAG,CAAC,eAAe,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;QACnD,CAAC;QACD,MAAM,IAAI,EAAE,CAAC;IACf,CAAC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAqB,EAAE,QAAwB;IAC/E,KAAK,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;QAC3D,IAAI,OAAO,KAAK,SAAS;YAAE,SAAS;QACpC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;gBACpC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC1C,MAAM,IAAI,EAAE,CAAC;oBACb,OAAO;gBACT,CAAC;gBACD,OAAO,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACtE,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The plugin registry (decision-33): every installed plugin, registered once
|
|
3
|
+
* at boot, and what the dependency graph says about each.
|
|
4
|
+
*
|
|
5
|
+
* Installed and enabled are separate. Installed is fixed for the life of the
|
|
6
|
+
* process: the plugins handed to `createCms`. Enabled is the `plugins` key of
|
|
7
|
+
* `site.json`, read per request, so every question that depends on it takes
|
|
8
|
+
* the enabled set as an argument rather than holding one.
|
|
9
|
+
*/
|
|
10
|
+
import type { Plugin, PluginCommand, PluginDataFolder, PluginEditorAction, PluginFederationMiddleware, PluginRouteHandler, PluginScreen, PluginSettingField, PluginSiteInfo } from '../plugin.ts';
|
|
11
|
+
import type { PluginFetchOptions } from './fetch.ts';
|
|
12
|
+
import type { PluginSettingsPlace } from './settings.ts';
|
|
13
|
+
/** A plugin as it arrived, and a description of where it came from. */
|
|
14
|
+
export interface InstalledPlugin {
|
|
15
|
+
plugin: Plugin;
|
|
16
|
+
/** Where it came from, as the Plugins screen and a boot error name it. */
|
|
17
|
+
source: string;
|
|
18
|
+
/**
|
|
19
|
+
* Why it could not be loaded, such as a folder whose module failed to
|
|
20
|
+
* import. Such a plugin is never registered, and `plugin` only names it.
|
|
21
|
+
*/
|
|
22
|
+
problem?: string | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* The ranges a folder install's `plugin.json` names, of `@geekity/cms` and
|
|
25
|
+
* of each plugin it requires. npm checks them for a package it installs.
|
|
26
|
+
*/
|
|
27
|
+
peerDependencies?: Readonly<Record<string, string>> | undefined;
|
|
28
|
+
}
|
|
29
|
+
/** One public route a plugin declared in `register`. */
|
|
30
|
+
export interface PluginRoute {
|
|
31
|
+
path: string;
|
|
32
|
+
handler: PluginRouteHandler;
|
|
33
|
+
}
|
|
34
|
+
/** What a plugin declared in `register`. */
|
|
35
|
+
export interface PluginContributions {
|
|
36
|
+
routes: readonly PluginRoute[];
|
|
37
|
+
federation: readonly PluginFederationMiddleware[];
|
|
38
|
+
screen: PluginScreen | undefined;
|
|
39
|
+
commands: readonly PluginCommand[];
|
|
40
|
+
/** The settings fields it declared, empty when it has none. */
|
|
41
|
+
settings: readonly PluginSettingField[];
|
|
42
|
+
/** Its buttons beside editor fields, in the order it declared them. */
|
|
43
|
+
editorActions: readonly PluginEditorAction[];
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* What plugins read through the registry: the site's folders, its
|
|
47
|
+
* environment, its base URL and title, and which addresses they may fetch.
|
|
48
|
+
*/
|
|
49
|
+
export interface PluginRegistryOptions extends PluginFetchOptions {
|
|
50
|
+
dataDir: string;
|
|
51
|
+
contentDir: string;
|
|
52
|
+
env: Readonly<Record<string, string | undefined>>;
|
|
53
|
+
siteInfo(): PluginSiteInfo;
|
|
54
|
+
}
|
|
55
|
+
/** An installed plugin after registration. */
|
|
56
|
+
export interface RegisteredPlugin extends InstalledPlugin, PluginContributions {
|
|
57
|
+
/** Why it cannot run, or `undefined` when it can be enabled. */
|
|
58
|
+
problem: string | undefined;
|
|
59
|
+
/** Where its settings are read from and written to. */
|
|
60
|
+
settingsPlace: PluginSettingsPlace;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Where one requirement of a plugin stands. `blocked` is a plugin that is
|
|
64
|
+
* enabled but cannot run, because something it requires is not running.
|
|
65
|
+
*/
|
|
66
|
+
export type RequirementState = 'enabled' | 'blocked' | 'disabled' | 'unavailable' | 'missing';
|
|
67
|
+
export interface Requirement {
|
|
68
|
+
name: string;
|
|
69
|
+
range: string;
|
|
70
|
+
state: RequirementState;
|
|
71
|
+
}
|
|
72
|
+
export interface PluginRegistry {
|
|
73
|
+
/** Every installed plugin, in the order it was installed. */
|
|
74
|
+
readonly plugins: readonly RegisteredPlugin[];
|
|
75
|
+
find(name: string): RegisteredPlugin | undefined;
|
|
76
|
+
/** Why the plugin cannot run, or `undefined`. */
|
|
77
|
+
problem(name: string): string | undefined;
|
|
78
|
+
/**
|
|
79
|
+
* The plugins that run under this enabled set: enabled, available, and
|
|
80
|
+
* with everything they require running.
|
|
81
|
+
*/
|
|
82
|
+
active(enabled: ReadonlySet<string>): ReadonlySet<string>;
|
|
83
|
+
/** Each plugin this one requires, and where it stands. */
|
|
84
|
+
requirements(name: string, enabled: ReadonlySet<string>): Requirement[];
|
|
85
|
+
/** The enabled plugins that require this one. */
|
|
86
|
+
enabledDependents(name: string, enabled: ReadonlySet<string>): string[];
|
|
87
|
+
/**
|
|
88
|
+
* Start the plugins that should run and stop the ones that should not, so
|
|
89
|
+
* the running set is {@link PluginRegistry.active}. Safe to call on every
|
|
90
|
+
* request: when nothing changed it does nothing. Calls are serialized.
|
|
91
|
+
*/
|
|
92
|
+
reconcile(enabled: ReadonlySet<string>): Promise<void>;
|
|
93
|
+
/** Stop every running plugin, dependents first. Nothing starts after. */
|
|
94
|
+
close(): Promise<void>;
|
|
95
|
+
}
|
|
96
|
+
/** Two installed plugins with one name. */
|
|
97
|
+
export declare class DuplicatePluginError extends Error {
|
|
98
|
+
constructor(name: string, first: string, second: string);
|
|
99
|
+
}
|
|
100
|
+
/** npm's rule for a package name, scoped or not. */
|
|
101
|
+
export declare const PACKAGE_NAME: RegExp;
|
|
102
|
+
/**
|
|
103
|
+
* Register every installed plugin and resolve the dependency graph. Throws
|
|
104
|
+
* {@link DuplicatePluginError} when two plugins share a name; every other
|
|
105
|
+
* problem leaves that plugin unavailable and the site booting.
|
|
106
|
+
*/
|
|
107
|
+
export declare function createPluginRegistry(installed: readonly InstalledPlugin[], options: PluginRegistryOptions): PluginRegistry;
|
|
108
|
+
/** `data/plugins/<package name>/`, which only its plugin reads and writes. */
|
|
109
|
+
export declare function pluginDataFolder(dataDir: string, name: string): PluginDataFolder;
|
|
110
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/plugins/registry.ts"],"names":[],"mappings":"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"}
|