@moxxy/config 0.28.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moxxy/config",
3
- "version": "0.28.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.28.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/tsconfig": "0.0.0",
48
- "@moxxy/vitest-preset": "0.0.0"
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",
@@ -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 { applyInitConfig, setPluginEnabled } from './user-config.js';
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
+ });