Skip to content
This repository has been archived by the owner on Jan 18, 2024. It is now read-only.

Commit

Permalink
Added currentFullName to the public config (#3376)
Browse files Browse the repository at this point in the history
* Added `currentFullName` to the public config

* Update User.ts
  • Loading branch information
EvanBacon authored Apr 8, 2021
1 parent 095c95f commit d9d4248
Show file tree
Hide file tree
Showing 8 changed files with 176 additions and 31 deletions.
5 changes: 5 additions & 0 deletions packages/config/__mocks__/os.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const os = jest.requireActual('os');

os.homedir = jest.fn(() => '/home');

module.exports = os;
5 changes: 5 additions & 0 deletions packages/config/src/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
import { ConfigError } from './Errors';
import { getExpoSDKVersion } from './Project';
import { getDynamicConfig, getStaticConfig } from './getConfig';
import { getCurrentFullName } from './getCurrentFullName';
import { withConfigPlugins } from './plugins/withConfigPlugins';
import { withInternal } from './plugins/withInternal';
import { getRootPackageJsonPath } from './resolvePackageJson';
Expand Down Expand Up @@ -141,6 +142,10 @@ export function getConfig(projectRoot: string, options: GetConfigOptions = {}):
if (configWithDefaultValues.exp.android?.config) {
delete configWithDefaultValues.exp.android.config;
}

// This value will be overwritten when the manifest is being served from the host (i.e. not completely accurate).
// @ts-ignore: currentFullName not on type yet.
configWithDefaultValues.exp.currentFullName = getCurrentFullName(configWithDefaultValues.exp);
}

return configWithDefaultValues;
Expand Down
8 changes: 5 additions & 3 deletions packages/config/src/__tests__/ConfigParsing-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ describe(getConfig, () => {
// - generated `.expo` object is created and the language hint is added
describe('language support', () => {
beforeEach(() => {
delete process.env.EXPO_DEBUG;
const projectRoot = 'js';
setCustomConfigPath(projectRoot, undefined);
});
Expand All @@ -109,7 +110,7 @@ describe(getConfig, () => {
expect(exp.name).toBe('rewrote+ts-config-test');
expect(exp._internal).toStrictEqual({
dynamicConfigPath: 'ts/app.config.ts',
isDebug: true,
isDebug: false,
packageJsonPath: 'ts/package.json',
projectRoot: 'ts',
staticConfigPath: null,
Expand All @@ -132,7 +133,7 @@ describe(getConfig, () => {
expect(exp.slug).toBe('someslug+config');
expect(exp._internal).toStrictEqual({
dynamicConfigPath: 'js/app.config.js',
isDebug: true,
isDebug: false,
packageJsonPath: 'js/package.json',
projectRoot: 'js',
staticConfigPath: 'js/app.json',
Expand Down Expand Up @@ -166,6 +167,7 @@ describe(getConfig, () => {

describe('behavior', () => {
beforeEach(() => {
delete process.env.EXPO_DEBUG;
resetCustomConfigPaths();
});

Expand Down Expand Up @@ -209,7 +211,7 @@ describe(getConfig, () => {

expect(exp._internal).toStrictEqual({
dynamicConfigPath: null,
isDebug: true,
isDebug: false,
packageJsonPath: 'custom-location-json/package.json',
projectRoot: 'custom-location-json',
staticConfigPath: 'custom-location-json/src/app.staging.json',
Expand Down
47 changes: 47 additions & 0 deletions packages/config/src/__tests__/getCurrentFullName-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { ensureDir } from 'fs-extra';

import { getAccountUsername } from '../getCurrentFullName';
import { getExpoHomeDirectory, getUserState } from '../getUserState';

jest.mock('os');
jest.mock('fs');

describe(getAccountUsername, () => {
beforeEach(() => {
delete process.env.EXPO_CLI_USERNAME;
delete process.env.EAS_BUILD_USERNAME;
});

it(`gets the account name from EXPO_CLI_USERNAME`, () => {
process.env.EXPO_CLI_USERNAME = 'expo-cli-username';
process.env.EAS_BUILD_USERNAME = 'eas-build-username';
expect(getAccountUsername()).toBe('expo-cli-username');
});
it(`gets the account name from EAS_BUILD_USERNAME`, () => {
process.env.EAS_BUILD_USERNAME = 'eas-build-username';
expect(getAccountUsername()).toBe('eas-build-username');
});
it(`gets the account name from owner`, () => {
process.env.EXPO_CLI_USERNAME = 'expo-cli-username';
process.env.EAS_BUILD_USERNAME = 'eas-build-username';
expect(getAccountUsername({ owner: 'owner-username' })).toBe('owner-username');
});
it(`gets the account name from owner 2`, () => {
expect(getAccountUsername({ owner: 'owner-username' })).toBe('owner-username');
});
it(`uses anonymous name`, () => {
// Ensure the test doesn't interact with the developer's state.json
expect(getExpoHomeDirectory()).toBe('/home/.expo');
expect(getAccountUsername()).toBe('anonymous');
});
it(`uses previously authenticated username`, async () => {
// Ensure the test doesn't interact with the developer's state.json
expect(getExpoHomeDirectory()).toBe('/home/.expo');
// Ensure the dir exists
await ensureDir(getExpoHomeDirectory());
// Set a username...
await getUserState().setAsync('auth', { username: 'bacon-boi' });
// Check the username...
expect(getAccountUsername()).toBe('bacon-boi');
});
});
28 changes: 28 additions & 0 deletions packages/config/src/__tests__/getUserState-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { getExpoHomeDirectory } from '../getUserState';

jest.mock('os');
jest.mock('fs');

describe(getExpoHomeDirectory, () => {
beforeEach(() => {
delete process.env.__UNSAFE_EXPO_HOME_DIRECTORY;
delete process.env.EXPO_STAGING;
delete process.env.EXPO_LOCAL;
});

it(`gets the default state directory`, () => {
expect(getExpoHomeDirectory()).toBe('/home/.expo');
});
it(`gets the staging state directory`, () => {
process.env.EXPO_STAGING = 'true';
expect(getExpoHomeDirectory()).toBe('/home/.expo-staging');
});
it(`gets the local state directory`, () => {
process.env.EXPO_LOCAL = 'true';
expect(getExpoHomeDirectory()).toBe('/home/.expo-local');
});
it(`gets the custom state directory`, () => {
process.env.__UNSAFE_EXPO_HOME_DIRECTORY = '/foobar/yolo';
expect(getExpoHomeDirectory()).toBe('/foobar/yolo');
});
});
28 changes: 28 additions & 0 deletions packages/config/src/getCurrentFullName.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { ExpoConfig } from '@expo/config-types';

import { getUserState } from './getUserState';

const ANONYMOUS_USERNAME = 'anonymous';

/**
* Used in expo-constants to generate the `id` property statically for an app in custom managed workflow.
* This `id` is used for legacy Expo services AuthSession proxy and Expo notifications device ID.
*
* @param manifest
* @returns
*/
export function getCurrentFullName(manifest: Pick<ExpoConfig, 'owner' | 'slug'>): string {
const username = getAccountUsername(manifest);
return `@${username}/${manifest.slug}`;
}

export function getAccountUsername(manifest: Pick<ExpoConfig, 'owner'> = {}): string {
// TODO: Must match what's generated in Expo Go.
const username =
manifest.owner || process.env.EXPO_CLI_USERNAME || process.env.EAS_BUILD_USERNAME;
if (username) {
return username;
}
// Statically get the username from the global user state.
return getUserState().read().auth?.username || ANONYMOUS_USERNAME;
}
58 changes: 58 additions & 0 deletions packages/config/src/getUserState.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import JsonFile from '@expo/json-file';
import { boolish } from 'getenv';
import { homedir } from 'os';
import * as path from 'path';

export type UserSettingsData = {
developmentCodeSigningId?: string;
appleId?: string;
accessToken?: string;
auth?: UserData | null;
ignoreBundledBinaries?: string[];
openDevToolsAtStartup?: boolean;
PATH?: string;
sendTo?: string;
uuid?: string;
};

export type UserData = {
appleId?: string;
userId?: string;
username?: string;
currentConnection?: ConnectionType;
sessionSecret?: string;
};

export type ConnectionType =
| 'Access-Token-Authentication'
| 'Username-Password-Authentication'
| 'facebook'
| 'google-oauth2'
| 'github';

// The ~/.expo directory is used to store authentication sessions,
// which are shared between EAS CLI and Expo CLI.
export function getExpoHomeDirectory() {
const home = homedir();

if (process.env.__UNSAFE_EXPO_HOME_DIRECTORY) {
return process.env.__UNSAFE_EXPO_HOME_DIRECTORY;
} else if (boolish('EXPO_STAGING', false)) {
return path.join(home, '.expo-staging');
} else if (boolish('EXPO_LOCAL', false)) {
return path.join(home, '.expo-local');
}
return path.join(home, '.expo');
}

export function getUserStatePath() {
return path.join(getExpoHomeDirectory(), 'state.json');
}

export function getUserState() {
return new JsonFile<UserSettingsData>(getUserStatePath(), {
jsonParseErrorDefault: {},
// This will ensure that an error isn't thrown if the file doesn't exist.
cantReadFileDefault: {},
});
}
28 changes: 0 additions & 28 deletions packages/xdl/src/User.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { ExpoConfig } from '@expo/config-types';
import camelCase from 'lodash/camelCase';
import isEmpty from 'lodash/isEmpty';
import snakeCase from 'lodash/snakeCase';
Expand Down Expand Up @@ -290,33 +289,6 @@ export class UserManagerInstance {
return user;
}

/**
* Used in expo-constants to generate the `id` property statically for an app in custom managed workflow.
* This `id` is used for legacy Expo services AuthSession proxy and Expo notifications device ID.
*
* @param manifest
* @returns
*/
async getProjectCurrentFullNameAsync(manifest: ExpoConfig): Promise<string> {
const username = await this.getProjectAccountNameAsync(manifest);
return `@${username}/${manifest.slug}`;
}

async getProjectAccountNameAsync(manifest: ExpoConfig): Promise<string> {
// TODO: Must match what's generated in Expo Go.
if (manifest.owner) {
return manifest.owner;
} else if (process.env.EAS_BUILD_USERNAME) {
return process.env.EAS_BUILD_USERNAME;
} else if (!ConnectionStatus.isOffline()) {
const username = await this.getCurrentUsernameAsync();
if (username) {
return username;
}
}
return ANONYMOUS_USERNAME;
}

async getCurrentUsernameAsync(): Promise<string | null> {
const token = UserSettings.accessToken();
if (token) {
Expand Down

0 comments on commit d9d4248

Please sign in to comment.