@moku-labs/core 0.1.0-alpha.3 → 0.1.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +247 -11
- package/dist/index.d.cts +272 -124
- package/dist/index.d.mts +272 -124
- package/dist/index.mjs +246 -11
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -32,6 +32,8 @@ const RESERVED_NAMES = new Set([
|
|
|
32
32
|
"require",
|
|
33
33
|
"has",
|
|
34
34
|
"config",
|
|
35
|
+
"global",
|
|
36
|
+
"state",
|
|
35
37
|
"__proto__",
|
|
36
38
|
"constructor",
|
|
37
39
|
"prototype"
|
|
@@ -108,6 +110,37 @@ function validatePlugins(id, plugins) {
|
|
|
108
110
|
checkDuplicateNames(id, names);
|
|
109
111
|
checkDependencyOrder(id, plugins, names);
|
|
110
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* Validate core plugins: no reserved names, no duplicates.
|
|
115
|
+
*
|
|
116
|
+
* @param id - Framework identifier for error messages.
|
|
117
|
+
* @param corePlugins - The core plugin list to validate.
|
|
118
|
+
* @throws {TypeError} If validation fails.
|
|
119
|
+
* @example
|
|
120
|
+
* ```ts
|
|
121
|
+
* validateCorePlugins("my-site", [logPlugin, envPlugin]); // throws if invalid
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
124
|
+
function validateCorePlugins(id, corePlugins) {
|
|
125
|
+
const names = corePlugins.map((p) => p.name);
|
|
126
|
+
checkReservedNames(id, names);
|
|
127
|
+
checkDuplicateNames(id, names);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Validate that no regular plugin name conflicts with a core plugin name.
|
|
131
|
+
*
|
|
132
|
+
* @param id - Framework identifier for error messages.
|
|
133
|
+
* @param plugins - The regular plugin list.
|
|
134
|
+
* @param corePluginNames - Set of core plugin names.
|
|
135
|
+
* @throws {TypeError} If a name conflict is found.
|
|
136
|
+
* @example
|
|
137
|
+
* ```ts
|
|
138
|
+
* checkCorePluginConflicts("my-site", [routerPlugin], new Set(["log", "env"]));
|
|
139
|
+
* ```
|
|
140
|
+
*/
|
|
141
|
+
function checkCorePluginConflicts(id, plugins, corePluginNames) {
|
|
142
|
+
for (const plugin of plugins) if (corePluginNames.has(plugin.name)) throw new TypeError(`[${id}] Plugin name "${plugin.name}" conflicts with core plugin "${plugin.name}".\n Choose a different plugin name.`);
|
|
143
|
+
}
|
|
111
144
|
|
|
112
145
|
//#endregion
|
|
113
146
|
//#region src/app.ts
|
|
@@ -302,6 +335,7 @@ function registerPluginHooks(flatPlugins, buildPluginContext, registerHook) {
|
|
|
302
335
|
* @param runtime - The kernel runtime with shared state.
|
|
303
336
|
* @param resolvedConfigs - The resolved per-plugin config map.
|
|
304
337
|
* @param states - The plugin state map.
|
|
338
|
+
* @param coreApis - Core plugin APIs to spread onto every plugin context.
|
|
305
339
|
* @returns A factory function that produces a PluginContext for any plugin.
|
|
306
340
|
* @example
|
|
307
341
|
* ```ts
|
|
@@ -309,7 +343,7 @@ function registerPluginHooks(flatPlugins, buildPluginContext, registerHook) {
|
|
|
309
343
|
* const ctx = factory(routerPlugin);
|
|
310
344
|
* ```
|
|
311
345
|
*/
|
|
312
|
-
function createContextFactory(runtime, resolvedConfigs, states) {
|
|
346
|
+
function createContextFactory(runtime, resolvedConfigs, states, coreApis) {
|
|
313
347
|
const has = createHas(runtime);
|
|
314
348
|
return (plugin) => ({
|
|
315
349
|
global: runtime.globalConfig,
|
|
@@ -317,7 +351,8 @@ function createContextFactory(runtime, resolvedConfigs, states) {
|
|
|
317
351
|
state: states.get(plugin.name),
|
|
318
352
|
emit: runtime.emit,
|
|
319
353
|
require: createRequire(runtime, (name) => `[${runtime.id}] Plugin "${plugin.name}" requires "${name}", but "${name}" is not registered.\n Add "${name}" to your plugin list.`),
|
|
320
|
-
has
|
|
354
|
+
has,
|
|
355
|
+
...coreApis
|
|
321
356
|
});
|
|
322
357
|
}
|
|
323
358
|
/**
|
|
@@ -364,6 +399,10 @@ async function executeStop(flatPlugins, globalConfig) {
|
|
|
364
399
|
* @param runtime - The kernel runtime with shared state and APIs.
|
|
365
400
|
* @param flatPlugins - The flattened plugin list.
|
|
366
401
|
* @param buildPluginContext - Factory that builds context for a plugin.
|
|
402
|
+
* @param corePluginData - Core plugin instances, resolved configs, and states.
|
|
403
|
+
* @param corePluginData.plugins - The core plugin instances.
|
|
404
|
+
* @param corePluginData.configs - Resolved core plugin config map.
|
|
405
|
+
* @param corePluginData.states - Core plugin state map.
|
|
367
406
|
* @param consumer - Optional consumer lifecycle callbacks.
|
|
368
407
|
* @returns A frozen app object with lifecycle methods and plugin APIs.
|
|
369
408
|
* @example
|
|
@@ -372,13 +411,17 @@ async function executeStop(flatPlugins, globalConfig) {
|
|
|
372
411
|
* await app.start();
|
|
373
412
|
* ```
|
|
374
413
|
*/
|
|
375
|
-
function buildApp(runtime, flatPlugins, buildPluginContext, consumer) {
|
|
414
|
+
function buildApp(runtime, flatPlugins, buildPluginContext, corePluginData, consumer) {
|
|
376
415
|
let started = false;
|
|
377
416
|
const appRequire = createRequire(runtime, (name) => `[${runtime.id}] app.require("${name}") failed: "${name}" is not registered.\n Check your plugin list.`);
|
|
378
417
|
const appHas = createHas(runtime);
|
|
379
418
|
const app = {
|
|
380
419
|
start: async () => {
|
|
381
420
|
if (started) throw new Error(`[${runtime.id}] App already started.\n start() can only be called once.`);
|
|
421
|
+
for (const plugin of corePluginData.plugins) if (plugin.spec.onStart) await plugin.spec.onStart({
|
|
422
|
+
config: corePluginData.configs.get(plugin.name) ?? {},
|
|
423
|
+
state: corePluginData.states.get(plugin.name)
|
|
424
|
+
});
|
|
382
425
|
for (const plugin of flatPlugins) if (plugin.spec.onStart) await plugin.spec.onStart(buildPluginContext(plugin));
|
|
383
426
|
if (consumer?.onStart) await consumer.onStart(buildCallbackContext(runtime));
|
|
384
427
|
started = true;
|
|
@@ -386,6 +429,10 @@ function buildApp(runtime, flatPlugins, buildPluginContext, consumer) {
|
|
|
386
429
|
stop: async () => {
|
|
387
430
|
if (!started) throw new Error(`[${runtime.id}] App not started.\n Call start() before stop().`);
|
|
388
431
|
await executeStop(flatPlugins, runtime.globalConfig);
|
|
432
|
+
for (const plugin of corePluginData.plugins.toReversed()) if (plugin.spec.onStop) await plugin.spec.onStop({
|
|
433
|
+
config: corePluginData.configs.get(plugin.name) ?? {},
|
|
434
|
+
state: corePluginData.states.get(plugin.name)
|
|
435
|
+
});
|
|
389
436
|
if (consumer?.onStop) await consumer.onStop(buildCallbackContext(runtime));
|
|
390
437
|
},
|
|
391
438
|
emit: (eventName, payload) => {
|
|
@@ -398,6 +445,59 @@ function buildApp(runtime, flatPlugins, buildPluginContext, consumer) {
|
|
|
398
445
|
return Object.freeze(app);
|
|
399
446
|
}
|
|
400
447
|
/**
|
|
448
|
+
* Initialize core plugins: resolve configs, create states, build APIs, run onInit.
|
|
449
|
+
*
|
|
450
|
+
* @param corePlugins - Core plugin instances.
|
|
451
|
+
* @param corePluginConfigs - Config overrides from createCoreConfig.
|
|
452
|
+
* @param frameworkPluginConfigs - Config overrides from createCore.
|
|
453
|
+
* @param consumerPluginConfigs - Config overrides from createApp.
|
|
454
|
+
* @returns Resolved configs, states, core APIs map, and shared apis Map.
|
|
455
|
+
* @example
|
|
456
|
+
* ```ts
|
|
457
|
+
* const { coreResolvedConfigs, coreStates, coreApis, apis } = initCorePlugins(
|
|
458
|
+
* corePlugins, corePluginConfigs, frameworkPluginConfigs, consumerPluginConfigs
|
|
459
|
+
* );
|
|
460
|
+
* ```
|
|
461
|
+
*/
|
|
462
|
+
function initCorePlugins(corePlugins, corePluginConfigs, frameworkPluginConfigs, consumerPluginConfigs) {
|
|
463
|
+
const coreResolvedConfigs = /* @__PURE__ */ new Map();
|
|
464
|
+
for (const plugin of corePlugins) {
|
|
465
|
+
const merged = Object.freeze({
|
|
466
|
+
...plugin.spec.config,
|
|
467
|
+
...asRecord(corePluginConfigs[plugin.name]),
|
|
468
|
+
...asRecord(frameworkPluginConfigs[plugin.name]),
|
|
469
|
+
...asRecord(consumerPluginConfigs[plugin.name])
|
|
470
|
+
});
|
|
471
|
+
coreResolvedConfigs.set(plugin.name, merged);
|
|
472
|
+
}
|
|
473
|
+
const coreStates = /* @__PURE__ */ new Map();
|
|
474
|
+
for (const plugin of corePlugins) if (plugin.spec.createState) {
|
|
475
|
+
const pluginConfig = coreResolvedConfigs.get(plugin.name) ?? {};
|
|
476
|
+
coreStates.set(plugin.name, plugin.spec.createState({ config: pluginConfig }));
|
|
477
|
+
} else coreStates.set(plugin.name, {});
|
|
478
|
+
const coreApis = {};
|
|
479
|
+
const apis = /* @__PURE__ */ new Map();
|
|
480
|
+
for (const plugin of corePlugins) if (plugin.spec.api) {
|
|
481
|
+
const context = {
|
|
482
|
+
config: coreResolvedConfigs.get(plugin.name) ?? {},
|
|
483
|
+
state: coreStates.get(plugin.name)
|
|
484
|
+
};
|
|
485
|
+
const api = plugin.spec.api(context);
|
|
486
|
+
coreApis[plugin.name] = api;
|
|
487
|
+
apis.set(plugin.name, api);
|
|
488
|
+
}
|
|
489
|
+
for (const plugin of corePlugins) if (plugin.spec.onInit) plugin.spec.onInit({
|
|
490
|
+
config: coreResolvedConfigs.get(plugin.name) ?? {},
|
|
491
|
+
state: coreStates.get(plugin.name)
|
|
492
|
+
});
|
|
493
|
+
return {
|
|
494
|
+
coreResolvedConfigs,
|
|
495
|
+
coreStates,
|
|
496
|
+
coreApis,
|
|
497
|
+
apis
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
401
501
|
* The kernel — creates and initializes the application.
|
|
402
502
|
*
|
|
403
503
|
* Receives pre-flattened, pre-validated plugins and all captured context from
|
|
@@ -412,15 +512,15 @@ function buildApp(runtime, flatPlugins, buildPluginContext, consumer) {
|
|
|
412
512
|
* ```
|
|
413
513
|
*/
|
|
414
514
|
function kernel(parameters) {
|
|
415
|
-
const { id, configDefaults, frameworkPluginConfigs, flatPlugins, configOverrides, consumerPluginConfigs, onReady, onError, consumer } = parameters;
|
|
416
|
-
const pluginNameSet = new Set(flatPlugins.map((plugin) => plugin.name));
|
|
515
|
+
const { id, configDefaults, frameworkPluginConfigs, flatPlugins, corePlugins, corePluginConfigs, configOverrides, consumerPluginConfigs, onReady, onError, consumer } = parameters;
|
|
516
|
+
const pluginNameSet = new Set([...corePlugins.map((plugin) => plugin.name), ...flatPlugins.map((plugin) => plugin.name)]);
|
|
417
517
|
const globalConfig = Object.freeze({
|
|
418
518
|
...configDefaults,
|
|
419
519
|
...configOverrides
|
|
420
520
|
});
|
|
521
|
+
const { coreResolvedConfigs, coreStates, coreApis, apis } = initCorePlugins(corePlugins, corePluginConfigs, frameworkPluginConfigs, consumerPluginConfigs);
|
|
421
522
|
const resolvedConfigs = resolvePluginConfigs(flatPlugins, frameworkPluginConfigs, consumerPluginConfigs);
|
|
422
523
|
const states = createPluginStates(flatPlugins, globalConfig, resolvedConfigs);
|
|
423
|
-
const apis = /* @__PURE__ */ new Map();
|
|
424
524
|
const { emit, registerHook } = buildEventBus(onError || consumer?.onError ? (error) => {
|
|
425
525
|
if (onError) onError(error);
|
|
426
526
|
if (consumer?.onError) consumer.onError(error, buildCallbackContext(runtime));
|
|
@@ -432,13 +532,17 @@ function kernel(parameters) {
|
|
|
432
532
|
apis,
|
|
433
533
|
pluginNameSet
|
|
434
534
|
};
|
|
435
|
-
const buildPluginContext = createContextFactory(runtime, resolvedConfigs, states);
|
|
535
|
+
const buildPluginContext = createContextFactory(runtime, resolvedConfigs, states, coreApis);
|
|
436
536
|
registerPluginHooks(flatPlugins, buildPluginContext, registerHook);
|
|
437
537
|
for (const plugin of flatPlugins) if (plugin.spec.api) apis.set(plugin.name, plugin.spec.api(buildPluginContext(plugin)));
|
|
438
538
|
for (const plugin of flatPlugins) if (plugin.spec.onInit) plugin.spec.onInit(buildPluginContext(plugin));
|
|
439
539
|
if (onReady) onReady({ config: globalConfig });
|
|
440
540
|
if (consumer?.onReady) consumer.onReady(buildCallbackContext(runtime));
|
|
441
|
-
return buildApp(runtime, flatPlugins, buildPluginContext,
|
|
541
|
+
return buildApp(runtime, flatPlugins, buildPluginContext, {
|
|
542
|
+
plugins: corePlugins,
|
|
543
|
+
configs: coreResolvedConfigs,
|
|
544
|
+
states: coreStates
|
|
545
|
+
}, consumer);
|
|
442
546
|
}
|
|
443
547
|
|
|
444
548
|
//#endregion
|
|
@@ -453,6 +557,8 @@ function kernel(parameters) {
|
|
|
453
557
|
* @param frameworkId - The framework identifier for error messages.
|
|
454
558
|
* @param configDefaults - Default config values captured from Step 1.
|
|
455
559
|
* @param createPlugin - Bound createPlugin function from Step 1.
|
|
560
|
+
* @param corePlugins - Core plugin instances from createCoreConfig.
|
|
561
|
+
* @param corePluginConfigs - Core plugin config overrides from createCoreConfig.
|
|
456
562
|
* @returns A createCore function bound to the framework's Config and Events types.
|
|
457
563
|
* @example
|
|
458
564
|
* ```ts
|
|
@@ -461,7 +567,7 @@ function kernel(parameters) {
|
|
|
461
567
|
* );
|
|
462
568
|
* ```
|
|
463
569
|
*/
|
|
464
|
-
function createCoreFactory(frameworkId, configDefaults, createPlugin) {
|
|
570
|
+
function createCoreFactory(frameworkId, configDefaults, createPlugin, corePlugins, corePluginConfigs) {
|
|
465
571
|
/**
|
|
466
572
|
* Step 2: Captures framework default plugins and returns createApp.
|
|
467
573
|
*
|
|
@@ -495,11 +601,14 @@ function createCoreFactory(frameworkId, configDefaults, createPlugin) {
|
|
|
495
601
|
const appOptions = consumerOptions ?? {};
|
|
496
602
|
const allPlugins = [...defaultPlugins, ...appOptions.plugins ?? []];
|
|
497
603
|
validatePlugins(frameworkId, allPlugins);
|
|
604
|
+
checkCorePluginConflicts(frameworkId, allPlugins, new Set(corePlugins.map((p) => p.name)));
|
|
498
605
|
return kernel({
|
|
499
606
|
id: frameworkId,
|
|
500
607
|
configDefaults,
|
|
501
608
|
frameworkPluginConfigs,
|
|
502
609
|
flatPlugins: allPlugins,
|
|
610
|
+
corePlugins,
|
|
611
|
+
corePluginConfigs,
|
|
503
612
|
configOverrides: appOptions.config ?? {},
|
|
504
613
|
consumerPluginConfigs: appOptions.pluginConfigs ?? {},
|
|
505
614
|
onReady,
|
|
@@ -692,6 +801,8 @@ function createPluginFactory(frameworkId) {
|
|
|
692
801
|
* @param id - Framework identifier used in error messages.
|
|
693
802
|
* @param options - Configuration options containing the default config values.
|
|
694
803
|
* @param options.config - Default configuration values for the framework.
|
|
804
|
+
* @param options.plugins - Optional core plugin instances to register.
|
|
805
|
+
* @param options.pluginConfigs - Optional config overrides for core plugins.
|
|
695
806
|
* @returns An object with createPlugin (bound to Config/Events) and createCore.
|
|
696
807
|
* @example
|
|
697
808
|
* ```ts
|
|
@@ -704,12 +815,137 @@ function createPluginFactory(frameworkId) {
|
|
|
704
815
|
function createCoreConfig(id, options) {
|
|
705
816
|
const configDefaults = options.config;
|
|
706
817
|
const frameworkId = id;
|
|
818
|
+
const corePlugins = options.plugins ?? [];
|
|
819
|
+
const corePluginConfigs = options.pluginConfigs ?? {};
|
|
820
|
+
validateCorePlugins(frameworkId, corePlugins);
|
|
707
821
|
const createPlugin = createPluginFactory(frameworkId);
|
|
708
822
|
return {
|
|
709
823
|
createPlugin,
|
|
710
|
-
createCore: createCoreFactory(frameworkId, configDefaults, createPlugin)
|
|
824
|
+
createCore: createCoreFactory(frameworkId, configDefaults, createPlugin, corePlugins, corePluginConfigs)
|
|
825
|
+
};
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
//#endregion
|
|
829
|
+
//#region src/core-plugin.ts
|
|
830
|
+
/**
|
|
831
|
+
* Reserved names that cannot be used for core plugins.
|
|
832
|
+
* Includes regular reserved names plus context property names that would collide.
|
|
833
|
+
*/
|
|
834
|
+
const CORE_PLUGIN_RESERVED_NAMES = new Set([
|
|
835
|
+
"start",
|
|
836
|
+
"stop",
|
|
837
|
+
"emit",
|
|
838
|
+
"require",
|
|
839
|
+
"has",
|
|
840
|
+
"config",
|
|
841
|
+
"global",
|
|
842
|
+
"state",
|
|
843
|
+
"__proto__",
|
|
844
|
+
"constructor",
|
|
845
|
+
"prototype"
|
|
846
|
+
]);
|
|
847
|
+
/** Fields that core plugins must not have. */
|
|
848
|
+
const CORE_PLUGIN_FORBIDDEN_FIELDS = [
|
|
849
|
+
"depends",
|
|
850
|
+
"events",
|
|
851
|
+
"hooks"
|
|
852
|
+
];
|
|
853
|
+
/**
|
|
854
|
+
* Asserts that a core plugin name is a non-empty string and not reserved.
|
|
855
|
+
*
|
|
856
|
+
* @param name - Candidate core plugin name.
|
|
857
|
+
* @example
|
|
858
|
+
* ```ts
|
|
859
|
+
* assertValidCorePluginName("log"); // ok
|
|
860
|
+
* assertValidCorePluginName("config"); // throws
|
|
861
|
+
* ```
|
|
862
|
+
*/
|
|
863
|
+
function assertValidCorePluginName(name) {
|
|
864
|
+
if (typeof name !== "string" || name.length === 0) throw new TypeError("Core plugin name must be a non-empty string.\n Pass a non-empty string as the first argument to createCorePlugin.");
|
|
865
|
+
if (CORE_PLUGIN_RESERVED_NAMES.has(name)) throw new TypeError(`Core plugin name "${name}" conflicts with a reserved name.\n Choose a different core plugin name.`);
|
|
866
|
+
}
|
|
867
|
+
/**
|
|
868
|
+
* Asserts that the core plugin spec is a non-null object.
|
|
869
|
+
*
|
|
870
|
+
* @param name - Validated core plugin name.
|
|
871
|
+
* @param spec - Candidate core plugin spec.
|
|
872
|
+
* @example
|
|
873
|
+
* ```ts
|
|
874
|
+
* assertValidCorePluginSpec("log", { api: () => ({}) }); // ok
|
|
875
|
+
* ```
|
|
876
|
+
*/
|
|
877
|
+
function assertValidCorePluginSpec(name, spec) {
|
|
878
|
+
if (isRecord(spec)) return;
|
|
879
|
+
throw new TypeError(`Core plugin "${name}" has invalid spec: expected an object.\n Provide a plugin specification object as the second argument.`);
|
|
880
|
+
}
|
|
881
|
+
/**
|
|
882
|
+
* Asserts that the core plugin spec does not contain forbidden fields.
|
|
883
|
+
*
|
|
884
|
+
* @param name - Validated core plugin name.
|
|
885
|
+
* @param spec - Validated core plugin spec.
|
|
886
|
+
* @example
|
|
887
|
+
* ```ts
|
|
888
|
+
* assertNoCorePluginForbiddenFields("log", { api: () => ({}) }); // ok
|
|
889
|
+
* assertNoCorePluginForbiddenFields("log", { depends: [] }); // throws
|
|
890
|
+
* ```
|
|
891
|
+
*/
|
|
892
|
+
function assertNoCorePluginForbiddenFields(name, spec) {
|
|
893
|
+
for (const field of CORE_PLUGIN_FORBIDDEN_FIELDS) if (field in spec) throw new TypeError(`Core plugin "${name}" cannot have "${field}".\n Core plugins are self-contained — remove the forbidden field.`);
|
|
894
|
+
}
|
|
895
|
+
/**
|
|
896
|
+
* Validates lifecycle handlers and factories on a core plugin spec.
|
|
897
|
+
*
|
|
898
|
+
* @param name - Validated core plugin name.
|
|
899
|
+
* @param spec - Validated core plugin spec.
|
|
900
|
+
* @example
|
|
901
|
+
* ```ts
|
|
902
|
+
* assertValidCorePluginCallbacks("log", { api: () => ({}) }); // ok
|
|
903
|
+
* ```
|
|
904
|
+
*/
|
|
905
|
+
function assertValidCorePluginCallbacks(name, spec) {
|
|
906
|
+
for (const field of [
|
|
907
|
+
"api",
|
|
908
|
+
"createState",
|
|
909
|
+
"onInit",
|
|
910
|
+
"onStart",
|
|
911
|
+
"onStop"
|
|
912
|
+
]) {
|
|
913
|
+
const value = spec[field];
|
|
914
|
+
if (value !== void 0 && typeof value !== "function") throw new TypeError(`Core plugin "${name}" has invalid ${field}: expected a function.\n Provide a function for ${field} or remove it from the spec.`);
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
/**
|
|
918
|
+
* Creates a core plugin instance. Core plugins are standalone, self-contained
|
|
919
|
+
* infrastructure plugins (log, storage, env) whose APIs are injected directly
|
|
920
|
+
* onto every regular plugin's context.
|
|
921
|
+
*
|
|
922
|
+
* @param name - Unique core plugin name (inferred as literal string type).
|
|
923
|
+
* @param spec - Core plugin specification: config, createState, api, lifecycle.
|
|
924
|
+
* @returns A CorePluginInstance carrying phantom types for compile-time inference.
|
|
925
|
+
* @example
|
|
926
|
+
* ```ts
|
|
927
|
+
* const logPlugin = createCorePlugin("log", {
|
|
928
|
+
* config: { level: "info" },
|
|
929
|
+
* createState: () => ({ entries: [] as string[] }),
|
|
930
|
+
* api: ctx => ({
|
|
931
|
+
* info: (msg: string) => { ctx.state.entries.push(msg); console.log(msg); },
|
|
932
|
+
* }),
|
|
933
|
+
* });
|
|
934
|
+
* ```
|
|
935
|
+
*/
|
|
936
|
+
function createCorePlugin(name, spec) {
|
|
937
|
+
assertValidCorePluginName(name);
|
|
938
|
+
assertValidCorePluginSpec(name, spec);
|
|
939
|
+
assertNoCorePluginForbiddenFields(name, spec);
|
|
940
|
+
assertValidCorePluginCallbacks(name, spec);
|
|
941
|
+
return {
|
|
942
|
+
name,
|
|
943
|
+
spec,
|
|
944
|
+
_corePlugin: true,
|
|
945
|
+
_phantom: {}
|
|
711
946
|
};
|
|
712
947
|
}
|
|
713
948
|
|
|
714
949
|
//#endregion
|
|
715
|
-
exports.createCoreConfig = createCoreConfig;
|
|
950
|
+
exports.createCoreConfig = createCoreConfig;
|
|
951
|
+
exports.createCorePlugin = createCorePlugin;
|