@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.
Files changed (182) hide show
  1. package/README.md +96 -160
  2. package/admin/pages/documents/editor.njk +48 -0
  3. package/admin/pages/federation/settings.njk +1 -59
  4. package/admin/pages/plugins/installed.njk +113 -0
  5. package/admin/pages/plugins/screen.njk +129 -0
  6. package/admin/static/admin.css +144 -4
  7. package/admin/static/editor-actions.js +202 -0
  8. package/dist/admin/accounts.d.ts +18 -39
  9. package/dist/admin/accounts.d.ts.map +1 -1
  10. package/dist/admin/accounts.js +19 -48
  11. package/dist/admin/accounts.js.map +1 -1
  12. package/dist/admin/documents.d.ts +5 -0
  13. package/dist/admin/documents.d.ts.map +1 -1
  14. package/dist/admin/documents.js +17 -8
  15. package/dist/admin/documents.js.map +1 -1
  16. package/dist/admin/editor-actions.d.ts +35 -0
  17. package/dist/admin/editor-actions.d.ts.map +1 -0
  18. package/dist/admin/editor-actions.js +187 -0
  19. package/dist/admin/editor-actions.js.map +1 -0
  20. package/dist/admin/federation.d.ts +4 -5
  21. package/dist/admin/federation.d.ts.map +1 -1
  22. package/dist/admin/federation.js +4 -5
  23. package/dist/admin/federation.js.map +1 -1
  24. package/dist/admin/index.d.ts +1 -1
  25. package/dist/admin/index.d.ts.map +1 -1
  26. package/dist/admin/index.js +1 -1
  27. package/dist/admin/index.js.map +1 -1
  28. package/dist/admin/menu.d.ts +1 -1
  29. package/dist/admin/menu.d.ts.map +1 -1
  30. package/dist/admin/menu.js +10 -3
  31. package/dist/admin/menu.js.map +1 -1
  32. package/dist/admin/plugins.d.ts +24 -0
  33. package/dist/admin/plugins.d.ts.map +1 -0
  34. package/dist/admin/plugins.js +312 -0
  35. package/dist/admin/plugins.js.map +1 -0
  36. package/dist/admin/routes.d.ts.map +1 -1
  37. package/dist/admin/routes.js +5 -1
  38. package/dist/admin/routes.js.map +1 -1
  39. package/dist/admin/settings-federation.d.ts +0 -25
  40. package/dist/admin/settings-federation.d.ts.map +1 -1
  41. package/dist/admin/settings-federation.js +1 -54
  42. package/dist/admin/settings-federation.js.map +1 -1
  43. package/dist/admin/settings.d.ts +2 -14
  44. package/dist/admin/settings.d.ts.map +1 -1
  45. package/dist/admin/settings.js +1 -21
  46. package/dist/admin/settings.js.map +1 -1
  47. package/dist/admin/store.d.ts +8 -1
  48. package/dist/admin/store.d.ts.map +1 -1
  49. package/dist/admin/store.js +7 -3
  50. package/dist/admin/store.js.map +1 -1
  51. package/dist/admin/templates.d.ts +2 -0
  52. package/dist/admin/templates.d.ts.map +1 -1
  53. package/dist/admin/templates.js +2 -0
  54. package/dist/admin/templates.js.map +1 -1
  55. package/dist/cli.d.ts +2 -3
  56. package/dist/cli.d.ts.map +1 -1
  57. package/dist/cli.js +278 -212
  58. package/dist/cli.js.map +1 -1
  59. package/dist/config.d.ts +20 -0
  60. package/dist/config.d.ts.map +1 -1
  61. package/dist/config.js +6 -0
  62. package/dist/config.js.map +1 -1
  63. package/dist/content/store.d.ts +6 -0
  64. package/dist/content/store.d.ts.map +1 -1
  65. package/dist/content/store.js +3 -0
  66. package/dist/content/store.js.map +1 -1
  67. package/dist/drain.d.ts +28 -0
  68. package/dist/drain.d.ts.map +1 -0
  69. package/dist/drain.js +106 -0
  70. package/dist/drain.js.map +1 -0
  71. package/dist/env.d.ts +11 -0
  72. package/dist/env.d.ts.map +1 -1
  73. package/dist/federation/federation.d.ts +4 -2
  74. package/dist/federation/federation.d.ts.map +1 -1
  75. package/dist/federation/federation.js +16 -21
  76. package/dist/federation/federation.js.map +1 -1
  77. package/dist/federation/inbox.d.ts +23 -3
  78. package/dist/federation/inbox.d.ts.map +1 -1
  79. package/dist/federation/inbox.js +63 -1
  80. package/dist/federation/inbox.js.map +1 -1
  81. package/dist/federation/index.d.ts +0 -4
  82. package/dist/federation/index.d.ts.map +1 -1
  83. package/dist/federation/index.js +0 -2
  84. package/dist/federation/index.js.map +1 -1
  85. package/dist/federation/mount.d.ts +6 -12
  86. package/dist/federation/mount.d.ts.map +1 -1
  87. package/dist/federation/mount.js +3 -50
  88. package/dist/federation/mount.js.map +1 -1
  89. package/dist/federation/queue.d.ts +22 -0
  90. package/dist/federation/queue.d.ts.map +1 -0
  91. package/dist/federation/queue.js +58 -0
  92. package/dist/federation/queue.js.map +1 -0
  93. package/dist/files/atomic.d.ts +13 -0
  94. package/dist/files/atomic.d.ts.map +1 -1
  95. package/dist/files/atomic.js +45 -0
  96. package/dist/files/atomic.js.map +1 -1
  97. package/dist/index.d.ts +30 -3
  98. package/dist/index.d.ts.map +1 -1
  99. package/dist/index.js +156 -79
  100. package/dist/index.js.map +1 -1
  101. package/dist/plugin.d.ts +524 -0
  102. package/dist/plugin.d.ts.map +1 -0
  103. package/dist/plugin.js +23 -0
  104. package/dist/plugin.js.map +1 -0
  105. package/dist/plugins/enabled.d.ts +23 -0
  106. package/dist/plugins/enabled.d.ts.map +1 -0
  107. package/dist/plugins/enabled.js +49 -0
  108. package/dist/plugins/enabled.js.map +1 -0
  109. package/dist/plugins/federation.d.ts +26 -0
  110. package/dist/plugins/federation.d.ts.map +1 -0
  111. package/dist/plugins/federation.js +114 -0
  112. package/dist/plugins/federation.js.map +1 -0
  113. package/dist/plugins/fetch.d.ts +15 -0
  114. package/dist/plugins/fetch.d.ts.map +1 -0
  115. package/dist/plugins/fetch.js +33 -0
  116. package/dist/plugins/fetch.js.map +1 -0
  117. package/dist/plugins/folder.d.ts +50 -0
  118. package/dist/plugins/folder.d.ts.map +1 -0
  119. package/dist/plugins/folder.js +171 -0
  120. package/dist/plugins/folder.js.map +1 -0
  121. package/dist/plugins/install.d.ts +45 -0
  122. package/dist/plugins/install.d.ts.map +1 -0
  123. package/dist/plugins/install.js +275 -0
  124. package/dist/plugins/install.js.map +1 -0
  125. package/dist/plugins/mount.d.ts +17 -0
  126. package/dist/plugins/mount.d.ts.map +1 -0
  127. package/dist/plugins/mount.js +44 -0
  128. package/dist/plugins/mount.js.map +1 -0
  129. package/dist/plugins/registry.d.ts +110 -0
  130. package/dist/plugins/registry.d.ts.map +1 -0
  131. package/dist/plugins/registry.js +447 -0
  132. package/dist/plugins/registry.js.map +1 -0
  133. package/dist/plugins/settings.d.ts +64 -0
  134. package/dist/plugins/settings.d.ts.map +1 -0
  135. package/dist/plugins/settings.js +219 -0
  136. package/dist/plugins/settings.js.map +1 -0
  137. package/dist/plugins/site.d.ts +17 -0
  138. package/dist/plugins/site.d.ts.map +1 -0
  139. package/dist/plugins/site.js +67 -0
  140. package/dist/plugins/site.js.map +1 -0
  141. package/dist/supervisor/primary.d.ts +47 -0
  142. package/dist/supervisor/primary.d.ts.map +1 -0
  143. package/dist/supervisor/primary.js +208 -0
  144. package/dist/supervisor/primary.js.map +1 -0
  145. package/dist/supervisor/protocol.d.ts +37 -0
  146. package/dist/supervisor/protocol.d.ts.map +1 -0
  147. package/dist/supervisor/protocol.js +29 -0
  148. package/dist/supervisor/protocol.js.map +1 -0
  149. package/dist/supervisor/supervision.d.ts +25 -0
  150. package/dist/supervisor/supervision.d.ts.map +1 -0
  151. package/dist/supervisor/supervision.js +7 -0
  152. package/dist/supervisor/supervision.js.map +1 -0
  153. package/dist/supervisor/worker.d.ts +29 -0
  154. package/dist/supervisor/worker.d.ts.map +1 -0
  155. package/dist/supervisor/worker.js +97 -0
  156. package/dist/supervisor/worker.js.map +1 -0
  157. package/dist/web/maintenance.d.ts +2 -2
  158. package/dist/web/maintenance.js +2 -2
  159. package/dist/web/negotiate.d.ts +4 -3
  160. package/dist/web/negotiate.d.ts.map +1 -1
  161. package/dist/web/negotiate.js +4 -3
  162. package/dist/web/negotiate.js.map +1 -1
  163. package/dist/web/routes.d.ts.map +1 -1
  164. package/dist/web/routes.js +33 -14
  165. package/dist/web/routes.js.map +1 -1
  166. package/package.json +10 -1
  167. package/dist/comments/conversation.d.ts +0 -29
  168. package/dist/comments/conversation.d.ts.map +0 -1
  169. package/dist/comments/conversation.js +0 -60
  170. package/dist/comments/conversation.js.map +0 -1
  171. package/dist/federation/import-wordpress.d.ts +0 -128
  172. package/dist/federation/import-wordpress.d.ts.map +0 -1
  173. package/dist/federation/import-wordpress.js +0 -426
  174. package/dist/federation/import-wordpress.js.map +0 -1
  175. package/dist/federation/wordpress.d.ts +0 -131
  176. package/dist/federation/wordpress.d.ts.map +0 -1
  177. package/dist/federation/wordpress.js +0 -342
  178. package/dist/federation/wordpress.js.map +0 -1
  179. package/dist/web/comments.d.ts +0 -60
  180. package/dist/web/comments.d.ts.map +0 -1
  181. package/dist/web/comments.js +0 -207
  182. package/dist/web/comments.js.map +0 -1
@@ -0,0 +1,26 @@
1
+ /**
2
+ * The federation phase plugins answer in (decision-33): after the canonical
3
+ * federation, before stored ids. A plugin running a federation of its own
4
+ * reaches the site's through {@link PluginFederationContext}, and everything
5
+ * that crosses is plain data, because a bundled plugin carries its own copy
6
+ * of Fedify and an object built by one copy fails the other's type checks.
7
+ */
8
+ import type { KvStore } from '@fedify/fedify';
9
+ import type { MiddlewareHandler } from 'hono';
10
+ import type { GeekityEnv } from '../env.ts';
11
+ import type { SiteFederation } from '../federation/federation.ts';
12
+ import type { PluginRegistry } from './registry.ts';
13
+ /** What every plugin federation shares with the site's own. */
14
+ export interface PluginFederationOptions {
15
+ registry: PluginRegistry;
16
+ canonical: SiteFederation;
17
+ kv: KvStore;
18
+ allowPrivateAddress: boolean;
19
+ }
20
+ /**
21
+ * Run each active plugin's federation middleware in turn. A request no
22
+ * plugin answers, and every request while none is active, goes on to the
23
+ * rest of the site.
24
+ */
25
+ export declare function pluginFederation(options: PluginFederationOptions): MiddlewareHandler<GeekityEnv>;
26
+ //# sourceMappingURL=federation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"federation.d.ts","sourceRoot":"","sources":["../../src/plugins/federation.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,KAAK,EAAW,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAGvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAG5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAWlE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD,+DAA+D;AAC/D,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,cAAc,CAAC;IACzB,SAAS,EAAE,cAAc,CAAC;IAC1B,EAAE,EAAE,OAAO,CAAC;IACZ,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,iBAAiB,CAAC,UAAU,CAAC,CAsBhG"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * The federation phase plugins answer in (decision-33): after the canonical
3
+ * federation, before stored ids. A plugin running a federation of its own
4
+ * reaches the site's through {@link PluginFederationContext}, and everything
5
+ * that crosses is plain data, because a bundled plugin carries its own copy
6
+ * of Fedify and an object built by one copy fails the other's type checks.
7
+ */
8
+ import { listUsers } from '../admin/accounts.js';
9
+ import { userActor, userByUsername } from '../federation/actor.js';
10
+ import { lastOutboxCursor, outboxPage } from '../federation/federation.js';
11
+ import { followersPage, lastFollowersCursor } from '../federation/followers.js';
12
+ import { receiveActivity } from '../federation/inbox.js';
13
+ import { loadActorKeyPairs } from '../federation/keys.js';
14
+ import { contextData } from '../federation/mount.js';
15
+ import { authorNames } from '../web/authors.js';
16
+ import { pluginSite } from './site.js';
17
+ /**
18
+ * Run each active plugin's federation middleware in turn. A request no
19
+ * plugin answers, and every request while none is active, goes on to the
20
+ * rest of the site.
21
+ */
22
+ export function pluginFederation(options) {
23
+ const mounted = options.registry.plugins.filter((entry) => entry.problem === undefined && entry.federation.length > 0);
24
+ return async (c, next) => {
25
+ const running = mounted
26
+ .filter((entry) => c.var.activePlugins.has(entry.plugin.name))
27
+ .flatMap((entry) => entry.federation);
28
+ if (running.length === 0)
29
+ return await next();
30
+ const context = federationContext(c, options);
31
+ const dispatch = async (index) => {
32
+ const middleware = running[index];
33
+ if (middleware === undefined) {
34
+ await next();
35
+ return c.res;
36
+ }
37
+ return await middleware(context, () => dispatch(index + 1));
38
+ };
39
+ return await dispatch(0);
40
+ };
41
+ }
42
+ function federationContext(c, options) {
43
+ const { config } = c.var;
44
+ const canonical = () => options.canonical.createContext(c.req.raw, contextData(c));
45
+ const userNamed = (username) => userByUsername(config.dataDir, username);
46
+ return {
47
+ request: c.req.raw,
48
+ site: pluginSite({ admin: c.var.admin, config }),
49
+ kv: options.kv,
50
+ allowPrivateAddress: options.allowPrivateAddress,
51
+ now: () => config.now(),
52
+ async actor(username) {
53
+ const user = userNamed(username);
54
+ if (user === undefined)
55
+ return undefined;
56
+ const context = canonical();
57
+ const actor = await userActor(context, user, { baseUrl: config.baseUrl });
58
+ return (await actor.toJsonLd({ contextLoader: context.contextLoader }));
59
+ },
60
+ async keyPairs(username) {
61
+ if (userNamed(username) === undefined)
62
+ return [];
63
+ return await loadActorKeyPairs(config.dataDir, username);
64
+ },
65
+ outbox(username) {
66
+ const user = userNamed(username);
67
+ if (user === undefined)
68
+ return undefined;
69
+ const names = authorNames(listUsers(config.dataDir), user);
70
+ const totalItems = c.var.store.countByAuthor(names);
71
+ return {
72
+ totalItems,
73
+ firstCursor: '0',
74
+ lastCursor: lastOutboxCursor(totalItems),
75
+ async page(cursor) {
76
+ const context = canonical();
77
+ const page = outboxPage(context, names, cursor);
78
+ const items = await Promise.all(page.items.map(async (item) => (await item.toJsonLd({ contextLoader: context.contextLoader }))));
79
+ return {
80
+ items,
81
+ nextCursor: page.nextCursor ?? null,
82
+ prevCursor: page.prevCursor ?? null,
83
+ };
84
+ },
85
+ };
86
+ },
87
+ followers(username) {
88
+ if (userNamed(username) === undefined)
89
+ return undefined;
90
+ const totalItems = c.var.admin.countFollowers(username);
91
+ return {
92
+ totalItems,
93
+ firstCursor: '0',
94
+ lastCursor: lastFollowersCursor(totalItems),
95
+ page(cursor) {
96
+ const page = followersPage(canonical(), username, cursor);
97
+ return Promise.resolve({
98
+ items: page.items.map((recipient) => ({
99
+ id: recipient.id?.href ?? '',
100
+ inboxId: recipient.inboxId?.href ?? '',
101
+ sharedInboxId: recipient.endpoints?.sharedInbox?.href ?? null,
102
+ })),
103
+ nextCursor: page.nextCursor ?? null,
104
+ prevCursor: page.prevCursor ?? null,
105
+ });
106
+ },
107
+ };
108
+ },
109
+ async receive(activity, recipient) {
110
+ await receiveActivity(canonical(), activity, recipient);
111
+ },
112
+ };
113
+ }
114
+ //# sourceMappingURL=federation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"federation.js","sourceRoot":"","sources":["../../src/plugins/federation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * A plugin's outbound fetch (decision-33): `GET` another site's URL with the
3
+ * rule the site's federation keeps, so a plugin cannot be steered into the
4
+ * site's own network unless the site allows private addresses.
5
+ */
6
+ import type { PluginFetchInit } from '../plugin.ts';
7
+ import type { HostLookup } from '../webmention/public-address.ts';
8
+ /** What decides which addresses a plugin may reach. */
9
+ export interface PluginFetchOptions {
10
+ /** The site federation's own switch; on only for tests and private networks. */
11
+ allowPrivateAddress: boolean;
12
+ lookup: HostLookup;
13
+ }
14
+ export declare function pluginFetch(target: string, init: PluginFetchInit, options: PluginFetchOptions): Promise<Response>;
15
+ //# sourceMappingURL=fetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/plugins/fetch.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAGpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAKlE,uDAAuD;AACvD,MAAM,WAAW,kBAAkB;IACjC,gFAAgF;IAChF,mBAAmB,EAAE,OAAO,CAAC;IAC7B,MAAM,EAAE,UAAU,CAAC;CACpB;AAED,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,eAAe,EACrB,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,QAAQ,CAAC,CAqBnB"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * A plugin's outbound fetch (decision-33): `GET` another site's URL with the
3
+ * rule the site's federation keeps, so a plugin cannot be steered into the
4
+ * site's own network unless the site allows private addresses.
5
+ */
6
+ import { webUrl } from '../webmention/fetch-public.js';
7
+ import { publicHost } from '../webmention/public-address.js';
8
+ /** How many redirects are followed, each one checked like the first. */
9
+ const MAX_REDIRECTS = 5;
10
+ export async function pluginFetch(target, init, options) {
11
+ let at = target;
12
+ for (let hop = 0;; hop += 1) {
13
+ const url = webUrl(at);
14
+ if (url === undefined)
15
+ throw new Error(`${at} is not an http or https URL.`);
16
+ if (!options.allowPrivateAddress && !(await publicHost(url.hostname, options.lookup))) {
17
+ throw new Error(`${url.href} is not a public address.`);
18
+ }
19
+ const response = await fetch(url, {
20
+ ...(init.headers === undefined ? {} : { headers: init.headers }),
21
+ ...(init.signal === undefined ? {} : { signal: init.signal }),
22
+ redirect: 'manual',
23
+ });
24
+ const location = response.headers.get('location');
25
+ if (response.status < 300 || response.status >= 400 || location === null)
26
+ return response;
27
+ await response.body?.cancel();
28
+ if (hop === MAX_REDIRECTS)
29
+ throw new Error(`${target} redirected too many times.`);
30
+ at = new URL(location, url).href;
31
+ }
32
+ }
33
+ //# sourceMappingURL=fetch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../src/plugins/fetch.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAG7D,wEAAwE;AACxE,MAAM,aAAa,GAAG,CAAC,CAAC;AASxB,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAc,EACd,IAAqB,EACrB,OAA2B;IAE3B,IAAI,EAAE,GAAG,MAAM,CAAC;IAChB,KAAK,IAAI,GAAG,GAAG,CAAC,GAAI,GAAG,IAAI,CAAC,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;QACvB,IAAI,GAAG,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,GAAG,EAAE,+BAA+B,CAAC,CAAC;QAC7E,IAAI,CAAC,OAAO,CAAC,mBAAmB,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;YACtF,MAAM,IAAI,KAAK,CAAC,GAAG,GAAG,CAAC,IAAI,2BAA2B,CAAC,CAAC;QAC1D,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,GAAG,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;YAChE,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;YAC7D,QAAQ,EAAE,QAAQ;SACnB,CAAC,CAAC;QACH,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAClD,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,IAAI,QAAQ,KAAK,IAAI;YAAE,OAAO,QAAQ,CAAC;QAE1F,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QAC9B,IAAI,GAAG,KAAK,aAAa;YAAE,MAAM,IAAI,KAAK,CAAC,GAAG,MAAM,6BAA6B,CAAC,CAAC;QACnF,EAAE,GAAG,IAAI,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC;IACnC,CAAC;AACH,CAAC"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * The plugins folder (decision-33): one folder per plugin, `<name>/` or
3
+ * `@scope/<name>/`, each with a bundled `index.js` whose default export is
4
+ * the plugin, and the `plugin.json` manifest the bundle build writes beside
5
+ * it. `geekity serve` imports them at boot. The Plugins screen
6
+ * compares the folder with what the running worker loaded and offers Reload
7
+ * when they differ (TASK-288).
8
+ */
9
+ import type { InstalledPlugin } from './registry.ts';
10
+ export declare const PLUGIN_ENTRY = "index.js";
11
+ export declare const PLUGIN_MANIFEST = "plugin.json";
12
+ /**
13
+ * `plugin.json`: what the bundle build writes from the package's
14
+ * `package.json`, so a folder install can be checked without npm.
15
+ */
16
+ export interface PluginManifest {
17
+ readonly name: string;
18
+ readonly version: string;
19
+ readonly hostApi: number;
20
+ /** The ranges of `@geekity/cms` and of each plugin package it requires. */
21
+ readonly peerDependencies: Readonly<Record<string, string>>;
22
+ }
23
+ /** One plugin's folder as it stood when it was scanned. */
24
+ export interface PluginFolder {
25
+ /** Its package name: the folder's path under the plugins folder. */
26
+ readonly name: string;
27
+ readonly directory: string;
28
+ /** A hash of every file in it, so a replaced bundle reads as changed. */
29
+ readonly fingerprint: string;
30
+ }
31
+ export interface PluginFolderChanges {
32
+ readonly added: readonly string[];
33
+ readonly removed: readonly string[];
34
+ readonly updated: readonly string[];
35
+ }
36
+ /** Every plugin folder, by name. A missing folder, or none named, holds none. */
37
+ export declare function scanPluginFolders(pluginsDir: string | undefined): PluginFolder[];
38
+ /** What changed between two scans, or `undefined` when nothing did. */
39
+ export declare function pluginFolderChanges(loaded: readonly PluginFolder[], current: readonly PluginFolder[]): PluginFolderChanges | undefined;
40
+ /**
41
+ * Import each folder's bundle. A folder that cannot be loaded comes back as
42
+ * an unavailable plugin, named by its folder, so the site still boots.
43
+ */
44
+ export declare function importPluginFolders(folders: readonly PluginFolder[]): Promise<InstalledPlugin[]>;
45
+ /**
46
+ * The folder's `plugin.json`, or `undefined` when it has none, as a folder
47
+ * copied by hand may not. Throws when the file is there but unusable.
48
+ */
49
+ export declare function readPluginManifest(directory: string): PluginManifest | undefined;
50
+ //# sourceMappingURL=folder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"folder.d.ts","sourceRoot":"","sources":["../../src/plugins/folder.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AASH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,eAAO,MAAM,YAAY,aAAa,CAAC;AACvC,eAAO,MAAM,eAAe,gBAAgB,CAAC;AAE7C;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,2EAA2E;IAC3E,QAAQ,CAAC,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC7D;AAED,2DAA2D;AAC3D,MAAM,WAAW,YAAY;IAC3B,oEAAoE;IACpE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,yEAAyE;IACzE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED,iFAAiF;AACjF,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,YAAY,EAAE,CAahF;AAED,uEAAuE;AACvE,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,SAAS,YAAY,EAAE,EAC/B,OAAO,EAAE,SAAS,YAAY,EAAE,GAC/B,mBAAmB,GAAG,SAAS,CAWjC;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,SAAS,YAAY,EAAE,GAC/B,OAAO,CAAC,eAAe,EAAE,CAAC,CAmB5B;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CA4BhF"}
@@ -0,0 +1,171 @@
1
+ /**
2
+ * The plugins folder (decision-33): one folder per plugin, `<name>/` or
3
+ * `@scope/<name>/`, each with a bundled `index.js` whose default export is
4
+ * the plugin, and the `plugin.json` manifest the bundle build writes beside
5
+ * it. `geekity serve` imports them at boot. The Plugins screen
6
+ * compares the folder with what the running worker loaded and offers Reload
7
+ * when they differ (TASK-288).
8
+ */
9
+ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
10
+ if (typeof path === "string" && /^\.\.?\//.test(path)) {
11
+ return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
12
+ return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
13
+ });
14
+ }
15
+ return path;
16
+ };
17
+ import { createHash } from 'node:crypto';
18
+ import { existsSync, readdirSync, readFileSync } from 'node:fs';
19
+ import path from 'node:path';
20
+ import { pathToFileURL } from 'node:url';
21
+ import { HOST_API_VERSION } from '../plugin.js';
22
+ export const PLUGIN_ENTRY = 'index.js';
23
+ export const PLUGIN_MANIFEST = 'plugin.json';
24
+ /** Every plugin folder, by name. A missing folder, or none named, holds none. */
25
+ export function scanPluginFolders(pluginsDir) {
26
+ if (pluginsDir === undefined)
27
+ return [];
28
+ const folders = [];
29
+ for (const entry of subdirectories(pluginsDir)) {
30
+ if (!entry.startsWith('@')) {
31
+ folders.push(folder(pluginsDir, entry));
32
+ continue;
33
+ }
34
+ for (const scoped of subdirectories(path.join(pluginsDir, entry))) {
35
+ folders.push(folder(pluginsDir, `${entry}/${scoped}`));
36
+ }
37
+ }
38
+ return folders.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
39
+ }
40
+ /** What changed between two scans, or `undefined` when nothing did. */
41
+ export function pluginFolderChanges(loaded, current) {
42
+ const before = new Map(loaded.map((entry) => [entry.name, entry.fingerprint]));
43
+ const now = new Map(current.map((entry) => [entry.name, entry.fingerprint]));
44
+ const added = current.filter((entry) => !before.has(entry.name)).map((entry) => entry.name);
45
+ const removed = loaded.filter((entry) => !now.has(entry.name)).map((entry) => entry.name);
46
+ const updated = current
47
+ .filter((entry) => before.has(entry.name) && before.get(entry.name) !== entry.fingerprint)
48
+ .map((entry) => entry.name);
49
+ return added.length + removed.length + updated.length === 0
50
+ ? undefined
51
+ : { added, removed, updated };
52
+ }
53
+ /**
54
+ * Import each folder's bundle. A folder that cannot be loaded comes back as
55
+ * an unavailable plugin, named by its folder, so the site still boots.
56
+ */
57
+ export async function importPluginFolders(folders) {
58
+ const installed = [];
59
+ for (const { name, directory } of folders) {
60
+ const source = `the plugins folder, ${name}`;
61
+ let manifest;
62
+ try {
63
+ manifest = readPluginManifest(directory);
64
+ }
65
+ catch (error) {
66
+ installed.push({ plugin: placeholder(name), source, problem: messageOf(error) });
67
+ continue;
68
+ }
69
+ const loaded = await importBundle(directory);
70
+ installed.push(typeof loaded === 'string'
71
+ ? { plugin: placeholder(name, manifest?.version), source, problem: loaded }
72
+ : { plugin: loaded, source, peerDependencies: manifest?.peerDependencies });
73
+ }
74
+ return installed;
75
+ }
76
+ /**
77
+ * The folder's `plugin.json`, or `undefined` when it has none, as a folder
78
+ * copied by hand may not. Throws when the file is there but unusable.
79
+ */
80
+ export function readPluginManifest(directory) {
81
+ let text;
82
+ try {
83
+ text = readFileSync(path.join(directory, PLUGIN_MANIFEST), 'utf8');
84
+ }
85
+ catch {
86
+ return undefined;
87
+ }
88
+ let value;
89
+ try {
90
+ value = JSON.parse(text);
91
+ }
92
+ catch {
93
+ throw new Error(`Its ${PLUGIN_MANIFEST} is not JSON.`);
94
+ }
95
+ const manifest = value;
96
+ const peers = manifest?.peerDependencies;
97
+ if (typeof manifest?.name !== 'string' ||
98
+ typeof manifest.version !== 'string' ||
99
+ !Number.isInteger(manifest.hostApi) ||
100
+ typeof peers !== 'object' ||
101
+ peers === null ||
102
+ !Object.values(peers).every((range) => typeof range === 'string')) {
103
+ throw new Error(`Its ${PLUGIN_MANIFEST} needs a name, a version, a hostApi number and peerDependencies.`);
104
+ }
105
+ return manifest;
106
+ }
107
+ /** The bundle's plugin, or why it could not be loaded. */
108
+ async function importBundle(directory) {
109
+ const entry = path.join(directory, PLUGIN_ENTRY);
110
+ if (!existsSync(entry))
111
+ return `It has no ${PLUGIN_ENTRY}.`;
112
+ let module;
113
+ try {
114
+ module = (await import(__rewriteRelativeImportExtension(pathToFileURL(entry).href)));
115
+ }
116
+ catch (error) {
117
+ return `Its ${PLUGIN_ENTRY} failed to load: ${messageOf(error)}`;
118
+ }
119
+ return isPlugin(module.default)
120
+ ? module.default
121
+ : `Its ${PLUGIN_ENTRY} does not export a plugin as its default export.`;
122
+ }
123
+ /** What the Plugins screen shows of a plugin it could not load. */
124
+ function placeholder(name, version = '') {
125
+ return {
126
+ name,
127
+ version,
128
+ label: name,
129
+ description: '',
130
+ hostApi: HOST_API_VERSION,
131
+ register() { },
132
+ };
133
+ }
134
+ function messageOf(error) {
135
+ return error instanceof Error ? error.message : String(error);
136
+ }
137
+ function folder(pluginsDir, name) {
138
+ const directory = path.join(pluginsDir, ...name.split('/'));
139
+ const hash = createHash('sha256');
140
+ for (const file of filesUnder(directory)) {
141
+ hash.update(path.relative(directory, file));
142
+ hash.update('\0');
143
+ hash.update(readFileSync(file));
144
+ hash.update('\0');
145
+ }
146
+ return { name, directory, fingerprint: hash.digest('hex') };
147
+ }
148
+ /** Visible subdirectories: a folder being written beside the live one starts with a dot. */
149
+ function subdirectories(directory) {
150
+ try {
151
+ return readdirSync(directory, { withFileTypes: true })
152
+ .filter((entry) => entry.isDirectory() && !entry.name.startsWith('.'))
153
+ .map((entry) => entry.name);
154
+ }
155
+ catch {
156
+ return [];
157
+ }
158
+ }
159
+ function filesUnder(directory) {
160
+ return readdirSync(directory, { withFileTypes: true, recursive: true })
161
+ .filter((entry) => entry.isFile())
162
+ .map((entry) => path.join(entry.parentPath, entry.name))
163
+ .sort();
164
+ }
165
+ function isPlugin(value) {
166
+ return (typeof value === 'object' &&
167
+ value !== null &&
168
+ typeof value.name === 'string' &&
169
+ typeof value.register === 'function');
170
+ }
171
+ //# sourceMappingURL=folder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"folder.js","sourceRoot":"","sources":["../../src/plugins/folder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
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 type { PluginManifest } from './folder.ts';
11
+ export declare const DEFAULT_REGISTRY = "https://registry.npmjs.org/";
12
+ export interface PackageSpec {
13
+ name: string;
14
+ /** A version, a dist-tag or a range; `latest` when none was given. */
15
+ wanted: string;
16
+ }
17
+ /** `@scope/name@1.2.3`, `name@next` or a bare name. */
18
+ export declare function parsePackageSpec(spec: string): PackageSpec;
19
+ export interface AddedPlugin {
20
+ manifest: PluginManifest;
21
+ directory: string;
22
+ /** The version it replaced, when the folder held one. */
23
+ replaced: string | undefined;
24
+ }
25
+ /** Fetch, check and install one plugin package. Throws, leaving the folder alone, when it cannot. */
26
+ export declare function addPlugin(spec: PackageSpec, options: {
27
+ pluginsDir: string;
28
+ registry: string;
29
+ }): Promise<AddedPlugin>;
30
+ /** Delete a plugin's folder. Throws when there is none. */
31
+ export declare function removePlugin(name: string, pluginsDir: string): Promise<string>;
32
+ /**
33
+ * A line for each plugin the manifest requires that is not installed or not
34
+ * in range, and for a core out of range. `installed` maps each installed
35
+ * plugin to its version, or to `undefined` when that is not known.
36
+ */
37
+ export declare function requirementNotes(manifest: PluginManifest, installed: ReadonlyMap<string, string | undefined>, coreVersion: string): string[];
38
+ /**
39
+ * The regular files in a gzipped tar, by path with the archive's top folder
40
+ * (`package/` in an npm tarball) removed. Links and devices are skipped.
41
+ */
42
+ export declare function unpackTarball(gzipped: Buffer): Map<string, Buffer>;
43
+ /** Each plugin folder by name, with the version its `plugin.json` names, when it has a usable one. */
44
+ export declare function installedFolders(pluginsDir: string): Map<string, string | undefined>;
45
+ //# sourceMappingURL=install.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/plugins/install.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAYH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGlD,eAAO,MAAM,gBAAgB,gCAAgC,CAAC;AAK9D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,sEAAsE;IACtE,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,uDAAuD;AACvD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAU1D;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,cAAc,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9B;AAED,qGAAqG;AACrG,wBAAsB,SAAS,CAC7B,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAChD,OAAO,CAAC,WAAW,CAAC,CAuCtB;AAED,2DAA2D;AAC3D,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CASpF;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,cAAc,EACxB,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EAClD,WAAW,EAAE,MAAM,GAClB,MAAM,EAAE,CAuBV;AA0ED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CA6BlE;AAsDD,sGAAsG;AACtG,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAOpF"}