@graphcommerce/next-config 9.0.0-canary.98 → 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.
- package/CHANGELOG.md +219 -1149
- package/__tests__/commands/copyFiles.ts +512 -0
- package/__tests__/config/utils/__snapshots__/mergeEnvIntoConfig.ts.snap +6 -0
- package/__tests__/config/utils/mergeEnvIntoConfig.ts +9 -20
- package/__tests__/config/utils/rewriteLegancyEnv.ts +32 -36
- package/__tests__/interceptors/findPlugins.ts +80 -74
- package/__tests__/interceptors/generateInterceptors.ts +78 -135
- package/__tests__/interceptors/parseStructure.ts +2 -2
- package/__tests__/utils/resolveDependenciesSync.ts +11 -10
- package/dist/commands/codegen.js +18 -0
- package/dist/commands/copyFiles.js +292 -0
- package/dist/commands/copyRoutes.js +20 -0
- package/dist/config/commands/exportConfig.js +1 -1
- package/dist/config/commands/generateConfig.js +2 -2
- package/dist/config/demoConfig.js +2 -2
- package/dist/config/utils/mergeEnvIntoConfig.js +18 -20
- package/dist/config/utils/rewriteLegacyEnv.js +2 -2
- package/dist/generated/config.js +13 -1
- package/dist/index.js +3 -1
- package/dist/interceptors/InterceptorPlugin.js +4 -3
- package/dist/interceptors/Visitor.js +5 -9
- package/dist/interceptors/commands/codegenInterceptors.js +2 -2
- package/dist/interceptors/extractExports.js +9 -54
- package/dist/interceptors/findOriginalSource.js +2 -1
- package/dist/interceptors/findPlugins.js +5 -8
- package/dist/interceptors/generateInterceptor.js +12 -10
- package/dist/interceptors/generateInterceptors.js +3 -2
- package/dist/interceptors/parseStructure.js +1 -1
- package/dist/interceptors/writeInterceptors.js +2 -2
- package/dist/utils/TopologicalSort.js +4 -0
- package/dist/utils/isMonorepo.js +40 -6
- package/dist/utils/resolveDependenciesSync.js +9 -2
- package/dist/utils/sig.js +34 -0
- package/dist/withGraphCommerce.js +3 -2
- package/package.json +17 -16
- package/src/commands/codegen.ts +18 -0
- package/src/commands/copyFiles.ts +328 -0
- package/src/config/commands/exportConfig.ts +1 -1
- package/src/config/commands/generateConfig.ts +3 -3
- package/src/config/demoConfig.ts +5 -5
- package/src/config/index.ts +1 -1
- package/src/config/utils/exportConfigToEnv.ts +1 -1
- package/src/config/utils/mergeEnvIntoConfig.ts +22 -25
- package/src/config/utils/replaceConfigInString.ts +1 -1
- package/src/config/utils/rewriteLegacyEnv.ts +5 -4
- package/src/generated/config.ts +36 -0
- package/src/index.ts +6 -5
- package/src/interceptors/InterceptorPlugin.ts +10 -7
- package/src/interceptors/RenameVisitor.ts +1 -1
- package/src/interceptors/Visitor.ts +10 -15
- package/src/interceptors/commands/codegenInterceptors.ts +2 -2
- package/src/interceptors/extractExports.ts +4 -46
- package/src/interceptors/findOriginalSource.ts +5 -4
- package/src/interceptors/findPlugins.ts +8 -9
- package/src/interceptors/generateInterceptor.ts +15 -12
- package/src/interceptors/generateInterceptors.ts +7 -13
- package/src/interceptors/parseStructure.ts +4 -4
- package/src/interceptors/swc.ts +2 -1
- package/src/interceptors/writeInterceptors.ts +3 -3
- package/src/utils/TopologicalSort.ts +4 -0
- package/src/utils/isMonorepo.ts +46 -5
- package/src/utils/packageRoots.ts +1 -1
- package/src/utils/resolveDependenciesSync.ts +14 -2
- package/src/utils/sig.ts +37 -0
- package/src/withGraphCommerce.ts +7 -5
- package/dist/config/commands/generateIntercetors.js +0 -9
- package/dist/interceptors/commands/generateIntercetors.js +0 -9
- package/dist/runtimeCachingOptimizations.js +0 -28
- 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
|
|
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 {
|
|
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
|
|
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(([
|
|
92
|
+
Object.entries(i).forEach(([, { sourcePath }]) => {
|
|
90
93
|
const absoluteFilePath = path.join(process.cwd(), sourcePath)
|
|
91
94
|
compilation.fileDependencies.add(absoluteFilePath)
|
|
92
95
|
})
|
|
@@ -1,17 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* This is an implementation of
|
|
3
|
-
* https://github.com/swc-project/swc/blob/main/
|
|
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
|
|
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
|
|
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
|
-
|
|
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 = `🔌 ${
|
|
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 ?
|
|
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 = '/**
|
|
70
|
-
export const SOURCE_END = '/**
|
|
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 ?
|
|
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
|
-
?
|
|
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
|
|
5
|
-
import
|
|
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
|
-
|
|
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.
|
|
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(
|
|
23
|
+
if (errors.length) console.error('Plugin error for', errors.join('\n'))
|
|
24
24
|
|
|
25
25
|
const {
|
|
26
26
|
config: moduleConfig,
|
package/src/interceptors/swc.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Output, Program
|
|
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 = []
|
package/src/utils/isMonorepo.ts
CHANGED
|
@@ -1,8 +1,49 @@
|
|
|
1
|
+
import fs from 'node:fs'
|
|
1
2
|
import path from 'node:path'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
|
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
|
-
|
|
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) =>
|
|
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,
|