mikser-io 10.14.0 → 11.0.2
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/package.json +1 -1
- package/src/inventory.js +43 -33
- package/src/plugins/api.js +5 -0
- package/src/plugins/commands.js +1 -1
- package/src/plugins/data.js +5 -0
- package/src/plugins/documents.js +1 -1
- package/src/plugins/files.js +1 -0
- package/src/plugins/front-matter.js +5 -0
- package/src/plugins/json.js +5 -0
- package/src/plugins/mapper.js +5 -0
- package/src/plugins/observer.js +1 -0
- package/src/plugins/preview.js +1 -1
- package/src/plugins/render/file.js +1 -1
- package/src/plugins/render/hbs.js +1 -0
- package/src/plugins/render/href.js +1 -1
- package/src/plugins/render/resource.js +1 -1
- package/src/plugins/resources.js +1 -0
- package/src/plugins/shares.js +5 -0
- package/src/plugins/sources.js +7 -2
- package/src/plugins/validator.js +5 -0
- package/src/plugins/yaml.js +5 -0
- package/src/plugins.js +78 -2
package/package.json
CHANGED
package/src/inventory.js
CHANGED
|
@@ -30,39 +30,29 @@ function repositoryUrl(repository) {
|
|
|
30
30
|
.replace(/\.git$/, '')
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
//
|
|
33
|
+
// Every mikser package INSTALLED beside this one, described.
|
|
34
34
|
//
|
|
35
|
-
//
|
|
36
|
-
//
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
// A lifecycle plugin that mounts nothing is recognised by the surface it
|
|
53
|
-
// publishes on the runtime.
|
|
54
|
-
if (runtime.options?.layouts) active.add('mikser-io-layouts')
|
|
55
|
-
if (runtime.options?.preview) active.add('mikser-io-preview')
|
|
56
|
-
// The engine itself is always running; saying otherwise would be odd.
|
|
57
|
-
active.add('mikser-io')
|
|
58
|
-
return active
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Every mikser package installed beside this one, described.
|
|
35
|
+
// Installed, and nothing more. This list used to carry an `active` flag,
|
|
36
|
+
// derived by probing whatever surfaces a plugin happened to expose — a route
|
|
37
|
+
// here, a CLI flag there. Two things were wrong with it and only the second
|
|
38
|
+
// was dangerous.
|
|
39
|
+
//
|
|
40
|
+
// The probe went stale silently: it tested `runtime.options.layouts`, which
|
|
41
|
+
// stopped being layouts' API object two majors ago and is now the `--layouts`
|
|
42
|
+
// folder flag, so layouts read as inactive on every site that did not pass a
|
|
43
|
+
// flag it has no reason to pass. It also tested `runtime.options.preview` for
|
|
44
|
+
// a package, `mikser-io-preview`, that does not exist.
|
|
45
|
+
//
|
|
46
|
+
// And the flag was three-valued in code and two-valued in its contract:
|
|
47
|
+
// present meant running, absent meant EITHER not running or not detectable,
|
|
48
|
+
// and an agent told to read it "to know what the system can do" could only
|
|
49
|
+
// read absence as off. On a real site that said no schema validation and no
|
|
50
|
+
// git sync while both were running — and git sync is the only route by which
|
|
51
|
+
// an agent's own edit reaches the repository.
|
|
62
52
|
//
|
|
63
|
-
//
|
|
64
|
-
//
|
|
65
|
-
//
|
|
53
|
+
// What is running is now answered by the runtime recording what it loads, in
|
|
54
|
+
// plugins.js. This answers a different and still useful question: what is on
|
|
55
|
+
// disk, what version, and where to read about it.
|
|
66
56
|
export function inventory({ workingFolder = runtime.options?.workingFolder } = {}) {
|
|
67
57
|
const root = path.join(workingFolder ?? '.', 'node_modules')
|
|
68
58
|
let names = []
|
|
@@ -72,7 +62,6 @@ export function inventory({ workingFolder = runtime.options?.workingFolder } = {
|
|
|
72
62
|
return []
|
|
73
63
|
}
|
|
74
64
|
|
|
75
|
-
const active = activeNames()
|
|
76
65
|
const plugins = []
|
|
77
66
|
for (const name of names.sort()) {
|
|
78
67
|
try {
|
|
@@ -82,7 +71,6 @@ export function inventory({ workingFolder = runtime.options?.workingFolder } = {
|
|
|
82
71
|
name,
|
|
83
72
|
version: manifest.version ?? null,
|
|
84
73
|
...(manifest.description ? { summary: manifest.description } : {}),
|
|
85
|
-
...(active.has(name) ? { active: true } : {}),
|
|
86
74
|
...(manifest.homepage ? { homepage: manifest.homepage } : {}),
|
|
87
75
|
...(repository ? { repository } : {}),
|
|
88
76
|
npm: `https://www.npmjs.com/package/${name}`,
|
|
@@ -91,3 +79,25 @@ export function inventory({ workingFolder = runtime.options?.workingFolder } = {
|
|
|
91
79
|
}
|
|
92
80
|
return plugins
|
|
93
81
|
}
|
|
82
|
+
|
|
83
|
+
// What this runtime LOADED — the answer to "what is running".
|
|
84
|
+
//
|
|
85
|
+
// Read from the record plugins.js keeps as it loads, not derived from
|
|
86
|
+
// surfaces afterwards. Every loaded plugin appears, including one that named
|
|
87
|
+
// nothing: `package: null` means "running, and did not say what it is", which
|
|
88
|
+
// is a different statement from not running and must never be collapsed into
|
|
89
|
+
// one. Nothing here is ever absent because it could not be detected — a plugin
|
|
90
|
+
// that is loaded is in this list.
|
|
91
|
+
export function loadedPlugins({ workingFolder = runtime.options?.workingFolder } = {}) {
|
|
92
|
+
const root = path.join(workingFolder ?? '.', 'node_modules')
|
|
93
|
+
const versionOf = (name) => {
|
|
94
|
+
if (!name) return null
|
|
95
|
+
try {
|
|
96
|
+
return JSON.parse(readFileSync(path.join(root, name, 'package.json'), 'utf8')).version ?? null
|
|
97
|
+
} catch { return null }
|
|
98
|
+
}
|
|
99
|
+
return (runtime.plugins ?? []).map(entry => ({
|
|
100
|
+
...entry,
|
|
101
|
+
...(entry.package ? { version: versionOf(entry.package) } : {}),
|
|
102
|
+
}))
|
|
103
|
+
}
|
package/src/plugins/api.js
CHANGED
|
@@ -1209,5 +1209,10 @@ export function api(options = {}) {
|
|
|
1209
1209
|
}
|
|
1210
1210
|
}
|
|
1211
1211
|
})
|
|
1212
|
+
|
|
1213
|
+
// Names this package to the runtime's loaded-plugin record — see
|
|
1214
|
+
// plugins.js. A plugin that declares nothing still reports as loaded,
|
|
1215
|
+
// but as `package: null`.
|
|
1216
|
+
return { module: import.meta.url }
|
|
1212
1217
|
}
|
|
1213
1218
|
}
|
package/src/plugins/commands.js
CHANGED
package/src/plugins/data.js
CHANGED
|
@@ -216,5 +216,10 @@ export function data(options = {}) {
|
|
|
216
216
|
}
|
|
217
217
|
}
|
|
218
218
|
})
|
|
219
|
+
|
|
220
|
+
// Names this package to the runtime's loaded-plugin record — see
|
|
221
|
+
// plugins.js. A plugin that declares nothing still reports as loaded,
|
|
222
|
+
// but as `package: null`.
|
|
223
|
+
return { module: import.meta.url }
|
|
219
224
|
}
|
|
220
225
|
}
|
package/src/plugins/documents.js
CHANGED
package/src/plugins/files.js
CHANGED
|
@@ -20,5 +20,10 @@ export function frontMatter(options = {}) {
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
})
|
|
23
|
+
|
|
24
|
+
// Names this package to the runtime's loaded-plugin record — see
|
|
25
|
+
// plugins.js. A plugin that declares nothing still reports as loaded,
|
|
26
|
+
// but as `package: null`.
|
|
27
|
+
return { module: import.meta.url }
|
|
23
28
|
}
|
|
24
29
|
}
|
package/src/plugins/json.js
CHANGED
|
@@ -16,5 +16,10 @@ export function json(options = {}) {
|
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
})
|
|
19
|
+
|
|
20
|
+
// Names this package to the runtime's loaded-plugin record — see
|
|
21
|
+
// plugins.js. A plugin that declares nothing still reports as loaded,
|
|
22
|
+
// but as `package: null`.
|
|
23
|
+
return { module: import.meta.url }
|
|
19
24
|
}
|
|
20
25
|
}
|
package/src/plugins/mapper.js
CHANGED
|
@@ -22,5 +22,10 @@ export function mapper(options = {}) {
|
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
})
|
|
25
|
+
|
|
26
|
+
// Names this package to the runtime's loaded-plugin record — see
|
|
27
|
+
// plugins.js. A plugin that declares nothing still reports as loaded,
|
|
28
|
+
// but as `package: null`.
|
|
29
|
+
return { module: import.meta.url }
|
|
25
30
|
}
|
|
26
31
|
}
|
package/src/plugins/observer.js
CHANGED
package/src/plugins/preview.js
CHANGED
|
@@ -164,5 +164,5 @@ export function load({ runtime, options, track, logger }) {
|
|
|
164
164
|
}
|
|
165
165
|
|
|
166
166
|
export function fileHelpers(options = {}) {
|
|
167
|
-
return { name: options.name ?? 'file', options, load }
|
|
167
|
+
return { name: options.name ?? 'file', options, load, module: import.meta.url }
|
|
168
168
|
}
|
|
@@ -24,5 +24,5 @@ export function load({ runtime, entity, state, options, track }) {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
export function resourceUrlHelper(options = {}) {
|
|
27
|
-
return { name: options.name ?? 'resource', options, load }
|
|
27
|
+
return { name: options.name ?? 'resource', options, load, module: import.meta.url }
|
|
28
28
|
}
|
package/src/plugins/resources.js
CHANGED
package/src/plugins/shares.js
CHANGED
|
@@ -38,5 +38,10 @@ export function shares(options = {}) {
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
})
|
|
41
|
+
|
|
42
|
+
// Names this package to the runtime's loaded-plugin record — see
|
|
43
|
+
// plugins.js. A plugin that declares nothing still reports as loaded,
|
|
44
|
+
// but as `package: null`.
|
|
45
|
+
return { module: import.meta.url }
|
|
41
46
|
}
|
|
42
47
|
}
|
package/src/plugins/sources.js
CHANGED
|
@@ -31,8 +31,10 @@ export function sources(options = {}) {
|
|
|
31
31
|
const { useLogger } = core
|
|
32
32
|
if (!collections.length) {
|
|
33
33
|
// No collections is a legitimate config (a flag turned them all
|
|
34
|
-
// off); nothing to register, and nothing to complain about.
|
|
35
|
-
|
|
34
|
+
// off); nothing to register, and nothing to complain about. Still
|
|
35
|
+
// names itself: the plugin IS loaded, and a config that turned its
|
|
36
|
+
// collections off must not make it look undetectable.
|
|
37
|
+
return { module: import.meta.url }
|
|
36
38
|
}
|
|
37
39
|
for (const [collection, config] of collections) {
|
|
38
40
|
const {
|
|
@@ -63,6 +65,9 @@ export function sources(options = {}) {
|
|
|
63
65
|
})
|
|
64
66
|
}
|
|
65
67
|
useLogger?.()?.debug('Sources registered: %s', collections.map(([c]) => c).join(', '))
|
|
68
|
+
// Names this package to the runtime's loaded-plugin record, so ping
|
|
69
|
+
// reports it as running rather than as undetectable.
|
|
70
|
+
return { module: import.meta.url }
|
|
66
71
|
}
|
|
67
72
|
}
|
|
68
73
|
|
package/src/plugins/validator.js
CHANGED
|
@@ -14,5 +14,10 @@ export function validator(options = {}) {
|
|
|
14
14
|
})
|
|
15
15
|
}
|
|
16
16
|
})
|
|
17
|
+
|
|
18
|
+
// Names this package to the runtime's loaded-plugin record — see
|
|
19
|
+
// plugins.js. A plugin that declares nothing still reports as loaded,
|
|
20
|
+
// but as `package: null`.
|
|
21
|
+
return { module: import.meta.url }
|
|
17
22
|
}
|
|
18
23
|
}
|
package/src/plugins/yaml.js
CHANGED
|
@@ -22,5 +22,10 @@ export function yaml(options = {}) {
|
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
})
|
|
25
|
+
|
|
26
|
+
// Names this package to the runtime's loaded-plugin record — see
|
|
27
|
+
// plugins.js. A plugin that declares nothing still reports as loaded,
|
|
28
|
+
// but as `package: null`.
|
|
29
|
+
return { module: import.meta.url }
|
|
25
30
|
}
|
|
26
31
|
}
|
package/src/plugins.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { useLogger } from './engine/index.js'
|
|
2
2
|
import { onLoad } from './lifecycle.js'
|
|
3
3
|
import { resetServices } from './services.js'
|
|
4
|
+
import path from 'node:path'
|
|
5
|
+
import { fileURLToPath } from 'node:url'
|
|
6
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
4
7
|
import runtime from './runtime.js'
|
|
5
8
|
|
|
6
9
|
import * as core from '../index.js'
|
|
@@ -40,6 +43,9 @@ onLoad(() => {
|
|
|
40
43
|
// always sees a Map, never undefined.
|
|
41
44
|
runtime.renderers = runtime.renderers ?? new Map()
|
|
42
45
|
runtime.postprocessors = runtime.postprocessors ?? new Map()
|
|
46
|
+
// Rebuilt, not appended to: loadPlugins runs again on a config change, and
|
|
47
|
+
// a list that accumulated would report every plugin twice.
|
|
48
|
+
runtime.plugins = []
|
|
43
49
|
|
|
44
50
|
const factoryEntries = []
|
|
45
51
|
let registeredRenderers = 0
|
|
@@ -62,6 +68,8 @@ onLoad(() => {
|
|
|
62
68
|
continue
|
|
63
69
|
}
|
|
64
70
|
runtime.renderers.set(name, entry)
|
|
71
|
+
recordPlugin({ kind: 'renderer', name,
|
|
72
|
+
package: packageOfModule(entry.module), module: entry.module ?? null })
|
|
65
73
|
registeredRenderers++
|
|
66
74
|
continue
|
|
67
75
|
}
|
|
@@ -72,6 +80,8 @@ onLoad(() => {
|
|
|
72
80
|
continue
|
|
73
81
|
}
|
|
74
82
|
runtime.postprocessors.set(name, entry)
|
|
83
|
+
recordPlugin({ kind: 'postprocessor', name,
|
|
84
|
+
package: packageOfModule(entry.module), module: entry.module ?? null })
|
|
75
85
|
registeredPostprocessors++
|
|
76
86
|
continue
|
|
77
87
|
}
|
|
@@ -140,17 +150,83 @@ onLoad(() => {
|
|
|
140
150
|
logger.error('Plugin factory threw on registration: %s', err.message)
|
|
141
151
|
continue
|
|
142
152
|
}
|
|
143
|
-
|
|
153
|
+
// `plugin-7` names nothing a reader can act on. A plugin that
|
|
154
|
+
// declared its module has already said where it is, so the file's own
|
|
155
|
+
// stem is a better name than its position in an array.
|
|
156
|
+
const declaredName = descriptor?.module
|
|
157
|
+
? path.basename(String(descriptor.module).split('?')[0]).replace(/\.[cm]?js$/, '')
|
|
158
|
+
: null
|
|
159
|
+
const label = descriptor?.collection ?? descriptor?.type ?? declaredName ?? `plugin-${index + 1}`
|
|
160
|
+
const registered = []
|
|
144
161
|
for (const name of hookNames) {
|
|
145
|
-
|
|
162
|
+
const added = runtime.hooks[name].slice(before.get(name))
|
|
163
|
+
if (added.length) registered.push(name)
|
|
164
|
+
for (const hook of added) {
|
|
146
165
|
// A plugin registering the same function twice keeps its first
|
|
147
166
|
// label rather than being renamed by a later registration.
|
|
148
167
|
if (typeof hook === 'function' && !hook.mikserPlugin) hook.mikserPlugin = label
|
|
149
168
|
}
|
|
150
169
|
}
|
|
170
|
+
// Recorded whether or not it named itself. A plugin that declares
|
|
171
|
+
// nothing is still loaded, and the list must say so — that is the
|
|
172
|
+
// whole difference between this and the probe it replaces.
|
|
173
|
+
recordPlugin({
|
|
174
|
+
kind: 'lifecycle',
|
|
175
|
+
label,
|
|
176
|
+
package: packageOfModule(descriptor?.module),
|
|
177
|
+
module: descriptor?.module ?? null,
|
|
178
|
+
...(descriptor?.collection ? { collection: descriptor.collection } : {}),
|
|
179
|
+
hooks: registered,
|
|
180
|
+
})
|
|
151
181
|
}
|
|
152
182
|
})
|
|
153
183
|
|
|
184
|
+
|
|
185
|
+
// The package a module belongs to, read from the nearest package.json.
|
|
186
|
+
//
|
|
187
|
+
// Walked up from the file rather than pattern-matched on the path: a plugin
|
|
188
|
+
// developed in a workspace sits at `~/Projects/mikser/mikser-io-git`, and the
|
|
189
|
+
// same plugin installed sits at `<site>/node_modules/mikser-io-git`. Only the
|
|
190
|
+
// manifest is true in both, and only the manifest is true for a plugin whose
|
|
191
|
+
// package is not named for it.
|
|
192
|
+
function packageOfModule(moduleUrl) {
|
|
193
|
+
if (typeof moduleUrl !== 'string') return null
|
|
194
|
+
let dir
|
|
195
|
+
try {
|
|
196
|
+
dir = path.dirname(moduleUrl.startsWith('file:') ? fileURLToPath(moduleUrl) : moduleUrl)
|
|
197
|
+
} catch { return null }
|
|
198
|
+
for (let depth = 0; depth < 12; depth++) {
|
|
199
|
+
const manifest = path.join(dir, 'package.json')
|
|
200
|
+
if (existsSync(manifest)) {
|
|
201
|
+
try { return JSON.parse(readFileSync(manifest, 'utf8')).name ?? null } catch { return null }
|
|
202
|
+
}
|
|
203
|
+
const parent = path.dirname(dir)
|
|
204
|
+
if (parent === dir) break
|
|
205
|
+
dir = parent
|
|
206
|
+
}
|
|
207
|
+
return null
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// What this runtime LOADED, recorded as it loads it.
|
|
211
|
+
//
|
|
212
|
+
// Not derived afterwards. The previous answer was assembled by inventory.js
|
|
213
|
+
// from whatever surfaces happened to be observable — a route here, a CLI flag
|
|
214
|
+
// there — which made "is this plugin running" a question about how well the
|
|
215
|
+
// probe was maintained rather than about the plugin. It reported layouts as
|
|
216
|
+
// not running on every site that did not pass `--layouts`, because the flag it
|
|
217
|
+
// probed had stopped being an API object two majors earlier and nothing failed
|
|
218
|
+
// when it went stale.
|
|
219
|
+
//
|
|
220
|
+
// A plugin names itself by returning `module: import.meta.url` from its
|
|
221
|
+
// factory, the same self-naming `registerRoute` and `provideService` already
|
|
222
|
+
// require. One that names nothing is still recorded and still reported as
|
|
223
|
+
// LOADED — its `package` is null, which says "this is running and did not say
|
|
224
|
+
// what it is", never "this is not running".
|
|
225
|
+
function recordPlugin(entry) {
|
|
226
|
+
runtime.plugins = runtime.plugins ?? []
|
|
227
|
+
runtime.plugins.push(entry)
|
|
228
|
+
}
|
|
229
|
+
|
|
154
230
|
function kebabToCamel(s) {
|
|
155
231
|
return s.replace(/-([a-z])/g, (_, c) => c.toUpperCase())
|
|
156
232
|
}
|