@youcan/app 2.2.0 → 2.3.0
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/dist/cli/commands/app/dev.d.ts +3 -4
- package/dist/cli/commands/app/dev.js +40 -35
- package/dist/cli/commands/app/env/show.d.ts +7 -0
- package/dist/cli/commands/app/env/show.js +29 -0
- package/dist/cli/commands/app/generate/extension.d.ts +1 -1
- package/dist/cli/commands/app/generate/extension.js +1 -1
- package/dist/cli/commands/app/install.d.ts +1 -1
- package/dist/cli/commands/app/install.js +1 -1
- package/dist/cli/services/dev/workers/app-worker.js +1 -2
- package/dist/cli/services/dev/workers/index.d.ts +5 -2
- package/dist/cli/services/dev/workers/index.js +9 -3
- package/dist/cli/services/dev/workers/tunnel-worker.d.ts +15 -0
- package/dist/cli/services/dev/workers/tunnel-worker.js +57 -0
- package/dist/cli/services/dev/workers/web-worker.d.ts +5 -4
- package/dist/cli/services/dev/workers/web-worker.js +4 -1
- package/dist/types.d.ts +15 -0
- package/dist/util/app-command.d.ts +8 -0
- package/dist/util/app-command.js +41 -0
- package/package.json +8 -3
- package/dist/util/theme-command.d.ts +0 -3
- package/dist/util/theme-command.js +0 -6
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import { AppCommand } from '@/util/
|
|
1
|
+
import { AppCommand } from '@/util/app-command';
|
|
2
2
|
declare class Dev extends AppCommand {
|
|
3
3
|
static description: string;
|
|
4
|
-
private app;
|
|
5
|
-
private session;
|
|
6
4
|
private readonly hotKeys;
|
|
7
5
|
run(): Promise<any>;
|
|
6
|
+
private prepareNetworkOptions;
|
|
8
7
|
reloadWorkers(): Promise<void>;
|
|
9
8
|
private runWorkers;
|
|
10
|
-
private syncAppConfig;
|
|
11
9
|
private prepareDevProcesses;
|
|
10
|
+
private buildEnvironmentVariables;
|
|
12
11
|
private openAppPreview;
|
|
13
12
|
}
|
|
14
13
|
export default Dev;
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import { Session, Tasks, UI,
|
|
2
|
-
import {
|
|
1
|
+
import { Session, Tasks, UI, System, Services, Env, Http } from '@youcan/cli-kit';
|
|
2
|
+
import { bootTunnelWorker, bootAppWorker, bootWebWorker, bootExtensionWorker } from '../../services/dev/workers/index.js';
|
|
3
|
+
import { AppCommand } from '../../../util/app-command.js';
|
|
3
4
|
import { load } from '../../../util/app-loader.js';
|
|
4
|
-
import { APP_CONFIG_FILENAME } from '../../../constants.js';
|
|
5
|
-
import { bootAppWorker, bootWebWorker, bootExtensionWorker } from '../../services/dev/workers/index.js';
|
|
6
5
|
|
|
7
6
|
class Dev extends AppCommand {
|
|
8
7
|
static description = 'Run the app in dev mode';
|
|
9
|
-
app;
|
|
10
|
-
session;
|
|
11
8
|
hotKeys = [
|
|
12
9
|
{
|
|
13
10
|
keyboardKey: 'p',
|
|
@@ -25,60 +22,68 @@ class Dev extends AppCommand {
|
|
|
25
22
|
this.app = await load();
|
|
26
23
|
const { workers } = await Tasks.run({ cmd: this, workers: [] }, [
|
|
27
24
|
{
|
|
28
|
-
title: '
|
|
29
|
-
task: async () =>
|
|
25
|
+
title: 'Preparing network options...',
|
|
26
|
+
task: async (ctx) => {
|
|
27
|
+
ctx.workers.push(await this.prepareNetworkOptions());
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
title: 'Syncing app configuration...',
|
|
32
|
+
task: async () => { await this.syncAppConfig(); },
|
|
30
33
|
},
|
|
31
34
|
{
|
|
32
35
|
title: 'Preparing dev processes...',
|
|
33
36
|
task: async (ctx) => {
|
|
34
|
-
ctx.workers
|
|
37
|
+
ctx.workers.push(...await this.prepareDevProcesses());
|
|
35
38
|
},
|
|
36
39
|
},
|
|
37
40
|
]);
|
|
38
41
|
UI.renderDevOutput({ hotKeys: this.hotKeys, cmd: this });
|
|
39
42
|
this.runWorkers(workers);
|
|
40
43
|
}
|
|
44
|
+
async prepareNetworkOptions() {
|
|
45
|
+
const port = await System.getNextAvailablePort(3000);
|
|
46
|
+
// Start by `localhost` until a tunneled url is available
|
|
47
|
+
const appUrl = `http://localhost:${port}`;
|
|
48
|
+
this.app.networkConfig = { port, appUrl };
|
|
49
|
+
const worker = await bootTunnelWorker(this, this.app, new Services.Cloudflared());
|
|
50
|
+
return worker;
|
|
51
|
+
}
|
|
41
52
|
async reloadWorkers() {
|
|
42
53
|
this.controller = new AbortController();
|
|
54
|
+
// Preserve network config.
|
|
55
|
+
const networkConfig = this.app.networkConfig;
|
|
43
56
|
this.app = await load();
|
|
57
|
+
this.app.networkConfig = networkConfig;
|
|
44
58
|
await this.syncAppConfig();
|
|
45
59
|
await this.runWorkers(await this.prepareDevProcesses());
|
|
46
60
|
}
|
|
47
61
|
async runWorkers(workers) {
|
|
48
|
-
await Promise.all(workers.map(worker => worker.run())).catch(_ => { });
|
|
49
|
-
}
|
|
50
|
-
async syncAppConfig() {
|
|
51
|
-
const endpoint = this.app.config.id == null
|
|
52
|
-
? `${Env.apiHostname()}/apps/create`
|
|
53
|
-
: `${Env.apiHostname()}/apps/${this.app.config.id}/update`;
|
|
54
|
-
const res = await Http.post(endpoint, {
|
|
55
|
-
headers: { Authorization: `Bearer ${this.session.access_token}` },
|
|
56
|
-
body: JSON.stringify({
|
|
57
|
-
name: this.app.config.name,
|
|
58
|
-
app_url: this.app.config.app_url,
|
|
59
|
-
redirect_urls: this.app.config.redirect_urls,
|
|
60
|
-
}),
|
|
61
|
-
});
|
|
62
|
-
this.app.config = {
|
|
63
|
-
name: res.name,
|
|
64
|
-
id: res.id,
|
|
65
|
-
app_url: res.app_url,
|
|
66
|
-
redirect_urls: res.redirect_urls,
|
|
67
|
-
oauth: {
|
|
68
|
-
scopes: res.scopes,
|
|
69
|
-
client_id: res.client_id,
|
|
70
|
-
},
|
|
71
|
-
};
|
|
72
|
-
await Filesystem.writeJsonFile(Path.join(this.app.root, APP_CONFIG_FILENAME), this.app.config);
|
|
62
|
+
await Promise.all(workers.map(worker => worker.run())).catch((_) => { });
|
|
73
63
|
}
|
|
74
64
|
async prepareDevProcesses() {
|
|
75
65
|
const promises = [
|
|
76
66
|
bootAppWorker(this, this.app),
|
|
77
67
|
];
|
|
78
|
-
this.app.webs.forEach(web => promises.unshift(bootWebWorker(this, this.app, web)));
|
|
68
|
+
this.app.webs.forEach(web => promises.unshift(bootWebWorker(this, this.app, web, this.buildEnvironmentVariables())));
|
|
79
69
|
this.app.extensions.forEach(ext => promises.unshift(bootExtensionWorker(this, this.app, ext)));
|
|
80
70
|
return Promise.all(promises);
|
|
81
71
|
}
|
|
72
|
+
buildEnvironmentVariables() {
|
|
73
|
+
if (!this.app.remoteConfig) {
|
|
74
|
+
throw new Error('remote app config not loaded');
|
|
75
|
+
}
|
|
76
|
+
if (!this.app.networkConfig) {
|
|
77
|
+
throw new Error('app network config is not set');
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
YOUCAN_API_KEY: this.app.remoteConfig.client_id,
|
|
81
|
+
YOUCAN_API_SECRET: this.app.remoteConfig.client_secret,
|
|
82
|
+
YOUCAN_API_SCOPES: this.app.remoteConfig.scopes.join(','),
|
|
83
|
+
APP_URL: this.app.networkConfig.appUrl,
|
|
84
|
+
PORT: this.app.networkConfig.port.toString(),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
82
87
|
async openAppPreview() {
|
|
83
88
|
const endpointUrl = `${Env.apiHostname()}/apps/${this.app.config.id}/authorization-url`;
|
|
84
89
|
const { url } = await Http.get(endpointUrl);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Session, Tasks, Color } from '@youcan/cli-kit';
|
|
2
|
+
import { AppCommand } from '../../../../util/app-command.js';
|
|
3
|
+
import { load } from '../../../../util/app-loader.js';
|
|
4
|
+
|
|
5
|
+
class EnvShow extends AppCommand {
|
|
6
|
+
static description = 'Display app environment variables';
|
|
7
|
+
async run() {
|
|
8
|
+
this.app = await load();
|
|
9
|
+
this.session = await Session.authenticate(this);
|
|
10
|
+
await Tasks.run({}, [
|
|
11
|
+
{
|
|
12
|
+
title: 'Syncing app configuration..',
|
|
13
|
+
task: async () => { await this.syncAppConfig(); },
|
|
14
|
+
},
|
|
15
|
+
]);
|
|
16
|
+
await this.printEnvironmentVariables();
|
|
17
|
+
}
|
|
18
|
+
async printEnvironmentVariables() {
|
|
19
|
+
if (!this.app.remoteConfig) {
|
|
20
|
+
throw new Error('remote app config not loaded');
|
|
21
|
+
}
|
|
22
|
+
this.log();
|
|
23
|
+
this.log(`${Color.yellow('YOUCAN_API_KEY')}=%s`, this.app.remoteConfig.client_id);
|
|
24
|
+
this.log(`${Color.yellow('YOUCAN_API_SECRET')}=%s`, this.app.remoteConfig.client_secret);
|
|
25
|
+
this.log(`${Color.yellow('YOUCAN_API_SCOPES')}=%s`, this.app.remoteConfig.scopes.join(','));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export { EnvShow as default };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Path, Filesystem, String, Tasks } from '@youcan/cli-kit';
|
|
2
|
-
import { AppCommand } from '../../../../util/
|
|
2
|
+
import { AppCommand } from '../../../../util/app-command.js';
|
|
3
3
|
import extensions from '../../../services/generate/extensions/index.js';
|
|
4
4
|
import { ensureExtensionDirectoryExists, initThemeExtension } from '../../../services/generate/generate.js';
|
|
5
5
|
import { APP_CONFIG_FILENAME } from '../../../../constants.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Session, Tasks, Http, Env, System } from '@youcan/cli-kit';
|
|
2
2
|
import { load } from '../../../util/app-loader.js';
|
|
3
|
-
import { AppCommand } from '../../../util/
|
|
3
|
+
import { AppCommand } from '../../../util/app-command.js';
|
|
4
4
|
|
|
5
5
|
class Install extends AppCommand {
|
|
6
6
|
static description = 'Generate an app installation URL';
|
|
@@ -11,8 +11,7 @@ class AppWorker extends Worker.Abstract {
|
|
|
11
11
|
this.app = app;
|
|
12
12
|
this.logger = new Worker.Logger('app', 'green');
|
|
13
13
|
}
|
|
14
|
-
async boot() {
|
|
15
|
-
}
|
|
14
|
+
async boot() { }
|
|
16
15
|
async run() {
|
|
17
16
|
await this.command.output.wait(500);
|
|
18
17
|
this.logger.write('watching for config updates...');
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import type { Cli, Worker } from '@youcan/cli-kit';
|
|
1
|
+
import type { Cli, Services, Worker } from '@youcan/cli-kit';
|
|
2
2
|
import WebWorker from './web-worker';
|
|
3
3
|
import AppWorker from './app-worker';
|
|
4
|
+
import TunnelWorker from './tunnel-worker';
|
|
4
5
|
import type { App, Extension, Web } from '@/types';
|
|
5
6
|
import type DevCommand from '@/cli/commands/app/dev';
|
|
7
|
+
import type { AppCommand } from '@/util/app-command';
|
|
6
8
|
export interface ExtensionWorkerCtor {
|
|
7
9
|
new (command: Cli.Command, app: App, extension: Extension): Worker.Interface;
|
|
8
10
|
}
|
|
9
11
|
export declare function bootAppWorker(command: DevCommand, app: App): Promise<AppWorker>;
|
|
10
12
|
export declare function bootExtensionWorker(command: Cli.Command, app: App, extension: Extension): Promise<Worker.Interface>;
|
|
11
|
-
export declare function bootWebWorker(command: Cli.Command, app: App, web: Web): Promise<WebWorker>;
|
|
13
|
+
export declare function bootWebWorker(command: Cli.Command, app: App, web: Web, env: Record<string, string>): Promise<WebWorker>;
|
|
14
|
+
export declare function bootTunnelWorker(command: AppCommand, app: App, tunnel: Services.Cloudflared): Promise<TunnelWorker>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import ThemeExtensionWorker from './theme-extension-worker.js';
|
|
2
2
|
import WebWorker from './web-worker.js';
|
|
3
3
|
import AppWorker from './app-worker.js';
|
|
4
|
+
import TunnelWorker from './tunnel-worker.js';
|
|
4
5
|
|
|
5
6
|
const EXTENSION_WORKERS = {
|
|
6
7
|
theme: ThemeExtensionWorker,
|
|
@@ -16,10 +17,15 @@ async function bootExtensionWorker(command, app, extension) {
|
|
|
16
17
|
await worker.boot();
|
|
17
18
|
return worker;
|
|
18
19
|
}
|
|
19
|
-
async function bootWebWorker(command, app, web) {
|
|
20
|
-
const worker = new WebWorker(command, app, web);
|
|
20
|
+
async function bootWebWorker(command, app, web, env) {
|
|
21
|
+
const worker = new WebWorker(command, app, web, env);
|
|
22
|
+
await worker.boot();
|
|
23
|
+
return worker;
|
|
24
|
+
}
|
|
25
|
+
async function bootTunnelWorker(command, app, tunnel) {
|
|
26
|
+
const worker = new TunnelWorker(command, app, tunnel);
|
|
21
27
|
await worker.boot();
|
|
22
28
|
return worker;
|
|
23
29
|
}
|
|
24
30
|
|
|
25
|
-
export { bootAppWorker, bootExtensionWorker, bootWebWorker };
|
|
31
|
+
export { bootAppWorker, bootExtensionWorker, bootTunnelWorker, bootWebWorker };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Worker } from '@youcan/cli-kit';
|
|
2
|
+
import type { Services } from '@youcan/cli-kit';
|
|
3
|
+
import type { App } from '@/types';
|
|
4
|
+
import type { AppCommand } from '@/util/app-command';
|
|
5
|
+
export default class TunnelWorker extends Worker.Abstract {
|
|
6
|
+
private command;
|
|
7
|
+
private app;
|
|
8
|
+
private tunnelService;
|
|
9
|
+
private readonly logger;
|
|
10
|
+
private url;
|
|
11
|
+
constructor(command: AppCommand, app: App, tunnelService: Services.Cloudflared);
|
|
12
|
+
boot(): Promise<void>;
|
|
13
|
+
run(): Promise<void>;
|
|
14
|
+
private checkForError;
|
|
15
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Worker, System } from '@youcan/cli-kit';
|
|
2
|
+
|
|
3
|
+
class TunnelWorker extends Worker.Abstract {
|
|
4
|
+
command;
|
|
5
|
+
app;
|
|
6
|
+
tunnelService;
|
|
7
|
+
logger;
|
|
8
|
+
url = null;
|
|
9
|
+
constructor(command, app, tunnelService) {
|
|
10
|
+
super();
|
|
11
|
+
this.command = command;
|
|
12
|
+
this.app = app;
|
|
13
|
+
this.tunnelService = tunnelService;
|
|
14
|
+
this.logger = new Worker.Logger('tunnel', 'dim');
|
|
15
|
+
}
|
|
16
|
+
async boot() {
|
|
17
|
+
if (!this.app.networkConfig) {
|
|
18
|
+
throw new Error('app network config is not set');
|
|
19
|
+
}
|
|
20
|
+
this.logger.write('start tunneling the app');
|
|
21
|
+
await this.tunnelService.tunnel(this.app.networkConfig.port);
|
|
22
|
+
// Stop the execution for while and see if the tunnel is available.
|
|
23
|
+
await System.sleep(5);
|
|
24
|
+
const url = this.tunnelService.getUrl();
|
|
25
|
+
if (url) {
|
|
26
|
+
this.logger.write(`tunneled url obtained: \`${url}\``);
|
|
27
|
+
this.url = url;
|
|
28
|
+
this.app.networkConfig.appUrl = this.url;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async run() {
|
|
32
|
+
const timeInterval = 500;
|
|
33
|
+
if (this.url) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
setInterval(() => {
|
|
37
|
+
if (this.url !== null) {
|
|
38
|
+
this.checkForError();
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
this.url = this.tunnelService.getUrl();
|
|
42
|
+
if (this.url) {
|
|
43
|
+
this.logger.write(`tunneled url obtained: \`${this.url}\``);
|
|
44
|
+
this.app.networkConfig.appUrl = this.url;
|
|
45
|
+
this.command.syncAppConfig();
|
|
46
|
+
}
|
|
47
|
+
}, timeInterval);
|
|
48
|
+
}
|
|
49
|
+
checkForError() {
|
|
50
|
+
const error = this.tunnelService.getError();
|
|
51
|
+
if (error) {
|
|
52
|
+
throw new Error(`Tunnel stopped: ${error}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export { TunnelWorker as default };
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { type Cli, Worker } from '@youcan/cli-kit';
|
|
2
2
|
import type { App, Web } from '@/types';
|
|
3
3
|
export default class WebWorker extends Worker.Abstract {
|
|
4
|
-
private command;
|
|
5
|
-
private app;
|
|
6
|
-
private web;
|
|
4
|
+
private readonly command;
|
|
5
|
+
private readonly app;
|
|
6
|
+
private readonly web;
|
|
7
|
+
private readonly env;
|
|
7
8
|
private logger;
|
|
8
|
-
constructor(command: Cli.Command, app: App, web: Web);
|
|
9
|
+
constructor(command: Cli.Command, app: App, web: Web, env: Record<string, string>);
|
|
9
10
|
boot(): Promise<void>;
|
|
10
11
|
run(): Promise<void>;
|
|
11
12
|
}
|
|
@@ -4,12 +4,14 @@ class WebWorker extends Worker.Abstract {
|
|
|
4
4
|
command;
|
|
5
5
|
app;
|
|
6
6
|
web;
|
|
7
|
+
env;
|
|
7
8
|
logger;
|
|
8
|
-
constructor(command, app, web) {
|
|
9
|
+
constructor(command, app, web, env) {
|
|
9
10
|
super();
|
|
10
11
|
this.command = command;
|
|
11
12
|
this.app = app;
|
|
12
13
|
this.web = web;
|
|
14
|
+
this.env = env;
|
|
13
15
|
this.logger = new Worker.Logger(this.web.config.name || 'web', 'blue');
|
|
14
16
|
}
|
|
15
17
|
async boot() {
|
|
@@ -20,6 +22,7 @@ class WebWorker extends Worker.Abstract {
|
|
|
20
22
|
stdout: this.logger,
|
|
21
23
|
signal: this.command.controller.signal,
|
|
22
24
|
stderr: new Worker.Logger(this.web.config.name || 'web', 'red'),
|
|
25
|
+
env: this.env,
|
|
23
26
|
});
|
|
24
27
|
}
|
|
25
28
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -11,6 +11,16 @@ export type AppConfig = {
|
|
|
11
11
|
scopes: string[];
|
|
12
12
|
};
|
|
13
13
|
} & InitialAppConfig;
|
|
14
|
+
export interface RemoteAppConfig {
|
|
15
|
+
id: string;
|
|
16
|
+
name: string;
|
|
17
|
+
app_url: string;
|
|
18
|
+
owner_id: string;
|
|
19
|
+
client_id: string;
|
|
20
|
+
client_secret: string;
|
|
21
|
+
redirect_urls: string[];
|
|
22
|
+
scopes: string[];
|
|
23
|
+
}
|
|
14
24
|
export interface ExtensionConfig {
|
|
15
25
|
[key: string]: unknown;
|
|
16
26
|
type: string;
|
|
@@ -54,6 +64,11 @@ export interface App {
|
|
|
54
64
|
root: string;
|
|
55
65
|
webs: Web[];
|
|
56
66
|
config: AppConfig;
|
|
67
|
+
remoteConfig?: RemoteAppConfig;
|
|
68
|
+
networkConfig?: {
|
|
69
|
+
appUrl: string;
|
|
70
|
+
port: number;
|
|
71
|
+
};
|
|
57
72
|
extensions: Extension[];
|
|
58
73
|
}
|
|
59
74
|
export interface ExtensionFileDescriptor {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Session } from '@youcan/cli-kit';
|
|
2
|
+
import { Cli } from '@youcan/cli-kit';
|
|
3
|
+
import type { App } from '@/types';
|
|
4
|
+
export declare abstract class AppCommand extends Cli.Command {
|
|
5
|
+
protected app: App;
|
|
6
|
+
protected session: Session.StoreSession;
|
|
7
|
+
syncAppConfig(): Promise<App>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Cli, Env, Http, Filesystem, Path } from '@youcan/cli-kit';
|
|
2
|
+
import { APP_CONFIG_FILENAME } from '../constants.js';
|
|
3
|
+
|
|
4
|
+
class AppCommand extends Cli.Command {
|
|
5
|
+
app;
|
|
6
|
+
session;
|
|
7
|
+
async syncAppConfig() {
|
|
8
|
+
const endpoint = this.app.config.id == null
|
|
9
|
+
? `${Env.apiHostname()}/apps/create`
|
|
10
|
+
: `${Env.apiHostname()}/apps/${this.app.config.id}/update`;
|
|
11
|
+
if (!this.app.networkConfig) {
|
|
12
|
+
throw new Error('app network config is not set');
|
|
13
|
+
}
|
|
14
|
+
const backUrl = new URL('/auth/callback', this.app.networkConfig.appUrl).toString();
|
|
15
|
+
const res = await Http.post(endpoint, {
|
|
16
|
+
headers: { Authorization: `Bearer ${this.session.access_token}` },
|
|
17
|
+
body: JSON.stringify({
|
|
18
|
+
name: this.app.config.name,
|
|
19
|
+
app_url: this.app.networkConfig.appUrl,
|
|
20
|
+
redirect_urls: [
|
|
21
|
+
backUrl,
|
|
22
|
+
],
|
|
23
|
+
}),
|
|
24
|
+
});
|
|
25
|
+
this.app.config = {
|
|
26
|
+
name: res.name,
|
|
27
|
+
id: res.id,
|
|
28
|
+
app_url: res.app_url,
|
|
29
|
+
redirect_urls: res.redirect_urls,
|
|
30
|
+
oauth: {
|
|
31
|
+
scopes: res.scopes,
|
|
32
|
+
client_id: res.client_id,
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
await Filesystem.writeJsonFile(Path.join(this.app.root, APP_CONFIG_FILENAME), this.app.config);
|
|
36
|
+
this.app.remoteConfig = res;
|
|
37
|
+
return this.app;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export { AppCommand };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@youcan/app",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.3.0",
|
|
5
5
|
"description": "OCLIF plugin for building apps",
|
|
6
6
|
"author": "YouCan <contact@youcan.shop> (https://youcan.shop)",
|
|
7
7
|
"license": "MIT",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@oclif/core": "^2.15.0",
|
|
19
19
|
"dayjs": "^1.11.10",
|
|
20
|
-
"@youcan/cli-kit": "2.
|
|
20
|
+
"@youcan/cli-kit": "2.3.0"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@oclif/plugin-legacy": "^1.3.0",
|
|
@@ -25,7 +25,12 @@
|
|
|
25
25
|
"shx": "^0.3.4"
|
|
26
26
|
},
|
|
27
27
|
"oclif": {
|
|
28
|
-
"commands": "./dist/cli/commands"
|
|
28
|
+
"commands": "./dist/cli/commands",
|
|
29
|
+
"topics": {
|
|
30
|
+
"app:env": {
|
|
31
|
+
"description": "Manage app environment variables"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
29
34
|
},
|
|
30
35
|
"scripts": {
|
|
31
36
|
"build": "shx rm -rf dist && tsc --noEmit && rollup --config rollup.config.js",
|