@graphcommerce/next-config 10.0.0-canary.68 β†’ 10.0.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/CHANGELOG.md CHANGED
@@ -1,5 +1,131 @@
1
1
  # Change Log
2
2
 
3
+ ## 10.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - [#2546](https://github.com/graphcommerce-org/graphcommerce/pull/2546) [`ed9332a`](https://github.com/graphcommerce-org/graphcommerce/commit/ed9332a7f78966d932041d9a7725641edc92b28d) - ## GraphCommerce 10 - Turbopack Support
8
+
9
+ This major release brings full Turbopack compatibility, dramatically improving development speed.
10
+
11
+ ### πŸš€ Turbopack-Compatible Interceptor System
12
+
13
+ The entire plugin/interceptor system has been rewritten to work with Turbopack:
14
+
15
+ - **No more Webpack plugins** - Removed `InterceptorPlugin` webpack plugin entirely
16
+ - **File-based interception** - Original files are moved to `.original.tsx` and replaced with interceptor content
17
+ - **Direct imports** - Interceptors import from `.original` files instead of embedding source
18
+ - **New CLI commands**:
19
+ - `graphcommerce codegen-interceptors` - Generate interceptor files
20
+ - `graphcommerce cleanup-interceptors` - Reset interceptor system, restore original files
21
+ - **Stable file hashing** - Deterministic interceptor generation for better caching
22
+
23
+ ### βš™οΈ Treeshakable Configuration System
24
+
25
+ Replaced Webpack `DefinePlugin`-based `import.meta.graphCommerce` with a new generated configuration system:
26
+
27
+ - **New `codegen-config-values` command** - Generates TypeScript files with precise typing
28
+ - **Schema-driven** - Dynamically introspects Zod schemas to determine all available properties
29
+ - **Fully treeshakable** - Unused config values are eliminated from the bundle
30
+ - **Type-safe** - Uses `Get<GraphCommerceConfig, 'path'>` for nested property access
31
+ - **Separate files for nested objects** - Optimal treeshaking for complex configurations
32
+
33
+ ### πŸ”§ withGraphCommerce Changes
34
+
35
+ - **Removed** `InterceptorPlugin` - No longer needed with file-based interception
36
+ - **Removed** `DefinePlugin` for `import.meta.graphCommerce` - Replaced with generated config
37
+ - **Removed** `@mui/*` alias rewrites - No longer required
38
+ - **Added** Turbopack loader rules for `.yaml`, `.yml`, and `.po` files
39
+ - **Added** `serverExternalPackages` for all `@whatwg-node/*` packages
40
+ - **Added** `optimizePackageImports` for better bundle optimization
41
+ - **Added** `images.qualities: [52, 75]` for Next.js image optimization
42
+
43
+ ### πŸ“¦ Lingui Configuration
44
+
45
+ - **Renamed** `lingui.config.js` β†’ `lingui.config.ts` with TypeScript support
46
+ - **Updated** `@graphcommerce/lingui-next/config` to TypeScript with proper exports
47
+ - **Simplified** formatter options
48
+
49
+ ### βš›οΈ React 19 & Next.js 16 Compatibility
50
+
51
+ - Updated `RefObject<T>` types for React 19 (now includes `null` by default)
52
+ - Replaced deprecated `React.VFC` with `React.FC`
53
+ - Fixed `useRef` calls to require explicit initial values
54
+ - Updated `MutableRefObject` usage in `framer-scroller`
55
+
56
+ ### πŸ“‹ ESLint 9 Flat Config
57
+
58
+ - Migrated from legacy `.eslintrc` to new flat config format (`eslint.config.mjs`)
59
+ - Updated `@typescript-eslint/*` packages to v8
60
+ - Fixed AST selector for `SxProps` rule (`typeParameters` β†’ `typeArguments`)
61
+
62
+ ### πŸ”„ Apollo Client
63
+
64
+ - Fixed deprecated `name` option β†’ `clientAwareness: { name: 'ssr' }`
65
+ - Updated error handling types to accept `ApolloError | null | undefined`
66
+
67
+ ### ⚠️ Breaking Changes
68
+
69
+ - **Node.js 24.x not supported** - Restricted to `>=20 <24.0.0` due to [nodejs/undici#4290](https://github.com/nodejs/undici/issues/4290)
70
+ - **Interceptor files changed** - Original components now at `.original.tsx`
71
+ - **Config access changed** - Use generated config values instead of `import.meta.graphCommerce`
72
+ - **ESLint config format** - Must use flat config (`eslint.config.mjs`)
73
+ - **Lingui config** - Rename `lingui.config.js` to `lingui.config.ts`
74
+
75
+ ### πŸ—‘οΈ Removed
76
+
77
+ - `InterceptorPlugin` webpack plugin
78
+ - `configToImportMeta` utility
79
+ - Webpack `DefinePlugin` usage for config
80
+ - `@mui/*` modern alias rewrites
81
+ - Debug plugins (`CircularDependencyPlugin`, `DuplicatesPlugin`) ([@paales](https://github.com/paales))
82
+
83
+ - [#2565](https://github.com/graphcommerce-org/graphcommerce/pull/2565) [`c96dfcd`](https://github.com/graphcommerce-org/graphcommerce/commit/c96dfcdca981baca387c270ad9e2b9515cdd00cc) - Updated to Apollo Client 4 ([@paales](https://github.com/paales))
84
+
85
+ ### Minor Changes
86
+
87
+ - [#2565](https://github.com/graphcommerce-org/graphcommerce/pull/2565) [`ea75841`](https://github.com/graphcommerce-org/graphcommerce/commit/ea758413b1ee8b8f2584e8f4135cb582fb87445f) - Migrated to vitest ([@paales](https://github.com/paales))
88
+
89
+ ### Patch Changes
90
+
91
+ - [#2487](https://github.com/graphcommerce-org/graphcommerce/pull/2487) [`8b25322`](https://github.com/graphcommerce-org/graphcommerce/commit/8b253224997b59ac74d72813214dfc224f526c0a) - When a dependency is optional or has peerDependenciesMeta set to optional, make sure it doesn't crash when it is not found when calling resolveDependenciesSync ([@paales](https://github.com/paales))
92
+
93
+ - [#2487](https://github.com/graphcommerce-org/graphcommerce/pull/2487) [`2c79a4c`](https://github.com/graphcommerce-org/graphcommerce/commit/2c79a4cba2779bc367104ebb13e6c0d6feb6574f) - Remove redirects for `/product/$type/[url]` routes, those haven't been used for years anymore. ([@paales](https://github.com/paales))
94
+
95
+ - [#2472](https://github.com/graphcommerce-org/graphcommerce/pull/2472) [`905157b`](https://github.com/graphcommerce-org/graphcommerce/commit/905157bec2c9e1dcf51b6e6f7b6913aa9be7b609) - Solve issue with chalk compilation because we’re not migrated to esm modules. ([@paales](https://github.com/paales))
96
+
97
+ - [`f6b9c0d`](https://github.com/graphcommerce-org/graphcommerce/commit/f6b9c0d2bc5f678fc6cde279f1590b30ef631f8a) - Temporarily pin prettier to 3.5.3 to fix the GraphCommerce build: https://github.com/hosseinmd/prettier-plugin-jsdoc/pull/246/files ([@paales](https://github.com/paales))
98
+
99
+ - [#2487](https://github.com/graphcommerce-org/graphcommerce/pull/2487) [`30b7356`](https://github.com/graphcommerce-org/graphcommerce/commit/30b7356790efbac0f0017ef61cb1619b920100ab) - Solve issue where withGraphCommerce had a hard dependency on Magento specific configurations ([@paales](https://github.com/paales))
100
+
101
+ - [`62b71d5`](https://github.com/graphcommerce-org/graphcommerce/commit/62b71d5ed1d482fdb5b76dc19ac4d55fc41fb191) - Solve issue: TypeError: InMemoryLRUCache is not a constructor ([@paales](https://github.com/paales))
102
+
103
+ - [#2537](https://github.com/graphcommerce-org/graphcommerce/pull/2537) [`6492d81`](https://github.com/graphcommerce-org/graphcommerce/commit/6492d819a858ffdc01a97e6914053e9cc14c8fc5) - Reduce exported scope of config so we dont introduce a hidden dependency on Magento ([@paales](https://github.com/paales))
104
+
105
+ - [`f508396`](https://github.com/graphcommerce-org/graphcommerce/commit/f50839619c75c8f7b1782c079f1c25998cb9217b) - Solve issue where optional chaining for import.meta.graphCommmerce configuration paths didn't work. ([@paales](https://github.com/paales))
106
+
107
+ - [#2499](https://github.com/graphcommerce-org/graphcommerce/pull/2499) [`9cf0450`](https://github.com/graphcommerce-org/graphcommerce/commit/9cf0450a41c4c74292b96f5795c7428f9d6a930c) - Remove the 'ignored' string when loading the graphcommerce config env variable loading, as that isn't always correct ([@paales](https://github.com/paales))
108
+
109
+ - [#2487](https://github.com/graphcommerce-org/graphcommerce/pull/2487) [`9825f59`](https://github.com/graphcommerce-org/graphcommerce/commit/9825f59b8626c315e6092950faceeab4311a5424) - Remove rewriteLegacyEnv as that hasn't been used for years ([@paales](https://github.com/paales))
110
+
111
+ - [#2487](https://github.com/graphcommerce-org/graphcommerce/pull/2487) [`5ffa0ee`](https://github.com/graphcommerce-org/graphcommerce/commit/5ffa0ee1d620f4f1c38bc5df36cbd527bcc43cf9) - Migrated `@graphcommerce/next-config` package to `"type": "module"` ([@paales](https://github.com/paales))
112
+
113
+ ## 10.0.0-canary.72
114
+
115
+ ## 10.0.0-canary.71
116
+
117
+ ## 10.0.0-canary.70
118
+
119
+ ### Major Changes
120
+
121
+ - [#2565](https://github.com/graphcommerce-org/graphcommerce/pull/2565) [`c96dfcd`](https://github.com/graphcommerce-org/graphcommerce/commit/c96dfcdca981baca387c270ad9e2b9515cdd00cc) - Updated to Apollo Client 4 ([@paales](https://github.com/paales))
122
+
123
+ ### Minor Changes
124
+
125
+ - [#2565](https://github.com/graphcommerce-org/graphcommerce/pull/2565) [`ea75841`](https://github.com/graphcommerce-org/graphcommerce/commit/ea758413b1ee8b8f2584e8f4135cb582fb87445f) - Migrated to vitest ([@paales](https://github.com/paales))
126
+
127
+ ## 10.0.0-canary.69
128
+
3
129
  ## 10.0.0-canary.68
4
130
 
5
131
  ## 10.0.0-canary.67
@@ -1,32 +1,49 @@
1
+ // Import after mocks are defined
1
2
  import fs from 'fs/promises'
2
3
  import path from 'path'
4
+ import fg from 'fast-glob'
5
+ import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
3
6
  import { copyFiles } from '../../src/commands/copyFiles'
4
7
  import { resolveDependenciesSync } from '../../src/utils/resolveDependenciesSync'
5
8
 
6
9
  // Mock fs/promises
7
- jest.mock('fs/promises', () => ({
8
- readFile: jest.fn(),
9
- writeFile: jest.fn(),
10
- mkdir: jest.fn(),
11
- readdir: jest.fn(),
12
- stat: jest.fn(),
13
- unlink: jest.fn(),
14
- rmdir: jest.fn(),
10
+ vi.mock('fs/promises', () => ({
11
+ default: {
12
+ readFile: vi.fn(),
13
+ writeFile: vi.fn(),
14
+ mkdir: vi.fn(),
15
+ readdir: vi.fn(),
16
+ stat: vi.fn(),
17
+ unlink: vi.fn(),
18
+ rmdir: vi.fn(),
19
+ },
20
+ readFile: vi.fn(),
21
+ writeFile: vi.fn(),
22
+ mkdir: vi.fn(),
23
+ readdir: vi.fn(),
24
+ stat: vi.fn(),
25
+ unlink: vi.fn(),
26
+ rmdir: vi.fn(),
15
27
  }))
16
28
 
17
29
  // Mock fast-glob
18
- jest.mock('fast-glob', () => ({
30
+ vi.mock('fast-glob', () => ({
19
31
  __esModule: true,
20
- default: jest.fn(),
32
+ default: vi.fn(),
21
33
  }))
22
34
 
23
35
  // Mock resolveDependenciesSync
24
- jest.mock('../../src/utils/resolveDependenciesSync', () => ({
25
- resolveDependenciesSync: jest.fn(),
36
+ vi.mock('../../src/utils/resolveDependenciesSync', () => ({
37
+ resolveDependenciesSync: vi.fn(),
26
38
  }))
27
39
 
40
+ // Get mocked versions
41
+ const mockFs = vi.mocked(fs)
42
+ const mockFg = vi.mocked(fg)
43
+ const mockResolveDependenciesSync = vi.mocked(resolveDependenciesSync)
44
+
28
45
  // Mock performance.now
29
- const mockPerformanceNow = jest.fn()
46
+ const mockPerformanceNow = vi.fn()
30
47
  global.performance = { now: mockPerformanceNow } as unknown as typeof performance
31
48
 
32
49
  // Mock process.cwd
@@ -34,7 +51,7 @@ const mockCwd = '/mock/cwd'
34
51
  // eslint-disable-next-line @typescript-eslint/unbound-method
35
52
  const originalCwd = process.cwd
36
53
  beforeAll(() => {
37
- process.cwd = jest.fn().mockReturnValue(mockCwd)
54
+ process.cwd = vi.fn().mockReturnValue(mockCwd)
38
55
  })
39
56
 
40
57
  afterAll(() => {
@@ -42,31 +59,31 @@ afterAll(() => {
42
59
  })
43
60
 
44
61
  describe('copyFiles', () => {
45
- let consoleLog: jest.SpyInstance
46
- let consoleInfo: jest.SpyInstance
47
- let consoleError: jest.SpyInstance
48
- let processExit: jest.SpyInstance
62
+ let consoleLog: ReturnType<typeof vi.spyOn>
63
+ let consoleInfo: ReturnType<typeof vi.spyOn>
64
+ let consoleError: ReturnType<typeof vi.spyOn>
65
+ let processExit: ReturnType<typeof vi.spyOn>
49
66
  let originalDebug: string | undefined
50
67
 
51
- beforeEach(() => {
52
- jest.clearAllMocks()
68
+ beforeEach(async () => {
69
+ vi.clearAllMocks()
53
70
  originalDebug = process.env.DEBUG
54
71
  process.env.DEBUG = undefined
55
- ;(resolveDependenciesSync as jest.Mock).mockReturnValue(
72
+ mockResolveDependenciesSync.mockReturnValue(
56
73
  new Map([
57
74
  ['@graphcommerce/package1', 'packages/package1'],
58
75
  ['@graphcommerce/package2', 'packages/package2'],
59
76
  ]),
60
77
  )
61
- consoleLog = jest.spyOn(console, 'log').mockImplementation(() => {})
62
- consoleInfo = jest.spyOn(console, 'info').mockImplementation(() => {})
63
- consoleError = jest.spyOn(console, 'error').mockImplementation(() => {})
64
- processExit = jest.spyOn(process, 'exit').mockImplementation(() => undefined as never)
78
+ consoleLog = vi.spyOn(console, 'log').mockImplementation(() => {})
79
+ consoleInfo = vi.spyOn(console, 'info').mockImplementation(() => {})
80
+ consoleError = vi.spyOn(console, 'error').mockImplementation(() => {})
81
+ processExit = vi.spyOn(process, 'exit').mockImplementation(() => undefined as never)
65
82
 
66
83
  // Setup default .gitignore mock
67
- ;(fs.readFile as jest.Mock).mockImplementation((filePath: string) => {
84
+ mockFs.readFile.mockImplementation((filePath) => {
68
85
  if (filePath === path.join(mockCwd, '.gitignore')) {
69
- return Promise.resolve('existing\ngitignore\ncontent')
86
+ return Promise.resolve('existing\ngitignore\ncontent') as ReturnType<typeof fs.readFile>
70
87
  }
71
88
  return Promise.reject(new Error(`ENOENT: no such file or directory, open '${filePath}'`))
72
89
  })
@@ -87,12 +104,11 @@ describe('copyFiles', () => {
87
104
  })
88
105
 
89
106
  it('should handle empty source directories', async () => {
90
- const fg = jest.requireMock('fast-glob').default as jest.Mock
91
- fg.mockResolvedValue([])
107
+ mockFg.mockResolvedValue([])
92
108
 
93
109
  await copyFiles()
94
110
 
95
- expect(fg).toHaveBeenCalledWith('**/*', {
111
+ expect(mockFg).toHaveBeenCalledWith('**/*', {
96
112
  cwd: mockCwd,
97
113
  dot: true,
98
114
  ignore: ['**/dist/**', '**/build/**', '**/.next/**', '**/.git/**', '**/node_modules/**'],
@@ -101,48 +117,49 @@ describe('copyFiles', () => {
101
117
  })
102
118
 
103
119
  it('should copy files and add management comments', async () => {
104
- const fg = jest.requireMock('fast-glob').default as jest.Mock
105
- fg.mockResolvedValueOnce([]) // First scan for existing files
120
+ mockFg
121
+ .mockResolvedValueOnce([]) // First scan for existing files
106
122
  .mockResolvedValueOnce(['file.ts']) // Second scan for package files
107
- ;(fs.readFile as jest.Mock).mockImplementation((filePath: string) => {
123
+ mockFs.readFile.mockImplementation((filePath) => {
108
124
  if (filePath === path.join('packages/package1/copy', 'file.ts')) {
109
- return Promise.resolve(Buffer.from('content'))
125
+ return Promise.resolve(Buffer.from('content')) as ReturnType<typeof fs.readFile>
110
126
  }
111
127
  if (filePath === path.join(mockCwd, '.gitignore')) {
112
- return Promise.resolve('existing\ngitignore\ncontent')
128
+ return Promise.resolve('existing\ngitignore\ncontent') as ReturnType<typeof fs.readFile>
113
129
  }
114
130
  return Promise.reject(new Error(`ENOENT: no such file or directory, open '${filePath}'`))
115
131
  })
116
132
 
117
- const mockStat = fs.stat as jest.Mock
118
- mockStat.mockResolvedValue({ isDirectory: () => false })
133
+ mockFs.stat.mockResolvedValue({ isDirectory: () => false } as Awaited<
134
+ ReturnType<typeof fs.stat>
135
+ >)
119
136
 
120
137
  await copyFiles()
121
138
 
122
139
  // Verify file was written with management comments
123
- const writeCall = (fs.writeFile as jest.Mock).mock.calls.find(
140
+ const writeCall = mockFs.writeFile.mock.calls.find(
124
141
  (call) => call[0] === path.join(mockCwd, 'file.ts'),
125
142
  )
126
143
  expect(writeCall).toBeTruthy()
127
- const content = writeCall[1].toString()
144
+ const content = writeCall![1].toString()
128
145
  expect(content).toContain('// managed by: graphcommerce')
129
146
  expect(content).toContain('// to modify this file, change it to managed by: local')
130
147
  expect(content).toContain('content')
131
148
 
132
149
  // Verify .gitignore was updated
133
- const gitignoreCall = (fs.writeFile as jest.Mock).mock.calls.find(
150
+ const gitignoreCall = mockFs.writeFile.mock.calls.find(
134
151
  (call) => call[0] === path.join(mockCwd, '.gitignore'),
135
152
  )
136
153
  expect(gitignoreCall).toBeTruthy()
137
- const gitignoreContent = gitignoreCall[1].toString()
154
+ const gitignoreContent = gitignoreCall![1].toString()
138
155
  expect(gitignoreContent).toContain('# managed by: graphcommerce')
139
156
  expect(gitignoreContent).toContain('file.ts')
140
157
  expect(gitignoreContent).toContain('# end managed by: graphcommerce')
141
158
  })
142
159
 
143
160
  it('should handle existing managed files with identical content', async () => {
144
- const fg = jest.requireMock('fast-glob').default as jest.Mock
145
- fg.mockResolvedValueOnce([]) // First scan for existing files
161
+ mockFg
162
+ .mockResolvedValueOnce([]) // First scan for existing files
146
163
  .mockResolvedValueOnce(['file.ts']) // Second scan for package files
147
164
 
148
165
  const sourceContent = Buffer.from('content')
@@ -153,15 +170,15 @@ describe('copyFiles', () => {
153
170
  sourceContent,
154
171
  ])
155
172
 
156
- ;(fs.readFile as jest.Mock).mockImplementation((filePath: string) => {
173
+ mockFs.readFile.mockImplementation((filePath) => {
157
174
  if (filePath === path.join('packages/package1/copy', 'file.ts')) {
158
- return Promise.resolve(sourceContent)
175
+ return Promise.resolve(sourceContent) as ReturnType<typeof fs.readFile>
159
176
  }
160
177
  if (filePath === path.join(mockCwd, 'file.ts')) {
161
- return Promise.resolve(managedContent)
178
+ return Promise.resolve(managedContent) as ReturnType<typeof fs.readFile>
162
179
  }
163
180
  if (filePath === path.join(mockCwd, '.gitignore')) {
164
- return Promise.resolve('existing\ngitignore\ncontent')
181
+ return Promise.resolve('existing\ngitignore\ncontent') as ReturnType<typeof fs.readFile>
165
182
  }
166
183
  return Promise.reject(new Error(`ENOENT: no such file or directory, open '${filePath}'`))
167
184
  })
@@ -169,13 +186,16 @@ describe('copyFiles', () => {
169
186
  await copyFiles()
170
187
 
171
188
  // Should not write to the file since content is identical
172
- expect(fs.writeFile).toHaveBeenCalledTimes(1) // Only .gitignore should be written
173
- expect(fs.writeFile).toHaveBeenCalledWith(path.join(mockCwd, '.gitignore'), expect.any(String))
189
+ expect(mockFs.writeFile).toHaveBeenCalledTimes(1) // Only .gitignore should be written
190
+ expect(mockFs.writeFile).toHaveBeenCalledWith(
191
+ path.join(mockCwd, '.gitignore'),
192
+ expect.any(String),
193
+ )
174
194
  })
175
195
 
176
196
  it('should update existing managed files with different content', async () => {
177
- const fg = jest.requireMock('fast-glob').default as jest.Mock
178
- fg.mockResolvedValueOnce([]) // First scan for existing files
197
+ mockFg
198
+ .mockResolvedValueOnce([]) // First scan for existing files
179
199
  .mockResolvedValueOnce(['file.ts']) // Second scan for package files
180
200
 
181
201
  const sourceContent = Buffer.from('new content')
@@ -186,15 +206,15 @@ describe('copyFiles', () => {
186
206
  Buffer.from('old content'),
187
207
  ])
188
208
 
189
- ;(fs.readFile as jest.Mock).mockImplementation((filePath: string) => {
209
+ mockFs.readFile.mockImplementation((filePath) => {
190
210
  if (filePath === path.join('packages/package1/copy', 'file.ts')) {
191
- return Promise.resolve(sourceContent)
211
+ return Promise.resolve(sourceContent) as ReturnType<typeof fs.readFile>
192
212
  }
193
213
  if (filePath === path.join(mockCwd, 'file.ts')) {
194
- return Promise.resolve(oldContent)
214
+ return Promise.resolve(oldContent) as ReturnType<typeof fs.readFile>
195
215
  }
196
216
  if (filePath === path.join(mockCwd, '.gitignore')) {
197
- return Promise.resolve('existing\ngitignore\ncontent')
217
+ return Promise.resolve('existing\ngitignore\ncontent') as ReturnType<typeof fs.readFile>
198
218
  }
199
219
  return Promise.reject(new Error(`ENOENT: no such file or directory, open '${filePath}'`))
200
220
  })
@@ -202,25 +222,25 @@ describe('copyFiles', () => {
202
222
  await copyFiles()
203
223
 
204
224
  // Should write the new content
205
- const writeCall = (fs.writeFile as jest.Mock).mock.calls.find(
225
+ const writeCall = mockFs.writeFile.mock.calls.find(
206
226
  (call) => call[0] === path.join(mockCwd, 'file.ts'),
207
227
  )
208
228
  expect(writeCall).toBeTruthy()
209
- const content = writeCall[1].toString()
229
+ const content = writeCall![1].toString()
210
230
  expect(content).toContain('new content')
211
231
  expect(consoleInfo).toHaveBeenCalledWith('Updated managed file: file.ts')
212
232
  })
213
233
 
214
234
  it('should create new files with management comments', async () => {
215
- const fg = jest.requireMock('fast-glob').default as jest.Mock
216
- fg.mockResolvedValueOnce([]) // First scan for existing files
235
+ mockFg
236
+ .mockResolvedValueOnce([]) // First scan for existing files
217
237
  .mockResolvedValueOnce(['new-file.ts']) // Second scan for package files
218
- ;(fs.readFile as jest.Mock).mockImplementation((filePath: string) => {
238
+ mockFs.readFile.mockImplementation((filePath) => {
219
239
  if (filePath === path.join('packages/package1/copy', 'new-file.ts')) {
220
- return Promise.resolve(Buffer.from('content'))
240
+ return Promise.resolve(Buffer.from('content')) as ReturnType<typeof fs.readFile>
221
241
  }
222
242
  if (filePath === path.join(mockCwd, '.gitignore')) {
223
- return Promise.resolve('existing\ngitignore\ncontent')
243
+ return Promise.resolve('existing\ngitignore\ncontent') as ReturnType<typeof fs.readFile>
224
244
  }
225
245
  if (filePath === path.join(mockCwd, 'new-file.ts')) {
226
246
  return Promise.reject(new Error('ENOENT: no such file or directory'))
@@ -233,22 +253,27 @@ describe('copyFiles', () => {
233
253
  expect(consoleInfo).toHaveBeenCalledWith(
234
254
  'Creating new file: new-file.ts\nSource: packages/package1/copy/new-file.ts',
235
255
  )
236
- expect(fs.writeFile).toHaveBeenCalledWith(path.join(mockCwd, 'new-file.ts'), expect.any(Buffer))
256
+ expect(mockFs.writeFile).toHaveBeenCalledWith(
257
+ path.join(mockCwd, 'new-file.ts'),
258
+ expect.any(Buffer),
259
+ )
237
260
  })
238
261
 
239
262
  it('should handle locally managed files', async () => {
240
- const fg = jest.requireMock('fast-glob').default as jest.Mock
241
- fg.mockResolvedValueOnce([]) // First scan for existing files
263
+ mockFg
264
+ .mockResolvedValueOnce([]) // First scan for existing files
242
265
  .mockResolvedValueOnce(['file.ts']) // Second scan for package files
243
- ;(fs.readFile as jest.Mock).mockImplementation((filePath: string) => {
266
+ mockFs.readFile.mockImplementation((filePath) => {
244
267
  if (filePath === path.join('packages/package1/copy', 'file.ts')) {
245
- return Promise.resolve(Buffer.from('content'))
268
+ return Promise.resolve(Buffer.from('content')) as ReturnType<typeof fs.readFile>
246
269
  }
247
270
  if (filePath === path.join(mockCwd, 'file.ts')) {
248
- return Promise.resolve(Buffer.from('// managed by: local\ncontent'))
271
+ return Promise.resolve(Buffer.from('// managed by: local\ncontent')) as ReturnType<
272
+ typeof fs.readFile
273
+ >
249
274
  }
250
275
  if (filePath === path.join(mockCwd, '.gitignore')) {
251
- return Promise.resolve('existing\ngitignore\ncontent')
276
+ return Promise.resolve('existing\ngitignore\ncontent') as ReturnType<typeof fs.readFile>
252
277
  }
253
278
  return Promise.reject(new Error(`ENOENT: no such file or directory, open '${filePath}'`))
254
279
  })
@@ -256,42 +281,44 @@ describe('copyFiles', () => {
256
281
  await copyFiles()
257
282
 
258
283
  // Should not overwrite locally managed files
259
- expect(fs.writeFile).toHaveBeenCalledTimes(1) // Only .gitignore should be written
260
- expect(fs.writeFile).toHaveBeenCalledWith(path.join(mockCwd, '.gitignore'), expect.any(String))
284
+ expect(mockFs.writeFile).toHaveBeenCalledTimes(1) // Only .gitignore should be written
285
+ expect(mockFs.writeFile).toHaveBeenCalledWith(
286
+ path.join(mockCwd, '.gitignore'),
287
+ expect.any(String),
288
+ )
261
289
  })
262
290
 
263
291
  it('should create destination directory if it does not exist', async () => {
264
- const fg = jest.requireMock('fast-glob').default as jest.Mock
265
- fg.mockResolvedValueOnce([]) // First scan for existing files
292
+ mockFg
293
+ .mockResolvedValueOnce([]) // First scan for existing files
266
294
  .mockResolvedValueOnce(['nested/file.ts']) // Second scan for package files
267
- ;(fs.readFile as jest.Mock).mockImplementation((filePath: string) => {
295
+ mockFs.readFile.mockImplementation((filePath) => {
268
296
  if (filePath === path.join('packages/package1/copy', 'nested/file.ts')) {
269
- return Promise.resolve(Buffer.from('content'))
297
+ return Promise.resolve(Buffer.from('content')) as ReturnType<typeof fs.readFile>
270
298
  }
271
299
  if (filePath === path.join(mockCwd, '.gitignore')) {
272
- return Promise.resolve('existing\ngitignore\ncontent')
300
+ return Promise.resolve('existing\ngitignore\ncontent') as ReturnType<typeof fs.readFile>
273
301
  }
274
302
  return Promise.reject(new Error(`ENOENT: no such file or directory, open '${filePath}'`))
275
303
  })
276
304
 
277
- const mockMkdir = fs.mkdir as jest.Mock
278
- mockMkdir.mockResolvedValue(undefined)
305
+ mockFs.mkdir.mockResolvedValue(undefined)
279
306
 
280
307
  await copyFiles()
281
308
 
282
- expect(mockMkdir).toHaveBeenCalledWith(path.join(mockCwd, 'nested'), { recursive: true })
309
+ expect(mockFs.mkdir).toHaveBeenCalledWith(path.join(mockCwd, 'nested'), { recursive: true })
283
310
  })
284
311
 
285
312
  it('should handle errors gracefully', async () => {
286
- const fg = jest.requireMock('fast-glob').default as jest.Mock
287
- fg.mockResolvedValueOnce([]) // First scan for existing files
313
+ mockFg
314
+ .mockResolvedValueOnce([]) // First scan for existing files
288
315
  .mockResolvedValueOnce(['file.ts']) // Second scan for package files
289
- ;(fs.readFile as jest.Mock).mockImplementation((filePath: string) => {
316
+ mockFs.readFile.mockImplementation((filePath) => {
290
317
  if (filePath === path.join('packages/package1/copy', 'file.ts')) {
291
318
  return Promise.reject(new Error('Read error'))
292
319
  }
293
320
  if (filePath === path.join(mockCwd, '.gitignore')) {
294
- return Promise.resolve('existing\ngitignore\ncontent')
321
+ return Promise.resolve('existing\ngitignore\ncontent') as ReturnType<typeof fs.readFile>
295
322
  }
296
323
  return Promise.reject(new Error(`ENOENT: no such file or directory, open '${filePath}'`))
297
324
  })
@@ -307,8 +334,8 @@ describe('copyFiles', () => {
307
334
  })
308
335
 
309
336
  it('should detect file conflicts between packages', async () => {
310
- const fg = jest.requireMock('fast-glob').default as jest.Mock
311
- fg.mockResolvedValueOnce([]) // First scan for existing files
337
+ mockFg
338
+ .mockResolvedValueOnce([]) // First scan for existing files
312
339
  .mockResolvedValueOnce(['conflict.ts']) // Package 1 files
313
340
  .mockResolvedValueOnce(['conflict.ts']) // Package 2 files
314
341
 
@@ -321,40 +348,41 @@ describe('copyFiles', () => {
321
348
  })
322
349
 
323
350
  it('should remove files that are no longer provided', async () => {
324
- const fg = jest.requireMock('fast-glob').default as jest.Mock
325
- fg.mockResolvedValueOnce(['old-file.ts']) // First scan finds existing managed file
351
+ mockFg
352
+ .mockResolvedValueOnce(['old-file.ts']) // First scan finds existing managed file
326
353
  .mockResolvedValueOnce([]) // Second scan finds no files in packages
327
354
 
328
355
  // Mock existing managed file
329
- ;(fs.readFile as jest.Mock).mockImplementation((filePath: string) => {
356
+ mockFs.readFile.mockImplementation((filePath) => {
330
357
  if (filePath === path.join(mockCwd, 'old-file.ts')) {
331
- return Promise.resolve(Buffer.from('// managed by: graphcommerce\ncontent'))
358
+ return Promise.resolve(Buffer.from('// managed by: graphcommerce\ncontent')) as ReturnType<
359
+ typeof fs.readFile
360
+ >
332
361
  }
333
362
  if (filePath === path.join(mockCwd, '.gitignore')) {
334
- return Promise.resolve('existing\ngitignore\ncontent')
363
+ return Promise.resolve('existing\ngitignore\ncontent') as ReturnType<typeof fs.readFile>
335
364
  }
336
365
  return Promise.reject(new Error(`ENOENT: no such file or directory, open '${filePath}'`))
337
366
  })
338
367
 
339
368
  // Mock directory checks
340
- const mockReaddir = fs.readdir as jest.Mock
341
- mockReaddir.mockImplementation((dirPath: string) => {
369
+ mockFs.readdir.mockImplementation((dirPath) => {
342
370
  if (dirPath === mockCwd) {
343
- return Promise.resolve(['old-file.ts'])
371
+ return Promise.resolve(['old-file.ts']) as ReturnType<typeof fs.readdir>
344
372
  }
345
- return Promise.resolve([])
373
+ return Promise.resolve([]) as ReturnType<typeof fs.readdir>
346
374
  })
347
375
 
348
376
  await copyFiles()
349
377
 
350
378
  // Verify file was removed
351
- expect(fs.unlink).toHaveBeenCalledWith(path.join(mockCwd, 'old-file.ts'))
379
+ expect(mockFs.unlink).toHaveBeenCalledWith(path.join(mockCwd, 'old-file.ts'))
352
380
 
353
381
  // Verify directory was checked
354
- expect(mockReaddir).toHaveBeenCalledWith(mockCwd)
382
+ expect(mockFs.readdir).toHaveBeenCalledWith(mockCwd)
355
383
 
356
384
  // Verify .gitignore was updated
357
- expect(fs.writeFile).toHaveBeenCalledWith(
385
+ expect(mockFs.writeFile).toHaveBeenCalledWith(
358
386
  path.join(mockCwd, '.gitignore'),
359
387
  expect.stringContaining('existing\ngitignore\ncontent'),
360
388
  )
@@ -362,15 +390,15 @@ describe('copyFiles', () => {
362
390
 
363
391
  it('should handle debug mode', async () => {
364
392
  process.env.DEBUG = 'true'
365
- const fg = jest.requireMock('fast-glob').default as jest.Mock
366
- fg.mockResolvedValueOnce([]) // First scan for existing files
393
+ mockFg
394
+ .mockResolvedValueOnce([]) // First scan for existing files
367
395
  .mockResolvedValueOnce(['file.ts']) // Second scan for package files
368
- ;(fs.readFile as jest.Mock).mockImplementation((filePath: string) => {
396
+ mockFs.readFile.mockImplementation((filePath) => {
369
397
  if (filePath === path.join('packages/package1/copy', 'file.ts')) {
370
- return Promise.resolve(Buffer.from('content'))
398
+ return Promise.resolve(Buffer.from('content')) as ReturnType<typeof fs.readFile>
371
399
  }
372
400
  if (filePath === path.join(mockCwd, '.gitignore')) {
373
- return Promise.resolve('existing\ngitignore\ncontent')
401
+ return Promise.resolve('existing\ngitignore\ncontent') as ReturnType<typeof fs.readFile>
374
402
  }
375
403
  return Promise.reject(new Error(`ENOENT: no such file or directory, open '${filePath}'`))
376
404
  })
@@ -382,18 +410,18 @@ describe('copyFiles', () => {
382
410
  })
383
411
 
384
412
  it('should handle unmanaged files', async () => {
385
- const fg = jest.requireMock('fast-glob').default as jest.Mock
386
- fg.mockResolvedValueOnce([]) // First scan for existing files
413
+ mockFg
414
+ .mockResolvedValueOnce([]) // First scan for existing files
387
415
  .mockResolvedValueOnce(['file.ts']) // Second scan for package files
388
- ;(fs.readFile as jest.Mock).mockImplementation((filePath: string) => {
416
+ mockFs.readFile.mockImplementation((filePath) => {
389
417
  if (filePath === path.join('packages/package1/copy', 'file.ts')) {
390
- return Promise.resolve(Buffer.from('content'))
418
+ return Promise.resolve(Buffer.from('content')) as ReturnType<typeof fs.readFile>
391
419
  }
392
420
  if (filePath === path.join(mockCwd, 'file.ts')) {
393
- return Promise.resolve(Buffer.from('unmanaged content'))
421
+ return Promise.resolve(Buffer.from('unmanaged content')) as ReturnType<typeof fs.readFile>
394
422
  }
395
423
  if (filePath === path.join(mockCwd, '.gitignore')) {
396
- return Promise.resolve('existing\ngitignore\ncontent')
424
+ return Promise.resolve('existing\ngitignore\ncontent') as ReturnType<typeof fs.readFile>
397
425
  }
398
426
  return Promise.reject(new Error(`ENOENT: no such file or directory, open '${filePath}'`))
399
427
  })
@@ -406,32 +434,34 @@ describe('copyFiles', () => {
406
434
  })
407
435
 
408
436
  it('should cleanup nested empty directories', async () => {
409
- const fg = jest.requireMock('fast-glob').default as jest.Mock
410
- fg.mockResolvedValueOnce(['nested/deeply/file.ts']) // First scan finds existing managed file
437
+ mockFg
438
+ .mockResolvedValueOnce(['nested/deeply/file.ts']) // First scan finds existing managed file
411
439
  .mockResolvedValueOnce([]) // Second scan finds no files in packages
412
440
 
413
441
  // Mock existing managed file
414
- ;(fs.readFile as jest.Mock).mockImplementation((filePath: string) => {
442
+ mockFs.readFile.mockImplementation((filePath) => {
415
443
  if (filePath === path.join(mockCwd, 'nested/deeply/file.ts')) {
416
- return Promise.resolve(Buffer.from('// managed by: graphcommerce\ncontent'))
444
+ return Promise.resolve(Buffer.from('// managed by: graphcommerce\ncontent')) as ReturnType<
445
+ typeof fs.readFile
446
+ >
417
447
  }
418
448
  if (filePath === path.join(mockCwd, '.gitignore')) {
419
- return Promise.resolve('existing\ngitignore\ncontent')
449
+ return Promise.resolve('existing\ngitignore\ncontent') as ReturnType<typeof fs.readFile>
420
450
  }
421
451
  return Promise.reject(new Error(`ENOENT: no such file or directory, open '${filePath}'`))
422
452
  })
423
453
 
424
454
  // Mock directory checks to simulate empty directories
425
- ;(fs.readdir as jest.Mock).mockReturnValue(Promise.resolve([]))
455
+ mockFs.readdir.mockReturnValue(Promise.resolve([]) as ReturnType<typeof fs.readdir>)
426
456
 
427
457
  await copyFiles()
428
458
 
429
459
  // Verify file was removed
430
- expect(fs.unlink).toHaveBeenCalledWith(path.join(mockCwd, 'nested/deeply/file.ts'))
460
+ expect(mockFs.unlink).toHaveBeenCalledWith(path.join(mockCwd, 'nested/deeply/file.ts'))
431
461
 
432
462
  // Verify directories were checked and removed in the correct order
433
- const readdirCalls = (fs.readdir as jest.Mock).mock.calls.map((call) => call[0])
434
- const rmdirCalls = (fs.rmdir as jest.Mock).mock.calls.map((call) => call[0])
463
+ const readdirCalls = mockFs.readdir.mock.calls.map((call) => call[0])
464
+ const rmdirCalls = mockFs.rmdir.mock.calls.map((call) => call[0])
435
465
 
436
466
  // Both directories should have been checked
437
467
  expect(readdirCalls).toContain(path.join(mockCwd, 'nested/deeply'))
@@ -448,54 +478,60 @@ describe('copyFiles', () => {
448
478
  })
449
479
 
450
480
  it('should handle partial directory cleanup', async () => {
451
- const fg = jest.requireMock('fast-glob').default as jest.Mock
452
- fg.mockResolvedValueOnce(['nested/remove.ts']) // First scan finds existing managed file
481
+ mockFg
482
+ .mockResolvedValueOnce(['nested/remove.ts']) // First scan finds existing managed file
453
483
  .mockResolvedValueOnce([]) // Second scan finds no files in packages
454
484
 
455
485
  // Mock existing managed file
456
- ;(fs.readFile as jest.Mock).mockImplementation((filePath: string) => {
486
+ mockFs.readFile.mockImplementation((filePath) => {
457
487
  if (filePath === path.join(mockCwd, 'nested/remove.ts')) {
458
- return Promise.resolve(Buffer.from('// managed by: graphcommerce\nremove content'))
488
+ return Promise.resolve(
489
+ Buffer.from('// managed by: graphcommerce\nremove content'),
490
+ ) as ReturnType<typeof fs.readFile>
459
491
  }
460
492
  if (filePath === path.join(mockCwd, '.gitignore')) {
461
- return Promise.resolve('existing\ngitignore\ncontent')
493
+ return Promise.resolve('existing\ngitignore\ncontent') as ReturnType<typeof fs.readFile>
462
494
  }
463
495
  return Promise.reject(new Error(`ENOENT: no such file or directory, open '${filePath}'`))
464
496
  })
465
497
 
466
498
  // Mock directory check to show directory is not empty
467
- ;(fs.readdir as jest.Mock).mockReturnValue(Promise.resolve(['other-file.ts']))
499
+ mockFs.readdir.mockReturnValue(
500
+ Promise.resolve(['other-file.ts']) as ReturnType<typeof fs.readdir>,
501
+ )
468
502
 
469
503
  await copyFiles()
470
504
 
471
505
  // Verify file removal
472
- expect(fs.unlink).toHaveBeenCalledTimes(1)
473
- expect(fs.unlink).toHaveBeenCalledWith(path.join(mockCwd, 'nested/remove.ts'))
506
+ expect(mockFs.unlink).toHaveBeenCalledTimes(1)
507
+ expect(mockFs.unlink).toHaveBeenCalledWith(path.join(mockCwd, 'nested/remove.ts'))
474
508
 
475
509
  // Verify directory was checked but not removed (since it's not empty)
476
- expect(fs.readdir).toHaveBeenCalledWith(path.join(mockCwd, 'nested'))
477
- expect(fs.rmdir).not.toHaveBeenCalled()
510
+ expect(mockFs.readdir).toHaveBeenCalledWith(path.join(mockCwd, 'nested'))
511
+ expect(mockFs.rmdir).not.toHaveBeenCalled()
478
512
  })
479
513
 
480
514
  it('should handle directory removal errors gracefully', async () => {
481
- const fg = jest.requireMock('fast-glob').default as jest.Mock
482
- fg.mockResolvedValueOnce(['nested/file.ts']) // First scan finds existing managed file
515
+ mockFg
516
+ .mockResolvedValueOnce(['nested/file.ts']) // First scan finds existing managed file
483
517
  .mockResolvedValueOnce([]) // Second scan finds no files in packages
484
518
 
485
519
  // Mock existing managed file
486
- ;(fs.readFile as jest.Mock).mockImplementation((filePath: string) => {
520
+ mockFs.readFile.mockImplementation((filePath) => {
487
521
  if (filePath === path.join(mockCwd, 'nested/file.ts')) {
488
- return Promise.resolve(Buffer.from('// managed by: graphcommerce\ncontent'))
522
+ return Promise.resolve(Buffer.from('// managed by: graphcommerce\ncontent')) as ReturnType<
523
+ typeof fs.readFile
524
+ >
489
525
  }
490
526
  if (filePath === path.join(mockCwd, '.gitignore')) {
491
- return Promise.resolve('existing\ngitignore\ncontent')
527
+ return Promise.resolve('existing\ngitignore\ncontent') as ReturnType<typeof fs.readFile>
492
528
  }
493
529
  return Promise.reject(new Error(`ENOENT: no such file or directory, open '${filePath}'`))
494
530
  })
495
531
 
496
532
  // Mock directory is empty but removal fails with EACCES
497
- ;(fs.readdir as jest.Mock).mockReturnValue(Promise.resolve([]))
498
- ;(fs.rmdir as jest.Mock).mockImplementation(() => {
533
+ mockFs.readdir.mockReturnValue(Promise.resolve([]) as ReturnType<typeof fs.readdir>)
534
+ mockFs.rmdir.mockImplementation(() => {
499
535
  const error = new Error('EACCES: permission denied') as NodeJS.ErrnoException
500
536
  error.code = 'EACCES'
501
537
  return Promise.reject(error)
@@ -504,7 +540,7 @@ describe('copyFiles', () => {
504
540
  await copyFiles()
505
541
 
506
542
  // Verify file removal still succeeded
507
- expect(fs.unlink).toHaveBeenCalledWith(path.join(mockCwd, 'nested/file.ts'))
543
+ expect(mockFs.unlink).toHaveBeenCalledWith(path.join(mockCwd, 'nested/file.ts'))
508
544
 
509
545
  // Verify error was logged but didn't crash the process
510
546
  expect(consoleError).toHaveBeenCalledWith(
@@ -1,4 +1,4 @@
1
- // Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
3
  exports[`parses an env config object 1`] = `
4
4
  {
@@ -737,14 +737,6 @@ it('finds plugins', () => {
737
737
  "targetModule": "@graphcommerce/graphql",
738
738
  "type": "function",
739
739
  },
740
- {
741
- "enabled": true,
742
- "sourceExport": "meshConfig",
743
- "sourceModule": "@graphcommerce/graphql-mesh/plugins/meshConfigFake",
744
- "targetExport": "meshConfig",
745
- "targetModule": "@graphcommerce/graphql-mesh/meshConfig",
746
- "type": "function",
747
- },
748
740
  ]
749
741
  `)
750
742
  expect(disabled).toMatchInlineSnapshot(
@@ -1,3 +1,4 @@
1
+ import { vi } from 'vitest'
1
2
  import type { GraphCommerceConfig } from '../../src/generated/config'
2
3
  import { findOriginalSource } from '../../src/interceptors/findOriginalSource'
3
4
  import { generateInterceptors } from '../../src/interceptors/generateInterceptors'
@@ -524,9 +525,9 @@ export const plugin: FunctionPlugin<typeof getSitemapPathsType> = (prev, ...args
524
525
  return prev(...args)
525
526
  }
526
527
  `
527
- console.error = jest.fn()
528
+ console.error = vi.fn()
528
529
  const plugins = parseStructure(parseSync(src), fakeconfig, './plugins/MyPlugin.tsx')
529
- expect((console.error as jest.Mock).mock.calls[0][0]).toMatchInlineSnapshot(
530
+ expect((console.error as ReturnType<typeof vi.fn>).mock.calls[0][0]).toMatchInlineSnapshot(
530
531
  '"Plugin configuration invalid! See ./plugins/MyPlugin.tsx"',
531
532
  )
532
533
  expect(plugins).toMatchInlineSnapshot('[]')
@@ -1,7 +1,7 @@
1
1
  import 'cosmiconfig';
2
2
  import '../generated/config.js';
3
- export { l as loadConfig, r as replaceConfigInString } from '../loadConfig-nJiCKeL1.js';
3
+ export { l as loadConfig, r as replaceConfigInString } from '../loadConfig-CZYUe1jE.js';
4
4
  import 'zod';
5
- import '@apollo/client/utilities/index.js';
5
+ import '@apollo/client/utilities/internal';
6
6
  import 'chalk';
7
7
  import 'lodash';
@@ -39,14 +39,12 @@ function GraphCommerceConfigSchema() {
39
39
  customerXMagentoCacheIdDisable: z.boolean().nullish(),
40
40
  dataLayer: z.lazy(() => DatalayerConfigSchema().nullish()),
41
41
  debug: z.lazy(() => GraphCommerceDebugConfigSchema().nullish()),
42
- demoMode: z.boolean().default(true).nullish(),
43
42
  enableGuestCheckoutLogin: z.boolean().nullish(),
44
43
  googleAnalyticsId: z.string().nullish(),
45
44
  googlePlaystore: z.lazy(() => GraphCommerceGooglePlaystoreConfigSchema().nullish()),
46
45
  googleRecaptchaKey: z.string().nullish(),
47
46
  googleTagmanagerId: z.string().nullish(),
48
47
  graphqlMeshEditMode: z.boolean().default(false).nullish(),
49
- hygraphEndpoint: z.string().min(1),
50
48
  hygraphManagementApi: z.string().nullish(),
51
49
  hygraphProjectId: z.string().nullish(),
52
50
  hygraphWriteAccessToken: z.string().nullish(),
@@ -101,7 +99,6 @@ function GraphCommerceStorefrontConfigSchema() {
101
99
  googleAnalyticsId: z.string().nullish(),
102
100
  googleRecaptchaKey: z.string().nullish(),
103
101
  googleTagmanagerId: z.string().nullish(),
104
- hygraphLocales: z.array(z.string().min(1)).nullish(),
105
102
  linguiLocale: z.string().nullish(),
106
103
  locale: z.string().min(1),
107
104
  magentoStoreCode: z.string().min(1),
package/dist/index.js CHANGED
@@ -4,10 +4,11 @@ import path from 'path';
4
4
  import { glob, sync } from 'glob';
5
5
  import { findParentPath } from './utils/findParentPath.js';
6
6
  import { spawn } from 'child_process';
7
- import { l as loadConfig, t as toEnvStr } from './loadConfig-nJiCKeL1.js';
8
- export { r as replaceConfigInString } from './loadConfig-nJiCKeL1.js';
7
+ import { l as loadConfig, t as toEnvStr } from './loadConfig-CZYUe1jE.js';
8
+ export { r as replaceConfigInString } from './loadConfig-CZYUe1jE.js';
9
9
  import { parseFileSync, parseSync as parseSync$1, transformFileSync } from '@swc/core';
10
10
  import fs$1, { writeFileSync, readFileSync, existsSync, rmSync, mkdirSync } from 'fs';
11
+ import { resolve as resolve$2 } from 'import-meta-resolve';
11
12
  import assert from 'assert';
12
13
  import crypto from 'crypto';
13
14
  import lodash from 'lodash';
@@ -19,7 +20,7 @@ import { generate } from '@graphql-codegen/cli';
19
20
  import { GraphCommerceConfigSchema } from './generated/config.js';
20
21
  export { GraphCommerceDebugConfigSchema, GraphCommerceStorefrontConfigSchema } from './generated/config.js';
21
22
  import 'cosmiconfig';
22
- import '@apollo/client/utilities/index.js';
23
+ import '@apollo/client/utilities/internal';
23
24
  import 'chalk';
24
25
 
25
26
  async function fsExists(file) {
@@ -248,7 +249,7 @@ function sig() {
248
249
 
249
250
  const resolveCache = /* @__PURE__ */ new Map();
250
251
  function findPackageJson(id, root) {
251
- let dir = id.startsWith("/") ? id : import.meta.resolve(id);
252
+ let dir = id.startsWith("/") ? id : resolve$2(id, import.meta.url);
252
253
  if (dir.startsWith("file://")) dir = new URL(dir).pathname;
253
254
  let packageJsonLocation = path.join(dir, "package.json");
254
255
  while (!fs$1.existsSync(packageJsonLocation)) {
@@ -1,6 +1,6 @@
1
1
  import { cosmiconfigSync } from 'cosmiconfig';
2
2
  import { GraphCommerceConfigSchema } from './generated/config.js';
3
- import { cloneDeep, mergeDeep } from '@apollo/client/utilities/index.js';
3
+ import { cloneDeep, mergeDeep } from '@apollo/client/utilities/internal';
4
4
  import chalk from 'chalk';
5
5
  import lodash from 'lodash';
6
6
  import { z, ZodEffects, ZodOptional, ZodNullable, ZodDefault, ZodLazy, ZodObject, ZodArray, ZodNumber, ZodString, ZodEnum, ZodBoolean } from 'zod';
package/package.json CHANGED
@@ -2,9 +2,8 @@
2
2
  "name": "@graphcommerce/next-config",
3
3
  "homepage": "https://www.graphcommerce.org/",
4
4
  "repository": "github:graphcommerce-org/graphcommerce",
5
- "version": "10.0.0-canary.68",
5
+ "version": "10.0.0",
6
6
  "type": "module",
7
- "types": "./src/index.ts",
8
7
  "exports": {
9
8
  ".": {
10
9
  "types": "./src/index.ts",
@@ -44,16 +43,16 @@
44
43
  },
45
44
  "dependencies": {
46
45
  "@graphql-codegen/cli": "6.1.0",
47
- "@swc/core": "1.15.3",
48
- "@swc/wasm-web": "^1.15.3",
46
+ "@swc/core": "1.15.7",
47
+ "@swc/wasm-web": "^1.15.7",
49
48
  "@types/js-yaml": "^4.0.9",
50
49
  "@types/lodash": "^4.17.21",
51
50
  "chalk": "^4.1.2",
52
51
  "cosmiconfig": "^8.3.6",
53
52
  "fast-glob": "^3.3.3",
54
- "glob": "^10.4.5",
53
+ "glob": "^10.5.0",
55
54
  "graphql": "^16.12.0",
56
- "inspectpack": "^4.7.1",
55
+ "import-meta-resolve": "^4.1.0",
57
56
  "js-yaml": "^4.1.1",
58
57
  "js-yaml-loader": "^1.2.2",
59
58
  "lodash": "^4.17.21",
@@ -64,7 +63,7 @@
64
63
  },
65
64
  "peerDependencies": {
66
65
  "@apollo/client": "*",
67
- "@graphcommerce/prettier-config-pwa": "^10.0.0-canary.68",
66
+ "@graphcommerce/prettier-config-pwa": "^10.0.0",
68
67
  "@lingui/loader": "*",
69
68
  "@lingui/macro": "*",
70
69
  "@lingui/react": "*",
@@ -1,4 +1,4 @@
1
- import { cloneDeep, mergeDeep } from '@apollo/client/utilities'
1
+ import { cloneDeep, mergeDeep } from '@apollo/client/utilities/internal'
2
2
  import chalk from 'chalk'
3
3
  import lodash from 'lodash'
4
4
  import type { ZodAny, ZodRawShape, ZodTypeAny } from 'zod'
@@ -212,14 +212,6 @@ export type GraphCommerceConfig = {
212
212
  dataLayer?: InputMaybe<DatalayerConfig>
213
213
  /** Debug configuration for GraphCommerce */
214
214
  debug?: InputMaybe<GraphCommerceDebugConfig>
215
- /**
216
- * Enables some demo specific code that is probably not useful for a project:
217
- *
218
- * - Adds the "BY GC" to the product list items.
219
- * - Adds "dominant_color" attribute swatches to the product list items.
220
- * - Creates a big list items in the product list.
221
- */
222
- demoMode?: InputMaybe<Scalars['Boolean']['input']>
223
215
  /**
224
216
  * Enable Guest Checkout Login: During customer login, GraphCommerce queries Magento to determine
225
217
  * whether the customer account already exists or not. If not, the sign-up form is shown instead.
@@ -264,14 +256,6 @@ export type GraphCommerceConfig = {
264
256
  * developing new resolvers this should be set to true.
265
257
  */
266
258
  graphqlMeshEditMode?: InputMaybe<Scalars['Boolean']['input']>
267
- /**
268
- * The Hygraph endpoint.
269
- *
270
- * > Read-only endpoint that allows low latency and high read-throughput content delivery.
271
- *
272
- * Project settings -> API Access -> High Performance Read-only Content API
273
- */
274
- hygraphEndpoint: Scalars['String']['input']
275
259
  /**
276
260
  * Hygraph Management API. **Only used for migrations.**
277
261
  *
@@ -483,11 +467,6 @@ export type GraphCommerceStorefrontConfig = {
483
467
  googleRecaptchaKey?: InputMaybe<Scalars['String']['input']>
484
468
  /** The Google Tagmanager ID to be used per locale. */
485
469
  googleTagmanagerId?: InputMaybe<Scalars['String']['input']>
486
- /**
487
- * Add a gcms-locales header to make sure queries return in a certain language, can be an array to
488
- * define fallbacks.
489
- */
490
- hygraphLocales?: InputMaybe<Array<Scalars['String']['input']>>
491
470
  /** Custom locale used to load the .po files. Must be a valid locale, also used for Intl functions. */
492
471
  linguiLocale?: InputMaybe<Scalars['String']['input']>
493
472
  /**
@@ -623,14 +602,12 @@ export function GraphCommerceConfigSchema(): z.ZodObject<Properties<GraphCommerc
623
602
  customerXMagentoCacheIdDisable: z.boolean().nullish(),
624
603
  dataLayer: z.lazy(() => DatalayerConfigSchema().nullish()),
625
604
  debug: z.lazy(() => GraphCommerceDebugConfigSchema().nullish()),
626
- demoMode: z.boolean().default(true).nullish(),
627
605
  enableGuestCheckoutLogin: z.boolean().nullish(),
628
606
  googleAnalyticsId: z.string().nullish(),
629
607
  googlePlaystore: z.lazy(() => GraphCommerceGooglePlaystoreConfigSchema().nullish()),
630
608
  googleRecaptchaKey: z.string().nullish(),
631
609
  googleTagmanagerId: z.string().nullish(),
632
610
  graphqlMeshEditMode: z.boolean().default(false).nullish(),
633
- hygraphEndpoint: z.string().min(1),
634
611
  hygraphManagementApi: z.string().nullish(),
635
612
  hygraphProjectId: z.string().nullish(),
636
613
  hygraphWriteAccessToken: z.string().nullish(),
@@ -697,7 +674,6 @@ export function GraphCommerceStorefrontConfigSchema(): z.ZodObject<
697
674
  googleAnalyticsId: z.string().nullish(),
698
675
  googleRecaptchaKey: z.string().nullish(),
699
676
  googleTagmanagerId: z.string().nullish(),
700
- hygraphLocales: z.array(z.string().min(1)).nullish(),
701
677
  linguiLocale: z.string().nullish(),
702
678
  locale: z.string().min(1),
703
679
  magentoStoreCode: z.string().min(1),
@@ -1,5 +1,6 @@
1
1
  import fs from 'fs'
2
2
  import path from 'path'
3
+ import { resolve as resolveModule } from 'import-meta-resolve'
3
4
  import type { PackageJson } from 'type-fest'
4
5
  import { PackagesSort } from './PackagesSort'
5
6
  import { sig } from './sig'
@@ -10,7 +11,7 @@ type DependencyStructure = Record<string, { dirName: string; dependencies: strin
10
11
  const resolveCache: Map<string, PackageNames> = new Map<string, PackageNames>()
11
12
 
12
13
  function findPackageJson(id: string, root: string) {
13
- let dir = id.startsWith('/') ? id : import.meta.resolve(id)
14
+ let dir = id.startsWith('/') ? id : resolveModule(id, import.meta.url)
14
15
 
15
16
  if (dir.startsWith('file://')) dir = new URL(dir).pathname
16
17
 
@@ -1,5 +1,3 @@
1
- // import CircularDependencyPlugin from 'circular-dependency-plugin'
2
- // import { DuplicatesPlugin } from 'inspectpack/plugin'
3
1
  import type { NextConfig } from 'next'
4
2
  import type { DomainLocale } from 'next/dist/server/config'
5
3
  import type { Configuration } from 'webpack'