@moxxy/config 0.27.0 → 0.28.1
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 +4 -4
- package/src/user-config.test.ts +37 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moxxy/config",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.1",
|
|
4
4
|
"description": "defineConfig + moxxy.config.ts loader. Walks the file tree from cwd, also reads ~/.moxxy/config.{ts,js,mjs}, merges by precedence, and resolves the final shape the CLI consumes.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"moxxy",
|
|
@@ -38,14 +38,14 @@
|
|
|
38
38
|
"jiti": "^2.4.2",
|
|
39
39
|
"yaml": "^2.6.0",
|
|
40
40
|
"zod": "^3.24.0",
|
|
41
|
-
"@moxxy/sdk": "0.
|
|
41
|
+
"@moxxy/sdk": "0.28.1"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/node": "^22.10.0",
|
|
45
45
|
"typescript": "^5.7.3",
|
|
46
46
|
"vitest": "^2.1.8",
|
|
47
|
-
"@moxxy/
|
|
48
|
-
"@moxxy/
|
|
47
|
+
"@moxxy/vitest-preset": "0.0.0",
|
|
48
|
+
"@moxxy/tsconfig": "0.0.0"
|
|
49
49
|
},
|
|
50
50
|
"scripts": {
|
|
51
51
|
"build": "tsc -p tsconfig.json",
|
package/src/user-config.test.ts
CHANGED
|
@@ -3,7 +3,12 @@ import * as os from 'node:os';
|
|
|
3
3
|
import * as path from 'node:path';
|
|
4
4
|
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
5
5
|
import { parse as parseYaml } from 'yaml';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
applyInitConfig,
|
|
8
|
+
loadDisabledProviders,
|
|
9
|
+
setPluginEnabled,
|
|
10
|
+
setProviderEnabled,
|
|
11
|
+
} from './user-config.js';
|
|
7
12
|
import { moxxyConfigSchema } from './schema.js';
|
|
8
13
|
|
|
9
14
|
let tmp: string;
|
|
@@ -111,3 +116,34 @@ describe('applyInitConfig', () => {
|
|
|
111
116
|
expect(raw).toContain('# my hand-written config');
|
|
112
117
|
});
|
|
113
118
|
});
|
|
119
|
+
|
|
120
|
+
describe('setProviderEnabled', () => {
|
|
121
|
+
it('serializes two concurrent toggles so neither update is lost', async () => {
|
|
122
|
+
// Two rapid cross-client toggles (e.g. desktop + mobile hitting the same
|
|
123
|
+
// runner) each read-merge-write config.yaml on DIFFERENT providers. Without
|
|
124
|
+
// the config writer's mutex the second read would see the pre-first-write
|
|
125
|
+
// snapshot and clobber the first provider's flag (last-writer-wins). The
|
|
126
|
+
// module-level `configMutex` makes the second reader see the first's result.
|
|
127
|
+
await Promise.all([
|
|
128
|
+
setProviderEnabled('openai', false, { configPath }),
|
|
129
|
+
setProviderEnabled('anthropic', false, { configPath }),
|
|
130
|
+
]);
|
|
131
|
+
|
|
132
|
+
// Both landed: the file must reflect both disabled flags, not just one.
|
|
133
|
+
const parsed = (await readParsed()) as {
|
|
134
|
+
plugins: { provider: { items: Record<string, { enabled: boolean }> } };
|
|
135
|
+
};
|
|
136
|
+
expect(parsed.plugins.provider.items.openai).toEqual({ enabled: false });
|
|
137
|
+
expect(parsed.plugins.provider.items.anthropic).toEqual({ enabled: false });
|
|
138
|
+
expect([...(await loadDisabledProviders({ configPath }))].sort()).toEqual([
|
|
139
|
+
'anthropic',
|
|
140
|
+
'openai',
|
|
141
|
+
]);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('a later toggle overwrites the same provider flag deterministically', async () => {
|
|
145
|
+
await setProviderEnabled('openai', false, { configPath });
|
|
146
|
+
await setProviderEnabled('openai', true, { configPath });
|
|
147
|
+
expect(await loadDisabledProviders({ configPath })).toEqual([]);
|
|
148
|
+
});
|
|
149
|
+
});
|