@startupjs/bundler 0.60.0-canary.1 → 0.60.0-canary.4
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/lib/eliminatorLoader.js +2 -2
- package/lib/startupjsLoader.js +3 -0
- package/metro-babel-transformer.js +0 -14
- package/metro-config.js +38 -1
- package/nodeLoader.mjs +1 -1
- package/package.json +4 -4
- package/lib/replaceObserverLoader.js +0 -128
- package/lib/utils.js +0 -12
package/lib/eliminatorLoader.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// TODO: add support for source maps
|
|
2
2
|
const babel = require('@babel/core')
|
|
3
|
-
const { isStartupjsPluginEcosystemFile, CONFIG_FILENAME_REGEX } = require('
|
|
3
|
+
const { isStartupjsPluginEcosystemFile, CONFIG_FILENAME_REGEX } = require('babel-preset-startupjs/utils')
|
|
4
4
|
|
|
5
5
|
const PLUGIN_KEYS = ['name', 'for', 'order', 'enabled']
|
|
6
6
|
const PROJECT_KEYS = ['plugins', 'modules']
|
|
@@ -20,7 +20,7 @@ module.exports = function eliminatorLoader (source) {
|
|
|
20
20
|
if (!(
|
|
21
21
|
isStartupjsPluginEcosystemFile(filename) ||
|
|
22
22
|
(clientModel && isModelFile(filename, source))
|
|
23
|
-
)) return source
|
|
23
|
+
)) return source // source inside Program is state.file.code
|
|
24
24
|
|
|
25
25
|
const envs = this.query.envs
|
|
26
26
|
if (!envs) throw Error("eliminatorLoader: envs not provided (for example ['features', 'isomorphic', 'client'])")
|
package/lib/startupjsLoader.js
CHANGED
|
@@ -15,7 +15,10 @@ module.exports = function startupjsLoader (source) {
|
|
|
15
15
|
configFile: false,
|
|
16
16
|
presets: [
|
|
17
17
|
[require('babel-preset-startupjs'), {
|
|
18
|
+
// in Program: state.file.opts.caller.platform when used in metro
|
|
19
|
+
// when used in metro - state.file.opts.caller.bundler === 'metro'
|
|
18
20
|
platform,
|
|
21
|
+
// in Program: state.file.opts.envName when used in metro
|
|
19
22
|
env
|
|
20
23
|
}],
|
|
21
24
|
[require('cssxjs/babel'), { platform }]
|
|
@@ -2,10 +2,8 @@ const stylusToCssLoader = require('cssxjs/loaders/stylusToCssLoader')
|
|
|
2
2
|
const cssToReactNativeLoader = require('cssxjs/loaders/cssToReactNativeLoader')
|
|
3
3
|
const mdxExamplesLoader = require('./lib/mdxExamplesLoader')
|
|
4
4
|
const getMDXLoader = require('./lib/getMDXLoader')
|
|
5
|
-
const eliminatorLoader = require('./lib/eliminatorLoader')
|
|
6
5
|
const callLoader = require('./lib/callLoader')
|
|
7
6
|
const asyncSvgLoader = require('./lib/asyncSvgLoader')
|
|
8
|
-
const startupjsLoader = require('./lib/startupjsLoader')
|
|
9
7
|
|
|
10
8
|
module.exports.transform = async function startupjsMetroBabelTransform ({
|
|
11
9
|
src, filename, options: { upstreamTransformer, ...options } = {}
|
|
@@ -27,18 +25,6 @@ module.exports.transform = async function startupjsMetroBabelTransform ({
|
|
|
27
25
|
src = callLoader(mdxLoader, src, filename)
|
|
28
26
|
}
|
|
29
27
|
|
|
30
|
-
// js transformations
|
|
31
|
-
if (/\.[mc]?[jt]sx?$/.test(filename)) {
|
|
32
|
-
src = callLoader(eliminatorLoader, src, filename, {
|
|
33
|
-
envs: ['features', 'isomorphic', 'client'],
|
|
34
|
-
useRequireContext: true,
|
|
35
|
-
clientModel: true
|
|
36
|
-
})
|
|
37
|
-
}
|
|
38
|
-
if ((/\.mdx?$/.test(filename) || /\.[mc]?[jt]sx?$/.test(filename)) && /['"](?:startupjs)['"]/.test(src)) {
|
|
39
|
-
src = callLoader(startupjsLoader, src, filename, { platform })
|
|
40
|
-
}
|
|
41
|
-
|
|
42
28
|
return upstreamTransformer.transform({ src, filename, options })
|
|
43
29
|
}
|
|
44
30
|
|
package/metro-config.js
CHANGED
|
@@ -5,11 +5,15 @@ const { join, resolve } = require('path')
|
|
|
5
5
|
|
|
6
6
|
// To pass existing config for modification, pass it as 'upstreamConfig' in options:
|
|
7
7
|
// config = getDefaultConfig(__dirname, { upstreamConfig })
|
|
8
|
-
exports.getDefaultConfig = function getDefaultConfig (projectRoot, {
|
|
8
|
+
exports.getDefaultConfig = function getDefaultConfig (projectRoot, {
|
|
9
|
+
upstreamConfig,
|
|
10
|
+
checkStartupjsBabel = true
|
|
11
|
+
} = {}) {
|
|
9
12
|
let packageJson = {}
|
|
10
13
|
try {
|
|
11
14
|
packageJson = JSON.parse(readFileSync(join(projectRoot, 'package.json'), 'utf8'))
|
|
12
15
|
} catch (err) {}
|
|
16
|
+
if (checkStartupjsBabel) _checkStartupjsBabel(projectRoot)
|
|
13
17
|
const features = getFeatures(projectRoot)
|
|
14
18
|
upstreamConfig ??= getUpstreamConfig(projectRoot)
|
|
15
19
|
const isExpo = checkIfExpo(upstreamConfig)
|
|
@@ -143,3 +147,36 @@ function getMonorepoRootPackageJson (projectRoot) {
|
|
|
143
147
|
} catch (err) {}
|
|
144
148
|
}
|
|
145
149
|
}
|
|
150
|
+
|
|
151
|
+
function _checkStartupjsBabel (projectRoot) {
|
|
152
|
+
const babelConfigPath = join(projectRoot, 'babel.config.cjs')
|
|
153
|
+
if (!existsSync(babelConfigPath)) {
|
|
154
|
+
console.error('ERROR:', ERRORS.missingBabelConfig)
|
|
155
|
+
throw Error(ERRORS.missingBabelConfig)
|
|
156
|
+
}
|
|
157
|
+
const babelConfig = readFileSync(join(projectRoot, 'babel.config.cjs'), 'utf8')
|
|
158
|
+
if (!babelConfig.includes('startupjs/babel')) {
|
|
159
|
+
console.error('ERROR:', ERRORS.noStartupjsBabelPreset)
|
|
160
|
+
throw Error(ERRORS.noStartupjsBabelPreset)
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const ERRORS = {
|
|
165
|
+
missingBabelConfig: `
|
|
166
|
+
Missing babel.config.cjs with 'startupjs/babel' preset.
|
|
167
|
+
Please create babel.config.cjs following the instructions from Expo (or pure React Native) documentation,
|
|
168
|
+
and add 'startupjs/babel' as the LAST item in the 'presets' array.
|
|
169
|
+
|
|
170
|
+
To ignore this error (if you want to use a custom babel preset to transform startupjs code),
|
|
171
|
+
you can pass the option 'checkStartupjsBabel: false'
|
|
172
|
+
when calling 'getDefaultConfig(projectRoot, options)' from 'metro.config.cjs'.
|
|
173
|
+
`,
|
|
174
|
+
noStartupjsBabelPreset: `
|
|
175
|
+
Your babel.config.cjs is missing 'startupjs/babel' preset.
|
|
176
|
+
Please add 'startupjs/babel' as the LAST item in the 'presets' array of your babel.config.cjs.
|
|
177
|
+
|
|
178
|
+
To ignore this error (if you want to use a custom babel preset to transform startupjs code),
|
|
179
|
+
you can pass the option 'checkStartupjsBabel: false'
|
|
180
|
+
when calling 'getDefaultConfig(projectRoot, options)' from 'metro.config.cjs'.
|
|
181
|
+
`
|
|
182
|
+
}
|
package/nodeLoader.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises'
|
|
2
2
|
import { fileURLToPath } from 'node:url'
|
|
3
|
+
import { isStartupjsPluginEcosystemFile } from 'babel-preset-startupjs/utils'
|
|
3
4
|
import callLoader from './lib/callLoader.js'
|
|
4
5
|
import yamlLoader from './lib/yamlLoader.js'
|
|
5
6
|
import eliminatorLoader from './lib/eliminatorLoader.js'
|
|
6
|
-
import { isStartupjsPluginEcosystemFile } from './lib/utils.js'
|
|
7
7
|
|
|
8
8
|
export function resolve (specifier, context, nextResolve) {
|
|
9
9
|
const { parentURL = null } = context
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@startupjs/bundler",
|
|
3
|
-
"version": "0.60.0-canary.
|
|
3
|
+
"version": "0.60.0-canary.4",
|
|
4
4
|
"description": "Opinionated scripts and configs to develop a react-native-web project",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"publishConfig": {
|
|
@@ -18,13 +18,13 @@
|
|
|
18
18
|
"@babel/core": "^7.9.0",
|
|
19
19
|
"@babel/plugin-syntax-jsx": "^7.0.0",
|
|
20
20
|
"@mdx-js/mdx": "^2.3.0",
|
|
21
|
-
"@startupjs/babel-plugin-eliminator": "^0.60.0-canary.
|
|
21
|
+
"@startupjs/babel-plugin-eliminator": "^0.60.0-canary.2",
|
|
22
22
|
"@startupjs/babel-plugin-startupjs-plugins": "^0.60.0-canary.1",
|
|
23
23
|
"@startupjs/server": "^0.60.0-canary.0",
|
|
24
24
|
"@svgr/core": "^8.1.0",
|
|
25
25
|
"@svgr/plugin-jsx": "^8.1.0",
|
|
26
26
|
"@svgr/plugin-svgo": "^8.1.0",
|
|
27
|
-
"babel-preset-startupjs": "^0.60.0-canary.
|
|
27
|
+
"babel-preset-startupjs": "^0.60.0-canary.2",
|
|
28
28
|
"connect": "^3.7.0",
|
|
29
29
|
"lodash": "^4.17.20",
|
|
30
30
|
"remark-gfm": "^1.0.0"
|
|
@@ -33,5 +33,5 @@
|
|
|
33
33
|
"cssxjs": "*",
|
|
34
34
|
"react-native-svg": "*"
|
|
35
35
|
},
|
|
36
|
-
"gitHead": "
|
|
36
|
+
"gitHead": "0df84565f3b2e659c625ba605e43d4420c6fe7e1"
|
|
37
37
|
}
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
const OBSERVER_REGEX = /(^|\W)observer\(/
|
|
2
|
-
const OBSERVER_REPLACE = 'observer.__wrapObserverMeta(observer.__makeObserver('
|
|
3
|
-
const OPTIONS_ANCHORS = ['forwardRef:', 'suspenseProps:']
|
|
4
|
-
|
|
5
|
-
// INFO:
|
|
6
|
-
//
|
|
7
|
-
// The problem seems to be with observer() creating an additional
|
|
8
|
-
// wrapper react component to host Suspense and ContextMeta.
|
|
9
|
-
// While it also makes the target Component observable at the
|
|
10
|
-
// same time.
|
|
11
|
-
//
|
|
12
|
-
// Creation of an additional wrapper component with only one
|
|
13
|
-
// function observer() seems to confuse Fast Refresh and it loses state
|
|
14
|
-
// of such components.
|
|
15
|
-
//
|
|
16
|
-
// The temporary solution for this (until it is fixed in react-native)
|
|
17
|
-
// is to separate observer() into 2 functions:
|
|
18
|
-
// 1. observer.__wrapObserverMeta() -- wraps component into an
|
|
19
|
-
// additional component with Suspense and ContextMeta
|
|
20
|
-
// 2. observer.__makeObserver() -- modifies component to become
|
|
21
|
-
// observable
|
|
22
|
-
//
|
|
23
|
-
// So the following transformation transforms code the following way:
|
|
24
|
-
// observer(App)
|
|
25
|
-
// V V V
|
|
26
|
-
// observer.__wrapObserverMeta(observer.__makeObserver(App))
|
|
27
|
-
//
|
|
28
|
-
// It's important to make this transformation as a separate step before
|
|
29
|
-
// the usual babel transformation fires. Otherwise, if you put it
|
|
30
|
-
// into a generic babel.config.js list of plugins, Fast Refresh
|
|
31
|
-
// will still not properly work.
|
|
32
|
-
//
|
|
33
|
-
// It makes sense to only do this in development
|
|
34
|
-
|
|
35
|
-
module.exports = function replaceObserverLoader (source) {
|
|
36
|
-
const match = source.match(OBSERVER_REGEX)
|
|
37
|
-
if (!match) return source
|
|
38
|
-
const matchIndex = match.index
|
|
39
|
-
const matchStr = match[0]
|
|
40
|
-
const matchLength = matchStr.length
|
|
41
|
-
let openBr = 1 // Count opened brackets, we start from one already opened
|
|
42
|
-
let lastCloseCurlyBrIndex
|
|
43
|
-
let lastOpenCurlyBrIndex
|
|
44
|
-
|
|
45
|
-
// TODO: Improve figuring out that we are actually in a comment.
|
|
46
|
-
// It will bug out when someone is specifying 'http://'
|
|
47
|
-
// and other places inside strings.
|
|
48
|
-
|
|
49
|
-
// // Track when we are inside a comment
|
|
50
|
-
// let inBlockComment = false
|
|
51
|
-
// let inLineComment = false
|
|
52
|
-
|
|
53
|
-
for (let i = matchIndex + matchLength; i < source.length; i++) {
|
|
54
|
-
const char = source.charAt(i)
|
|
55
|
-
|
|
56
|
-
// TODO: Improve comments. See comment above for details.
|
|
57
|
-
|
|
58
|
-
// // Handle comments (ignore any chars inside them)
|
|
59
|
-
|
|
60
|
-
// const prevChar = (i > 0 ? source.charAt(i - 1) : '')
|
|
61
|
-
// const lastTwoChars = `${prevChar}${char}`
|
|
62
|
-
|
|
63
|
-
// // - exit comment
|
|
64
|
-
|
|
65
|
-
// if (inBlockComment) {
|
|
66
|
-
// if (lastTwoChars === '*/') inBlockComment = false
|
|
67
|
-
// continue
|
|
68
|
-
// }
|
|
69
|
-
|
|
70
|
-
// if (inLineComment) {
|
|
71
|
-
// if (char === '\n') inLineComment = false
|
|
72
|
-
// continue
|
|
73
|
-
// }
|
|
74
|
-
|
|
75
|
-
// // - enter comment
|
|
76
|
-
|
|
77
|
-
// if (lastTwoChars === '/*') {
|
|
78
|
-
// inBlockComment = true
|
|
79
|
-
// continue
|
|
80
|
-
// }
|
|
81
|
-
|
|
82
|
-
// if (lastTwoChars === '//') {
|
|
83
|
-
// inLineComment = true
|
|
84
|
-
// continue
|
|
85
|
-
// }
|
|
86
|
-
|
|
87
|
-
// Brackets counting logic
|
|
88
|
-
|
|
89
|
-
switch (char) {
|
|
90
|
-
case ')':
|
|
91
|
-
--openBr
|
|
92
|
-
break
|
|
93
|
-
case '(':
|
|
94
|
-
++openBr
|
|
95
|
-
break
|
|
96
|
-
case '{':
|
|
97
|
-
lastOpenCurlyBrIndex = i
|
|
98
|
-
break
|
|
99
|
-
case '}':
|
|
100
|
-
lastCloseCurlyBrIndex = i
|
|
101
|
-
break
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (openBr <= 0) {
|
|
105
|
-
let options = ''
|
|
106
|
-
|
|
107
|
-
if (lastOpenCurlyBrIndex && lastCloseCurlyBrIndex) {
|
|
108
|
-
const sourceBetweenCurlyBrackets =
|
|
109
|
-
source.slice(lastOpenCurlyBrIndex, lastCloseCurlyBrIndex + 1)
|
|
110
|
-
|
|
111
|
-
for (const anchor of OPTIONS_ANCHORS) {
|
|
112
|
-
if (sourceBetweenCurlyBrackets.includes(anchor)) {
|
|
113
|
-
options = sourceBetweenCurlyBrackets
|
|
114
|
-
break
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
if (options) options = ', ' + options
|
|
120
|
-
|
|
121
|
-
source = source.slice(0, i) + ')' + options + source.slice(i)
|
|
122
|
-
break
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
source = source.replace(OBSERVER_REGEX, '$1' + OBSERVER_REPLACE)
|
|
127
|
-
return replaceObserverLoader(source)
|
|
128
|
-
}
|
package/lib/utils.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
// NOTE: startupjs.config.cjs is used by the old bundler. This regex does not include it.
|
|
2
|
-
exports.CONFIG_FILENAME_REGEX = /(?:^|[\\/])startupjs\.config\.m?[jt]sx?$/
|
|
3
|
-
exports.PLUGIN_FILENAME_REGEX = /(?:^|[.\\/])plugin\.[mc]?[jt]sx?$/
|
|
4
|
-
exports.LOAD_CONFIG_FILENAME_REGEX = /(?:^|[\\/])loadStartupjsConfig\.m?[jt]sx?$/
|
|
5
|
-
|
|
6
|
-
exports.isStartupjsPluginEcosystemFile = filename => {
|
|
7
|
-
return (
|
|
8
|
-
exports.PLUGIN_FILENAME_REGEX.test(filename) ||
|
|
9
|
-
exports.CONFIG_FILENAME_REGEX.test(filename) ||
|
|
10
|
-
exports.LOAD_CONFIG_FILENAME_REGEX.test(filename)
|
|
11
|
-
)
|
|
12
|
-
}
|