babel-preset-startupjs 0.59.0-canary.9 → 0.60.0-canary.11
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/index.js +268 -246
- package/package.json +12 -37
- package/utils.js +35 -0
- package/constants.json +0 -3
- package/esNextPreset.js +0 -79
- package/metroPresetWithTypescript.js +0 -18
- package/pure.js +0 -86
package/index.js
CHANGED
|
@@ -1,264 +1,286 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Compilation pipeline:
|
|
3
|
+
* 1. Transform pug to jsx
|
|
4
|
+
* 2. Auto-load startupjs plugins
|
|
5
|
+
* 3. Run eliminator to remove code targeting other envs
|
|
6
|
+
* 4. Transform CSS modules
|
|
7
|
+
*
|
|
8
|
+
* Options:
|
|
9
|
+
* platform - Force platform to compile to (e.g. 'ios', 'android', 'web').
|
|
10
|
+
* Default: 'web' (or auto-detected on React Native)
|
|
11
|
+
* On React Native (Metro) this gets automatically detected inside babel plugins.
|
|
12
|
+
* reactType - Force the React type - RN or pure web React (e.g. 'react-native', 'web').
|
|
13
|
+
* Default: undefined (auto-detected)
|
|
14
|
+
* This shouldn't be needed in most cases since it will be automatically detected.
|
|
15
|
+
* cache - Force the CSS caching library instance (e.g. 'teamplay').
|
|
16
|
+
* Default: undefined (auto-detected)
|
|
17
|
+
* This shouldn't be needed in most cases since it will be automatically detected.
|
|
18
|
+
* transformPug - Whether to transform pug to jsx.
|
|
19
|
+
* Default: true
|
|
20
|
+
* transformCss - Whether to transform CSS modules (styl/css files and styl`` css`` in JSX).
|
|
21
|
+
* Default: true
|
|
22
|
+
* useRequireContext - Whether to use require.context for loading startupjs plugins.
|
|
23
|
+
* The underlying environment must support require.context (e.g. Metro, Webpack).
|
|
24
|
+
* Default: true
|
|
25
|
+
* clientOnly - Whether to transform model/*.js files to keep only the client-relevant code.
|
|
26
|
+
* Default: true
|
|
27
|
+
* This option is required when building for the client (React Native or web) so that
|
|
28
|
+
* server-only code is removed from model files and secret information is not leaked to the client.
|
|
29
|
+
* envs - Array of envs to keep during code elimination of the startupjs config and plugins.
|
|
30
|
+
* Default: ['features', 'isomorphic', 'client']
|
|
31
|
+
* On the server, this should usually include 'server' instead of 'client':
|
|
32
|
+
* ['features', 'isomorphic', 'server']
|
|
33
|
+
* isStartupjsFile - A function (filename, code) => boolean that checks whether the given file
|
|
34
|
+
* is part of the startupjs ecosystem (a plugin, startupjs.config.js, loadStartupjsConfig.js or a model file).
|
|
35
|
+
* Default: a function that returns true for all startupjs plugin ecosystem files. And also
|
|
36
|
+
* when clientOnly is true, it also returns true for model/*.js files to keep only client-relevant code there.
|
|
37
|
+
* docgen - Whether to enable docgen features - magic exports of JSON schemas from TypeScript interfaces.
|
|
38
|
+
* Default: false
|
|
39
|
+
*/
|
|
40
|
+
const { createStartupjsFileChecker, CONFIG_FILENAME_REGEX } = require('./utils.js')
|
|
41
|
+
const PLUGIN_KEYS = ['name', 'for', 'order', 'enabled']
|
|
42
|
+
const PROJECT_KEYS = ['plugins', 'modules']
|
|
43
|
+
const ALL_ENVS = ['features', 'isomorphic', 'client', 'server', 'build']
|
|
44
|
+
const MAGIC_IMPORTS = ['startupjs/registry', '@startupjs/registry']
|
|
7
45
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
[require('babel-plugin-module-resolver'), {
|
|
24
|
-
alias: {
|
|
25
|
-
...DIRECTORY_ALIASES,
|
|
26
|
-
...alias
|
|
27
|
-
}
|
|
28
|
-
}],
|
|
29
|
-
[require('@startupjs/babel-plugin-transform-react-pug'), {
|
|
30
|
-
classAttribute: 'styleName'
|
|
31
|
-
}],
|
|
32
|
-
[require('@startupjs/babel-plugin-react-pug-classnames'), {
|
|
33
|
-
classAttribute: 'styleName'
|
|
34
|
-
}],
|
|
35
|
-
[require('@babel/plugin-proposal-decorators'), { legacy: true }]
|
|
36
|
-
]
|
|
37
|
-
|
|
38
|
-
const dotenvPlugin = ({ production, mockBaseUrl, envName = APP_ENV } = {}) => {
|
|
39
|
-
if (!envName) {
|
|
40
|
-
envName = production ? 'production' : 'local'
|
|
41
|
-
}
|
|
42
|
-
const options = {
|
|
43
|
-
moduleName: '@env',
|
|
44
|
-
path: ['.env', `.env.${envName}`]
|
|
45
|
-
}
|
|
46
|
-
if (mockBaseUrl) {
|
|
47
|
-
options.override = {
|
|
48
|
-
BASE_URL: "typeof window !== 'undefined' && window.location && window.location.origin"
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
return [require('@startupjs/babel-plugin-dotenv'), options]
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const i18nPlugin = (options) => {
|
|
55
|
-
return [require('@startupjs/babel-plugin-i18n-extract'), options]
|
|
56
|
-
}
|
|
46
|
+
module.exports = (api, {
|
|
47
|
+
platform,
|
|
48
|
+
reactType,
|
|
49
|
+
cache,
|
|
50
|
+
compileCssImports,
|
|
51
|
+
cssFileExtensions,
|
|
52
|
+
transformCss = true,
|
|
53
|
+
transformPug = true,
|
|
54
|
+
useRequireContext = true,
|
|
55
|
+
clientOnly = true,
|
|
56
|
+
envs = ['features', 'isomorphic', 'client'],
|
|
57
|
+
isStartupjsFile = createStartupjsFileChecker({ clientOnly }),
|
|
58
|
+
docgen = false
|
|
59
|
+
} = {}) => {
|
|
60
|
+
const isMetro = api.caller(caller => caller?.name === 'metro')
|
|
57
61
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
webpackHotModuleReloading: !production,
|
|
62
|
-
filetypes: {
|
|
63
|
-
'.styl': {}
|
|
64
|
-
},
|
|
65
|
-
transform: (src, filepath) => {
|
|
66
|
-
if (!/\.styl$/.test(filepath)) return src
|
|
67
|
-
return stylusToCssLoader.call({ resourcePath: filepath }, src)
|
|
68
|
-
},
|
|
69
|
-
generateScopedName
|
|
70
|
-
}]
|
|
62
|
+
// By default on Metro we don't need to compile CSS imports since we are relying on the custom
|
|
63
|
+
// StartupJS metro-babel-transformer which handles CSS imports as separate files.
|
|
64
|
+
if (compileCssImports == null && isMetro) compileCssImports = false
|
|
71
65
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
66
|
+
// on Metro we transform any CSS imports since StartupJS metro-babel-transformer
|
|
67
|
+
// turns off Expo's default CSS support and handles only our CSS imports.
|
|
68
|
+
// When used in a plain Web project though though,
|
|
69
|
+
// we want to only handle the default ['cssx.css', 'cssx.styl'] extensions.
|
|
70
|
+
if (cssFileExtensions == null && isMetro) cssFileExtensions = ['styl', 'css']
|
|
76
71
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
72
|
+
return {
|
|
73
|
+
overrides: [{
|
|
74
|
+
test: isJsxSource,
|
|
75
|
+
plugins: [
|
|
76
|
+
// support JSX syntax
|
|
77
|
+
require('@babel/plugin-syntax-jsx')
|
|
78
|
+
]
|
|
79
|
+
}, {
|
|
80
|
+
test: isTypeScriptSource,
|
|
81
|
+
plugins: [
|
|
82
|
+
// support TypeScript syntax
|
|
83
|
+
require('@babel/plugin-syntax-typescript')
|
|
84
|
+
]
|
|
85
|
+
}, {
|
|
86
|
+
test: isTsxSource,
|
|
87
|
+
plugins: [
|
|
88
|
+
// support TypeScript + JSX syntax
|
|
89
|
+
[require('@babel/plugin-syntax-typescript'), {
|
|
90
|
+
isTSX: true
|
|
91
|
+
}]
|
|
92
|
+
]
|
|
93
|
+
}, {
|
|
94
|
+
plugins: [
|
|
95
|
+
docgen && [require('@startupjs/babel-plugin-ts-to-json-schema'), {
|
|
96
|
+
magicExportName: '_PropsJsonSchema',
|
|
97
|
+
interfaceMatch: 'export interface'
|
|
98
|
+
}],
|
|
86
99
|
|
|
87
|
-
//
|
|
100
|
+
// transform pug to jsx. This generates a bunch of new AST nodes
|
|
101
|
+
// (it's important to do this first before any dead code elimination runs)
|
|
102
|
+
transformPug && [require('cssxjs/babel/plugin-react-pug'), { classAttribute: 'styleName' }],
|
|
88
103
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
i18nPlugin()
|
|
102
|
-
]
|
|
103
|
-
}
|
|
104
|
+
// inline CSS modules (styl`` in the same JSX file -- similar to how it is in Vue.js)
|
|
105
|
+
transformCss && [require('cssxjs/babel/plugin-rn-stylename-inline'), {
|
|
106
|
+
platform
|
|
107
|
+
}],
|
|
108
|
+
// CSS modules (separate .styl/.css file)
|
|
109
|
+
transformCss && [require('cssxjs/babel/plugin-rn-stylename-to-style'), {
|
|
110
|
+
extensions: cssFileExtensions,
|
|
111
|
+
useImport: true,
|
|
112
|
+
reactType,
|
|
113
|
+
cache,
|
|
114
|
+
compileCssImports
|
|
115
|
+
}],
|
|
104
116
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
{ useTransformReactJSXExperimental: true }
|
|
110
|
-
]
|
|
111
|
-
],
|
|
112
|
-
plugins: [
|
|
113
|
-
dotenvPlugin({ production: true }),
|
|
114
|
-
nativeReactCssModulesPlatformExtensionsPlugin(),
|
|
115
|
-
...nativeReactCssModulesPlugins({ useImport: false }),
|
|
116
|
-
i18nPlugin()
|
|
117
|
-
]
|
|
118
|
-
}
|
|
117
|
+
// auto-load startupjs plugins
|
|
118
|
+
// traverse "exports" of package.json and all dependencies to find all startupjs plugins
|
|
119
|
+
// and automatically import them in the main startupjs.config.js file
|
|
120
|
+
[require('@startupjs/babel-plugin-startupjs-plugins'), { useRequireContext }],
|
|
119
121
|
|
|
120
|
-
//
|
|
121
|
-
//
|
|
122
|
+
// run eliminator to remove code targeting other envs.
|
|
123
|
+
// For example, only keep code related to 'client' and 'isomorphic' envs
|
|
124
|
+
// (in which case any code related to 'server' and 'build' envs will be removed)
|
|
125
|
+
[require('@startupjs/babel-plugin-eliminator'), {
|
|
126
|
+
shouldTransformFileChecker: isStartupjsFile,
|
|
127
|
+
trimObjects: [{
|
|
128
|
+
magicFilenameRegex: CONFIG_FILENAME_REGEX,
|
|
129
|
+
magicExport: 'default',
|
|
130
|
+
targetObjectJsonPath: '$.modules.*',
|
|
131
|
+
ensureOnlyKeys: ALL_ENVS,
|
|
132
|
+
keepKeys: envs
|
|
133
|
+
}, {
|
|
134
|
+
magicFilenameRegex: CONFIG_FILENAME_REGEX,
|
|
135
|
+
magicExport: 'default',
|
|
136
|
+
targetObjectJsonPath: '$.plugins.*',
|
|
137
|
+
ensureOnlyKeys: ALL_ENVS,
|
|
138
|
+
keepKeys: envs
|
|
139
|
+
}, {
|
|
140
|
+
magicFilenameRegex: CONFIG_FILENAME_REGEX,
|
|
141
|
+
magicExport: 'default',
|
|
142
|
+
targetObjectJsonPath: '$',
|
|
143
|
+
// envs on the top level are the alias for '$.modules.startupjs'
|
|
144
|
+
ensureOnlyKeys: [...PROJECT_KEYS, ...ALL_ENVS],
|
|
145
|
+
keepKeys: [...PROJECT_KEYS, ...envs]
|
|
146
|
+
}, {
|
|
147
|
+
functionName: 'createPlugin',
|
|
148
|
+
magicImports: MAGIC_IMPORTS,
|
|
149
|
+
ensureOnlyKeys: [...PLUGIN_KEYS, ...ALL_ENVS],
|
|
150
|
+
keepKeys: [...PLUGIN_KEYS, ...envs]
|
|
151
|
+
}],
|
|
152
|
+
...(clientOnly
|
|
153
|
+
? {
|
|
154
|
+
transformFunctionCalls: [{
|
|
155
|
+
// direct named exports of aggregation() within model/*.js files
|
|
156
|
+
// are replaced with aggregationHeader() calls.
|
|
157
|
+
// 'collection' is the filename without extension
|
|
158
|
+
// 'name' is the direct named export const name
|
|
159
|
+
//
|
|
160
|
+
// Example:
|
|
161
|
+
//
|
|
162
|
+
// // in model/games.js
|
|
163
|
+
// export const $$byGameId = aggregation(({ gameId }) => ({ gameId }))
|
|
164
|
+
//
|
|
165
|
+
// will be replaced with:
|
|
166
|
+
//
|
|
167
|
+
// __aggregationHeader({ collection: 'games', name: '$$byGameId' })
|
|
168
|
+
//
|
|
169
|
+
functionName: 'aggregation',
|
|
170
|
+
magicImports: ['startupjs'],
|
|
171
|
+
requirements: {
|
|
172
|
+
argumentsAmount: 1,
|
|
173
|
+
directNamedExportedAsConst: true
|
|
174
|
+
},
|
|
175
|
+
replaceWith: {
|
|
176
|
+
newFunctionNameFromSameImport: '__aggregationHeader',
|
|
177
|
+
newCallArgumentsTemplate: `[
|
|
178
|
+
{
|
|
179
|
+
collection: %%filenameWithoutExtension%%,
|
|
180
|
+
name: %%directNamedExportConstName%%
|
|
181
|
+
}
|
|
182
|
+
]`
|
|
183
|
+
}
|
|
184
|
+
}, {
|
|
185
|
+
// export default inside of aggregation() within a separate model/*.$$myAggregation.js files
|
|
186
|
+
// are replaced with aggregationHeader() calls.
|
|
187
|
+
// Filepath is stripped of the extensions and split into sections (by dots and slashes)
|
|
188
|
+
// 'name' is the last section.
|
|
189
|
+
// 'collection' is the section before it.
|
|
190
|
+
//
|
|
191
|
+
// Example:
|
|
192
|
+
//
|
|
193
|
+
// // in model/games/$$active.js
|
|
194
|
+
// export default aggregation(({ gameId }) => ({ gameId }))
|
|
195
|
+
//
|
|
196
|
+
// will be replaced with:
|
|
197
|
+
//
|
|
198
|
+
// __aggregationHeader({ collection: 'games', name: '$$active' })
|
|
199
|
+
//
|
|
200
|
+
functionName: 'aggregation',
|
|
201
|
+
magicImports: ['startupjs'],
|
|
202
|
+
requirements: {
|
|
203
|
+
argumentsAmount: 1,
|
|
204
|
+
directDefaultExported: true
|
|
205
|
+
},
|
|
206
|
+
replaceWith: {
|
|
207
|
+
newFunctionNameFromSameImport: '__aggregationHeader',
|
|
208
|
+
newCallArgumentsTemplate: `[
|
|
209
|
+
{
|
|
210
|
+
collection: %%folderAndFilenameWithoutExtension%%.split(/[\\\\/\\.]/).at(-2),
|
|
211
|
+
name: %%folderAndFilenameWithoutExtension%%.split(/[\\\\/\\.]/).at(-1)
|
|
212
|
+
}
|
|
213
|
+
]`
|
|
214
|
+
}
|
|
215
|
+
}, {
|
|
216
|
+
// TODO: this has to be implemented! It's not actually working yet.
|
|
122
217
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
218
|
+
// any other calls to aggregation() must explicitly define the collection and name
|
|
219
|
+
// as the second argument. If not, the build will fail.
|
|
220
|
+
//
|
|
221
|
+
// Example:
|
|
222
|
+
//
|
|
223
|
+
// aggregation(
|
|
224
|
+
// ({ gameId }) => ({ gameId }),
|
|
225
|
+
// { collection: 'games', name: 'byGameId' }
|
|
226
|
+
// )
|
|
227
|
+
//
|
|
228
|
+
// will be replaced with:
|
|
229
|
+
//
|
|
230
|
+
// __aggregationHeader({ collection: 'games', name: 'byGameId' })
|
|
231
|
+
//
|
|
232
|
+
functionName: 'aggregation',
|
|
233
|
+
magicImports: ['startupjs'],
|
|
234
|
+
requirements: {
|
|
235
|
+
argumentsAmount: 2
|
|
236
|
+
},
|
|
237
|
+
throwIfRequirementsNotMet: true,
|
|
238
|
+
replaceWith: {
|
|
239
|
+
newFunctionNameFromSameImport: '__aggregationHeader',
|
|
240
|
+
newCallArgumentsTemplate: '[%%argument1%%]' // 0-based index
|
|
241
|
+
}
|
|
242
|
+
}, {
|
|
243
|
+
// remove accessControl() calls (replace with undefined)
|
|
244
|
+
functionName: 'accessControl',
|
|
245
|
+
magicImports: ['startupjs'],
|
|
246
|
+
replaceWith: {
|
|
247
|
+
remove: true // replace the whole function call with undefined
|
|
248
|
+
}
|
|
249
|
+
}, {
|
|
250
|
+
// remove serverOnly() calls (replace with undefined)
|
|
251
|
+
functionName: 'serverOnly',
|
|
252
|
+
magicImports: ['startupjs'],
|
|
253
|
+
replaceWith: {
|
|
254
|
+
remove: true // replace the whole function call with undefined
|
|
255
|
+
}
|
|
256
|
+
}]
|
|
257
|
+
}
|
|
258
|
+
: {}
|
|
259
|
+
)
|
|
260
|
+
}],
|
|
140
261
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
262
|
+
// debugging features
|
|
263
|
+
require('@startupjs/babel-plugin-startupjs-debug'),
|
|
264
|
+
require('@startupjs/babel-plugin-i18n-extract')
|
|
265
|
+
].filter(Boolean)
|
|
145
266
|
}]
|
|
146
|
-
|
|
147
|
-
plugins: [
|
|
148
|
-
ASYNC && require('@startupjs/babel-plugin-startupjs'),
|
|
149
|
-
ASYNC && require('@startupjs/babel-plugin-import-to-react-lazy'),
|
|
150
|
-
dotenvPlugin({ production: true, mockBaseUrl: true }),
|
|
151
|
-
...nativeReactCssModulesPlugins({ platform: 'web' }),
|
|
152
|
-
i18nPlugin({ collectTranslations: true })
|
|
153
|
-
].filter(Boolean)
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
if (ASYNC) {
|
|
157
|
-
CONFIG_WEB_UNIVERSAL_PRODUCTION.sourceType = 'unambiguous'
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// web config for a pure web project. Uses babel-plugin-react-css-modules for CSS which allows
|
|
161
|
-
// to use the full browser CSS engine.
|
|
162
|
-
|
|
163
|
-
const CONFIG_WEB_PURE_DEVELOPMENT = {
|
|
164
|
-
presets: [
|
|
165
|
-
[require('./esNextPreset'), { debugJsx: true }]
|
|
166
|
-
// NOTE: If we start to face unknown errors in development or
|
|
167
|
-
// want to sync the whole presets/plugins stack with RN,
|
|
168
|
-
// just replace the optimized esNext preset above with the
|
|
169
|
-
// regular metro preset below:
|
|
170
|
-
// [require('./metroPresetWithTypescript')]
|
|
171
|
-
],
|
|
172
|
-
plugins: [
|
|
173
|
-
[require('@startupjs/babel-plugin-startupjs-debug')],
|
|
174
|
-
[require('react-refresh/babel'), { skipEnvCheck: true }],
|
|
175
|
-
dotenvPlugin({ mockBaseUrl: true }),
|
|
176
|
-
webReactCssModulesPlugin(),
|
|
177
|
-
i18nPlugin({ collectTranslations: true })
|
|
178
|
-
]
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
const CONFIG_WEB_PURE_PRODUCTION = {
|
|
182
|
-
presets: [
|
|
183
|
-
[require('./metroPresetWithTypescript'), {
|
|
184
|
-
disableImportExportTransform: !!ASYNC
|
|
185
|
-
}]
|
|
186
|
-
],
|
|
187
|
-
plugins: [
|
|
188
|
-
dotenvPlugin({ production: true, mockBaseUrl: true }),
|
|
189
|
-
webReactCssModulesPlugin({ production: true }),
|
|
190
|
-
i18nPlugin({ collectTranslations: true })
|
|
191
|
-
]
|
|
267
|
+
}
|
|
192
268
|
}
|
|
193
269
|
|
|
194
|
-
|
|
195
|
-
|
|
270
|
+
// all files which are not .ts or .tsx are considered to be pure JS with JSX support
|
|
271
|
+
function isJsxSource (fileName) {
|
|
272
|
+
if (!fileName) return false
|
|
273
|
+
return !isTypeScriptSource(fileName) && !isTsxSource(fileName)
|
|
196
274
|
}
|
|
197
275
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
presets: [
|
|
202
|
-
require('./esNextPreset')
|
|
203
|
-
// NOTE: If we start to face unknown errors or
|
|
204
|
-
// want to sync the whole presets/plugins stack with RN,
|
|
205
|
-
// just replace the optimized esNext preset above with the
|
|
206
|
-
// regular metro preset below:
|
|
207
|
-
// [require('./metroPresetWithTypescript')]
|
|
208
|
-
],
|
|
209
|
-
plugins: []
|
|
276
|
+
function isTypeScriptSource (fileName) {
|
|
277
|
+
if (!fileName) return false
|
|
278
|
+
return fileName.endsWith('.ts')
|
|
210
279
|
}
|
|
211
280
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
// There is a bug in metro when BABEL_ENV is a string "undefined".
|
|
218
|
-
// We have to workaround it and use NODE_ENV.
|
|
219
|
-
const env = (BABEL_ENV !== 'undefined' && BABEL_ENV) || NODE_ENV
|
|
220
|
-
|
|
221
|
-
const { presets = [], plugins = [], ...extra } = getConfig(env, MODE)
|
|
222
|
-
|
|
223
|
-
return {
|
|
224
|
-
presets,
|
|
225
|
-
plugins: basePlugins(options).concat(plugins),
|
|
226
|
-
...extra
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
function getConfig (env, mode) {
|
|
231
|
-
if (env === 'development') {
|
|
232
|
-
return CONFIG_NATIVE_DEVELOPMENT
|
|
233
|
-
} else if (env === 'production') {
|
|
234
|
-
return CONFIG_NATIVE_PRODUCTION
|
|
235
|
-
} else if (env === 'server') {
|
|
236
|
-
return CONFIG_SERVER
|
|
237
|
-
} else if (env === 'web_development') {
|
|
238
|
-
if (mode === 'web') {
|
|
239
|
-
return CONFIG_WEB_PURE_DEVELOPMENT
|
|
240
|
-
} else {
|
|
241
|
-
return CONFIG_WEB_UNIVERSAL_DEVELOPMENT
|
|
242
|
-
}
|
|
243
|
-
} else if (env === 'web_production') {
|
|
244
|
-
if (mode === 'web') {
|
|
245
|
-
return CONFIG_WEB_PURE_PRODUCTION
|
|
246
|
-
} else {
|
|
247
|
-
return CONFIG_WEB_UNIVERSAL_PRODUCTION
|
|
248
|
-
}
|
|
249
|
-
} else {
|
|
250
|
-
return {}
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
function generateScopedName (name, filename/* , css */) {
|
|
255
|
-
let hashSize = LOCAL_IDENT_NAME.match(/base64:(\d+)]/)
|
|
256
|
-
if (!hashSize) {
|
|
257
|
-
throw new Error(
|
|
258
|
-
'wrong LOCAL_IDENT_NAME. Change generateScopeName() accordingly'
|
|
259
|
-
)
|
|
260
|
-
}
|
|
261
|
-
hashSize = Number(hashSize[1])
|
|
262
|
-
if (new RegExp(`_.{${hashSize}}_$`).test(name)) return name
|
|
263
|
-
return generateScopedNameFactory(LOCAL_IDENT_NAME)(name, filename)
|
|
281
|
+
// NOTE: .tsx is the default when fileName is not provided.
|
|
282
|
+
// This is because we want to support the most overarching syntax by default.
|
|
283
|
+
function isTsxSource (fileName) {
|
|
284
|
+
if (!fileName) return true
|
|
285
|
+
return fileName.endsWith('.tsx')
|
|
264
286
|
}
|
package/package.json
CHANGED
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "babel-preset-startupjs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.60.0-canary.11",
|
|
4
4
|
"description": "Babel preset for compiling StartupJS app on server, web, native",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": "./index.js",
|
|
8
|
-
"./
|
|
9
|
-
"./pure": "./pure.js",
|
|
10
|
-
"./pure.js": "./pure.js",
|
|
11
|
-
"./constants": "./constants.json",
|
|
12
|
-
"./constants.json": "./constants.json"
|
|
8
|
+
"./utils": "./utils.js"
|
|
13
9
|
},
|
|
14
10
|
"publishConfig": {
|
|
15
11
|
"access": "public"
|
|
@@ -17,38 +13,17 @@
|
|
|
17
13
|
"license": "MIT",
|
|
18
14
|
"dependencies": {
|
|
19
15
|
"@babel/core": "^7.9.0",
|
|
20
|
-
"@babel/plugin-proposal-class-properties": "^7.0.0",
|
|
21
|
-
"@babel/plugin-proposal-decorators": "^7.8.0",
|
|
22
|
-
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1",
|
|
23
|
-
"@babel/plugin-proposal-optional-chaining": "^7.0.0",
|
|
24
|
-
"@babel/plugin-syntax-flow": "^7.2.0",
|
|
25
16
|
"@babel/plugin-syntax-jsx": "^7.0.0",
|
|
26
17
|
"@babel/plugin-syntax-typescript": "^7.23.3",
|
|
27
|
-
"@babel
|
|
28
|
-
"@babel
|
|
29
|
-
"@babel
|
|
30
|
-
"@babel
|
|
31
|
-
"@babel
|
|
32
|
-
"@babel
|
|
33
|
-
"@babel/plugin-transform-typescript": "^7.5.0",
|
|
34
|
-
"@babel/runtime": "^7.9.0",
|
|
35
|
-
"@startupjs/babel-plugin-dotenv": "^0.59.0-canary.0",
|
|
36
|
-
"@startupjs/babel-plugin-i18n-extract": "^0.59.0-canary.0",
|
|
37
|
-
"@startupjs/babel-plugin-import-to-react-lazy": "^0.59.0-canary.0",
|
|
38
|
-
"@startupjs/babel-plugin-react-css-modules": "^6.5.4-1",
|
|
39
|
-
"@startupjs/babel-plugin-react-pug-classnames": "^0.59.0-canary.0",
|
|
40
|
-
"@startupjs/babel-plugin-rn-stylename-inline": "^0.59.0-canary.9",
|
|
41
|
-
"@startupjs/babel-plugin-rn-stylename-to-style": "^0.59.0-canary.0",
|
|
42
|
-
"@startupjs/babel-plugin-startupjs": "^0.59.0-canary.0",
|
|
43
|
-
"@startupjs/babel-plugin-startupjs-debug": "^0.59.0-canary.0",
|
|
44
|
-
"@startupjs/babel-plugin-startupjs-utils": "^0.59.0-canary.0",
|
|
45
|
-
"@startupjs/babel-plugin-transform-react-pug": "^7.0.1-0",
|
|
46
|
-
"@startupjs/bundler": "^0.59.0-canary.9",
|
|
47
|
-
"babel-plugin-module-resolver": "^5.0.0",
|
|
48
|
-
"babel-plugin-react-native-platform-specific-extensions": "^1.1.1",
|
|
49
|
-
"babel-plugin-react-native-web-pass-classname": "^0.2.1",
|
|
50
|
-
"metro-react-native-babel-preset": "^0.76.8",
|
|
51
|
-
"react-refresh": "^0.10.0"
|
|
18
|
+
"@startupjs/babel-plugin-eliminator": "^0.60.0-canary.0",
|
|
19
|
+
"@startupjs/babel-plugin-i18n-extract": "^0.60.0-canary.7",
|
|
20
|
+
"@startupjs/babel-plugin-startupjs": "^0.60.0-canary.7",
|
|
21
|
+
"@startupjs/babel-plugin-startupjs-debug": "^0.60.0-canary.7",
|
|
22
|
+
"@startupjs/babel-plugin-startupjs-plugins": "^0.60.0-canary.0",
|
|
23
|
+
"@startupjs/babel-plugin-ts-to-json-schema": "^0.60.0-canary.11"
|
|
52
24
|
},
|
|
53
|
-
"
|
|
25
|
+
"peerDependencies": {
|
|
26
|
+
"cssxjs": "*"
|
|
27
|
+
},
|
|
28
|
+
"gitHead": "98f7cc4f4c26816b15366986e81de0a4b996f8b1"
|
|
54
29
|
}
|
package/utils.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
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
|
+
exports.MODEL_FILENAME_REGEX = /(?:^|[.\\/])model[\\/].*\.[mc]?[jt]sx?$/
|
|
6
|
+
const STARTUPJS_FILE_CONTENT_REGEX = /['"]startupjs['"]/
|
|
7
|
+
|
|
8
|
+
exports.isStartupjsPluginEcosystemFile = filename => {
|
|
9
|
+
return (
|
|
10
|
+
exports.PLUGIN_FILENAME_REGEX.test(filename) ||
|
|
11
|
+
exports.CONFIG_FILENAME_REGEX.test(filename) ||
|
|
12
|
+
exports.LOAD_CONFIG_FILENAME_REGEX.test(filename)
|
|
13
|
+
)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
exports.isModelFile = (filename, code) => {
|
|
17
|
+
return exports.MODEL_FILENAME_REGEX.test(filename) && STARTUPJS_FILE_CONTENT_REGEX.test(code)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
exports.createStartupjsFileChecker = ({ clientOnly } = {}) => {
|
|
21
|
+
return (filename, code) => {
|
|
22
|
+
if (exports.isStartupjsPluginEcosystemFile(filename)) return true
|
|
23
|
+
if (clientOnly) {
|
|
24
|
+
if (code != null) {
|
|
25
|
+
if (exports.isModelFile(filename, code)) return true
|
|
26
|
+
} else {
|
|
27
|
+
console.warn(
|
|
28
|
+
'[babel-preset-startupjs] File\'s source code must be provided when clientOnly is true. ' +
|
|
29
|
+
'Assuming false for isModelFile check. Filename:', filename
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return false
|
|
34
|
+
}
|
|
35
|
+
}
|
package/constants.json
DELETED
package/esNextPreset.js
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
// This is the same preset as metro's, but everything which is supported
|
|
2
|
-
// by Node 14+ and latest Chrome is stripped out.
|
|
3
|
-
|
|
4
|
-
module.exports = ({ debugJsx }) => {
|
|
5
|
-
const defaultPlugins = [
|
|
6
|
-
[require('@babel/plugin-syntax-flow')],
|
|
7
|
-
[require('@babel/plugin-proposal-nullish-coalescing-operator')],
|
|
8
|
-
[require('@babel/plugin-proposal-optional-chaining'), { loose: true }],
|
|
9
|
-
[require('@babel/plugin-proposal-class-properties'), { loose: true }],
|
|
10
|
-
[require('@babel/plugin-transform-function-name')]
|
|
11
|
-
]
|
|
12
|
-
const extraPlugins = [
|
|
13
|
-
[require('@babel/plugin-transform-react-jsx')],
|
|
14
|
-
...(debugJsx
|
|
15
|
-
? [
|
|
16
|
-
require('@babel/plugin-transform-react-jsx-source'),
|
|
17
|
-
require('@babel/plugin-transform-react-jsx-self')
|
|
18
|
-
]
|
|
19
|
-
: []),
|
|
20
|
-
[
|
|
21
|
-
require('@babel/plugin-transform-runtime'),
|
|
22
|
-
{
|
|
23
|
-
helpers: true,
|
|
24
|
-
regenerator: true
|
|
25
|
-
}
|
|
26
|
-
]
|
|
27
|
-
]
|
|
28
|
-
return {
|
|
29
|
-
comments: false,
|
|
30
|
-
compact: true,
|
|
31
|
-
overrides: [
|
|
32
|
-
// the flow strip types plugin must go BEFORE class properties!
|
|
33
|
-
// there'll be a test case that fails if you don't.
|
|
34
|
-
{
|
|
35
|
-
plugins: [require('@babel/plugin-transform-flow-strip-types')]
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
plugins: defaultPlugins
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
test: isTypeScriptSource,
|
|
42
|
-
plugins: [
|
|
43
|
-
[
|
|
44
|
-
require('@babel/plugin-transform-typescript'),
|
|
45
|
-
{
|
|
46
|
-
isTSX: false,
|
|
47
|
-
allowNamespaces: true,
|
|
48
|
-
onlyRemoveTypeImports: true
|
|
49
|
-
}
|
|
50
|
-
]
|
|
51
|
-
]
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
test: isTSXSource,
|
|
55
|
-
plugins: [
|
|
56
|
-
[
|
|
57
|
-
require('@babel/plugin-transform-typescript'),
|
|
58
|
-
{
|
|
59
|
-
isTSX: true,
|
|
60
|
-
allowNamespaces: true,
|
|
61
|
-
onlyRemoveTypeImports: true
|
|
62
|
-
}
|
|
63
|
-
]
|
|
64
|
-
]
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
plugins: extraPlugins
|
|
68
|
-
}
|
|
69
|
-
]
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function isTypeScriptSource (fileName) {
|
|
74
|
-
return !!fileName && fileName.endsWith('.ts')
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function isTSXSource (fileName) {
|
|
78
|
-
return !!fileName && fileName.endsWith('.tsx')
|
|
79
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
// metro has a hardcoded config for typescript babel plugin options.
|
|
2
|
-
// Here we run the default metro preset and then find the typescript plugin and monkeypatch
|
|
3
|
-
// its options to add the required 'onlyRemoveTypeImports: true' option.
|
|
4
|
-
// Without this option pug-related and style imports are gonna get stripped by typescript.
|
|
5
|
-
const metroPreset = require('metro-react-native-babel-preset')
|
|
6
|
-
|
|
7
|
-
module.exports = (...args) => patchTypescriptOptions(metroPreset(...args))
|
|
8
|
-
|
|
9
|
-
function patchTypescriptOptions (config) {
|
|
10
|
-
for (const override of config.overrides || []) {
|
|
11
|
-
for (const plugin of override.plugins || []) {
|
|
12
|
-
if (Array.isArray(plugin) && plugin[1] && plugin[1].isTSX != null) {
|
|
13
|
-
plugin[1].onlyRemoveTypeImports = true
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
return config
|
|
18
|
-
}
|
package/pure.js
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
module.exports = (api, { platform, env } = {}) => {
|
|
2
|
-
return {
|
|
3
|
-
overrides: [{
|
|
4
|
-
test: isJsxSource,
|
|
5
|
-
plugins: [
|
|
6
|
-
// support JSX syntax
|
|
7
|
-
require('@babel/plugin-syntax-jsx')
|
|
8
|
-
]
|
|
9
|
-
}, {
|
|
10
|
-
test: isTypeScriptSource,
|
|
11
|
-
plugins: [
|
|
12
|
-
// support TypeScript syntax
|
|
13
|
-
require('@babel/plugin-syntax-typescript')
|
|
14
|
-
]
|
|
15
|
-
}, {
|
|
16
|
-
test: isTsxSource,
|
|
17
|
-
plugins: [
|
|
18
|
-
// support TypeScript + JSX syntax
|
|
19
|
-
[require('@babel/plugin-syntax-typescript'), {
|
|
20
|
-
isTSX: true
|
|
21
|
-
}]
|
|
22
|
-
]
|
|
23
|
-
}, {
|
|
24
|
-
plugins: [
|
|
25
|
-
// transform pug to jsx. This generates a bunch of new AST nodes
|
|
26
|
-
// (it's important to do this first before any dead code elimination runs)
|
|
27
|
-
[require('@startupjs/babel-plugin-transform-react-pug'), {
|
|
28
|
-
classAttribute: 'styleName'
|
|
29
|
-
}],
|
|
30
|
-
// support calling sub-components in pug (like <Modal.Header />)
|
|
31
|
-
[require('@startupjs/babel-plugin-react-pug-classnames'), {
|
|
32
|
-
classAttribute: 'styleName'
|
|
33
|
-
}],
|
|
34
|
-
// turning on experimental startupjs features
|
|
35
|
-
[require('@startupjs/babel-plugin-startupjs-utils'), {
|
|
36
|
-
observerCache: true,
|
|
37
|
-
signals: true
|
|
38
|
-
}],
|
|
39
|
-
// debugging features
|
|
40
|
-
env === 'development' && require('@startupjs/babel-plugin-startupjs-debug'),
|
|
41
|
-
// .env files support for client
|
|
42
|
-
[require('@startupjs/babel-plugin-dotenv'), (() => {
|
|
43
|
-
const envName = env === 'production' ? 'production' : 'local'
|
|
44
|
-
const options = {
|
|
45
|
-
moduleName: '@env',
|
|
46
|
-
path: ['.env', `.env.${envName}`]
|
|
47
|
-
}
|
|
48
|
-
if (platform === 'web') {
|
|
49
|
-
options.override = {
|
|
50
|
-
BASE_URL: "typeof window !== 'undefined' && window.location && window.location.origin"
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
return options
|
|
54
|
-
})()],
|
|
55
|
-
// CSS modules (separate .styl/.css file)
|
|
56
|
-
[require('@startupjs/babel-plugin-rn-stylename-to-style'), {
|
|
57
|
-
extensions: ['styl', 'css'],
|
|
58
|
-
useImport: true
|
|
59
|
-
}],
|
|
60
|
-
// inline CSS modules (styl`` in the same JSX file -- similar to how it is in Vue.js)
|
|
61
|
-
[require('@startupjs/babel-plugin-rn-stylename-inline'), {
|
|
62
|
-
platform
|
|
63
|
-
}],
|
|
64
|
-
require('@startupjs/babel-plugin-i18n-extract')
|
|
65
|
-
].filter(Boolean)
|
|
66
|
-
}]
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// all files which are not .ts or .tsx are considered to be pure JS with JSX support
|
|
71
|
-
function isJsxSource (fileName) {
|
|
72
|
-
if (!fileName) return false
|
|
73
|
-
return !isTypeScriptSource(fileName) && !isTsxSource(fileName)
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function isTypeScriptSource (fileName) {
|
|
77
|
-
if (!fileName) return false
|
|
78
|
-
return fileName.endsWith('.ts')
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// NOTE: .tsx is the default when fileName is not provided.
|
|
82
|
-
// This is because we want to support the most overarching syntax by default.
|
|
83
|
-
function isTsxSource (fileName) {
|
|
84
|
-
if (!fileName) return true
|
|
85
|
-
return fileName.endsWith('.tsx')
|
|
86
|
-
}
|