From b79645ab9617d1e4846b2719e16deaa7c9802f09 Mon Sep 17 00:00:00 2001 From: Timothy Leung Date: Thu, 8 Feb 2024 16:59:16 +0000 Subject: [PATCH] Create foundry.config.json in create-app --- .../foundry.config.json | 11 ++++ .../foundry.config.json | 11 ++++ .../expected-template-vue/foundry.config.json | 11 ++++ packages/create-app/src/cli.test.ts | 2 + packages/create-app/src/cli.ts | 14 +++++ .../generateFoundryConfigJson.test.ts | 42 ++++++++++++++ .../src/generate/generateFoundryConfigJson.ts | 41 ++++++++++++++ .../src/prompts/promptApplicationRid.test.ts | 55 +++++++++++++++++++ .../src/prompts/promptApplicationRid.ts | 44 +++++++++++++++ packages/create-app/src/templates.ts | 4 ++ 10 files changed, 235 insertions(+) create mode 100644 packages/create-app/src/__snapshots__/expected-template-next-static-export/foundry.config.json create mode 100644 packages/create-app/src/__snapshots__/expected-template-react/foundry.config.json create mode 100644 packages/create-app/src/__snapshots__/expected-template-vue/foundry.config.json create mode 100644 packages/create-app/src/generate/generateFoundryConfigJson.test.ts create mode 100644 packages/create-app/src/generate/generateFoundryConfigJson.ts create mode 100644 packages/create-app/src/prompts/promptApplicationRid.test.ts create mode 100644 packages/create-app/src/prompts/promptApplicationRid.ts diff --git a/packages/create-app/src/__snapshots__/expected-template-next-static-export/foundry.config.json b/packages/create-app/src/__snapshots__/expected-template-next-static-export/foundry.config.json new file mode 100644 index 000000000..4fa0f3115 --- /dev/null +++ b/packages/create-app/src/__snapshots__/expected-template-next-static-export/foundry.config.json @@ -0,0 +1,11 @@ +{ + "foundryUrl": "https://example.palantirfoundry.com", + "site": { + "application": "ri.third-party-applications.main.application.fake", + "directory": "./out", + "autoVersion": { + "type": "git-describe", + "tagPrefix": "tag-prefix" + } + } +} diff --git a/packages/create-app/src/__snapshots__/expected-template-react/foundry.config.json b/packages/create-app/src/__snapshots__/expected-template-react/foundry.config.json new file mode 100644 index 000000000..9e1276f5f --- /dev/null +++ b/packages/create-app/src/__snapshots__/expected-template-react/foundry.config.json @@ -0,0 +1,11 @@ +{ + "foundryUrl": "https://example.palantirfoundry.com", + "site": { + "application": "ri.third-party-applications.main.application.fake", + "directory": "./dist", + "autoVersion": { + "type": "git-describe", + "tagPrefix": "tag-prefix" + } + } +} diff --git a/packages/create-app/src/__snapshots__/expected-template-vue/foundry.config.json b/packages/create-app/src/__snapshots__/expected-template-vue/foundry.config.json new file mode 100644 index 000000000..9e1276f5f --- /dev/null +++ b/packages/create-app/src/__snapshots__/expected-template-vue/foundry.config.json @@ -0,0 +1,11 @@ +{ + "foundryUrl": "https://example.palantirfoundry.com", + "site": { + "application": "ri.third-party-applications.main.application.fake", + "directory": "./dist", + "autoVersion": { + "type": "git-describe", + "tagPrefix": "tag-prefix" + } + } +} diff --git a/packages/create-app/src/cli.test.ts b/packages/create-app/src/cli.test.ts index 9814e1127..a32cac320 100644 --- a/packages/create-app/src/cli.test.ts +++ b/packages/create-app/src/cli.test.ts @@ -57,6 +57,8 @@ for (const template of TEMPLATES) { "https://example.palantirfoundry.com", "--application-url", "https://app.example.palantirfoundry.com", + "--application", + "ri.third-party-applications.main.application.fake", "--client-id", "123", "--osdk-package", diff --git a/packages/create-app/src/cli.ts b/packages/create-app/src/cli.ts index c6fc0b040..b481de5d0 100644 --- a/packages/create-app/src/cli.ts +++ b/packages/create-app/src/cli.ts @@ -27,8 +27,10 @@ import { generateEnvDevelopment, generateEnvProduction, } from "./generate/generateEnv.js"; +import { generateFoundryConfigJson } from "./generate/generateFoundryConfigJson.js"; import { generateNpmRc } from "./generate/generateNpmRc.js"; import { green } from "./highlight.js"; +import { promptApplicationRid } from "./prompts/promptApplicationRid.js"; import { promptApplicationUrl } from "./prompts/promptApplicationUrl.js"; import { promptClientId } from "./prompts/promptClientId.js"; import { promptFoundryUrl } from "./prompts/promptFoundryUrl.js"; @@ -46,6 +48,7 @@ interface CliArgs { foundryUrl?: string; applicationUrl?: string; skipApplicationUrl?: boolean; + application?: string; clientId?: string; osdkPackage?: string; osdkRegistryUrl?: string; @@ -86,6 +89,10 @@ export async function cli(args: string[] = process.argv) { describe: "Skip filling in URL the production application will be hosted on", }) + .option("application", { + type: "string", + describe: "Application resource identifier (rid)", + }) .option("client-id", { type: "string", describe: "OAuth client ID for application", @@ -106,6 +113,7 @@ export async function cli(args: string[] = process.argv) { const template: Template = await promptTemplate(parsed); const foundryUrl: string = await promptFoundryUrl(parsed); const applicationUrl: string | undefined = await promptApplicationUrl(parsed); + const application: string = await promptApplicationRid(parsed); const clientId: string = await promptClientId(parsed); const osdkPackage: string = await promptOsdkPackage(parsed); const osdkRegistryUrl: string = await promptOsdkRegistryUrl(parsed); @@ -183,6 +191,12 @@ export async function cli(args: string[] = process.argv) { clientId, }); fs.writeFileSync(path.join(root, ".env.production"), envProduction); + const foundryConfigJson = generateFoundryConfigJson({ + foundryUrl, + application, + directory: template.buildDirectory, + }); + fs.writeFileSync(path.join(root, "foundry.config.json"), foundryConfigJson); consola.success("Success"); diff --git a/packages/create-app/src/generate/generateFoundryConfigJson.test.ts b/packages/create-app/src/generate/generateFoundryConfigJson.test.ts new file mode 100644 index 000000000..e85c2200b --- /dev/null +++ b/packages/create-app/src/generate/generateFoundryConfigJson.test.ts @@ -0,0 +1,42 @@ +/* + * Copyright 2023 Palantir Technologies, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { expect, test } from "vitest"; +import { generateFoundryConfigJson } from "./generateFoundryConfigJson.js"; + +const expected = ` +{ + "foundryUrl": "https://example.palantirfoundry.com", + "site": { + "application": "ri.third-party-applications.main.application.fake", + "directory": "./dist", + "autoVersion": { + "type": "git-describe", + "tagPrefix": "tag-prefix" + } + } +} +`.trimStart(); + +test("it generates foundry.config.json", () => { + expect( + generateFoundryConfigJson({ + foundryUrl: "https://example.palantirfoundry.com", + application: "ri.third-party-applications.main.application.fake", + directory: "./dist", + }), + ).toEqual(expected); +}); diff --git a/packages/create-app/src/generate/generateFoundryConfigJson.ts b/packages/create-app/src/generate/generateFoundryConfigJson.ts new file mode 100644 index 000000000..0f886120a --- /dev/null +++ b/packages/create-app/src/generate/generateFoundryConfigJson.ts @@ -0,0 +1,41 @@ +/* + * Copyright 2023 Palantir Technologies, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export function generateFoundryConfigJson({ + foundryUrl, + application, + directory, +}: { + foundryUrl: string; + application: string; + directory: string; +}): string { + return JSON.stringify( + { + foundryUrl, + site: { + application, + directory, + autoVersion: { + type: "git-describe", + tagPrefix: "tag-prefix", + }, + }, + }, + null, + 2, + ) + "\n"; +} diff --git a/packages/create-app/src/prompts/promptApplicationRid.test.ts b/packages/create-app/src/prompts/promptApplicationRid.test.ts new file mode 100644 index 000000000..438ca4ec4 --- /dev/null +++ b/packages/create-app/src/prompts/promptApplicationRid.test.ts @@ -0,0 +1,55 @@ +/* + * Copyright 2023 Palantir Technologies, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { afterEach, expect, test, vi } from "vitest"; +import { consola } from "../consola.js"; +import { promptApplicationRid } from "./promptApplicationRid.js"; + +vi.mock("../consola.js"); + +afterEach(() => { + vi.restoreAllMocks(); +}); + +const valid = "ri.third-party-applications.main.application.fake"; + +test("it accepts valid application rid from prompt", async () => { + vi.mocked(consola).prompt.mockResolvedValueOnce(valid); + expect(await promptApplicationRid({})).toEqual(valid); + expect(vi.mocked(consola).prompt).toHaveBeenCalledTimes(1); +}); + +test("it prompts again if answered value is invalid", async () => { + vi.mocked(consola).prompt.mockResolvedValueOnce("ri.something.else.and.fake"); + vi.mocked(consola).prompt.mockResolvedValueOnce(valid); + expect(await promptApplicationRid({})).toEqual(valid); + expect(vi.mocked(consola).prompt).toHaveBeenCalledTimes(2); +}); + +test("it accepts valid initial value without prompt", async () => { + expect(await promptApplicationRid({ application: valid })).toEqual(valid); + expect(vi.mocked(consola).prompt).not.toHaveBeenCalled(); +}); + +test("it prompts if initial value is invalid", async () => { + vi.mocked(consola).prompt.mockResolvedValueOnce(valid); + expect( + await promptApplicationRid({ application: "ri.something.else.and.fake" }), + ).toEqual( + valid, + ); + expect(vi.mocked(consola).prompt).toHaveBeenCalledTimes(1); +}); diff --git a/packages/create-app/src/prompts/promptApplicationRid.ts b/packages/create-app/src/prompts/promptApplicationRid.ts new file mode 100644 index 000000000..53593f97a --- /dev/null +++ b/packages/create-app/src/prompts/promptApplicationRid.ts @@ -0,0 +1,44 @@ +/* + * Copyright 2023 Palantir Technologies, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { consola } from "../consola.js"; +import { italic } from "../highlight.js"; + +export async function promptApplicationRid( + { application }: { application?: string }, +): Promise { + while ( + application == null + || !/^ri\.third-party-applications\.[^.]+\.application\.[^.]+$/.test( + application, + ) + ) { + if (application != null) { + consola.fail( + "Please enter a valid application resource identifier (rid)", + ); + } + application = await consola.prompt( + `Enter the application resource identifier (rid) for your application from Developer Console:\n${ + italic( + "(Example ri.third-party-applications.main.application.1c66b352-4e00-40d2-995d-061c9d533ace)", + ) + }`, + { type: "text" }, + ); + } + return application; +} diff --git a/packages/create-app/src/templates.ts b/packages/create-app/src/templates.ts index fadda22bc..ef571f6f8 100644 --- a/packages/create-app/src/templates.ts +++ b/packages/create-app/src/templates.ts @@ -18,6 +18,7 @@ export interface Template { id: string; label: string; envPrefix: string; + buildDirectory: string; } export interface TemplateContext { @@ -30,15 +31,18 @@ export const TEMPLATES: readonly Template[] = [ id: "template-react", label: "React", envPrefix: "VITE_", + buildDirectory: "./dist", }, { id: "template-vue", label: "Vue", envPrefix: "VITE_", + buildDirectory: "./dist", }, { id: "template-next-static-export", label: "Next (static export)", envPrefix: "NEXT_PUBLIC_", + buildDirectory: "./out", }, ];