babel-preset-expo 12.0.0-preview.1 → 12.0.0-preview.3

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.
@@ -263,14 +263,94 @@ function reactServerActionsPlugin(api) {
263
263
  if (!state.file.metadata.isModuleMarkedWithUseServerDirective) {
264
264
  return;
265
265
  }
266
- // TODO: support variable functions
267
- throw path.buildCodeFrameError(`Not implemented: 'export default' declarations in "use server" files. Try using 'export { name as default }' instead.`);
266
+ // Convert `export default function foo() {}` to `function foo() {}; export { foo as default }`
267
+ if (path.node.declaration) {
268
+ if (t.isFunctionDeclaration(path.node.declaration)) {
269
+ let { id } = path.node.declaration;
270
+ if (id == null) {
271
+ const moduleScope = path.scope.getProgramParent();
272
+ const extractedIdentifier = moduleScope.generateUidIdentifier('$$INLINE_ACTION');
273
+ id = extractedIdentifier;
274
+ // Transform `async function () {}` to `async function $$INLINE_ACTION() {}`
275
+ path.node.declaration.id = extractedIdentifier;
276
+ }
277
+ const exportedSpecifier = t.exportSpecifier(id, t.identifier('default'));
278
+ path.replaceWith(path.node.declaration);
279
+ path.insertAfter(t.exportNamedDeclaration(null, [exportedSpecifier]));
280
+ }
281
+ else {
282
+ // Convert anonymous function expressions to named function expressions and export them as default.
283
+ // export default foo = async () => {}
284
+ // vvv
285
+ // const foo = async () => {}
286
+ // (() => _registerServerReference(foo, "file:///unknown", "default"))();
287
+ // export { foo as default };
288
+ if (t.isAssignmentExpression(path.node.declaration) &&
289
+ t.isArrowFunctionExpression(path.node.declaration.right)) {
290
+ if (!t.isIdentifier(path.node.declaration.left)) {
291
+ throw path.buildCodeFrameError(`Expected an assignment to an identifier but found ${path.node.declaration.left.type}.`);
292
+ }
293
+ const { left, right } = path.node.declaration;
294
+ const id = left;
295
+ const exportedSpecifier = t.exportSpecifier(id, t.identifier('default'));
296
+ // Replace `export default foo = async () => {}` with `const foo = async () => {}`
297
+ path.replaceWith(t.variableDeclaration('const', [t.variableDeclarator(id, right)]));
298
+ // Insert `(() => _registerServerReference(foo, "file:///unknown", "default"))();`
299
+ path.insertAfter(t.exportNamedDeclaration(null, [exportedSpecifier]));
300
+ }
301
+ else if (t.isArrowFunctionExpression(path.node.declaration) &&
302
+ path.node.declaration) {
303
+ // export default async () => {}
304
+ // Give the function a name
305
+ // const $$INLINE_ACTION = async () => {}
306
+ const moduleScope = path.scope.getProgramParent();
307
+ const extractedIdentifier = moduleScope.generateUidIdentifier('$$INLINE_ACTION');
308
+ // @ts-expect-error: Transform `export default async () => {}` to `const $$INLINE_ACTION = async () => {}`
309
+ path.node.declaration = t.variableDeclaration('const', [
310
+ t.variableDeclarator(extractedIdentifier, path.node.declaration),
311
+ ]);
312
+ // Strip the `export default`
313
+ path.replaceWith(path.node.declaration);
314
+ // export { $$INLINE_ACTION as default }
315
+ const exportedSpecifier = t.exportSpecifier(extractedIdentifier, t.identifier('default'));
316
+ path.insertAfter(t.exportNamedDeclaration(null, [exportedSpecifier]));
317
+ }
318
+ else if (
319
+ // Match `export default foo;`
320
+ t.isIdentifier(path.node.declaration)) {
321
+ // Ensure the `path.node.declaration` is a function or a variable for a function.
322
+ const binding = path.scope.getBinding(path.node.declaration.name);
323
+ const isServerActionType = t.isFunctionDeclaration(binding?.path.node ?? path.node.declaration) ||
324
+ t.isArrowFunctionExpression(binding?.path.node ?? path.node.declaration) ||
325
+ // `const foo = async () => {}`
326
+ (t.isVariableDeclarator(binding?.path.node) &&
327
+ t.isArrowFunctionExpression(binding?.path.node.init));
328
+ if (isServerActionType) {
329
+ // Convert `export default foo;` to `export { foo as default };`
330
+ const exportedSpecifier = t.exportSpecifier(path.node.declaration, t.identifier('default'));
331
+ path.replaceWith(t.exportNamedDeclaration(null, [exportedSpecifier]));
332
+ }
333
+ }
334
+ else {
335
+ // Unclear when this happens.
336
+ throw path.buildCodeFrameError(`Cannot create server action. Expected a assignment expression but found ${path.node.declaration.type}.`);
337
+ }
338
+ }
339
+ }
340
+ else {
341
+ // TODO: Unclear when this happens.
342
+ throw path.buildCodeFrameError(`Not implemented: 'export default' declarations in "use server" files. Try using 'export { name as default }' instead.`);
343
+ }
268
344
  },
269
345
  ExportNamedDeclaration(path, state) {
270
346
  assertExpoMetadata(state.file.metadata);
271
347
  if (!state.file.metadata.isModuleMarkedWithUseServerDirective) {
272
348
  return;
273
349
  }
350
+ // This can happen with `export {};` and TypeScript types.
351
+ if (!path.node.declaration && !path.node.specifiers.length) {
352
+ return;
353
+ }
274
354
  const registerServerReferenceId = addReactImport();
275
355
  const actionModuleId = getActionModuleId();
276
356
  const createRegisterCall = (identifier, exported = identifier) => {
@@ -287,11 +367,12 @@ function reactServerActionsPlugin(api) {
287
367
  for (const specifier of path.node.specifiers) {
288
368
  // `export * as ns from './foo';`
289
369
  if (t.isExportNamespaceSpecifier(specifier)) {
290
- throw path.buildCodeFrameError('Not implemented: Namespace exports');
370
+ throw path.buildCodeFrameError('Namespace exports for server actions are not supported. Re-export named actions instead: export { foo } from "./bar".');
291
371
  }
292
372
  else if (t.isExportDefaultSpecifier(specifier)) {
373
+ // NOTE: This is handled by ExportDefaultDeclaration
293
374
  // `export default foo;`
294
- throw path.buildCodeFrameError('Not implemented (ExportDefaultSpecifier in ExportNamedDeclaration)');
375
+ throw path.buildCodeFrameError('Internal error while extracting server actions. Expected `export default variable;` to be extracted. (ExportDefaultSpecifier in ExportNamedDeclaration)');
295
376
  }
296
377
  else if (t.isExportSpecifier(specifier)) {
297
378
  // `export { foo };`
@@ -311,9 +392,6 @@ function reactServerActionsPlugin(api) {
311
392
  }
312
393
  state.file.metadata.extractedActions.push({ localName, exportedName });
313
394
  }
314
- else {
315
- throw path.buildCodeFrameError('Not implemented: whatever this is');
316
- }
317
395
  }
318
396
  return;
319
397
  }
@@ -339,6 +417,14 @@ function reactServerActionsPlugin(api) {
339
417
  }
340
418
  return [innerPath.get('id').node];
341
419
  }
420
+ else if (
421
+ // TypeScript type exports
422
+ innerPath.isTypeAlias() ||
423
+ innerPath.isTSDeclareFunction() ||
424
+ innerPath.isTSInterfaceDeclaration() ||
425
+ innerPath.isTSTypeAliasDeclaration()) {
426
+ return [];
427
+ }
342
428
  else {
343
429
  throw innerPath.buildCodeFrameError(`Unimplemented server action export`);
344
430
  }
@@ -17,6 +17,7 @@ function expoUseDomDirectivePlugin(api) {
17
17
  // TODO: Is exporting
18
18
  const isProduction = api.caller(common_1.getIsProd);
19
19
  const platform = api.caller((caller) => caller?.platform);
20
+ const projectRoot = api.caller(common_1.getPossibleProjectRoot);
20
21
  return {
21
22
  name: 'expo-use-dom-directive',
22
23
  visitor: {
@@ -59,6 +60,23 @@ function expoUseDomDirectivePlugin(api) {
59
60
  if (!hasDefaultExport) {
60
61
  throw path.buildCodeFrameError('The "use dom" directive requires a default export to be present in the file.');
61
62
  }
63
+ // Assert that _layout routes cannot be used in DOM components.
64
+ const fileBasename = (0, path_1.basename)(filePath);
65
+ if (projectRoot &&
66
+ // Detecting if the file is in the router root would be extensive as it would cause a more complex
67
+ // cache key for each file. Instead, let's just check if the file is in the project root and is not a node_module,
68
+ // then we can assert that users should not use `_layout` or `+api` with "use dom".
69
+ filePath.includes(projectRoot) &&
70
+ !filePath.match(/node_modules/)) {
71
+ if (fileBasename.match(/^_layout\.[jt]sx?$/)) {
72
+ throw path.buildCodeFrameError('Layout routes cannot be marked as DOM components because they cannot render native views.');
73
+ }
74
+ else if (
75
+ // No API routes
76
+ fileBasename.match(/\+api\.[jt]sx?$/)) {
77
+ throw path.buildCodeFrameError('API routes cannot be marked as DOM components.');
78
+ }
79
+ }
62
80
  const outputKey = url_1.default.pathToFileURL(filePath).href;
63
81
  const proxyModule = [
64
82
  `import React from 'react';`,
@@ -81,7 +99,7 @@ function expoUseDomDirectivePlugin(api) {
81
99
  else {
82
100
  proxyModule.push(
83
101
  // Add the basename to improve the Safari debug preview option.
84
- `const source = { uri: new URL("/_expo/@dom/${(0, path_1.basename)(filePath)}?file=" + ${JSON.stringify(outputKey)}, require("react-native/Libraries/Core/Devtools/getDevServer")().url).toString() };`);
102
+ `const source = { uri: new URL("/_expo/@dom/${fileBasename}?file=" + ${JSON.stringify(outputKey)}, require("react-native/Libraries/Core/Devtools/getDevServer")().url).toString() };`);
85
103
  }
86
104
  proxyModule.push(`
87
105
  export default React.forwardRef((props, ref) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "babel-preset-expo",
3
- "version": "12.0.0-preview.1",
3
+ "version": "12.0.0-preview.3",
4
4
  "description": "The Babel preset for Expo projects",
5
5
  "main": "build/index.js",
6
6
  "files": [
@@ -47,7 +47,7 @@
47
47
  "@babel/plugin-transform-parameters": "^7.22.15",
48
48
  "@babel/preset-react": "^7.22.15",
49
49
  "@babel/preset-typescript": "^7.23.0",
50
- "@react-native/babel-preset": "0.76.0",
50
+ "@react-native/babel-preset": "0.76.1",
51
51
  "babel-plugin-react-native-web": "~0.19.13",
52
52
  "react-refresh": "^0.14.2"
53
53
  },
@@ -70,5 +70,5 @@
70
70
  "jest": "^29.2.1",
71
71
  "react-compiler-runtime": "^19.0.0-beta-8a03594-20241020"
72
72
  },
73
- "gitHead": "0a07b965c4bef67e7718355a0dc770d524ad3cee"
73
+ "gitHead": "d5b7ec4949eb461634b2f02a1a0ff1df2a0e2a21"
74
74
  }