Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/@expo/config-plugins/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
### 🐛 Bug fixes

- Fix `getApplicationIdAsync` and `setPackageInBuildGradle` failing with the Gradle assignment syntax (`applicationId = '...'`). ([#47711](https://github.com/expo/expo/pull/47711) by [@idoyana](https://github.com/idoyana))
- [iOS] Quote and escape keys and values written to `.strings` files. ([#49605](https://github.com/expo/expo/pull/49605) by [@jakex7](https://github.com/jakex7))

### 💡 Others

Expand Down
8 changes: 7 additions & 1 deletion packages/@expo/config-plugins/src/ios/Locales.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ export const withLocales: ConfigPlugin = (config) => {
});
};

function escapeStringsLiteral(value: string): string {
return value.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n');
}

export async function writeStringsFile({
localesMap,
supportingDirectory,
Expand All @@ -40,7 +44,9 @@ export async function writeStringsFile({
const strings = path.join(dir, fileName);
const buffer = [];
for (const [plistKey, localVersion] of Object.entries(localizationObj)) {
buffer.push(`${plistKey} = "${localVersion}";`);
buffer.push(
`"${escapeStringsLiteral(plistKey)}" = "${escapeStringsLiteral(String(localVersion))}";`
);
}
// Write the file to the file system.
await fs.promises.writeFile(strings, buffer.join('\n'));
Expand Down
22 changes: 16 additions & 6 deletions packages/@expo/config-plugins/src/ios/__tests__/Locales-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ describe('e2e: iOS locales', () => {
ios: {
'Localizable.strings': {
NOTIF_KEY: 'de-notification',
'Sample Widget': 'DE Sample Widget',
'A sample widget.': 'DE A sample widget.',
'A "quoted" key': 'DE A "quoted" key',
},
},
android: {
Expand Down Expand Up @@ -125,18 +128,25 @@ describe('e2e: iOS locales', () => {
expect(after[infoPlists[0]!]).toMatchSnapshot();
// Test that the inlined locale is resolved.
expect(after[infoPlists[1]!]).toMatch(/spanish-name/);
expect(after[infoPlists[2]!]).toMatchInlineSnapshot(`"CFBundleDisplayName = "us-name";"`);
expect(after[infoPlists[2]!]).toMatchInlineSnapshot(`""CFBundleDisplayName" = "us-name";"`);
expect(after[infoPlists[3]!]).toMatchInlineSnapshot(`
"CFBundleDisplayName = "us-name";
app_name = "us-name";"
""CFBundleDisplayName" = "us-name";
"app_name" = "us-name";"
`);
expect(after[infoPlists[4]!]).toMatchInlineSnapshot(`"CFBundleDisplayName = "ar-name";"`);
expect(after[infoPlists[4]!]).toMatchInlineSnapshot(`""CFBundleDisplayName" = "ar-name";"`);
expect(localizableStrings).toStrictEqual([
'ios/testproject/Supporting/ar.lproj/Localizable.strings',
'ios/testproject/Supporting/de.lproj/Localizable.strings',
]);
expect(after[localizableStrings[0]!]).toMatchInlineSnapshot(`"NOTIF_KEY = "ar-notification";"`);
expect(after[localizableStrings[1]!]).toMatchInlineSnapshot(`"NOTIF_KEY = "de-notification";"`);
expect(after[localizableStrings[0]!]).toMatchInlineSnapshot(
`""NOTIF_KEY" = "ar-notification";"`
);
expect(after[localizableStrings[1]!]).toMatchInlineSnapshot(`
""NOTIF_KEY" = "de-notification";
"Sample Widget" = "DE Sample Widget";
"A sample widget." = "DE A sample widget.";
"A \\"quoted\\" key" = "DE A \\"quoted\\" key";"
`);

// Test a warning is thrown for an invalid locale JSON file.
expect(WarningAggregator.addWarningForPlatform).toHaveBeenCalledWith(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`e2e: iOS locales writes all the image files expected 1`] = `"CFBundleDisplayName = "french-name";"`;
exports[`e2e: iOS locales writes all the image files expected 1`] = `""CFBundleDisplayName" = "french-name";"`;
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ describe('built-in plugins', () => {
expect(after['ios/HelloWorld/Info.plist']).toMatch('UIApplicationSceneManifest');
expect(after['ios/HelloWorld/Info.plist']).toMatch('$(PRODUCT_MODULE_NAME).SceneDelegate');
expect(after['ios/HelloWorld/Supporting/en.lproj/InfoPlist.strings']).toMatch(
/foo = "uhh bar"/
/"foo" = "uhh bar"/
);
expect(after['ios/HelloWorld/GoogleService-Info.plist']).toBe(googleServiceInfoFixture);

Expand Down
6 changes: 6 additions & 0 deletions packages/create-expo-module/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,14 @@
"build"
],
"main": "build/index.js",
"exports": {
".": "./build/index.js",
"./package.json": "./package.json"
},
"scripts": {
"prebuild": "expo-module clean",
"build": "ncc build ./src/index.ts -o build/",
"prebuild:prod": "expo-module clean",
"build:prod": "ncc build ./src/index.ts -o build/ --minify --no-cache --no-source-map-register",
"clean": "expo-module clean",
"lint": "oxlint --config oxlint.config.mjs .",
Expand Down
19 changes: 14 additions & 5 deletions packages/create-expo-module/src/create-expo-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,16 @@ import { findGitHubEmail, findMyName } from './utils/git';
import { findGitHubUserFromEmail, guessRepoUrl } from './utils/github';
import { newStep } from './utils/ora';

const PACKAGE_NAME = 'create-expo-module';
const debug = require('debug')('create-expo-module:main') as typeof console.log;
const packageJson = require('../package.json');

const getPackageJson = () => {
try {
return require('create-expo-module/package.json');
} catch {
return null;
}
};

// `yarn run` may change the current working dir, then we should use `INIT_CWD` env.
const CWD = process.env.INIT_CWD || process.cwd();
Expand Down Expand Up @@ -462,7 +470,8 @@ async function createGitRepositoryAsync(targetDir: string) {
await spawnAsync('git', ['init'], { stdio: 'ignore', cwd: targetDir });
await spawnAsync('git', ['add', '-A'], { stdio: 'ignore', cwd: targetDir });

const commitMsg = `Initial commit\n\nGenerated by ${packageJson.name} ${packageJson.version}.`;
const pkg = getPackageJson();
const commitMsg = `Initial commit\n\nGenerated by ${pkg?.name ?? PACKAGE_NAME} ${pkg?.version ?? '0.0.0'}.`;
await spawnAsync('git', ['commit', '-m', commitMsg], {
stdio: 'ignore',
cwd: targetDir,
Expand Down Expand Up @@ -875,9 +884,9 @@ const program = new Command();
program.enablePositionalOptions();

program
.name(packageJson.name)
.version(packageJson.version)
.description(packageJson.description)
.name(getPackageJson()?.name ?? PACKAGE_NAME)
.version(getPackageJson()?.version ?? '0.0.0')
.description(getPackageJson()?.description ?? '')
.arguments('[path]')
.option(
'-s, --source <source_dir>',
Expand Down
12 changes: 9 additions & 3 deletions packages/create-expo-module/src/telemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ import path from 'node:path';
import type { CommandOptions } from './types';
import { env } from './utils/env';

const packageJson = require('../package.json');
const getPackageJson = () => {
try {
return require('create-expo-module/package.json');
} catch {
return null;
}
};

/** The telemetry client instance to use */
let client: TelemetryClient | null = null;
Expand Down Expand Up @@ -79,7 +85,7 @@ function getTelemetryContext() {

return {
os: { name: PLATFORM_NAMES[os.platform()] ?? os.platform(), version: os.release() },
app: { name: 'create-expo-module', version: packageJson.version ?? undefined },
app: { name: 'create-expo-module', version: getPackageJson()?.version ?? undefined },
};
}

Expand All @@ -100,7 +106,7 @@ export async function logEventAsync(event: Event) {

const commonProperties = {
source: 'create-expo-module',
source_version: packageJson.version ?? undefined,
source_version: getPackageJson()?.version ?? undefined,
};

getTelemetryClient().track({
Expand Down
1 change: 1 addition & 0 deletions packages/create-expo/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

- Support npm@12's dictionary-based `npm pack --json` format ([#48761](https://github.com/expo/expo/pull/48761) by [@kitten](https://github.com/kitten))
- Print the "make sure you have modules installed" warning when the dependency install fails ([#48929](https://github.com/expo/expo/issues/48929)) ([#48946](https://github.com/expo/expo/pull/48946) by [@expo-bot](https://github.com/expo-bot))
- [Internal] Fix sporadic `ncc` build failures ([#49615](https://github.com/expo/expo/pull/49615) by [@kitten](https://github.com/kitten))

### 💡 Others

Expand Down
8 changes: 7 additions & 1 deletion packages/create-expo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,15 @@
"build",
"template"
],
"main": "build",
"main": "build/index.js",
"exports": {
".": "./build/index.js",
"./package.json": "./package.json"
},
"scripts": {
"prebuild": "expo-module clean",
"build": "ncc build ./src/index.ts -o build/",
"prebuild:prod": "expo-module clean",
"build:prod": "ncc build ./src/index.ts -o build/ --minify --no-cache --no-source-map-register",
"clean": "expo-module clean",
"lint": "oxlint --config oxlint.config.mjs .",
Expand Down
18 changes: 13 additions & 5 deletions packages/create-expo/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,22 @@
import type { Spec } from 'arg';
import chalk from 'chalk';

import { CLI_NAME } from './cmd';
import { ExitError } from './error';
import { Log } from './log';
import { formatSelfCommand } from './resolvePackageManager';
import { assertWithOptionsArgs, printHelp, resolveStringOrBooleanArgsAsync } from './utils/args';
import { PACKAGE_NAME } from './utils/update-check';

const debug = require('debug')('expo:init:cli') as typeof console.log;

const getPackageJson = () => {
try {
return require('create-expo/package.json');
} catch {
return null;
}
};

async function run() {
const argv = process.argv.slice(2) ?? [];
const rawArgsMap: Spec = {
Expand All @@ -30,14 +38,14 @@ async function run() {
});

if (args['--version']) {
Log.exit(require('../package.json').version, 0);
Log.exit(getPackageJson()?.version ?? '0.0.0', 0);
}

if (args['--help']) {
const nameWithoutCreate = CLI_NAME.replace('create-', '');
const nameWithoutCreate = PACKAGE_NAME.replace('create-', '');
printHelp(
`Creates a new Expo project`,
chalk`npx ${CLI_NAME} {cyan <path>} [options]`,
chalk`npx ${PACKAGE_NAME} {cyan <path>} [options]`,
[
`-y, --yes Use the default options for creating a project`,
` --no-install Skip installing npm packages or CocoaPods`,
Expand All @@ -60,7 +68,7 @@ async function run() {
{gray The package manager used for installing}
{gray node modules is based on how you invoke the CLI:}

{bold npm:} {cyan npx ${CLI_NAME}}
{bold npm:} {cyan npx ${PACKAGE_NAME}}
{bold yarn:} {cyan yarn create ${nameWithoutCreate}}
{bold pnpm:} {cyan pnpm create ${nameWithoutCreate}}
{bold bun:} {cyan bun create ${nameWithoutCreate}}
Expand Down
1 change: 0 additions & 1 deletion packages/create-expo/src/cmd.ts

This file was deleted.

4 changes: 2 additions & 2 deletions packages/create-expo/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
import Debug from 'debug';
import { boolish } from 'getenv';

import { CLI_NAME } from './cmd';
import { PACKAGE_NAME } from './utils/update-check';

// Set the title of the process
process.title = CLI_NAME;
process.title = PACKAGE_NAME;

// Setup before requiring `debug`.
if (boolish('EXPO_DEBUG', false)) {
Expand Down
10 changes: 5 additions & 5 deletions packages/create-expo/src/resolvePackageManager.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as PackageManager from '@expo/package-manager';
import { execSync } from 'child_process';

import { CLI_NAME } from './cmd';
import { PACKAGE_NAME } from './utils/update-check';

export type PackageManagerName = 'npm' | 'pnpm' | 'yarn' | 'bun' | 'nub';

Expand Down Expand Up @@ -66,15 +66,15 @@ export function formatSelfCommand() {
const packageManager = resolvePackageManager();
switch (packageManager) {
case 'pnpm':
return `pnpx ${CLI_NAME}`;
return `pnpx ${PACKAGE_NAME}`;
case 'bun':
return `bunx ${CLI_NAME}`;
return `bunx ${PACKAGE_NAME}`;
case 'nub':
return `nubx ${CLI_NAME}`;
return `nubx ${PACKAGE_NAME}`;
case 'yarn':
case 'npm':
default:
return `npx ${CLI_NAME}`;
return `npx ${PACKAGE_NAME}`;
}
}

Expand Down
13 changes: 10 additions & 3 deletions packages/create-expo/src/telemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,20 @@ import os from 'os';
import { dotExpoHomeDirectory, getStateJsonPath } from './paths';
import { getSession } from './sessionStorage';
import { env } from './utils/env';
import { PACKAGE_NAME } from './utils/update-check';

const packageJSON = require('../package.json');
const getPackageJson = () => {
try {
return require('create-expo/package.json');
} catch {
return null;
}
};

const xdlUnifiedWriteKey = '1wabJGd5IiuF9Q8SGlcI90v8WTs';
const analyticsEndpoint = 'https://cdp.expo.dev/v1/batch';
const version = '1.0.0';
const library = packageJSON.name;
const library = PACKAGE_NAME;

//#region mostly copied from @expo/rudder-sdk-node https://github.com/expo/rudder-sdk-node/blob/main/index.ts
// some changes include:
Expand Down Expand Up @@ -177,7 +184,7 @@ function getAnalyticsContext(): Record<string, any> {
return {
os: { name: platform, version: os.release() },
device: { type: platform, model: platform },
app: { name: library, version: packageJSON.version },
app: { name: library, version: getPackageJson()?.version ?? undefined },
};
}
//#endregion
Expand Down
13 changes: 11 additions & 2 deletions packages/create-expo/src/utils/git.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,18 @@ import chalk from 'chalk';
import prompts from 'prompts';

import { env } from './env';
import { PACKAGE_NAME } from './update-check';

const debug = require('debug')('expo:init:git') as typeof console.log;

const getPackageJson = () => {
try {
return require('create-expo/package.json');
} catch {
return null;
}
};

/** Check if the given directory is inside an existing git repository */
async function isInsideGitRepoAsync(root: string): Promise<boolean> {
try {
Expand Down Expand Up @@ -59,14 +68,14 @@ export async function initGitRepoAsync(root: string) {
debug(chalk.dim('User chose to initialize git inside existing repo.'));
}

const packageJSON = require('../package.json');
const packageJSON = getPackageJson();

// not in git tree, so let's init
try {
await spawnAsync('git', ['init'], { stdio: 'ignore', cwd: root });
await spawnAsync('git', ['add', '-A'], { stdio: 'ignore', cwd: root });

const commitMsg = `Initial commit\n\nGenerated by ${packageJSON.name} ${packageJSON.version}.`;
const commitMsg = `Initial commit\n\nGenerated by ${packageJSON?.name ?? PACKAGE_NAME} ${packageJSON?.version ?? '0.0.0'}.`;
await spawnAsync('git', ['commit', '-m', commitMsg], {
stdio: 'ignore',
cwd: root,
Expand Down
21 changes: 17 additions & 4 deletions packages/create-expo/src/utils/update-check.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,30 @@
import chalk from 'chalk';
import checkForUpdate from 'update-check';

const packageJson = require('../package.json');
export const PACKAGE_NAME = 'create-expo';

const getPackageJson = () => {
try {
return require('create-expo/package.json');
} catch {
return null;
}
};

const debug = require('debug')('expo:init:update-check') as typeof console.log;

export default async function shouldUpdate(): Promise<void> {
try {
const res = await checkForUpdate(packageJson);
const pkg = getPackageJson();
const res = await checkForUpdate(pkg);
if (res?.latest) {
console.log();
console.log(chalk.yellow.bold(`A new version of \`${packageJson.name}\` is available`));
console.log(chalk`You can update by running: {cyan npm install -g ${packageJson.name}}`);
console.log(
chalk.yellow.bold(`A new version of \`${pkg?.name ?? PACKAGE_NAME}\` is available`)
);
console.log(
chalk`You can update by running: {cyan npm install -g ${pkg?.name ?? PACKAGE_NAME}}`
);
console.log();
}
} catch (error: any) {
Expand Down
Loading
Loading