@graphcommerce/next-config 8.1.0-canary.9 → 9.0.0-canary.100

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.
Files changed (45) hide show
  1. package/CHANGELOG.md +261 -67
  2. package/__tests__/config/utils/__snapshots__/mergeEnvIntoConfig.ts.snap +159 -3
  3. package/__tests__/config/utils/configToImportMeta.ts +0 -4
  4. package/__tests__/config/utils/mergeEnvIntoConfig.ts +20 -2
  5. package/__tests__/config/utils/rewriteLegancyEnv.ts +1 -1
  6. package/__tests__/interceptors/findPlugins.ts +366 -240
  7. package/__tests__/interceptors/generateInterceptors.ts +138 -59
  8. package/__tests__/interceptors/parseStructure.ts +132 -2
  9. package/__tests__/utils/resolveDependenciesSync.ts +39 -33
  10. package/dist/config/commands/exportConfig.js +1 -2
  11. package/dist/config/commands/generateConfig.js +1 -2
  12. package/dist/config/demoConfig.js +5 -0
  13. package/dist/config/loadConfig.js +1 -2
  14. package/dist/config/utils/configToImportMeta.js +1 -2
  15. package/dist/config/utils/diff.js +1 -1
  16. package/dist/config/utils/exportConfigToEnv.js +1 -2
  17. package/dist/config/utils/mergeEnvIntoConfig.js +12 -5
  18. package/dist/config/utils/replaceConfigInString.js +1 -2
  19. package/dist/config/utils/rewriteLegacyEnv.js +1 -2
  20. package/dist/generated/config.js +37 -16
  21. package/dist/interceptors/Visitor.js +1 -1
  22. package/dist/interceptors/commands/codegenInterceptors.js +1 -2
  23. package/dist/interceptors/extractExports.js +23 -20
  24. package/dist/interceptors/findOriginalSource.js +19 -4
  25. package/dist/interceptors/findPlugins.js +1 -2
  26. package/dist/interceptors/generateInterceptor.js +11 -12
  27. package/dist/interceptors/generateInterceptors.js +1 -2
  28. package/dist/interceptors/parseStructure.js +20 -7
  29. package/dist/interceptors/swc.js +2 -3
  30. package/dist/interceptors/writeInterceptors.js +8 -9
  31. package/dist/utils/isMonorepo.js +1 -2
  32. package/dist/utils/resolveDependenciesSync.js +3 -4
  33. package/dist/withGraphCommerce.js +22 -15
  34. package/package.json +10 -11
  35. package/src/config/demoConfig.ts +5 -0
  36. package/src/config/utils/mergeEnvIntoConfig.ts +9 -1
  37. package/src/generated/config.ts +109 -22
  38. package/src/interceptors/Visitor.ts +1 -1
  39. package/src/interceptors/extractExports.ts +21 -21
  40. package/src/interceptors/findOriginalSource.ts +17 -2
  41. package/src/interceptors/generateInterceptor.ts +4 -6
  42. package/src/interceptors/parseStructure.ts +25 -5
  43. package/src/interceptors/writeInterceptors.ts +7 -7
  44. package/src/utils/resolveDependenciesSync.ts +1 -1
  45. package/src/withGraphCommerce.ts +21 -13
@@ -32,6 +32,21 @@ function parseAndFindExport(
32
32
  break
33
33
  }
34
34
  }
35
+
36
+ if (node.type === 'ExportNamedDeclaration') {
37
+ for (const specifier of node.specifiers) {
38
+ if (specifier.type === 'ExportSpecifier') {
39
+ if (specifier.exported?.value === findExport) return resolved
40
+ } else if (specifier.type === 'ExportDefaultSpecifier') {
41
+ // todo
42
+ } else if (specifier.type === 'ExportNamespaceSpecifier') {
43
+ // todo
44
+ }
45
+ }
46
+ }
47
+
48
+ // todo: if (node.type === 'ExportDefaultDeclaration') {}
49
+ // todo: if (node.type === 'ExportDefaultExpression') {}
35
50
  }
36
51
 
37
52
  const exports = ast.body
@@ -78,7 +93,7 @@ export function findOriginalSource(
78
93
  if (!resolved?.source)
79
94
  return {
80
95
  resolved: undefined,
81
- error: new Error(`Could not resolve ${plug.targetModule}`),
96
+ error: new Error(`Plugin: Can not find module ${plug.targetModule} for ${plug.sourceModule}`),
82
97
  }
83
98
 
84
99
  // const cacheKey = `${plug.targetModule}#${plug.targetExport}`
@@ -95,7 +110,7 @@ export function findOriginalSource(
95
110
  return {
96
111
  resolved: undefined,
97
112
  error: new Error(
98
- `Can not find ${plug.targetModule}#${plug.sourceExport} for plugin ${plug.sourceModule}`,
113
+ `Plugin target not found ${plug.targetModule}#${plug.sourceExport} for plugin ${plug.sourceModule}#${plug.sourceExport}`,
99
114
  ),
100
115
  }
101
116
  }
@@ -14,7 +14,7 @@ type PluginBaseConfig = {
14
14
  sourceModule: string
15
15
  targetExport: string
16
16
  enabled: boolean
17
- ifConfig?: string | [string, string]
17
+ ifConfig?: string | [string, any]
18
18
  }
19
19
 
20
20
  export function isPluginBaseConfig(plugin: Partial<PluginBaseConfig>): plugin is PluginBaseConfig {
@@ -74,7 +74,7 @@ const sourceSuffix = 'Plugin'
74
74
  const interceptorSuffix = 'Interceptor'
75
75
  const disabledSuffix = 'Disabled'
76
76
  const name = (plugin: PluginConfig) =>
77
- `${plugin.sourceModule
77
+ `${plugin.sourceExport}${plugin.sourceModule
78
78
  .split('/')
79
79
  [plugin.sourceModule.split('/').length - 1].replace(/[^a-zA-Z0-9]/g, '')}`
80
80
 
@@ -180,9 +180,7 @@ export async function generateInterceptor(
180
180
  s.replace(originalSuffix, disabledSuffix),
181
181
  ).visitModule(ast)
182
182
 
183
- carryProps.push(interceptorPropsName(name(p)))
184
-
185
- result = `type ${interceptorPropsName(name(p))} = React.ComponentProps<typeof ${sourceName(name(p))}>`
183
+ carryProps.push(`React.ComponentProps<typeof ${sourceName(name(p))}>`)
186
184
 
187
185
  pluginSee.push(
188
186
  `@see {${sourceName(name(p))}} for replacement of the original source (original source not used)`,
@@ -225,7 +223,7 @@ export async function generateInterceptor(
225
223
  .filter((v) => !!v)
226
224
  .join('\n')
227
225
 
228
- const isComponent = plugins.every((p) => isReplacePluginConfig(p) || isReactPluginConfig(p))
226
+ const isComponent = plugins.every((p) => isReactPluginConfig(p))
229
227
  if (isComponent && plugins.some((p) => isMethodPluginConfig(p))) {
230
228
  throw new Error(`Cannot mix React and Method plugins for ${base} in ${dependency}.`)
231
229
  }
@@ -9,7 +9,7 @@ const pluginConfigParsed = z.object({
9
9
  type: z.enum(['component', 'function', 'replace']),
10
10
  module: z.string(),
11
11
  export: z.string(),
12
- ifConfig: z.union([z.string(), z.tuple([z.string(), z.string()])]).optional(),
12
+ ifConfig: z.union([z.string(), z.tuple([z.string(), z.unknown()])]).optional(),
13
13
  })
14
14
 
15
15
  function nonNullable<T>(value: T): value is NonNullable<T> {
@@ -34,10 +34,11 @@ export function parseStructure(ast: Module, gcConfig: GraphCommerceConfig, sourc
34
34
  } = exports
35
35
 
36
36
  const exportVals = Object.keys(rest)
37
+
37
38
  if (component && !moduleConfig) exportVals.push('Plugin')
38
39
  if (func && !moduleConfig) exportVals.push('plugin')
39
40
 
40
- return exportVals
41
+ const pluginConfigs = exportVals
41
42
  .map((exportVal) => {
42
43
  let config = isObject(moduleConfig) ? moduleConfig : {}
43
44
 
@@ -49,6 +50,7 @@ export function parseStructure(ast: Module, gcConfig: GraphCommerceConfig, sourc
49
50
  config = { ...moduleConfig, export: exportVal }
50
51
  } else {
51
52
  console.error(`Plugin configuration invalid! See ${sourceModule}`)
53
+ return null
52
54
  }
53
55
 
54
56
  const parsed = pluginConfigParsed.safeParse(config)
@@ -60,10 +62,17 @@ export function parseStructure(ast: Module, gcConfig: GraphCommerceConfig, sourc
60
62
  }
61
63
 
62
64
  let enabled = true
65
+
63
66
  if (parsed.data.ifConfig) {
64
- enabled = Array.isArray(parsed.data.ifConfig)
65
- ? get(gcConfig, parsed.data.ifConfig[0]) === parsed.data.ifConfig[1]
66
- : Boolean(get(gcConfig, parsed.data.ifConfig))
67
+ if (Array.isArray(parsed.data.ifConfig)) {
68
+ const isBoolean = typeof parsed.data.ifConfig[1] === 'boolean'
69
+ let confValue = get(gcConfig, parsed.data.ifConfig[0])
70
+ confValue = isBoolean ? Boolean(confValue) : confValue
71
+
72
+ enabled = confValue === parsed.data.ifConfig[1]
73
+ } else {
74
+ enabled = Boolean(get(gcConfig, parsed.data.ifConfig))
75
+ }
67
76
  }
68
77
 
69
78
  const val: PluginConfig = {
@@ -79,4 +88,15 @@ export function parseStructure(ast: Module, gcConfig: GraphCommerceConfig, sourc
79
88
  return val
80
89
  })
81
90
  .filter(nonNullable)
91
+
92
+ const newPluginConfigs = pluginConfigs.reduce<PluginConfig[]>((acc, pluginConfig) => {
93
+ if (
94
+ !acc.find((accPluginConfig) => accPluginConfig.sourceExport === pluginConfig.sourceExport)
95
+ ) {
96
+ acc.push(pluginConfig)
97
+ }
98
+ return acc
99
+ }, [])
100
+
101
+ return newPluginConfigs
82
102
  }
@@ -17,24 +17,24 @@ export async function writeInterceptors(
17
17
  cwd: string = process.cwd(),
18
18
  ) {
19
19
  const dependencies = resolveDependenciesSync(cwd)
20
- const existing: string[] = []
20
+ const existing = new Set<string>()
21
21
  dependencies.forEach((dependency) => {
22
22
  const files = globSync(
23
23
  [`${dependency}/**/*.interceptor.tsx`, `${dependency}/**/*.interceptor.ts`],
24
24
  { cwd },
25
25
  )
26
- existing.push(...files)
26
+ files.forEach((file) => existing.add(file))
27
27
  })
28
28
 
29
29
  const written = Object.entries(interceptors).map(async ([, plugin]) => {
30
30
  const extension = plugin.sourcePath.endsWith('.tsx') ? '.tsx' : '.ts'
31
31
  const relativeFile = `${plugin.fromRoot}.interceptor${extension}`
32
32
 
33
- if (existing.includes(relativeFile)) {
34
- delete existing[existing.indexOf(relativeFile)]
33
+ if (existing.has(relativeFile)) {
34
+ existing.delete(relativeFile)
35
35
  }
36
- if (existing.includes(`./${relativeFile}`)) {
37
- delete existing[existing.indexOf(`./${relativeFile}`)]
36
+ if (existing.has(`./${relativeFile}`)) {
37
+ existing.delete(`./${relativeFile}`)
38
38
  }
39
39
 
40
40
  const fileToWrite = path.join(cwd, relativeFile)
@@ -47,7 +47,7 @@ export async function writeInterceptors(
47
47
  })
48
48
 
49
49
  // Cleanup unused interceptors
50
- const cleaned = existing.map(
50
+ const cleaned = [...existing].map(
51
51
  async (file) => (await checkFileExists(file)) && (await fs.unlink(file)),
52
52
  )
53
53
 
@@ -32,7 +32,7 @@ function resolveRecursivePackageJson(
32
32
  ...Object.keys(packageJson.dependencies ?? []),
33
33
  ...Object.keys(packageJson.devDependencies ?? []),
34
34
  ...additionalDependencies,
35
- // ...Object.keys(packageJson.peerDependencies ?? {}),
35
+ ...Object.keys(packageJson.peerDependencies ?? {}),
36
36
  ].filter((name) => name.includes('graphcommerce')),
37
37
  ),
38
38
  ]
@@ -1,4 +1,4 @@
1
- import CircularDependencyPlugin from 'circular-dependency-plugin'
1
+ // import CircularDependencyPlugin from 'circular-dependency-plugin'
2
2
  import { DuplicatesPlugin } from 'inspectpack/plugin'
3
3
  import type { NextConfig } from 'next'
4
4
  import { DomainLocale } from 'next/dist/server/config'
@@ -112,8 +112,19 @@ export function withGraphCommerce(nextConfig: NextConfig, cwd: string): NextConf
112
112
  },
113
113
  transpilePackages,
114
114
  webpack: (config: Configuration, options) => {
115
- // Allow importing yml/yaml files for graphql-mesh
116
- config.module?.rules?.push({ test: /\.ya?ml$/, use: 'js-yaml-loader' })
115
+ if (!config.module) config.module = { rules: [] }
116
+
117
+ config.module = {
118
+ ...config.module,
119
+ rules: [
120
+ ...(config.module.rules ?? []),
121
+ // Allow importing yml/yaml files for graphql-mesh
122
+ { test: /\.ya?ml$/, use: 'js-yaml-loader' },
123
+ // @lingui .po file support
124
+ { test: /\.po/, use: '@lingui/loader' },
125
+ ],
126
+ exprContextCritical: false,
127
+ }
117
128
 
118
129
  if (!config.plugins) config.plugins = []
119
130
 
@@ -124,13 +135,13 @@ export function withGraphCommerce(nextConfig: NextConfig, cwd: string): NextConf
124
135
  config.plugins.push(new DefinePlugin({ 'globalThis.__DEV__': options.dev }))
125
136
 
126
137
  if (!options.isServer) {
127
- if (graphcommerceConfig.debug?.webpackCircularDependencyPlugin) {
128
- config.plugins.push(
129
- new CircularDependencyPlugin({
130
- exclude: /readable-stream|duplexer2|node_modules\/next/,
131
- }),
132
- )
133
- }
138
+ // if (graphcommerceConfig.debug?.webpackCircularDependencyPlugin) {
139
+ // config.plugins.push(
140
+ // new CircularDependencyPlugin({
141
+ // exclude: /readable-stream|duplexer2|node_modules\/next/,
142
+ // }),
143
+ // )
144
+ // }
134
145
  if (graphcommerceConfig.debug?.webpackDuplicatesPlugin) {
135
146
  config.plugins.push(
136
147
  new DuplicatesPlugin({
@@ -148,9 +159,6 @@ export function withGraphCommerce(nextConfig: NextConfig, cwd: string): NextConf
148
159
  }
149
160
  }
150
161
 
151
- // @lingui .po file support
152
- config.module?.rules?.push({ test: /\.po/, use: '@lingui/loader' })
153
-
154
162
  config.snapshot = {
155
163
  ...(config.snapshot ?? {}),
156
164
  managedPaths: [