@graphcommerce/next-config 9.0.0-canary.99 → 9.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.
Files changed (69) hide show
  1. package/CHANGELOG.md +219 -1151
  2. package/__tests__/commands/copyFiles.ts +512 -0
  3. package/__tests__/config/utils/__snapshots__/mergeEnvIntoConfig.ts.snap +6 -0
  4. package/__tests__/config/utils/mergeEnvIntoConfig.ts +9 -20
  5. package/__tests__/config/utils/rewriteLegancyEnv.ts +32 -36
  6. package/__tests__/interceptors/findPlugins.ts +76 -78
  7. package/__tests__/interceptors/generateInterceptors.ts +78 -135
  8. package/__tests__/interceptors/parseStructure.ts +2 -2
  9. package/__tests__/utils/resolveDependenciesSync.ts +11 -10
  10. package/dist/commands/codegen.js +18 -0
  11. package/dist/commands/copyFiles.js +292 -0
  12. package/dist/commands/copyRoutes.js +20 -0
  13. package/dist/config/commands/exportConfig.js +1 -1
  14. package/dist/config/commands/generateConfig.js +2 -2
  15. package/dist/config/demoConfig.js +2 -2
  16. package/dist/config/utils/mergeEnvIntoConfig.js +18 -20
  17. package/dist/config/utils/rewriteLegacyEnv.js +2 -2
  18. package/dist/generated/config.js +13 -1
  19. package/dist/index.js +3 -1
  20. package/dist/interceptors/InterceptorPlugin.js +4 -3
  21. package/dist/interceptors/Visitor.js +5 -9
  22. package/dist/interceptors/commands/codegenInterceptors.js +2 -2
  23. package/dist/interceptors/extractExports.js +9 -54
  24. package/dist/interceptors/findOriginalSource.js +2 -1
  25. package/dist/interceptors/findPlugins.js +5 -8
  26. package/dist/interceptors/generateInterceptor.js +12 -10
  27. package/dist/interceptors/generateInterceptors.js +3 -2
  28. package/dist/interceptors/parseStructure.js +1 -1
  29. package/dist/interceptors/writeInterceptors.js +2 -2
  30. package/dist/utils/TopologicalSort.js +4 -0
  31. package/dist/utils/isMonorepo.js +40 -6
  32. package/dist/utils/resolveDependenciesSync.js +9 -2
  33. package/dist/utils/sig.js +34 -0
  34. package/dist/withGraphCommerce.js +3 -2
  35. package/package.json +17 -16
  36. package/src/commands/codegen.ts +18 -0
  37. package/src/commands/copyFiles.ts +328 -0
  38. package/src/config/commands/exportConfig.ts +1 -1
  39. package/src/config/commands/generateConfig.ts +3 -3
  40. package/src/config/demoConfig.ts +5 -5
  41. package/src/config/index.ts +1 -1
  42. package/src/config/utils/exportConfigToEnv.ts +1 -1
  43. package/src/config/utils/mergeEnvIntoConfig.ts +22 -25
  44. package/src/config/utils/replaceConfigInString.ts +1 -1
  45. package/src/config/utils/rewriteLegacyEnv.ts +5 -4
  46. package/src/generated/config.ts +36 -0
  47. package/src/index.ts +6 -5
  48. package/src/interceptors/InterceptorPlugin.ts +10 -7
  49. package/src/interceptors/RenameVisitor.ts +1 -1
  50. package/src/interceptors/Visitor.ts +10 -15
  51. package/src/interceptors/commands/codegenInterceptors.ts +2 -2
  52. package/src/interceptors/extractExports.ts +4 -46
  53. package/src/interceptors/findOriginalSource.ts +5 -4
  54. package/src/interceptors/findPlugins.ts +8 -9
  55. package/src/interceptors/generateInterceptor.ts +15 -12
  56. package/src/interceptors/generateInterceptors.ts +7 -13
  57. package/src/interceptors/parseStructure.ts +4 -4
  58. package/src/interceptors/swc.ts +2 -1
  59. package/src/interceptors/writeInterceptors.ts +3 -3
  60. package/src/utils/TopologicalSort.ts +4 -0
  61. package/src/utils/isMonorepo.ts +46 -5
  62. package/src/utils/packageRoots.ts +1 -1
  63. package/src/utils/resolveDependenciesSync.ts +14 -2
  64. package/src/utils/sig.ts +37 -0
  65. package/src/withGraphCommerce.ts +7 -5
  66. package/dist/config/commands/generateIntercetors.js +0 -9
  67. package/dist/interceptors/commands/generateIntercetors.js +0 -9
  68. package/dist/runtimeCachingOptimizations.js +0 -28
  69. package/src/runtimeCachingOptimizations.ts +0 -27
@@ -1,9 +1,11 @@
1
1
  import path from 'path'
2
- import { Compiler } from 'webpack'
3
- import { GraphCommerceConfig } from '../generated/config'
4
- import { ResolveDependency, resolveDependency } from '../utils/resolveDependency'
2
+ import type { Compiler } from 'webpack'
3
+ import type { GraphCommerceConfig } from '../generated/config'
4
+ import type { ResolveDependency } from '../utils/resolveDependency'
5
+ import { resolveDependency } from '../utils/resolveDependency'
5
6
  import { findPlugins } from './findPlugins'
6
- import { generateInterceptors, GenerateInterceptorsReturn } from './generateInterceptors'
7
+ import type { GenerateInterceptorsReturn } from './generateInterceptors'
8
+ import { generateInterceptors } from './generateInterceptors'
7
9
  import { writeInterceptors } from './writeInterceptors'
8
10
 
9
11
  let interceptors: GenerateInterceptorsReturn | undefined
@@ -29,11 +31,11 @@ export class InterceptorPlugin {
29
31
  #generateInterceptors = async () => {
30
32
  if (generating) return {}
31
33
  generating = true
32
- const start = Date.now()
34
+ // const start = Date.now()
33
35
 
34
36
  // console.log('Generating interceptors...')
35
37
 
36
- const [plugins, errors] = findPlugins(this.config)
38
+ const [plugins] = findPlugins(this.config)
37
39
 
38
40
  // console.log(errors)
39
41
 
@@ -66,6 +68,7 @@ export class InterceptorPlugin {
66
68
  return generatedInterceptors
67
69
  }
68
70
 
71
+ /** @public */
69
72
  apply(compiler: Compiler): void {
70
73
  const logger = compiler.getInfrastructureLogger('InterceptorPlugin')
71
74
 
@@ -86,7 +89,7 @@ export class InterceptorPlugin {
86
89
 
87
90
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
88
91
  this.#generateInterceptors().then((i) => {
89
- Object.entries(i).forEach(([key, { sourcePath }]) => {
92
+ Object.entries(i).forEach(([, { sourcePath }]) => {
90
93
  const absoluteFilePath = path.join(process.cwd(), sourcePath)
91
94
  compilation.fileDependencies.add(absoluteFilePath)
92
95
  })
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable max-classes-per-file */
2
- import { Identifier } from '@swc/core'
2
+ import type { Identifier } from '@swc/core'
3
3
  import { Visitor } from './Visitor'
4
4
 
5
5
  export class RenameVisitor extends Visitor {
@@ -1,17 +1,10 @@
1
1
  /**
2
2
  * This is an implementation of
3
- * https://github.com/swc-project/swc/blob/main/node-swc/src/Visitor.ts
3
+ * https://github.com/swc-project/swc/blob/main/packages/core/src/Visitor.ts
4
4
  *
5
5
  * The JS API is deprecated, but there doesn't seem to be a valid alternative at this point.
6
6
  */
7
-
8
- /* eslint-disable @typescript-eslint/no-unused-vars */
9
- /* eslint-disable @typescript-eslint/no-explicit-any */
10
- /* eslint-disable no-param-reassign */
11
- /* eslint-disable class-methods-use-this */
12
- /* eslint-disable consistent-return */
13
- // eslint-disable-next-line import/no-extraneous-dependencies
14
- import {
7
+ import type {
15
8
  Accessibility,
16
9
  Argument,
17
10
  ArrayExpression,
@@ -54,9 +47,9 @@ import {
54
47
  ExportNamedDeclaration,
55
48
  ExportNamespaceSpecifier,
56
49
  ExportSpecifier,
57
- ExprOrSpread,
58
50
  Expression,
59
51
  ExpressionStatement,
52
+ ExprOrSpread,
60
53
  Fn,
61
54
  ForInStatement,
62
55
  ForOfStatement,
@@ -71,10 +64,10 @@ import {
71
64
  ImportDefaultSpecifier,
72
65
  ImportNamespaceSpecifier,
73
66
  ImportSpecifier,
74
- JSXAttrValue,
75
67
  JSXAttribute,
76
68
  JSXAttributeName,
77
69
  JSXAttributeOrSpread,
70
+ JSXAttrValue,
78
71
  JSXClosingElement,
79
72
  JSXClosingFragment,
80
73
  JSXElement,
@@ -188,8 +181,13 @@ import {
188
181
  YieldExpression,
189
182
  } from '@swc/types'
190
183
 
184
+ /* eslint-disable no-param-reassign */
185
+ /* eslint-disable class-methods-use-this */
186
+ /* eslint-disable consistent-return */
187
+
191
188
  /**
192
189
  * @deprecated JavaScript API is deprecated. Please use Wasm plugin instead.
190
+ * @public
193
191
  */
194
192
  export class Visitor {
195
193
  visitProgram(n: Program): Program {
@@ -782,7 +780,6 @@ export class Visitor {
782
780
  }
783
781
 
784
782
  visitTsPropertySignature(n: TsPropertySignature): TsPropertySignature {
785
- n.params = this.visitTsFnParameters(n.params)
786
783
  n.typeAnnotation = this.visitTsTypeAnnotation(n.typeAnnotation)
787
784
  return n
788
785
  }
@@ -873,7 +870,7 @@ export class Visitor {
873
870
  }
874
871
 
875
872
  visitTsFnParameters(params: TsFnParameter[]): TsFnParameter[] {
876
- return params?.map(this.visitTsFnParameter.bind(this))
873
+ return params.map(this.visitTsFnParameter.bind(this))
877
874
  }
878
875
 
879
876
  visitTsFnParameter(n: TsFnParameter): TsFnParameter {
@@ -1843,5 +1840,3 @@ export class Visitor {
1843
1840
  return n
1844
1841
  }
1845
1842
  }
1846
-
1847
- export default Visitor
@@ -1,9 +1,9 @@
1
+ import dotenv from 'dotenv'
1
2
  import { loadConfig } from '../../config/loadConfig'
2
3
  import { resolveDependency } from '../../utils/resolveDependency'
3
4
  import { findPlugins } from '../findPlugins'
4
5
  import { generateInterceptors } from '../generateInterceptors'
5
6
  import { writeInterceptors } from '../writeInterceptors'
6
- import dotenv from 'dotenv'
7
7
 
8
8
  dotenv.config()
9
9
 
@@ -11,7 +11,7 @@ dotenv.config()
11
11
  export async function codegenInterceptors() {
12
12
  const conf = loadConfig(process.cwd())
13
13
 
14
- const [plugins, errors] = findPlugins(conf)
14
+ const [plugins] = findPlugins(conf)
15
15
 
16
16
  const generatedInterceptors = await generateInterceptors(
17
17
  plugins,
@@ -1,4 +1,7 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+
1
3
  /* eslint-disable no-continue */
4
+
2
5
  /* eslint-disable max-classes-per-file */
3
6
  import type {
4
7
  ArrayExpression,
@@ -15,8 +18,6 @@ import type {
15
18
  TemplateLiteral,
16
19
  } from '@swc/core'
17
20
 
18
- export class NoSuchDeclarationError extends Error {}
19
-
20
21
  function isIdentifier(node: Node): node is Identifier {
21
22
  return node.type === 'Identifier'
22
23
  }
@@ -57,35 +58,7 @@ function isTemplateLiteral(node: Node): node is TemplateLiteral {
57
58
  return node.type === 'TemplateLiteral'
58
59
  }
59
60
 
60
- export class UnsupportedValueError extends Error {
61
- /** @example `config.runtime[0].value` */
62
- path?: string
63
-
64
- constructor(message: string, paths?: string[]) {
65
- super(message)
66
-
67
- // Generating "path" that looks like "config.runtime[0].value"
68
- let codePath: string | undefined
69
- if (Array.isArray(paths)) {
70
- codePath = ''
71
- for (const path of paths) {
72
- if (path[0] === '[') {
73
- // "array" + "[0]"
74
- codePath += path
75
- } else if (codePath === '') {
76
- codePath = path
77
- } else {
78
- // "object" + ".key"
79
- codePath += `.${path}`
80
- }
81
- }
82
- }
83
-
84
- this.path = codePath
85
- }
86
- }
87
-
88
- export const RUNTIME_VALUE = Symbol('RUNTIME_VALUE')
61
+ const RUNTIME_VALUE = Symbol('RUNTIME_VALUE')
89
62
 
90
63
  function extractValue(node: Node, path?: string[], optional: boolean = false): any {
91
64
  if (isNullLiteral(node)) {
@@ -113,7 +86,6 @@ function extractValue(node: Node, path?: string[], optional: boolean = false): a
113
86
  return undefined
114
87
  default:
115
88
  return RUNTIME_VALUE
116
- // throw new UnsupportedValueError(`Unknown identifier "${node.value}"`, path)
117
89
  }
118
90
  } else if (isArrayExpression(node)) {
119
91
  // e.g. [1, 2, 3]
@@ -124,10 +96,6 @@ function extractValue(node: Node, path?: string[], optional: boolean = false): a
124
96
  if (elem.spread) {
125
97
  // e.g. [ ...a ]
126
98
  return RUNTIME_VALUE
127
- // throw new UnsupportedValueError(
128
- // 'Unsupported spread operator in the Array Expression',
129
- // path,
130
- // )
131
99
  }
132
100
 
133
101
  arr.push(extractValue(elem.expression, path && [...path, `[${i}]`], optional))
@@ -145,10 +113,6 @@ function extractValue(node: Node, path?: string[], optional: boolean = false): a
145
113
  if (!isKeyValueProperty(prop)) {
146
114
  // e.g. { ...a }
147
115
  return RUNTIME_VALUE
148
- // throw new UnsupportedValueError(
149
- // 'Unsupported spread operator in the Object Expression',
150
- // path,
151
- // )
152
116
  }
153
117
 
154
118
  let key
@@ -160,10 +124,6 @@ function extractValue(node: Node, path?: string[], optional: boolean = false): a
160
124
  key = prop.key.value
161
125
  } else {
162
126
  return RUNTIME_VALUE
163
- // throw new UnsupportedValueError(
164
- // `Unsupported key type "${prop.key.type}" in the Object Expression`,
165
- // path,
166
- // )
167
127
  }
168
128
 
169
129
  obj[key] = extractValue(prop.value, path && [...path, key])
@@ -175,7 +135,6 @@ function extractValue(node: Node, path?: string[], optional: boolean = false): a
175
135
  if (node.expressions.length !== 0) {
176
136
  // TODO: should we add support for `${'e'}d${'g'}'e'`?
177
137
  return RUNTIME_VALUE
178
- // throw new UnsupportedValueError('Unsupported template literal with expressions', path)
179
138
  }
180
139
 
181
140
  // When TemplateLiteral has 0 expressions, the length of quasis is always 1.
@@ -192,7 +151,6 @@ function extractValue(node: Node, path?: string[], optional: boolean = false): a
192
151
  return cooked ?? raw
193
152
  } else {
194
153
  return RUNTIME_VALUE
195
- // throw new UnsupportedValueError(`Unsupported node type "${node.type}"`, path)
196
154
  }
197
155
  }
198
156
 
@@ -1,8 +1,8 @@
1
+ import type { ExportAllDeclaration } from '@swc/core'
1
2
  import path from 'path'
2
- import { ResolveDependency, ResolveDependencyReturn } from '../utils/resolveDependency'
3
- import { PluginConfig } from './generateInterceptor'
3
+ import type { ResolveDependency, ResolveDependencyReturn } from '../utils/resolveDependency'
4
+ import type { PluginConfig } from './generateInterceptor'
4
5
  import { parseSync } from './swc'
5
- import { ExportAllDeclaration } from '@swc/core'
6
6
 
7
7
  function parseAndFindExport(
8
8
  resolved: ResolveDependencyReturn,
@@ -25,6 +25,7 @@ function parseAndFindExport(
25
25
  if (declaration.id.type === 'Identifier') {
26
26
  if (declaration.id.value === findExport) return resolved
27
27
  } else {
28
+ // eslint-disable-next-line no-console
28
29
  console.log(declaration)
29
30
  }
30
31
  }
@@ -81,7 +82,7 @@ function parseAndFindExport(
81
82
  return undefined
82
83
  }
83
84
 
84
- const cachedResults = new Map<string, ResolveDependencyReturn>()
85
+ // const cachedResults = new Map<string, ResolveDependencyReturn>()
85
86
 
86
87
  export function findOriginalSource(
87
88
  plug: PluginConfig,
@@ -1,15 +1,16 @@
1
- // eslint-disable-next-line import/no-extraneous-dependencies
2
1
  import { parseFileSync } from '@swc/core'
3
- import chalk from 'chalk'
4
- // eslint-disable-next-line import/no-extraneous-dependencies
5
2
  import { sync as globSync } from 'glob'
6
- import { GraphCommerceConfig } from '../generated/config'
3
+ import type { GraphCommerceConfig } from '../generated/config'
7
4
  import { resolveDependenciesSync } from '../utils/resolveDependenciesSync'
8
- import { PluginConfig } from './generateInterceptor'
5
+ import type { PluginConfig } from './generateInterceptor'
9
6
  import { parseStructure } from './parseStructure'
10
7
 
11
8
  const pluginLogs: Record<string, string> = {}
12
9
 
10
+ // ANSI escape codes for console colors
11
+ const GREEN = '\x1b[32m'
12
+ const RESET = '\x1b[0m'
13
+
13
14
  export function findPlugins(config: GraphCommerceConfig, cwd: string = process.cwd()) {
14
15
  const dependencies = resolveDependenciesSync(cwd)
15
16
 
@@ -40,9 +41,7 @@ export function findPlugins(config: GraphCommerceConfig, cwd: string = process.c
40
41
  if (process.env.NODE_ENV === 'development' && debug) {
41
42
  const byExported = plugins.reduce(
42
43
  (acc, plugin) => {
43
- const key = `🔌 ${chalk.greenBright(
44
- `Plugins loaded for ${plugin.targetModule}#${plugin.targetExport}`,
45
- )}`
44
+ const key = `🔌 ${GREEN}Plugins loaded for ${plugin.targetModule}#${plugin.targetExport}${RESET}`
46
45
  if (!acc[key]) acc[key] = []
47
46
  acc[key].push(plugin)
48
47
  return acc
@@ -65,7 +64,7 @@ export function findPlugins(config: GraphCommerceConfig, cwd: string = process.c
65
64
  : `${c.ifConfig}`
66
65
  : ''
67
66
 
68
- return `${c.enabled ? `🟢` : `⚪️`} ${c.sourceModule} ${ifConfigStr}`
67
+ return `${c.enabled ? '🟢' : '⚪️'} ${c.sourceModule} ${ifConfigStr}`
69
68
  })
70
69
  .join('\n')
71
70
 
@@ -2,8 +2,8 @@
2
2
  import prettierConf from '@graphcommerce/prettier-config-pwa'
3
3
  // eslint-disable-next-line import/no-extraneous-dependencies
4
4
  import prettier from 'prettier'
5
- import { GraphCommerceDebugConfig } from '../generated/config'
6
- import { ResolveDependencyReturn } from '../utils/resolveDependency'
5
+ import type { GraphCommerceDebugConfig } from '../generated/config'
6
+ import type { ResolveDependencyReturn } from '../utils/resolveDependency'
7
7
  import { RenameVisitor } from './RenameVisitor'
8
8
  import { parseSync, printSync } from './swc'
9
9
 
@@ -14,9 +14,11 @@ type PluginBaseConfig = {
14
14
  sourceModule: string
15
15
  targetExport: string
16
16
  enabled: boolean
17
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
17
18
  ifConfig?: string | [string, any]
18
19
  }
19
20
 
21
+ /** @public */
20
22
  export function isPluginBaseConfig(plugin: Partial<PluginBaseConfig>): plugin is PluginBaseConfig {
21
23
  return (
22
24
  typeof plugin.type === 'string' &&
@@ -30,6 +32,7 @@ type ReactPluginConfig = PluginBaseConfig & { type: 'component' }
30
32
  type MethodPluginConfig = PluginBaseConfig & { type: 'function' }
31
33
  type ReplacePluginConfig = PluginBaseConfig & { type: 'replace' }
32
34
 
35
+ /** @public */
33
36
  export function isReactPluginConfig(
34
37
  plugin: Partial<PluginBaseConfig>,
35
38
  ): plugin is ReactPluginConfig {
@@ -37,6 +40,7 @@ export function isReactPluginConfig(
37
40
  return plugin.type === 'component'
38
41
  }
39
42
 
43
+ /** @public */
40
44
  export function isMethodPluginConfig(
41
45
  plugin: Partial<PluginBaseConfig>,
42
46
  ): plugin is MethodPluginConfig {
@@ -44,6 +48,7 @@ export function isMethodPluginConfig(
44
48
  return plugin.type === 'function'
45
49
  }
46
50
 
51
+ /** @public */
47
52
  export function isReplacePluginConfig(
48
53
  plugin: Partial<PluginBaseConfig>,
49
54
  ): plugin is ReactPluginConfig {
@@ -66,11 +71,10 @@ export type Interceptor = ResolveDependencyReturn & {
66
71
 
67
72
  export type MaterializedPlugin = Interceptor & { template: string }
68
73
 
69
- export const SOURCE_START = '/** Original source starts here (do not modify!): **/'
70
- export const SOURCE_END = '/** Original source ends here (do not modify!) **/'
74
+ export const SOURCE_START = '/** SOURCE_START */'
75
+ export const SOURCE_END = '/** SOURCE_END */'
71
76
 
72
77
  const originalSuffix = 'Original'
73
- const sourceSuffix = 'Plugin'
74
78
  const interceptorSuffix = 'Interceptor'
75
79
  const disabledSuffix = 'Disabled'
76
80
  const name = (plugin: PluginConfig) =>
@@ -103,9 +107,7 @@ const generateIdentifyer = (s: string) =>
103
107
  }, 0),
104
108
  ).toString()
105
109
 
106
- /**
107
- * The is on the first line, with the format: \/* hash:${identifer} *\/
108
- */
110
+ /** The is on the first line, with the format: /* hash:${identifer} */
109
111
  function extractIdentifier(source: string | undefined) {
110
112
  if (!source) return null
111
113
  const match = source.match(/\/\* hash:(\d+) \*\//)
@@ -193,7 +195,7 @@ export async function generateInterceptor(
193
195
  result = `
194
196
  type ${interceptorPropsName(name(p))} = ${carryProps.join(' & ')} & OmitPrev<React.ComponentProps<typeof ${sourceName(name(p))}>, 'Prev'>
195
197
 
196
- const ${interceptorName(name(p))} = (props: ${interceptorPropsName(name(p))}) => ${withBraces ? `{` : '('}
198
+ const ${interceptorName(name(p))} = (props: ${interceptorPropsName(name(p))}) => ${withBraces ? '{' : '('}
197
199
  ${config.pluginStatus ? `logOnce(\`🔌 Rendering ${base} with plugin(s): ${wrapChain} wrapping <${base}/>\`)` : ''}
198
200
 
199
201
  ${
@@ -202,8 +204,8 @@ export async function generateInterceptor(
202
204
  logOnce('${fileName(p)} does not spread props to prev: <Prev {...props}/>. This will cause issues if multiple plugins are applied to this component.')`
203
205
  : ''
204
206
  }
205
- ${withBraces ? `return` : ''} <${sourceName(name(p))} {...props} Prev={${carry}} />
206
- ${withBraces ? `}` : ')'}`
207
+ ${withBraces ? 'return' : ''} <${sourceName(name(p))} {...props} Prev={${carry}} />
208
+ ${withBraces ? '}' : ')'}`
207
209
 
208
210
  carryProps = [interceptorPropsName(name(p))]
209
211
  pluginSee.push(`@see {${sourceName(name(p))}} for source of applied plugin`)
@@ -270,7 +272,7 @@ export async function generateInterceptor(
270
272
  /* This file is automatically generated for ${dependency} */
271
273
  ${
272
274
  Object.values(targetExports).some((t) => t.some((p) => p.type === 'component'))
273
- ? `import type { DistributedOmit as OmitPrev } from 'type-fest'`
275
+ ? "import type { DistributedOmit as OmitPrev } from 'type-fest'"
274
276
  : ''
275
277
  }
276
278
 
@@ -287,6 +289,7 @@ export async function generateInterceptor(
287
289
  try {
288
290
  templateFormatted = await prettier.format(template, { ...prettierConf, parser: 'typescript' })
289
291
  } catch (e) {
292
+ // eslint-disable-next-line no-console
290
293
  console.log('Error formatting interceptor: ', e, 'using raw template.')
291
294
  templateFormatted = template
292
295
  }
@@ -1,17 +1,11 @@
1
- import path from 'node:path'
2
- import fs from 'node:fs/promises'
3
1
  // eslint-disable-next-line import/no-extraneous-dependencies
4
- import { GraphCommerceDebugConfig } from '../generated/config'
5
- import { ResolveDependency } from '../utils/resolveDependency'
2
+ import fs from 'node:fs/promises'
3
+ import path from 'node:path'
4
+ import type { GraphCommerceDebugConfig } from '../generated/config'
5
+ import type { ResolveDependency } from '../utils/resolveDependency'
6
6
  import { findOriginalSource } from './findOriginalSource'
7
- import {
8
- Interceptor,
9
- MaterializedPlugin,
10
- PluginConfig,
11
- generateInterceptor,
12
- isPluginConfig,
13
- moveRelativeDown,
14
- } from './generateInterceptor'
7
+ import type { Interceptor, MaterializedPlugin, PluginConfig } from './generateInterceptor'
8
+ import { generateInterceptor, isPluginConfig, moveRelativeDown } from './generateInterceptor'
15
9
 
16
10
  export type GenerateInterceptorsReturn = Record<string, MaterializedPlugin>
17
11
 
@@ -30,7 +24,7 @@ export async function generateInterceptors(
30
24
  const { error, resolved } = findOriginalSource(plug, result, resolve)
31
25
 
32
26
  if (error) {
33
- console.log(error.message)
27
+ console.error(error.message)
34
28
  return acc
35
29
  }
36
30
 
@@ -1,9 +1,9 @@
1
- import { Module } from '@swc/core'
1
+ import type { Module } from '@swc/core'
2
2
  import get from 'lodash/get'
3
3
  import { z } from 'zod'
4
- import { GraphCommerceConfig } from '../generated/config'
4
+ import type { GraphCommerceConfig } from '../generated/config'
5
5
  import { extractExports } from './extractExports'
6
- import { PluginConfig } from './generateInterceptor'
6
+ import type { PluginConfig } from './generateInterceptor'
7
7
 
8
8
  const pluginConfigParsed = z.object({
9
9
  type: z.enum(['component', 'function', 'replace']),
@@ -20,7 +20,7 @@ const isObject = (input: unknown): input is Record<string, unknown> =>
20
20
 
21
21
  export function parseStructure(ast: Module, gcConfig: GraphCommerceConfig, sourceModule: string) {
22
22
  const [exports, errors] = extractExports(ast)
23
- if (errors.length) console.error(`Plugin error for`, errors.join('\n'))
23
+ if (errors.length) console.error('Plugin error for', errors.join('\n'))
24
24
 
25
25
  const {
26
26
  config: moduleConfig,
@@ -1,4 +1,5 @@
1
- import { Output, Program, parseSync as parseSyncCore, printSync as printSyncCode } from '@swc/core'
1
+ import type { Output, Program } from '@swc/core'
2
+ import { parseSync as parseSyncCore, printSync as printSyncCode } from '@swc/core'
2
3
 
3
4
  export function parseSync(src: string) {
4
5
  return parseSyncCore(src, {
@@ -1,9 +1,9 @@
1
- import fs from 'node:fs/promises'
2
- import path from 'path'
3
1
  // eslint-disable-next-line import/no-extraneous-dependencies
4
2
  import { sync as globSync } from 'glob'
3
+ import fs from 'node:fs/promises'
4
+ import path from 'path'
5
5
  import { resolveDependenciesSync } from '../utils/resolveDependenciesSync'
6
- import { GenerateInterceptorsReturn } from './generateInterceptors'
6
+ import type { GenerateInterceptorsReturn } from './generateInterceptors'
7
7
 
8
8
  function checkFileExists(file: string) {
9
9
  return fs
@@ -23,14 +23,17 @@ export class TopologicalSort<KeyType, ValueType> {
23
23
  this.addMultipleInternalNodes(nodes)
24
24
  }
25
25
 
26
+ /** @public */
26
27
  addNode(key: KeyType, node: ValueType) {
27
28
  return this.addInternalNode(key, node)
28
29
  }
29
30
 
31
+ /** @public */
30
32
  addNodes(nodes: Map<KeyType, ValueType>) {
31
33
  this.addMultipleInternalNodes(nodes)
32
34
  }
33
35
 
36
+ /** @public */
34
37
  addEdge(fromKey: KeyType, toKey: KeyType) {
35
38
  assert(this.#nodes.has(fromKey), `Source package with ${fromKey} key should exist`)
36
39
  assert(this.#nodes.has(toKey), `Target package with ${toKey} key should exist`)
@@ -58,6 +61,7 @@ export class TopologicalSort<KeyType, ValueType> {
58
61
  sourceNode!.children.set(toKey, targetNode!)
59
62
  }
60
63
 
64
+ /** @public */
61
65
  sort(): Map<KeyType, INodeWithChildren<KeyType, ValueType>> {
62
66
  this.#visitedNodes = new Set()
63
67
  this.#sortedKeysStack = []
@@ -1,8 +1,49 @@
1
+ import fs from 'node:fs'
1
2
  import path from 'node:path'
2
3
 
3
- export function isMonorepo() {
4
- const root = process.cwd()
5
- const meshDir = path.dirname(require.resolve('@graphcommerce/graphql-mesh'))
6
- const relativePath = path.join(path.relative(meshDir, root), '/')
7
- return relativePath.startsWith(`..${path.sep}..${path.sep}examples`)
4
+ const debug = process.env.DEBUG === '1'
5
+ // eslint-disable-next-line no-console
6
+ const log = (message: string) => debug && console.log(`isMonorepo: ${message}`)
7
+
8
+ function findPackageJson(directory: string): { name: string } | null {
9
+ try {
10
+ const packageJsonPath = path.join(directory, 'package.json')
11
+ const content = fs.readFileSync(packageJsonPath, 'utf8')
12
+ return JSON.parse(content)
13
+ } catch {
14
+ return null
15
+ }
16
+ }
17
+
18
+ /**
19
+ * Finds the path of the parent @graphcommerce package if it exists Returns null if no parent
20
+ * package is found
21
+ */
22
+ export function findParentPath(directory: string): string | null {
23
+ let currentDir = directory
24
+ log(`Starting directory: ${currentDir}`)
25
+
26
+ // Start from the parent directory
27
+ currentDir = path.dirname(currentDir)
28
+ log(`Looking for parent packages starting from: ${currentDir}`)
29
+
30
+ // Keep going up until we find a root package or hit the filesystem root
31
+ while (currentDir !== path.parse(currentDir).root) {
32
+ const packageJson = findPackageJson(currentDir)
33
+
34
+ if (packageJson) {
35
+ log(`Found package.json in: ${currentDir}`)
36
+ log(`Package name: ${packageJson.name}`)
37
+
38
+ if (packageJson.name.startsWith('@graphcommerce/')) {
39
+ log(`Found parent @graphcommerce package at: ${currentDir}`)
40
+ return currentDir
41
+ }
42
+ }
43
+
44
+ currentDir = path.dirname(currentDir)
45
+ }
46
+
47
+ log('No parent @graphcommerce package found')
48
+ return null
8
49
  }
@@ -30,6 +30,6 @@ export const packageRoots = (packagePaths: string[]): string[] => {
30
30
 
31
31
  // Filter out the sub-paths which are part of another longer sub-path
32
32
  return roots.filter(
33
- (root, index, self) => self.findIndex((r) => r !== root && r.startsWith(`${root }/`)) === -1,
33
+ (root, index, self) => self.findIndex((r) => r !== root && r.startsWith(`${root}/`)) === -1,
34
34
  )
35
35
  }
@@ -2,6 +2,7 @@ import fs from 'node:fs'
2
2
  import path from 'node:path'
3
3
  import type { PackageJson } from 'type-fest'
4
4
  import { PackagesSort } from './PackagesSort'
5
+ import { g, sig } from './sig'
5
6
 
6
7
  type PackageNames = Map<string, string>
7
8
  type DependencyStructure = Record<string, { dirName: string; dependencies: string[] }>
@@ -18,13 +19,19 @@ function resolveRecursivePackageJson(
18
19
  const fileName = require.resolve(path.join(dependencyPath, 'package.json'))
19
20
  const packageJsonFile = fs.readFileSync(fileName, 'utf-8').toString()
20
21
  const packageJson = JSON.parse(packageJsonFile) as PackageJson
22
+ const e = [atob('QGdyYXBoY29tbWVyY2UvYWRvYmUtY29tbWVyY2U=')].filter((n) =>
23
+ !globalThis.gcl ? true : !globalThis.gcl.includes(n),
24
+ )
21
25
 
22
26
  if (!packageJson.name) throw Error(`Package ${packageJsonFile} does not have a name field`)
23
27
 
24
28
  // Previously processed
25
29
  if (dependencyStructure[packageJson.name]) return dependencyStructure
26
30
 
27
- if (!isRoot && !packageJson.name.includes('graphcommerce')) return dependencyStructure
31
+ // To have additional namespaces be considered as a graphcommerce package, set PRIVATE_PACKAGE_NAMESPACES
32
+ const namespaces = process.env.PRIVATE_PACKAGE_NAMESPACES?.split(',') ?? ['graphcommerce']
33
+ if (!isRoot && !namespaces.some((namespace) => packageJson.name?.includes(namespace)))
34
+ return dependencyStructure
28
35
 
29
36
  const dependencies = [
30
37
  ...new Set(
@@ -33,7 +40,11 @@ function resolveRecursivePackageJson(
33
40
  ...Object.keys(packageJson.devDependencies ?? []),
34
41
  ...additionalDependencies,
35
42
  ...Object.keys(packageJson.peerDependencies ?? {}),
36
- ].filter((name) => name.includes('graphcommerce')),
43
+ ].filter((name) =>
44
+ name.includes('graphcommerce')
45
+ ? !(e.length >= 0 && e.some((v) => name.startsWith(v)))
46
+ : false,
47
+ ),
37
48
  ),
38
49
  ]
39
50
 
@@ -79,6 +90,7 @@ export function sortDependencies(dependencyStructure: DependencyStructure): Pack
79
90
  export function resolveDependenciesSync(root = process.cwd()) {
80
91
  const cached = resolveCache.get(root)
81
92
  if (cached) return cached
93
+ sig()
82
94
 
83
95
  const dependencyStructure = resolveRecursivePackageJson(
84
96
  root,