@osdk/create-app 0.0.1
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/README.md +50 -0
- package/bin/createOsdkApp.mjs +5 -0
- package/build/js/index.cjs +339 -0
- package/build/js/index.cjs.map +1 -0
- package/build/js/index.mjs +329 -0
- package/build/js/index.mjs.map +1 -0
- package/build/types/__tests__/cli.test.d.ts +1 -0
- package/build/types/cli.d.ts +1 -0
- package/build/types/consola.d.ts +1 -0
- package/build/types/highlight.d.ts +2 -0
- package/build/types/index.d.ts +1 -0
- package/build/types/templates.d.ts +6 -0
- package/changelog/@unreleased/pr-26.v2.yml +5 -0
- package/changelog/@unreleased/pr-27.v2.yml +5 -0
- package/changelog/@unreleased/pr-33.v2.yml +5 -0
- package/package.json +64 -0
- package/templates/template-next-static-export/.eslintrc.json +4 -0
- package/templates/template-next-static-export/README.md.hbs +29 -0
- package/templates/template-next-static-export/next.config.js +7 -0
- package/templates/template-next-static-export/package.json.hbs +25 -0
- package/templates/template-next-static-export/public/dev-console.svg +25 -0
- package/templates/template-next-static-export/public/next.svg +20 -0
- package/templates/template-next-static-export/public/palantir.svg +3 -0
- package/templates/template-next-static-export/src/app/auth/callback/page.tsx +25 -0
- package/templates/template-next-static-export/src/app/globals.css +75 -0
- package/templates/template-next-static-export/src/app/icon.svg +25 -0
- package/templates/template-next-static-export/src/app/layout.module.css +11 -0
- package/templates/template-next-static-export/src/app/layout.tsx +59 -0
- package/templates/template-next-static-export/src/app/login/page.tsx +43 -0
- package/templates/template-next-static-export/src/app/page.module.css +7 -0
- package/templates/template-next-static-export/src/app/page.tsx.hbs +47 -0
- package/templates/template-next-static-export/src/lib/client.ts.hbs +15 -0
- package/templates/template-next-static-export/src/lib/useAuthenticated.ts +25 -0
- package/templates/template-next-static-export/tsconfig.json +27 -0
- package/templates/template-react/.eslintrc.cjs +18 -0
- package/templates/template-react/README.md.hbs +29 -0
- package/templates/template-react/index.html +13 -0
- package/templates/template-react/package.json.hbs +30 -0
- package/templates/template-react/public/dev-console.svg +25 -0
- package/templates/template-react/public/palantir.svg +3 -0
- package/templates/template-react/public/react.svg +1 -0
- package/templates/template-react/src/AuthCallback.tsx +24 -0
- package/templates/template-react/src/AuthenticatedRoute.tsx +33 -0
- package/templates/template-react/src/Home.module.css +7 -0
- package/templates/template-react/src/Home.tsx.hbs +41 -0
- package/templates/template-react/src/Layout.module.css +10 -0
- package/templates/template-react/src/Layout.tsx +37 -0
- package/templates/template-react/src/Login.tsx +40 -0
- package/templates/template-react/src/client.ts.hbs +15 -0
- package/templates/template-react/src/index.css +75 -0
- package/templates/template-react/src/main.tsx +33 -0
- package/templates/template-react/src/vite-env.d.ts +1 -0
- package/templates/template-react/tsconfig.json +25 -0
- package/templates/template-react/tsconfig.node.json +10 -0
- package/templates/template-react/vite.config.ts +10 -0
- package/templates/template-vue/.vscode/extensions.json +3 -0
- package/templates/template-vue/README.md.hbs +29 -0
- package/templates/template-vue/index.html +13 -0
- package/templates/template-vue/package.json.hbs +22 -0
- package/templates/template-vue/public/dev-console.svg +25 -0
- package/templates/template-vue/public/palantir.svg +3 -0
- package/templates/template-vue/public/vue.svg +1 -0
- package/templates/template-vue/src/AuthCallback.vue +22 -0
- package/templates/template-vue/src/Home.vue.hbs +44 -0
- package/templates/template-vue/src/Layout.vue +29 -0
- package/templates/template-vue/src/Login.vue +37 -0
- package/templates/template-vue/src/client.ts.hbs +15 -0
- package/templates/template-vue/src/main.ts +35 -0
- package/templates/template-vue/src/style.css +75 -0
- package/templates/template-vue/src/vite-env.d.ts +1 -0
- package/templates/template-vue/tsconfig.json +25 -0
- package/templates/template-vue/tsconfig.node.json +10 -0
- package/templates/template-vue/vite.config.ts +15 -0
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import { findUpSync } from 'find-up';
|
|
2
|
+
import Handlebars from 'handlebars';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
import yargs from 'yargs';
|
|
7
|
+
import { hideBin } from 'yargs/helpers';
|
|
8
|
+
import { createConsola, consola as consola$1 } from 'consola';
|
|
9
|
+
import { colorize } from 'consola/utils';
|
|
10
|
+
|
|
11
|
+
// src/cli.ts
|
|
12
|
+
var consola = createConsola({
|
|
13
|
+
// https://github.com/unjs/consola/issues/251
|
|
14
|
+
async prompt(...params) {
|
|
15
|
+
const response = await consola$1.prompt(...params);
|
|
16
|
+
if (typeof response === "symbol" && response.toString() === "Symbol(clack:cancel)") {
|
|
17
|
+
consola$1.fail("Operation cancelled");
|
|
18
|
+
process.exit(0);
|
|
19
|
+
}
|
|
20
|
+
return response;
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
function green(text) {
|
|
24
|
+
return colorize("green", text);
|
|
25
|
+
}
|
|
26
|
+
function italic(text) {
|
|
27
|
+
return colorize("italic", text);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// src/templates.ts
|
|
31
|
+
var TEMPLATES = [{
|
|
32
|
+
id: "template-react",
|
|
33
|
+
label: "React",
|
|
34
|
+
envPrefix: "VITE_"
|
|
35
|
+
}, {
|
|
36
|
+
id: "template-vue",
|
|
37
|
+
label: "Vue",
|
|
38
|
+
envPrefix: "VITE_"
|
|
39
|
+
}, {
|
|
40
|
+
id: "template-next-static-export",
|
|
41
|
+
label: "Next (static export)",
|
|
42
|
+
envPrefix: "NEXT_PUBLIC_"
|
|
43
|
+
}];
|
|
44
|
+
|
|
45
|
+
// src/cli.ts
|
|
46
|
+
async function cli(args = process.argv) {
|
|
47
|
+
const base = yargs(hideBin(args)).version("0.0.1").strict().help().command("$0 [project] [--<option>]", "Create a new OSDK application based on framework templates. Information may be provided through arguments to skip interactive prompts.", (yargs2) => yargs2.positional("project", {
|
|
48
|
+
type: "string",
|
|
49
|
+
describe: "Project name to create"
|
|
50
|
+
}).option("overwrite", {
|
|
51
|
+
type: "boolean",
|
|
52
|
+
describe: "Overwrite project directory if already exists"
|
|
53
|
+
}).option("template", {
|
|
54
|
+
type: "string",
|
|
55
|
+
describe: "Template name to use"
|
|
56
|
+
}).option("foundry-url", {
|
|
57
|
+
type: "string",
|
|
58
|
+
describe: "URL for the Foundry stack"
|
|
59
|
+
}).option("application-url", {
|
|
60
|
+
type: "string",
|
|
61
|
+
describe: "URL the production application will be hosted on"
|
|
62
|
+
}).option("skip-application-url", {
|
|
63
|
+
type: "boolean",
|
|
64
|
+
describe: "Skip filling in URL the production application will be hosted on"
|
|
65
|
+
}).option("client-id", {
|
|
66
|
+
type: "string",
|
|
67
|
+
describe: "OAuth client ID for application"
|
|
68
|
+
}).option("osdk-package", {
|
|
69
|
+
type: "string",
|
|
70
|
+
describe: "OSDK package name for application"
|
|
71
|
+
}).option("osdk-registry-url", {
|
|
72
|
+
type: "string",
|
|
73
|
+
describe: "URL for NPM registry to install OSDK package"
|
|
74
|
+
}));
|
|
75
|
+
const parsed = base.parseSync();
|
|
76
|
+
const project = await promptProject(parsed);
|
|
77
|
+
const overwrite = await promptOverwrite(parsed, project);
|
|
78
|
+
const template = await promptTemplate(parsed);
|
|
79
|
+
const foundryUrl = await promptFoundryUrl(parsed);
|
|
80
|
+
const applicationUrl = await promptApplicationUrl(parsed);
|
|
81
|
+
const clientId = await promptClientId(parsed);
|
|
82
|
+
const osdkPackage = await promptOsdkPackage(parsed);
|
|
83
|
+
const osdkRegistryUrl = await promptOsdkRegistryUrl(parsed);
|
|
84
|
+
consola.log("");
|
|
85
|
+
consola.start(`Creating project ${green(project)} using template ${green(template.id)}`);
|
|
86
|
+
const cwd = process.cwd();
|
|
87
|
+
const root = path.join(cwd, project);
|
|
88
|
+
if (fs.existsSync(root)) {
|
|
89
|
+
if (overwrite) {
|
|
90
|
+
consola.info(`Overwriting existing project directory`);
|
|
91
|
+
fs.rmSync(root, {
|
|
92
|
+
recursive: true,
|
|
93
|
+
force: true
|
|
94
|
+
});
|
|
95
|
+
fs.mkdirSync(root, {
|
|
96
|
+
recursive: true
|
|
97
|
+
});
|
|
98
|
+
} else {
|
|
99
|
+
consola.info(`Reusing existing project directory`);
|
|
100
|
+
}
|
|
101
|
+
} else {
|
|
102
|
+
consola.info(`Creating project directory`);
|
|
103
|
+
fs.mkdirSync(root, {
|
|
104
|
+
recursive: true
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
consola.info(`Copying files into project directory`);
|
|
108
|
+
const templatesDir = findUpSync("templates", {
|
|
109
|
+
cwd: path.dirname(fileURLToPath(import.meta.url)),
|
|
110
|
+
type: "directory"
|
|
111
|
+
});
|
|
112
|
+
if (templatesDir == null) {
|
|
113
|
+
throw new Error(`Could not find templates directory`);
|
|
114
|
+
}
|
|
115
|
+
const templateDir = path.resolve(templatesDir, template.id);
|
|
116
|
+
fs.cpSync(templateDir, root, {
|
|
117
|
+
recursive: true
|
|
118
|
+
});
|
|
119
|
+
const templateHbs = function(dir) {
|
|
120
|
+
fs.readdirSync(dir).forEach(function(file) {
|
|
121
|
+
file = dir + "/" + file;
|
|
122
|
+
const stat = fs.statSync(file);
|
|
123
|
+
if (stat.isDirectory()) {
|
|
124
|
+
templateHbs(file);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (!file.endsWith(".hbs")) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const hbsContext = {
|
|
131
|
+
project,
|
|
132
|
+
osdkPackage
|
|
133
|
+
};
|
|
134
|
+
const templated = Handlebars.compile(fs.readFileSync(file, "utf-8"))(hbsContext);
|
|
135
|
+
fs.writeFileSync(file.replace(/.hbs$/, ""), templated);
|
|
136
|
+
fs.rmSync(file);
|
|
137
|
+
});
|
|
138
|
+
};
|
|
139
|
+
templateHbs(root);
|
|
140
|
+
const npmRc = `//${osdkRegistryUrl.replace(/^https:\/\//, "")}:_authToken=\${FOUNDRY_SDK_AUTH_TOKEN}
|
|
141
|
+
${osdkPackage.split("/")[0]}:registry=${osdkRegistryUrl}
|
|
142
|
+
`;
|
|
143
|
+
fs.writeFileSync(path.join(root, ".npmrc"), npmRc);
|
|
144
|
+
const envDevelopment = `${template.envPrefix}FOUNDRY_API_URL=${foundryUrl}
|
|
145
|
+
${template.envPrefix}FOUNDRY_REDIRECT_URL=http://localhost:8080/auth/callback
|
|
146
|
+
${template.envPrefix}FOUNDRY_CLIENT_ID=${clientId}
|
|
147
|
+
`;
|
|
148
|
+
fs.writeFileSync(path.join(root, ".env.development"), envDevelopment);
|
|
149
|
+
const envProduction = `${template.envPrefix}FOUNDRY_API_URL=${foundryUrl}
|
|
150
|
+
${template.envPrefix}FOUNDRY_REDIRECT_URL=${applicationUrl != null ? applicationUrl : "<Fill in the domain at which you deploy your application>"}/auth/callback
|
|
151
|
+
${template.envPrefix}FOUNDRY_CLIENT_ID=${clientId}
|
|
152
|
+
`;
|
|
153
|
+
fs.writeFileSync(path.join(root, ".env.production"), envProduction);
|
|
154
|
+
consola.success("Success");
|
|
155
|
+
const cdRelative = path.relative(cwd, root);
|
|
156
|
+
consola.box({
|
|
157
|
+
message: `Done! Run the following commands to get started:
|
|
158
|
+
|
|
159
|
+
\`cd ${cdRelative}\`
|
|
160
|
+
\`export FOUNDRY_SDK_AUTH_TOKEN=<token>\`
|
|
161
|
+
\`npm install\`
|
|
162
|
+
\`npm run dev\``,
|
|
163
|
+
style: {
|
|
164
|
+
padding: 2,
|
|
165
|
+
borderColor: "green",
|
|
166
|
+
borderStyle: "rounded"
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
async function promptProject(parsed) {
|
|
171
|
+
let project = parsed.project;
|
|
172
|
+
while (project == null || !/^[a-zA-Z0-9-_]+$/.test(project)) {
|
|
173
|
+
if (project != null) {
|
|
174
|
+
consola.fail("Project name can only contain alphanumeric characters, hyphens and underscores");
|
|
175
|
+
}
|
|
176
|
+
project = await consola.prompt("Project name:", {
|
|
177
|
+
type: "text",
|
|
178
|
+
placeholder: "my-osdk-app",
|
|
179
|
+
default: "my-osdk-app"
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
return project;
|
|
183
|
+
}
|
|
184
|
+
async function promptOverwrite(parsed, project) {
|
|
185
|
+
if (!fs.existsSync(path.join(process.cwd(), project))) {
|
|
186
|
+
return true;
|
|
187
|
+
}
|
|
188
|
+
if (parsed.overwrite != null) {
|
|
189
|
+
return parsed.overwrite;
|
|
190
|
+
}
|
|
191
|
+
const result = await consola.prompt(
|
|
192
|
+
`The directory ${green(project)} already exists do you want to overwrite or ignore it?`,
|
|
193
|
+
{
|
|
194
|
+
type: "select",
|
|
195
|
+
options: [{
|
|
196
|
+
label: "Remove existing files and continue",
|
|
197
|
+
value: "overwrite"
|
|
198
|
+
}, {
|
|
199
|
+
label: "Ignore files and continue",
|
|
200
|
+
value: "ignore"
|
|
201
|
+
}, {
|
|
202
|
+
label: "Cancel",
|
|
203
|
+
value: "cancel"
|
|
204
|
+
}]
|
|
205
|
+
}
|
|
206
|
+
// Types for "select" are wrong the value is returned rather than the option object
|
|
207
|
+
// https://github.com/unjs/consola/pull/238
|
|
208
|
+
);
|
|
209
|
+
switch (result) {
|
|
210
|
+
case "overwrite":
|
|
211
|
+
return true;
|
|
212
|
+
case "ignore":
|
|
213
|
+
return false;
|
|
214
|
+
case "cancel":
|
|
215
|
+
consola.fail("Operation cancelled");
|
|
216
|
+
process.exit(0);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
async function promptTemplate(parsed) {
|
|
220
|
+
let template = TEMPLATES.find((t) => t.id === parsed.template);
|
|
221
|
+
if (template == null) {
|
|
222
|
+
const templateId = await consola.prompt(parsed.template != null ? `The provided template ${green(parsed.template)} is invalid please select a framework:` : "Select a framework:", {
|
|
223
|
+
type: "select",
|
|
224
|
+
options: TEMPLATES.map((template2) => ({
|
|
225
|
+
value: template2.id,
|
|
226
|
+
label: template2.label
|
|
227
|
+
}))
|
|
228
|
+
// Types for "select" are wrong the value is returned rather than the option object
|
|
229
|
+
// https://github.com/unjs/consola/pull/238
|
|
230
|
+
});
|
|
231
|
+
template = TEMPLATES.find((t) => t.id === templateId);
|
|
232
|
+
if (template == null) {
|
|
233
|
+
throw new Error(`Template ${templateId} should be found`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return template;
|
|
237
|
+
}
|
|
238
|
+
async function promptFoundryUrl(parsed) {
|
|
239
|
+
let foundryUrl = parsed.foundryUrl;
|
|
240
|
+
while (foundryUrl == null || !foundryUrl.startsWith("https://")) {
|
|
241
|
+
if (foundryUrl != null) {
|
|
242
|
+
consola.fail("Please enter a valid Foundry URL");
|
|
243
|
+
}
|
|
244
|
+
foundryUrl = await consola.prompt(`Enter the URL for your Foundry stack:
|
|
245
|
+
${italic("(Example https://example.palantirfoundry.com/)")}`, {
|
|
246
|
+
type: "text"
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
return foundryUrl.replace(/\/$/, "");
|
|
250
|
+
}
|
|
251
|
+
async function promptApplicationUrl(parsed) {
|
|
252
|
+
if (parsed.skipApplicationUrl) {
|
|
253
|
+
return void 0;
|
|
254
|
+
}
|
|
255
|
+
let applicationUrl = parsed.applicationUrl;
|
|
256
|
+
if (applicationUrl == null) {
|
|
257
|
+
const skip = await consola.prompt(
|
|
258
|
+
`Do you know the URL your production application will be hosted on? This is required to create a production build of your application with the correct OAuth redirect URL.`,
|
|
259
|
+
{
|
|
260
|
+
type: "select",
|
|
261
|
+
options: [{
|
|
262
|
+
label: "Yes, prefill it for me",
|
|
263
|
+
value: "yes"
|
|
264
|
+
}, {
|
|
265
|
+
label: "No, I will fill it in myself later",
|
|
266
|
+
value: "no"
|
|
267
|
+
}]
|
|
268
|
+
}
|
|
269
|
+
// Types for "select" are wrong the value is returned rather than the option object
|
|
270
|
+
// https://github.com/unjs/consola/pull/238
|
|
271
|
+
);
|
|
272
|
+
if (skip === "no") {
|
|
273
|
+
return void 0;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
while (applicationUrl == null || !/^https?:\/\//.test(applicationUrl)) {
|
|
277
|
+
if (applicationUrl != null) {
|
|
278
|
+
consola.fail("Please enter a valid application URL");
|
|
279
|
+
}
|
|
280
|
+
applicationUrl = await consola.prompt(`Enter the URL your production application will be hosted on:
|
|
281
|
+
${italic("(Example https://myapp.example.palantirfoundry.com/)")}`, {
|
|
282
|
+
type: "text"
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
return applicationUrl.replace(/\/$/, "");
|
|
286
|
+
}
|
|
287
|
+
async function promptClientId(parsed) {
|
|
288
|
+
let clientId = parsed.clientId;
|
|
289
|
+
while (clientId == null || !/^[0-9a-f]+$/.test(clientId)) {
|
|
290
|
+
if (clientId != null) {
|
|
291
|
+
consola.fail("Please enter a valid OAuth client ID");
|
|
292
|
+
}
|
|
293
|
+
clientId = await consola.prompt(`Enter the OAuth client ID for your application from Developer Console:
|
|
294
|
+
${italic("(Example 2650385ab6c5e0df3b44aff776b00a42)")}`, {
|
|
295
|
+
type: "text"
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
return clientId;
|
|
299
|
+
}
|
|
300
|
+
async function promptOsdkPackage(parsed) {
|
|
301
|
+
let osdkPackage = parsed.osdkPackage;
|
|
302
|
+
while (osdkPackage == null || !/^@[a-z0-9-]+\/sdk$/.test(osdkPackage)) {
|
|
303
|
+
if (osdkPackage != null) {
|
|
304
|
+
consola.fail("Please enter a valid OSDK package name");
|
|
305
|
+
}
|
|
306
|
+
osdkPackage = await consola.prompt(`Enter the OSDK package name for your application from Developer Console:
|
|
307
|
+
${italic("(Example @my-app/sdk)")}`, {
|
|
308
|
+
type: "text"
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
return osdkPackage;
|
|
312
|
+
}
|
|
313
|
+
async function promptOsdkRegistryUrl(parsed) {
|
|
314
|
+
let osdkRegistryUrl = parsed.osdkRegistryUrl;
|
|
315
|
+
while (osdkRegistryUrl == null || !/^https:\/\/[^/]+\/artifacts\/api\/repositories\/ri\.artifacts\.[^/]+\/contents\/release\/npm\/?$/.test(osdkRegistryUrl)) {
|
|
316
|
+
if (osdkRegistryUrl != null) {
|
|
317
|
+
consola.fail("Please enter a valid NPM registry URL to install your OSDK package");
|
|
318
|
+
}
|
|
319
|
+
osdkRegistryUrl = await consola.prompt(`Enter the NPM registry URL to install your OSDK package from Developer Console:
|
|
320
|
+
${italic("(Example https://example.palantirfoundry.com/artifacts/api/repositories/ri.artifacts.main.repository.a4a7fe1c-486f-4226-b706-7b90005f527d/contents/release/npm)")}`, {
|
|
321
|
+
type: "text"
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
return osdkRegistryUrl.replace(/\/$/, "");
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
export { cli };
|
|
328
|
+
//# sourceMappingURL=out.js.map
|
|
329
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cli.ts","../../src/consola.ts","../../src/highlight.ts","../../src/templates.ts"],"names":["yargs","template"],"mappings":"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","sourcesContent":["/*\n * Copyright 2023 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { findUpSync } from \"find-up\";\nimport Handlebars from \"handlebars\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport yargs from \"yargs\";\nimport { hideBin } from \"yargs/helpers\";\nimport { consola } from \"./consola.js\";\nimport { green, italic } from \"./highlight.js\";\nimport { TEMPLATES } from \"./templates.js\";\nexport async function cli(args = process.argv) {\n const base = yargs(hideBin(args)).version(process.env.PACKAGE_VERSION ?? \"\").strict().help().command(\"$0 [project] [--<option>]\", \"Create a new OSDK application based on framework templates. Information may be provided through arguments to skip interactive prompts.\", yargs => yargs.positional(\"project\", {\n type: \"string\",\n describe: \"Project name to create\"\n }).option(\"overwrite\", {\n type: \"boolean\",\n describe: \"Overwrite project directory if already exists\"\n }).option(\"template\", {\n type: \"string\",\n describe: \"Template name to use\"\n }).option(\"foundry-url\", {\n type: \"string\",\n describe: \"URL for the Foundry stack\"\n }).option(\"application-url\", {\n type: \"string\",\n describe: \"URL the production application will be hosted on\"\n }).option(\"skip-application-url\", {\n type: \"boolean\",\n describe: \"Skip filling in URL the production application will be hosted on\"\n }).option(\"client-id\", {\n type: \"string\",\n describe: \"OAuth client ID for application\"\n }).option(\"osdk-package\", {\n type: \"string\",\n describe: \"OSDK package name for application\"\n }).option(\"osdk-registry-url\", {\n type: \"string\",\n describe: \"URL for NPM registry to install OSDK package\"\n }));\n const parsed = base.parseSync();\n const project = await promptProject(parsed);\n const overwrite = await promptOverwrite(parsed, project);\n const template = await promptTemplate(parsed);\n const foundryUrl = await promptFoundryUrl(parsed);\n const applicationUrl = await promptApplicationUrl(parsed);\n const clientId = await promptClientId(parsed);\n const osdkPackage = await promptOsdkPackage(parsed);\n const osdkRegistryUrl = await promptOsdkRegistryUrl(parsed);\n consola.log(\"\");\n consola.start(`Creating project ${green(project)} using template ${green(template.id)}`);\n const cwd = process.cwd();\n const root = path.join(cwd, project);\n if (fs.existsSync(root)) {\n if (overwrite) {\n consola.info(`Overwriting existing project directory`);\n fs.rmSync(root, {\n recursive: true,\n force: true\n });\n fs.mkdirSync(root, {\n recursive: true\n });\n } else {\n consola.info(`Reusing existing project directory`);\n }\n } else {\n consola.info(`Creating project directory`);\n fs.mkdirSync(root, {\n recursive: true\n });\n }\n consola.info(`Copying files into project directory`);\n const templatesDir = findUpSync(\"templates\", {\n cwd: path.dirname(fileURLToPath(import.meta.url)),\n type: \"directory\"\n });\n if (templatesDir == null) {\n throw new Error(`Could not find templates directory`);\n }\n const templateDir = path.resolve(templatesDir, template.id);\n fs.cpSync(templateDir, root, {\n recursive: true\n });\n const templateHbs = function (dir) {\n fs.readdirSync(dir).forEach(function (file) {\n file = dir + \"/\" + file;\n const stat = fs.statSync(file);\n if (stat.isDirectory()) {\n templateHbs(file);\n return;\n }\n if (!file.endsWith(\".hbs\")) {\n return;\n }\n const hbsContext = {\n project,\n osdkPackage\n };\n const templated = Handlebars.compile(fs.readFileSync(file, \"utf-8\"))(hbsContext);\n fs.writeFileSync(file.replace(/.hbs$/, \"\"), templated);\n fs.rmSync(file);\n });\n };\n templateHbs(root);\n const npmRc = `//${osdkRegistryUrl.replace(/^https:\\/\\//, \"\")}:_authToken=\\${FOUNDRY_SDK_AUTH_TOKEN}\\n` + `${osdkPackage.split(\"/\")[0]}:registry=${osdkRegistryUrl}\\n`;\n fs.writeFileSync(path.join(root, \".npmrc\"), npmRc);\n const envDevelopment = `${template.envPrefix}FOUNDRY_API_URL=${foundryUrl}\\n` + `${template.envPrefix}FOUNDRY_REDIRECT_URL=http://localhost:8080/auth/callback\\n` + `${template.envPrefix}FOUNDRY_CLIENT_ID=${clientId}\\n`;\n fs.writeFileSync(path.join(root, \".env.development\"), envDevelopment);\n const envProduction = `${template.envPrefix}FOUNDRY_API_URL=${foundryUrl}\\n` + `${template.envPrefix}FOUNDRY_REDIRECT_URL=${applicationUrl != null ? applicationUrl : \"<Fill in the domain at which you deploy your application>\"}/auth/callback\\n` + `${template.envPrefix}FOUNDRY_CLIENT_ID=${clientId}\\n`;\n fs.writeFileSync(path.join(root, \".env.production\"), envProduction);\n consola.success(\"Success\");\n const cdRelative = path.relative(cwd, root);\n consola.box({\n message: `Done! Run the following commands to get started:\\n` + `\\n` + ` \\`cd ${cdRelative}\\`\\n` + ` \\`export FOUNDRY_SDK_AUTH_TOKEN=<token>\\`\\n` + ` \\`npm install\\`\\n` + ` \\`npm run dev\\``,\n style: {\n padding: 2,\n borderColor: \"green\",\n borderStyle: \"rounded\"\n }\n });\n}\nasync function promptProject(parsed) {\n let project = parsed.project;\n while (project == null || !/^[a-zA-Z0-9-_]+$/.test(project)) {\n if (project != null) {\n consola.fail(\"Project name can only contain alphanumeric characters, hyphens and underscores\");\n }\n project = await consola.prompt(\"Project name:\", {\n type: \"text\",\n placeholder: \"my-osdk-app\",\n default: \"my-osdk-app\"\n });\n }\n return project;\n}\nasync function promptOverwrite(parsed, project) {\n if (!fs.existsSync(path.join(process.cwd(), project))) {\n return true;\n }\n if (parsed.overwrite != null) {\n return parsed.overwrite;\n }\n const result = await consola.prompt(`The directory ${green(project)} already exists do you want to overwrite or ignore it?`, {\n type: \"select\",\n options: [{\n label: \"Remove existing files and continue\",\n value: \"overwrite\"\n }, {\n label: \"Ignore files and continue\",\n value: \"ignore\"\n }, {\n label: \"Cancel\",\n value: \"cancel\"\n }]\n }\n // Types for \"select\" are wrong the value is returned rather than the option object\n // https://github.com/unjs/consola/pull/238\n );\n switch (result) {\n case \"overwrite\":\n return true;\n case \"ignore\":\n return false;\n case \"cancel\":\n consola.fail(\"Operation cancelled\");\n process.exit(0);\n }\n}\nasync function promptTemplate(parsed) {\n let template = TEMPLATES.find(t => t.id === parsed.template);\n if (template == null) {\n const templateId = await consola.prompt(parsed.template != null ? `The provided template ${green(parsed.template)} is invalid please select a framework:` : \"Select a framework:\", {\n type: \"select\",\n options: TEMPLATES.map(template => ({\n value: template.id,\n label: template.label\n }))\n // Types for \"select\" are wrong the value is returned rather than the option object\n // https://github.com/unjs/consola/pull/238\n });\n template = TEMPLATES.find(t => t.id === templateId);\n if (template == null) {\n throw new Error(`Template ${templateId} should be found`);\n }\n }\n return template;\n}\nasync function promptFoundryUrl(parsed) {\n let foundryUrl = parsed.foundryUrl;\n while (foundryUrl == null || !foundryUrl.startsWith(\"https://\")) {\n if (foundryUrl != null) {\n consola.fail(\"Please enter a valid Foundry URL\");\n }\n foundryUrl = await consola.prompt(`Enter the URL for your Foundry stack:\\n${italic(\"(Example https://example.palantirfoundry.com/)\")}`, {\n type: \"text\"\n });\n }\n return foundryUrl.replace(/\\/$/, \"\");\n}\nasync function promptApplicationUrl(parsed) {\n if (parsed.skipApplicationUrl) {\n return undefined;\n }\n let applicationUrl = parsed.applicationUrl;\n if (applicationUrl == null) {\n const skip = await consola.prompt(`Do you know the URL your production application will be hosted on? This is required to create a production build of your application with the correct OAuth redirect URL.`, {\n type: \"select\",\n options: [{\n label: \"Yes, prefill it for me\",\n value: \"yes\"\n }, {\n label: \"No, I will fill it in myself later\",\n value: \"no\"\n }]\n }\n // Types for \"select\" are wrong the value is returned rather than the option object\n // https://github.com/unjs/consola/pull/238\n );\n if (skip === \"no\") {\n return undefined;\n }\n }\n while (applicationUrl == null || !/^https?:\\/\\//.test(applicationUrl)) {\n if (applicationUrl != null) {\n consola.fail(\"Please enter a valid application URL\");\n }\n applicationUrl = await consola.prompt(`Enter the URL your production application will be hosted on:\\n${italic(\"(Example https://myapp.example.palantirfoundry.com/)\")}`, {\n type: \"text\"\n });\n }\n return applicationUrl.replace(/\\/$/, \"\");\n}\nasync function promptClientId(parsed) {\n let clientId = parsed.clientId;\n while (clientId == null || !/^[0-9a-f]+$/.test(clientId)) {\n if (clientId != null) {\n consola.fail(\"Please enter a valid OAuth client ID\");\n }\n clientId = await consola.prompt(`Enter the OAuth client ID for your application from Developer Console:\\n${italic(\"(Example 2650385ab6c5e0df3b44aff776b00a42)\")}`, {\n type: \"text\"\n });\n }\n return clientId;\n}\nasync function promptOsdkPackage(parsed) {\n let osdkPackage = parsed.osdkPackage;\n while (osdkPackage == null || !/^@[a-z0-9-]+\\/sdk$/.test(osdkPackage)) {\n if (osdkPackage != null) {\n consola.fail(\"Please enter a valid OSDK package name\");\n }\n osdkPackage = await consola.prompt(`Enter the OSDK package name for your application from Developer Console:\\n${italic(\"(Example @my-app/sdk)\")}`, {\n type: \"text\"\n });\n }\n return osdkPackage;\n}\nasync function promptOsdkRegistryUrl(parsed) {\n let osdkRegistryUrl = parsed.osdkRegistryUrl;\n while (osdkRegistryUrl == null || !/^https:\\/\\/[^/]+\\/artifacts\\/api\\/repositories\\/ri\\.artifacts\\.[^/]+\\/contents\\/release\\/npm\\/?$/.test(osdkRegistryUrl)) {\n if (osdkRegistryUrl != null) {\n consola.fail(\"Please enter a valid NPM registry URL to install your OSDK package\");\n }\n osdkRegistryUrl = await consola.prompt(`Enter the NPM registry URL to install your OSDK package from Developer Console:\\n${italic(\"(Example https://example.palantirfoundry.com/artifacts/api/repositories/ri.artifacts.main.repository.a4a7fe1c-486f-4226-b706-7b90005f527d/contents/release/npm)\")}`, {\n type: \"text\"\n });\n }\n return osdkRegistryUrl.replace(/\\/$/, \"\");\n}","/*\n * Copyright 2023 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { consola as defaultConsola, createConsola } from \"consola\";\nexport const consola = createConsola({\n // https://github.com/unjs/consola/issues/251\n async prompt(...params) {\n const response = await defaultConsola.prompt(...params);\n if (typeof response === \"symbol\" && response.toString() === \"Symbol(clack:cancel)\") {\n defaultConsola.fail(\"Operation cancelled\");\n process.exit(0);\n }\n return response;\n }\n});","/*\n * Copyright 2023 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { colorize } from \"consola/utils\";\nexport function green(text) {\n return colorize(\"green\", text);\n}\nexport function italic(text) {\n return colorize(\"italic\", text);\n}","/*\n * Copyright 2023 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const TEMPLATES = [{\n id: \"template-react\",\n label: \"React\",\n envPrefix: \"VITE_\"\n}, {\n id: \"template-vue\",\n label: \"Vue\",\n envPrefix: \"VITE_\"\n}, {\n id: \"template-next-static-export\",\n label: \"Next (static export)\",\n envPrefix: \"NEXT_PUBLIC_\"\n}];"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function cli(args?: string[]): Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const consola: import("consola/core").ConsolaInstance;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { cli } from "./cli.js";
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@osdk/create-app",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "",
|
|
5
|
+
"access": "public",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./build/types/index.d.ts",
|
|
10
|
+
"import": "./build/js/index.mjs",
|
|
11
|
+
"require": "./build/js/index.cjs"
|
|
12
|
+
},
|
|
13
|
+
"./*": {
|
|
14
|
+
"types": "./build/types/public/*.d.ts",
|
|
15
|
+
"import": "./build/js/public/*.mjs",
|
|
16
|
+
"require": "./build/js/public/*.cjs"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"consola": "^3.2.3",
|
|
21
|
+
"find-up": "^6.3.0",
|
|
22
|
+
"handlebars": "^4.7.8",
|
|
23
|
+
"yargs": "^17.7.2"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@types/node": "^18.0.0",
|
|
27
|
+
"@types/tmp": "^0.2.6",
|
|
28
|
+
"@types/yargs": "^17.0.29",
|
|
29
|
+
"dir-compare": "^4.2.0",
|
|
30
|
+
"tmp": "^0.2.1",
|
|
31
|
+
"typescript": "^5.2.2"
|
|
32
|
+
},
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public"
|
|
35
|
+
},
|
|
36
|
+
"bin": {
|
|
37
|
+
"create-osdk-app": "bin/createOsdkApp.mjs"
|
|
38
|
+
},
|
|
39
|
+
"files": [
|
|
40
|
+
"build/types",
|
|
41
|
+
"build/js",
|
|
42
|
+
"changelog",
|
|
43
|
+
"CHANGELOG_OLD.md",
|
|
44
|
+
"package.json",
|
|
45
|
+
"templates",
|
|
46
|
+
"*.d.ts"
|
|
47
|
+
],
|
|
48
|
+
"main": "./build/js/index.cjs",
|
|
49
|
+
"module": "./build/js/index.mjs",
|
|
50
|
+
"types": "./build/types/index.d.ts",
|
|
51
|
+
"type": "module",
|
|
52
|
+
"scripts": {
|
|
53
|
+
"clean": "rm -rf lib dist types build tsconfig.tsbuildinfo",
|
|
54
|
+
"dev:transpile": "tsup --watch",
|
|
55
|
+
"fix-lint": "eslint . --fix && dprint fmt --config $(find-up dprint.json)",
|
|
56
|
+
"lint": "eslint . && dprint check --config $(find-up dprint.json)",
|
|
57
|
+
"test": "vitest run",
|
|
58
|
+
"test:watch": "vitest",
|
|
59
|
+
"transpile": "tsup",
|
|
60
|
+
"transpileWatch": "tsup --watch",
|
|
61
|
+
"typecheck": "tsc-absolute --build",
|
|
62
|
+
"update-snapshots": "UPDATE_SNAPSHOTS=true vitest run"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# {{project}}
|
|
2
|
+
|
|
3
|
+
This project was generated with `@osdk/create-app` demonstrates using the OSDK package `{{osdkPackage}}` with React on top of Next.js. Check out the [Next.js](https://nextjs.org/docs) docs for further configuration.
|
|
4
|
+
|
|
5
|
+
## Developing
|
|
6
|
+
|
|
7
|
+
Run the following command or equivalent with your preferred package manager to start a local development server on `http://localhost:8080`:
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm run dev
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Development configuration is stored in `.env.development`.
|
|
14
|
+
|
|
15
|
+
In order to make API requests to Foundry, CORS must be configured for the stack to allow `http://localhost:8080` to load resources. The configured OAuth client must also allow `http://localhost:8080/auth/callback` as a redirect URL.
|
|
16
|
+
|
|
17
|
+
## Deploying
|
|
18
|
+
|
|
19
|
+
Run the following command or equivalent with your preferred package manager to create a production build of your application:
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
npm run build
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Production configuration is stored in `.env.production`.
|
|
26
|
+
|
|
27
|
+
If you did not fill in the URL your production application will be hosted on you will need to fill in the `NEXT_PUBLIC_FOUNDRY_REDIRECT_URL` in `.env.production`.
|
|
28
|
+
|
|
29
|
+
In order to make API requests to Foundry, CORS must be configured for the stack to allow the production origin to load resources. The configured OAuth client must also allow the production origin auth callback as a redirect URL.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{project}}",
|
|
3
|
+
"private": true,
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "next dev -p 8080",
|
|
7
|
+
"build": "next build",
|
|
8
|
+
"start": "next start",
|
|
9
|
+
"lint": "next lint"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"{{osdkPackage}}": "latest",
|
|
13
|
+
"react": "^18",
|
|
14
|
+
"react-dom": "^18",
|
|
15
|
+
"next": "14.0.4"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"typescript": "^5",
|
|
19
|
+
"@types/node": "^20",
|
|
20
|
+
"@types/react": "^18",
|
|
21
|
+
"@types/react-dom": "^18",
|
|
22
|
+
"eslint": "^8",
|
|
23
|
+
"eslint-config-next": "14.0.4"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
3
|
+
<title>Developer Console Application</title>
|
|
4
|
+
<rect x="1" y="1" width="14" height="12" fill="white"/>
|
|
5
|
+
<g opacity="0.5">
|
|
6
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M1 0H15C15.55 0 16 0.45 16 1V13C16 13.55 15.55 14 15 14H1C0.45 14 0 13.55 0 13V1C0 0.45 0.45 0 1 0ZM15 13V1H1V13H15Z" fill="#10161A"/>
|
|
7
|
+
</g>
|
|
8
|
+
<rect x="1" y="1" width="14" height="3" fill="#72CA9B"/>
|
|
9
|
+
<rect x="1" y="4" width="14" height="1" fill="#32A467"/>
|
|
10
|
+
<rect x="2" y="2" width="1" height="1" fill="white"/>
|
|
11
|
+
<rect x="4" y="2" width="1" height="1" fill="white"/>
|
|
12
|
+
<rect x="6" y="2" width="1" height="1" fill="white"/>
|
|
13
|
+
<rect x="12" y="2" width="2" height="1" fill="white"/>
|
|
14
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M6 8H14C14.5523 8 15 8.44772 15 9V14C15 14.5523 14.5523 15 14 15H6C5.44772 15 5 14.5523 5 14V9C5 8.44772 5.44772 8 6 8Z" fill="white"/>
|
|
15
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M6 9H14V14H6V9Z" fill="url(#paint0_linear_1221_19327)"/>
|
|
16
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M8 10H7V11H8V12H7V13H8V12H9V11H8V10ZM13 12H10V13H13V12Z" fill="white"/>
|
|
17
|
+
<path opacity="0.5" fill-rule="evenodd" clip-rule="evenodd" d="M6 7H14C15.1046 7 16 7.89543 16 9V14C16 15.1046 15.1046 16 14 16H6C4.89543 16 4 15.1046 4 14V9C4 7.89543 4.89543 7 6 7ZM15 9C15 8.44772 14.5523 8 14 8H6C5.44772 8 5 8.44772 5 9V14C5 14.5523 5.44772 15 6 15H14C14.5523 15 15 14.5523 15 14V9Z" fill="#10161A"/>
|
|
18
|
+
<defs>
|
|
19
|
+
<linearGradient id="paint0_linear_1221_19327" x1="17.4913" y1="13.1561" x2="15.3484" y2="6.02991" gradientUnits="userSpaceOnUse">
|
|
20
|
+
<stop stop-color="#394B59"/>
|
|
21
|
+
<stop offset="0.827" stop-color="#394B59"/>
|
|
22
|
+
<stop offset="1" stop-color="#30404D"/>
|
|
23
|
+
</linearGradient>
|
|
24
|
+
</defs>
|
|
25
|
+
</svg>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<svg width="180" height="180" viewBox="0 0 180 180" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<mask id="mask0_408_134" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="180" height="180">
|
|
3
|
+
<circle cx="90" cy="90" r="90" fill="black"/>
|
|
4
|
+
</mask>
|
|
5
|
+
<g mask="url(#mask0_408_134)">
|
|
6
|
+
<circle cx="90" cy="90" r="90" fill="black"/>
|
|
7
|
+
<path d="M149.508 157.52L69.142 54H54V125.97H66.1136V69.3836L139.999 164.845C143.333 162.614 146.509 160.165 149.508 157.52Z" fill="url(#paint0_linear_408_134)"/>
|
|
8
|
+
<rect x="115" y="54" width="12" height="72" fill="url(#paint1_linear_408_134)"/>
|
|
9
|
+
</g>
|
|
10
|
+
<defs>
|
|
11
|
+
<linearGradient id="paint0_linear_408_134" x1="109" y1="116.5" x2="144.5" y2="160.5" gradientUnits="userSpaceOnUse">
|
|
12
|
+
<stop stop-color="white"/>
|
|
13
|
+
<stop offset="1" stop-color="white" stop-opacity="0"/>
|
|
14
|
+
</linearGradient>
|
|
15
|
+
<linearGradient id="paint1_linear_408_134" x1="121" y1="54" x2="120.799" y2="106.875" gradientUnits="userSpaceOnUse">
|
|
16
|
+
<stop stop-color="white"/>
|
|
17
|
+
<stop offset="1" stop-color="white" stop-opacity="0"/>
|
|
18
|
+
</linearGradient>
|
|
19
|
+
</defs>
|
|
20
|
+
</svg>
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.10768 6.06401C4.10768 8.3771 5.96702 10.2526 8.26059 10.2526C10.5543 10.2526 12.4138 8.3771 12.4138 6.06401C12.4138 3.7508 10.5543 1.87553 8.26059 1.87553C5.96702 1.87553 4.10768 3.7508 4.10768 6.06401ZM8.26093 13.923L13.6299 11.5848L14.5217 13.3091L8.26093 16L2 13.3091L2.89201 11.5848L8.26093 13.923ZM8.26101 0C4.94367 0 2.25442 2.71228 2.25442 6.05803C2.25442 9.40378 4.94367 12.1159 8.26101 12.1159C11.5782 12.1159 14.2676 9.40378 14.2676 6.05803C14.2676 2.71228 11.5782 0 8.26101 0Z" fill="#111418"/>
|
|
3
|
+
</svg>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import client from "@/lib/client";
|
|
3
|
+
import { useRouter } from "next/navigation";
|
|
4
|
+
import { useEffect, useState } from "react";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Component to render at `/auth/callback`
|
|
8
|
+
* This calls signIn() again to save the token, and then navigates the user back to the home page.
|
|
9
|
+
*/
|
|
10
|
+
function AuthCallback() {
|
|
11
|
+
const [error, setError] = useState<string | undefined>(undefined);
|
|
12
|
+
const router = useRouter();
|
|
13
|
+
|
|
14
|
+
// This effect conflicts with React 18 strict mode in development
|
|
15
|
+
// https://react.dev/learn/synchronizing-with-effects#how-to-handle-the-effect-firing-twice-in-development
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
client.auth
|
|
18
|
+
.signIn()
|
|
19
|
+
.then(() => router.replace("/"))
|
|
20
|
+
.catch((e: unknown) => setError((e as Error).message ?? e));
|
|
21
|
+
}, [router]);
|
|
22
|
+
return <div>{error != null ? error : "Authenticating…"}</div>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default AuthCallback;
|