@moxxy/config 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/config-writer.d.ts +30 -0
- package/dist/config-writer.d.ts.map +1 -0
- package/dist/config-writer.js +57 -0
- package/dist/config-writer.js.map +1 -0
- package/dist/define.d.ts +17 -0
- package/dist/define.d.ts.map +1 -0
- package/dist/define.js +18 -0
- package/dist/define.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/loader.d.ts +28 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +210 -0
- package/dist/loader.js.map +1 -0
- package/dist/merge.d.ts +9 -0
- package/dist/merge.d.ts.map +1 -0
- package/dist/merge.js +45 -0
- package/dist/merge.js.map +1 -0
- package/dist/plugin-settings-schema.d.ts +24 -0
- package/dist/plugin-settings-schema.d.ts.map +1 -0
- package/dist/plugin-settings-schema.js +17 -0
- package/dist/plugin-settings-schema.js.map +1 -0
- package/dist/plugin.d.ts +21 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +329 -0
- package/dist/plugin.js.map +1 -0
- package/dist/plugins-tree-schema.d.ts +444 -0
- package/dist/plugins-tree-schema.d.ts.map +1 -0
- package/dist/plugins-tree-schema.js +93 -0
- package/dist/plugins-tree-schema.js.map +1 -0
- package/dist/schema.d.ts +1200 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +198 -0
- package/dist/schema.js.map +1 -0
- package/dist/user-config.d.ts +77 -0
- package/dist/user-config.d.ts.map +1 -0
- package/dist/user-config.js +265 -0
- package/dist/user-config.js.map +1 -0
- package/package.json +56 -0
- package/src/config-writer.test.ts +52 -0
- package/src/config-writer.ts +88 -0
- package/src/define.ts +19 -0
- package/src/index.ts +64 -0
- package/src/loader.test.ts +122 -0
- package/src/loader.ts +232 -0
- package/src/loader.yaml.test.ts +149 -0
- package/src/merge.test.ts +78 -0
- package/src/merge.ts +44 -0
- package/src/plugin-settings-schema.ts +18 -0
- package/src/plugin.test.ts +310 -0
- package/src/plugin.ts +360 -0
- package/src/plugins-tree-schema.test.ts +25 -0
- package/src/plugins-tree-schema.ts +103 -0
- package/src/schema.ts +218 -0
- package/src/security-config.test.ts +30 -0
- package/src/user-config.test.ts +113 -0
- package/src/user-config.ts +359 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Moxxy (moxxy.ai)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type MoxxyConfig } from './schema.js';
|
|
2
|
+
/**
|
|
3
|
+
* The ONE schema-validated, comment-preserving dot-path config writer. Both
|
|
4
|
+
* the model-facing `config_set` tool (plugin.ts) and UI surfaces (the TUI's
|
|
5
|
+
* /settings panel) write through here, sharing a single mutex, so concurrent
|
|
6
|
+
* writers can't interleave and no surface can persist a structurally-invalid
|
|
7
|
+
* config.
|
|
8
|
+
*/
|
|
9
|
+
export type ConfigScope = 'user' | 'project';
|
|
10
|
+
/** Serializes every config write in this process (tool + UI surfaces). */
|
|
11
|
+
export declare const configWriteMutex: import("@moxxy/sdk").Mutex;
|
|
12
|
+
export declare function findScopePath(scope: ConfigScope, cwd: string): Promise<string | null>;
|
|
13
|
+
export declare function scopeDefaultPath(scope: ConfigScope, cwd: string): string;
|
|
14
|
+
export declare function parseDotPath(p: string): Array<string | number>;
|
|
15
|
+
export interface SetConfigValueOptions {
|
|
16
|
+
readonly scope: ConfigScope;
|
|
17
|
+
readonly cwd: string;
|
|
18
|
+
/** Dot path into the config (e.g. `context.reasoning`, `tui.hints`). */
|
|
19
|
+
readonly path: string;
|
|
20
|
+
/** The ALREADY-PARSED value to set (callers own string→value parsing). */
|
|
21
|
+
readonly value: unknown;
|
|
22
|
+
}
|
|
23
|
+
export interface SetConfigValueResult {
|
|
24
|
+
/** The file that was written. */
|
|
25
|
+
readonly path: string;
|
|
26
|
+
/** The full validated config snapshot after the write. */
|
|
27
|
+
readonly config: MoxxyConfig;
|
|
28
|
+
}
|
|
29
|
+
export declare function setConfigValue(opts: SetConfigValueOptions): Promise<SetConfigValueResult>;
|
|
30
|
+
//# sourceMappingURL=config-writer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-writer.d.ts","sourceRoot":"","sources":["../src/config-writer.ts"],"names":[],"mappings":"AAKA,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAElE;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,SAAS,CAAC;AAQ7C,0EAA0E;AAC1E,eAAO,MAAM,gBAAgB,4BAAgB,CAAC;AAE9C,wBAAsB,aAAa,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAW3F;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAExE;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAE9D;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,oBAAoB;IACnC,iCAAiC;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;CAC9B;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,qBAAqB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAyB/F"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { promises as fs } from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import { createMutex } from '@moxxy/sdk';
|
|
4
|
+
import { moxxyPath, writeFileAtomic } from '@moxxy/sdk/server';
|
|
5
|
+
import { findUpward } from './loader.js';
|
|
6
|
+
import { moxxyConfigSchema } from './schema.js';
|
|
7
|
+
const USER_YAML = () => moxxyPath('config.yaml');
|
|
8
|
+
// YAML names only — the writer round-trips documents with `setIn`, which it
|
|
9
|
+
// can't do for the .ts/.js configs loadConfig also honors.
|
|
10
|
+
const PROJECT_YAML_NAMES = ['moxxy.config.yaml', 'moxxy.config.yml'];
|
|
11
|
+
/** Serializes every config write in this process (tool + UI surfaces). */
|
|
12
|
+
export const configWriteMutex = createMutex();
|
|
13
|
+
export async function findScopePath(scope, cwd) {
|
|
14
|
+
if (scope === 'user') {
|
|
15
|
+
const yaml = USER_YAML();
|
|
16
|
+
try {
|
|
17
|
+
await fs.access(yaml);
|
|
18
|
+
return yaml;
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return findUpward(cwd, PROJECT_YAML_NAMES);
|
|
25
|
+
}
|
|
26
|
+
export function scopeDefaultPath(scope, cwd) {
|
|
27
|
+
return scope === 'user' ? USER_YAML() : path.join(cwd, 'moxxy.config.yaml');
|
|
28
|
+
}
|
|
29
|
+
export function parseDotPath(p) {
|
|
30
|
+
return p.split('.').map((seg) => (/^\d+$/.test(seg) ? Number(seg) : seg));
|
|
31
|
+
}
|
|
32
|
+
export async function setConfigValue(opts) {
|
|
33
|
+
return configWriteMutex.run(async () => {
|
|
34
|
+
const target = (await findScopePath(opts.scope, opts.cwd)) ?? scopeDefaultPath(opts.scope, opts.cwd);
|
|
35
|
+
await fs.mkdir(path.dirname(target), { recursive: true });
|
|
36
|
+
const yamlMod = (await import('yaml'));
|
|
37
|
+
let text = '';
|
|
38
|
+
try {
|
|
39
|
+
text = await fs.readFile(target, 'utf8');
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
/* new file */
|
|
43
|
+
}
|
|
44
|
+
const doc = yamlMod.parseDocument(text);
|
|
45
|
+
doc.setIn(parseDotPath(opts.path), opts.value);
|
|
46
|
+
const candidate = String(doc);
|
|
47
|
+
const parsed = yamlMod.parse(candidate);
|
|
48
|
+
const validated = moxxyConfigSchema.safeParse(parsed ?? {});
|
|
49
|
+
if (!validated.success) {
|
|
50
|
+
throw new Error(`config write to '${opts.path}' would produce an invalid config:\n` +
|
|
51
|
+
JSON.stringify(validated.error.issues, null, 2));
|
|
52
|
+
}
|
|
53
|
+
await writeFileAtomic(target, candidate);
|
|
54
|
+
return { path: target, config: validated.data };
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=config-writer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-writer.js","sourceRoot":"","sources":["../src/config-writer.ts"],"names":[],"mappings":"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"}
|
package/dist/define.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { MoxxyConfig } from './schema.js';
|
|
2
|
+
/**
|
|
3
|
+
* Typed configuration factory. Use in `moxxy.config.ts`:
|
|
4
|
+
*
|
|
5
|
+
* import { defineConfig } from '@moxxy/config';
|
|
6
|
+
*
|
|
7
|
+
* export default defineConfig({
|
|
8
|
+
* provider: { name: 'anthropic', model: 'claude-sonnet-4-6' },
|
|
9
|
+
* plugins: {
|
|
10
|
+
* '@moxxy/plugin-mcp': { enabled: true, options: { servers: [...] } },
|
|
11
|
+
* '@acme/moxxy-plugin-shell': { enabled: false },
|
|
12
|
+
* },
|
|
13
|
+
* watcher: 'auto',
|
|
14
|
+
* });
|
|
15
|
+
*/
|
|
16
|
+
export declare function defineConfig(config: MoxxyConfig): MoxxyConfig;
|
|
17
|
+
//# sourceMappingURL=define.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define.d.ts","sourceRoot":"","sources":["../src/define.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,CAE7D"}
|
package/dist/define.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed configuration factory. Use in `moxxy.config.ts`:
|
|
3
|
+
*
|
|
4
|
+
* import { defineConfig } from '@moxxy/config';
|
|
5
|
+
*
|
|
6
|
+
* export default defineConfig({
|
|
7
|
+
* provider: { name: 'anthropic', model: 'claude-sonnet-4-6' },
|
|
8
|
+
* plugins: {
|
|
9
|
+
* '@moxxy/plugin-mcp': { enabled: true, options: { servers: [...] } },
|
|
10
|
+
* '@acme/moxxy-plugin-shell': { enabled: false },
|
|
11
|
+
* },
|
|
12
|
+
* watcher: 'auto',
|
|
13
|
+
* });
|
|
14
|
+
*/
|
|
15
|
+
export function defineConfig(config) {
|
|
16
|
+
return config;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=define.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define.js","sourceRoot":"","sources":["../src/define.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,YAAY,CAAC,MAAmB;IAC9C,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { defineConfig } from './define.js';
|
|
2
|
+
export { loadConfig, type LoadConfigOptions, type LoadedConfig } from './loader.js';
|
|
3
|
+
export { mergeConfigs } from './merge.js';
|
|
4
|
+
export { buildConfigPlugin, type ConfigApplier, type ConfigApplyResult, } from './plugin.js';
|
|
5
|
+
export { moxxyConfigSchema, pluginSettingsSchema, permissionsConfigSchema, embeddingsConfigSchema, securityConfigSchema, watcherModeSchema, type MoxxyConfig, type PluginSettings, type PermissionsConfig, type EmbeddingsConfig, type SecurityConfig, type WatcherMode, } from './schema.js';
|
|
6
|
+
export { pluginsTreeSchema, providerSlotSchema, providerItemSchema, categorySlotSchema, PLUGIN_CATEGORY_KEYS, type PluginsTree, type ProviderSlot, type ProviderItem, type CategorySlot, type PluginCategoryKey, } from './plugins-tree-schema.js';
|
|
7
|
+
export { applyInitConfig, clearPluginState, defaultUserConfigPath, isPluginDisabled, loadActiveModel, loadActiveProvider, loadDisabledPackageNames, loadDisabledProviders, loadProviderItems, removeProviderItem, setCategoryDefault, setPluginEnabled, setProviderEnabled, setProviderItemConfig, setProviderModel, type ProviderItemState, type InitConfigSelections, type UserConfigOptions, } from './user-config.js';
|
|
8
|
+
export { configWriteMutex, setConfigValue, type ConfigScope, type SetConfigValueOptions, type SetConfigValueResult, } from './config-writer.js';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AACpF,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EACL,iBAAiB,EACjB,KAAK,aAAa,EAClB,KAAK,iBAAiB,GACvB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,EACjB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,WAAW,GACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,iBAAiB,GACvB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,qBAAqB,EACrB,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,wBAAwB,EACxB,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,qBAAqB,EACrB,gBAAgB,EAChB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,GACvB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,KAAK,WAAW,EAChB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,GAC1B,MAAM,oBAAoB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { defineConfig } from './define.js';
|
|
2
|
+
export { loadConfig } from './loader.js';
|
|
3
|
+
export { mergeConfigs } from './merge.js';
|
|
4
|
+
export { buildConfigPlugin, } from './plugin.js';
|
|
5
|
+
export { moxxyConfigSchema, pluginSettingsSchema, permissionsConfigSchema, embeddingsConfigSchema, securityConfigSchema, watcherModeSchema, } from './schema.js';
|
|
6
|
+
export { pluginsTreeSchema, providerSlotSchema, providerItemSchema, categorySlotSchema, PLUGIN_CATEGORY_KEYS, } from './plugins-tree-schema.js';
|
|
7
|
+
// Comment-preserving writers for ~/.moxxy/config.yaml — the single store that
|
|
8
|
+
// replaced ~/.moxxy/preferences.json (runtime provider/mode/model/disabled).
|
|
9
|
+
export { applyInitConfig, clearPluginState, defaultUserConfigPath, isPluginDisabled, loadActiveModel, loadActiveProvider, loadDisabledPackageNames, loadDisabledProviders, loadProviderItems, removeProviderItem, setCategoryDefault, setPluginEnabled, setProviderEnabled, setProviderItemConfig, setProviderModel, } from './user-config.js';
|
|
10
|
+
export { configWriteMutex, setConfigValue, } from './config-writer.js';
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,UAAU,EAA6C,MAAM,aAAa,CAAC;AACpF,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EACL,iBAAiB,GAGlB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,GAOlB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,GAMrB,MAAM,0BAA0B,CAAC;AAClC,8EAA8E;AAC9E,6EAA6E;AAC7E,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,qBAAqB,EACrB,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,wBAAwB,EACxB,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,qBAAqB,EACrB,gBAAgB,GAIjB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,gBAAgB,EAChB,cAAc,GAIf,MAAM,oBAAoB,CAAC"}
|
package/dist/loader.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type MoxxyConfig } from './schema.js';
|
|
2
|
+
export interface LoadConfigOptions {
|
|
3
|
+
readonly cwd: string;
|
|
4
|
+
readonly explicitPath?: string;
|
|
5
|
+
readonly skipUser?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface LoadedConfig {
|
|
8
|
+
readonly config: MoxxyConfig;
|
|
9
|
+
readonly sources: ReadonlyArray<{
|
|
10
|
+
scope: 'project' | 'user' | 'explicit';
|
|
11
|
+
path: string;
|
|
12
|
+
}>;
|
|
13
|
+
}
|
|
14
|
+
/** Cap upward filesystem traversal when searching for a project config.
|
|
15
|
+
* Shared with the config plugin's scope-resolution walk so the bound can't
|
|
16
|
+
* drift between load time (here) and edit time (plugin.ts). */
|
|
17
|
+
export declare const MAX_CONFIG_SEARCH_DEPTH = 12;
|
|
18
|
+
export declare function loadConfig(opts: LoadConfigOptions): Promise<LoadedConfig>;
|
|
19
|
+
/**
|
|
20
|
+
* Walk upward from `startDir` (bounded by {@link MAX_CONFIG_SEARCH_DEPTH})
|
|
21
|
+
* returning the first directory that holds one of `names`. The `names` list is
|
|
22
|
+
* a deliberate parameter: `loadConfig` searches every config extension while the
|
|
23
|
+
* config plugin's editor searches only the YAML names it can safely mutate — so
|
|
24
|
+
* the shared traversal invariant lives here, the divergent name set stays with
|
|
25
|
+
* the caller. Returns the full path, or null if none found within the bound.
|
|
26
|
+
*/
|
|
27
|
+
export declare function findUpward(startDir: string, names: ReadonlyArray<string>): Promise<string | null>;
|
|
28
|
+
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAKA,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAElE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;QAAE,KAAK,EAAE,SAAS,GAAG,MAAM,GAAG,UAAU,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC3F;AAkBD;;gEAEgE;AAChE,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAE1C,wBAAsB,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,YAAY,CAAC,CA4B/E;AAkID;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,GAC3B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAUxB"}
|
package/dist/loader.js
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { promises as fs } from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import { pathToFileURL } from 'node:url';
|
|
4
|
+
import { moxxyHome } from '@moxxy/sdk/server';
|
|
5
|
+
import { mergeConfigs } from './merge.js';
|
|
6
|
+
import { moxxyConfigSchema } from './schema.js';
|
|
7
|
+
const CONFIG_NAMES = [
|
|
8
|
+
'moxxy.config.yaml',
|
|
9
|
+
'moxxy.config.yml',
|
|
10
|
+
'moxxy.config.ts',
|
|
11
|
+
'moxxy.config.js',
|
|
12
|
+
'moxxy.config.mjs',
|
|
13
|
+
'moxxy.config.cjs',
|
|
14
|
+
];
|
|
15
|
+
const USER_CONFIG_NAMES = [
|
|
16
|
+
'config.yaml',
|
|
17
|
+
'config.yml',
|
|
18
|
+
'config.ts',
|
|
19
|
+
'config.js',
|
|
20
|
+
'config.mjs',
|
|
21
|
+
'config.cjs',
|
|
22
|
+
];
|
|
23
|
+
/** Cap upward filesystem traversal when searching for a project config.
|
|
24
|
+
* Shared with the config plugin's scope-resolution walk so the bound can't
|
|
25
|
+
* drift between load time (here) and edit time (plugin.ts). */
|
|
26
|
+
export const MAX_CONFIG_SEARCH_DEPTH = 12;
|
|
27
|
+
export async function loadConfig(opts) {
|
|
28
|
+
const sources = [];
|
|
29
|
+
const configs = [];
|
|
30
|
+
if (!opts.skipUser) {
|
|
31
|
+
const userPath = await findFile(moxxyHome(), USER_CONFIG_NAMES);
|
|
32
|
+
if (userPath) {
|
|
33
|
+
const cfg = await loadOne(userPath);
|
|
34
|
+
configs.push(cfg);
|
|
35
|
+
sources.push({ scope: 'user', path: userPath });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (opts.explicitPath) {
|
|
39
|
+
const cfg = await loadOne(opts.explicitPath);
|
|
40
|
+
configs.push(cfg);
|
|
41
|
+
sources.push({ scope: 'explicit', path: opts.explicitPath });
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
const projectPath = await findUpward(opts.cwd, CONFIG_NAMES);
|
|
45
|
+
if (projectPath) {
|
|
46
|
+
warnIfAncestorExecutableConfig(projectPath, opts.cwd);
|
|
47
|
+
const cfg = await loadOne(projectPath);
|
|
48
|
+
configs.push(cfg);
|
|
49
|
+
sources.push({ scope: 'project', path: projectPath });
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return { config: mergeConfigs(...configs), sources };
|
|
53
|
+
}
|
|
54
|
+
const EXECUTABLE_CONFIG_EXTS = new Set(['.ts', '.tsx', '.js', '.mjs', '.cjs']);
|
|
55
|
+
function isUnderDir(filePath, dir) {
|
|
56
|
+
const rel = path.relative(path.resolve(dir), path.resolve(filePath));
|
|
57
|
+
return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel));
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* The project-config upward walk resolves and then EXECUTES the first matching
|
|
61
|
+
* config above cwd. An ancestor (e.g. a shared home/temp parent or an untrusted
|
|
62
|
+
* outer repo) can therefore plant a config whose code runs with full process
|
|
63
|
+
* privileges. We keep the documented upward-walk behavior but surface the exact
|
|
64
|
+
* absolute path on stderr before running an ancestor *executable* config, so the
|
|
65
|
+
* operator can see what is about to execute. Non-executable YAML and at/under-cwd
|
|
66
|
+
* configs are silent (no new trust boundary widened).
|
|
67
|
+
*/
|
|
68
|
+
function warnIfAncestorExecutableConfig(filePath, cwd) {
|
|
69
|
+
if (!EXECUTABLE_CONFIG_EXTS.has(path.extname(filePath)))
|
|
70
|
+
return;
|
|
71
|
+
if (isUnderDir(filePath, cwd))
|
|
72
|
+
return;
|
|
73
|
+
console.warn(`[moxxy] executing project config from an ancestor directory: ${path.resolve(filePath)}`);
|
|
74
|
+
}
|
|
75
|
+
async function loadOne(filePath) {
|
|
76
|
+
const ext = path.extname(filePath);
|
|
77
|
+
let raw;
|
|
78
|
+
if (ext === '.yaml' || ext === '.yml') {
|
|
79
|
+
const yamlText = await fs.readFile(filePath, 'utf8');
|
|
80
|
+
const yamlMod = (await import('yaml'));
|
|
81
|
+
raw = yamlMod.parse(yamlText);
|
|
82
|
+
if (raw === null || raw === undefined)
|
|
83
|
+
raw = {};
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
let mod;
|
|
87
|
+
if (ext === '.ts' || ext === '.tsx') {
|
|
88
|
+
const jiti = await getJiti(path.dirname(filePath));
|
|
89
|
+
if (!jiti)
|
|
90
|
+
throw new Error(`Cannot load ${filePath}: jiti is required for .ts configs.`);
|
|
91
|
+
mod = jiti(filePath);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
mod = await importJsConfig(filePath);
|
|
95
|
+
}
|
|
96
|
+
raw = extractDefault(mod);
|
|
97
|
+
if (!raw) {
|
|
98
|
+
throw new Error(`Config file ${filePath} must default-export the result of defineConfig().`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const parsed = moxxyConfigSchema.safeParse(raw);
|
|
102
|
+
if (!parsed.success) {
|
|
103
|
+
throw new Error(`Invalid moxxy config at ${filePath}:\n` + JSON.stringify(parsed.error.issues, null, 2));
|
|
104
|
+
}
|
|
105
|
+
return parsed.data;
|
|
106
|
+
}
|
|
107
|
+
// Key the cache by cwd: a jiti instance binds its module-resolution /
|
|
108
|
+
// interopDefault base to the dir it was created with, so a single shared
|
|
109
|
+
// instance would resolve a SECOND project's `.ts` config relative imports
|
|
110
|
+
// against the FIRST project's dir. Long-lived hosts (desktop/runner) load
|
|
111
|
+
// configs for multiple workspaces in one process, so each cwd needs its own.
|
|
112
|
+
//
|
|
113
|
+
// Each entry carries its own module-resolution + compiled-module store, so an
|
|
114
|
+
// unbounded map would grow one jiti runtime per workspace dir forever. Cap it
|
|
115
|
+
// with a small LRU (re-insert on hit, drop the oldest on overflow) so a
|
|
116
|
+
// long-running host that opens many projects keeps only a bounded working set.
|
|
117
|
+
const MAX_CACHED_JITI = 16;
|
|
118
|
+
const cachedJiti = new Map();
|
|
119
|
+
async function getJiti(cwd) {
|
|
120
|
+
const existing = cachedJiti.get(cwd);
|
|
121
|
+
if (existing) {
|
|
122
|
+
// Mark as most-recently-used.
|
|
123
|
+
cachedJiti.delete(cwd);
|
|
124
|
+
cachedJiti.set(cwd, existing);
|
|
125
|
+
return existing;
|
|
126
|
+
}
|
|
127
|
+
try {
|
|
128
|
+
const mod = await import('jiti');
|
|
129
|
+
const factory = mod.createJiti ??
|
|
130
|
+
mod.default;
|
|
131
|
+
if (!factory)
|
|
132
|
+
return null;
|
|
133
|
+
const instance = factory(cwd, { interopDefault: true });
|
|
134
|
+
cachedJiti.set(cwd, instance);
|
|
135
|
+
while (cachedJiti.size > MAX_CACHED_JITI) {
|
|
136
|
+
const oldest = cachedJiti.keys().next().value;
|
|
137
|
+
if (oldest === undefined)
|
|
138
|
+
break;
|
|
139
|
+
cachedJiti.delete(oldest);
|
|
140
|
+
}
|
|
141
|
+
return instance;
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// The ESM module registry never evicts an entry once imported and offers no
|
|
148
|
+
// eviction API: every DISTINCT specifier is retained for the process lifetime
|
|
149
|
+
// along with its whole module graph. A naive `?v=${Date.now()}` cache-buster on
|
|
150
|
+
// every load therefore leaks one module per reload in the exact long-lived
|
|
151
|
+
// hosts (desktop/runner) this loader targets. Instead: import each JS config by
|
|
152
|
+
// its plain file URL the FIRST time (one registry entry, GC-stable), and only
|
|
153
|
+
// append a cache-buster when re-loading a path we've already imported — using a
|
|
154
|
+
// monotonic counter so same-millisecond reloads are still guaranteed unique
|
|
155
|
+
// (Date.now()'s 1ms resolution would otherwise return the stale cached module).
|
|
156
|
+
const importedJsConfigs = new Set();
|
|
157
|
+
let importReloadCounter = 0;
|
|
158
|
+
async function importJsConfig(filePath) {
|
|
159
|
+
const base = pathToFileURL(filePath).href;
|
|
160
|
+
if (importedJsConfigs.has(base)) {
|
|
161
|
+
return import(`${base}?v=${Date.now()}-${++importReloadCounter}`);
|
|
162
|
+
}
|
|
163
|
+
importedJsConfigs.add(base);
|
|
164
|
+
return import(base);
|
|
165
|
+
}
|
|
166
|
+
function extractDefault(mod) {
|
|
167
|
+
if (!mod)
|
|
168
|
+
return undefined;
|
|
169
|
+
if (typeof mod !== 'object')
|
|
170
|
+
return undefined;
|
|
171
|
+
const m = mod;
|
|
172
|
+
if (m.default && typeof m.default === 'object')
|
|
173
|
+
return m.default;
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Walk upward from `startDir` (bounded by {@link MAX_CONFIG_SEARCH_DEPTH})
|
|
178
|
+
* returning the first directory that holds one of `names`. The `names` list is
|
|
179
|
+
* a deliberate parameter: `loadConfig` searches every config extension while the
|
|
180
|
+
* config plugin's editor searches only the YAML names it can safely mutate — so
|
|
181
|
+
* the shared traversal invariant lives here, the divergent name set stays with
|
|
182
|
+
* the caller. Returns the full path, or null if none found within the bound.
|
|
183
|
+
*/
|
|
184
|
+
export async function findUpward(startDir, names) {
|
|
185
|
+
let cursor = path.resolve(startDir);
|
|
186
|
+
for (let i = 0; i < MAX_CONFIG_SEARCH_DEPTH; i++) {
|
|
187
|
+
const found = await findFile(cursor, names);
|
|
188
|
+
if (found)
|
|
189
|
+
return found;
|
|
190
|
+
const parent = path.dirname(cursor);
|
|
191
|
+
if (parent === cursor)
|
|
192
|
+
break;
|
|
193
|
+
cursor = parent;
|
|
194
|
+
}
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
async function findFile(dir, names) {
|
|
198
|
+
for (const name of names) {
|
|
199
|
+
const candidate = path.join(dir, name);
|
|
200
|
+
try {
|
|
201
|
+
await fs.access(candidate);
|
|
202
|
+
return candidate;
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
// continue
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return null;
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"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"}
|
package/dist/merge.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { MoxxyConfig } from './schema.js';
|
|
2
|
+
/**
|
|
3
|
+
* Deep-merge any number of configs in order. Later wins on scalars; arrays are concatenated;
|
|
4
|
+
* objects are merged key-by-key.
|
|
5
|
+
*
|
|
6
|
+
* Precedence (highest → lowest): CLI flags → project config → user config → defaults.
|
|
7
|
+
*/
|
|
8
|
+
export declare function mergeConfigs(...configs: ReadonlyArray<MoxxyConfig | undefined>): MoxxyConfig;
|
|
9
|
+
//# sourceMappingURL=merge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../src/merge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,OAAO,EAAE,aAAa,CAAC,WAAW,GAAG,SAAS,CAAC,GAAG,WAAW,CAO5F"}
|
package/dist/merge.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deep-merge any number of configs in order. Later wins on scalars; arrays are concatenated;
|
|
3
|
+
* objects are merged key-by-key.
|
|
4
|
+
*
|
|
5
|
+
* Precedence (highest → lowest): CLI flags → project config → user config → defaults.
|
|
6
|
+
*/
|
|
7
|
+
export function mergeConfigs(...configs) {
|
|
8
|
+
const out = {};
|
|
9
|
+
for (const cfg of configs) {
|
|
10
|
+
if (!cfg)
|
|
11
|
+
continue;
|
|
12
|
+
mergeInto(out, cfg);
|
|
13
|
+
}
|
|
14
|
+
return out;
|
|
15
|
+
}
|
|
16
|
+
// Keys that, when assigned via `target[key] = ...`, hit a prototype setter
|
|
17
|
+
// instead of creating an own data property — silently dropping the data AND
|
|
18
|
+
// replacing the merged object's prototype. A parsed config (JSON default-export
|
|
19
|
+
// or some YAML inputs) can carry an own enumerable `__proto__`/`constructor`/
|
|
20
|
+
// `prototype` key, so skip them defensively. Legitimate configs never use them.
|
|
21
|
+
const FORBIDDEN_MERGE_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
22
|
+
function mergeInto(target, source) {
|
|
23
|
+
for (const [key, value] of Object.entries(source)) {
|
|
24
|
+
if (value === undefined)
|
|
25
|
+
continue;
|
|
26
|
+
if (FORBIDDEN_MERGE_KEYS.has(key))
|
|
27
|
+
continue;
|
|
28
|
+
const existing = target[key];
|
|
29
|
+
if (Array.isArray(value)) {
|
|
30
|
+
target[key] = Array.isArray(existing) ? [...existing, ...value] : [...value];
|
|
31
|
+
}
|
|
32
|
+
else if (isPlainObject(value)) {
|
|
33
|
+
const base = isPlainObject(existing) ? { ...existing } : {};
|
|
34
|
+
mergeInto(base, value);
|
|
35
|
+
target[key] = base;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
target[key] = value;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function isPlainObject(v) {
|
|
43
|
+
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=merge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge.js","sourceRoot":"","sources":["../src/merge.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,GAAG,OAA+C;IAC7E,MAAM,GAAG,GAAgB,EAAE,CAAC;IAC5B,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,CAAC,GAAG;YAAE,SAAS;QACnB,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACtB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,2EAA2E;AAC3E,4EAA4E;AAC5E,gFAAgF;AAChF,8EAA8E;AAC9E,gFAAgF;AAChF,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC,CAAC;AAEhF,SAAS,SAAS,CAAC,MAA+B,EAAE,MAA+B;IACjF,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS;QAClC,IAAI,oBAAoB,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QAC5C,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC;QAC/E,CAAC;aAAM,IAAI,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5D,SAAS,CAAC,IAAI,EAAE,KAAgC,CAAC,CAAC;YAClD,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACtB,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,CAAU;IAC/B,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/** Per-package settings in the `plugins.packages` install/enable ledger. */
|
|
3
|
+
export declare const pluginSettingsSchema: z.ZodObject<{
|
|
4
|
+
/** Plug/unplug the whole package (all its contributions). Default true. */
|
|
5
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
6
|
+
/** Package-specific options passed to the plugin. */
|
|
7
|
+
options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
8
|
+
/**
|
|
9
|
+
* Optional per-contribution exclusions, e.g. `["tool:foo"]`, to suppress a
|
|
10
|
+
* single contribution of an otherwise-enabled package. Honored at
|
|
11
|
+
* registration time. Kept optional so the common case stays one line.
|
|
12
|
+
*/
|
|
13
|
+
exclude: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
14
|
+
}, "strict", z.ZodTypeAny, {
|
|
15
|
+
enabled?: boolean | undefined;
|
|
16
|
+
options?: Record<string, unknown> | undefined;
|
|
17
|
+
exclude?: string[] | undefined;
|
|
18
|
+
}, {
|
|
19
|
+
enabled?: boolean | undefined;
|
|
20
|
+
options?: Record<string, unknown> | undefined;
|
|
21
|
+
exclude?: string[] | undefined;
|
|
22
|
+
}>;
|
|
23
|
+
export type PluginSettings = z.infer<typeof pluginSettingsSchema>;
|
|
24
|
+
//# sourceMappingURL=plugin-settings-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-settings-schema.d.ts","sourceRoot":"","sources":["../src/plugin-settings-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,4EAA4E;AAC5E,eAAO,MAAM,oBAAoB;IAE7B,2EAA2E;;IAE3E,qDAAqD;;IAErD;;;;OAIG;;;;;;;;;;EAGI,CAAC;AACZ,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/** Per-package settings in the `plugins.packages` install/enable ledger. */
|
|
3
|
+
export const pluginSettingsSchema = z
|
|
4
|
+
.object({
|
|
5
|
+
/** Plug/unplug the whole package (all its contributions). Default true. */
|
|
6
|
+
enabled: z.boolean().optional(),
|
|
7
|
+
/** Package-specific options passed to the plugin. */
|
|
8
|
+
options: z.record(z.string(), z.unknown()).optional(),
|
|
9
|
+
/**
|
|
10
|
+
* Optional per-contribution exclusions, e.g. `["tool:foo"]`, to suppress a
|
|
11
|
+
* single contribution of an otherwise-enabled package. Honored at
|
|
12
|
+
* registration time. Kept optional so the common case stays one line.
|
|
13
|
+
*/
|
|
14
|
+
exclude: z.array(z.string()).optional(),
|
|
15
|
+
})
|
|
16
|
+
.strict();
|
|
17
|
+
//# sourceMappingURL=plugin-settings-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-settings-schema.js","sourceRoot":"","sources":["../src/plugin-settings-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,4EAA4E;AAC5E,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC;KAClC,MAAM,CAAC;IACN,2EAA2E;IAC3E,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC/B,qDAAqD;IACrD,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,EAAE;IACrD;;;;OAIG;IACH,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CACxC,CAAC;KACD,MAAM,EAAE,CAAC"}
|
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type Plugin } from '@moxxy/sdk';
|
|
2
|
+
import { type MoxxyConfig } from './schema.js';
|
|
3
|
+
/**
|
|
4
|
+
* Optional callback that the CLI (or any session host) can provide to apply
|
|
5
|
+
* config changes to a live session without a restart. The applier receives the
|
|
6
|
+
* full validated config snapshot AFTER the write; it should diff against its
|
|
7
|
+
* own cached state and update the parts it can apply safely.
|
|
8
|
+
*
|
|
9
|
+
* Return a list of changed paths that were reflected at runtime, plus any
|
|
10
|
+
* that need a session restart to take effect.
|
|
11
|
+
*/
|
|
12
|
+
export interface ConfigApplyResult {
|
|
13
|
+
readonly applied: ReadonlyArray<string>;
|
|
14
|
+
readonly pending: ReadonlyArray<string>;
|
|
15
|
+
}
|
|
16
|
+
export type ConfigApplier = (snapshot: MoxxyConfig) => Promise<ConfigApplyResult>;
|
|
17
|
+
export declare function buildConfigPlugin(opts?: {
|
|
18
|
+
cwd: string;
|
|
19
|
+
applier?: ConfigApplier;
|
|
20
|
+
}): Plugin;
|
|
21
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAEA,OAAO,EAA4C,KAAK,MAAM,EAAE,MAAM,YAAY,CAAC;AAGnF,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAGlE;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACxC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACzC;AACD,MAAM,MAAM,aAAa,GAAG,CAAC,QAAQ,EAAE,WAAW,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;AA6FlF,wBAAgB,iBAAiB,CAC/B,IAAI,GAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,aAAa,CAAA;CAA2B,GACtE,MAAM,CAmPR"}
|