@appsemble/cli 0.30.14-test.6 → 0.32.1-test.15
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 +3 -3
- package/commands/app/create.js +9 -4
- package/commands/app/delete.js +1 -1
- package/commands/app/export.js +1 -1
- package/commands/app/patch.d.ts +2 -0
- package/commands/app/patch.js +8 -0
- package/commands/app/update.js +1 -1
- package/commands/asset/publish.js +1 -1
- package/commands/cleanupSoftDeletedRecords.d.ts +6 -0
- package/commands/cleanupSoftDeletedRecords.js +40 -0
- package/commands/config/get.js +6 -2
- package/commands/config/set.js +6 -1
- package/commands/migrate.js +19 -0
- package/commands/serve.js +5 -1
- package/commands/start.js +19 -0
- package/commands/synchronizeTrainings.d.ts +6 -0
- package/commands/synchronizeTrainings.js +40 -0
- package/index.js +5 -0
- package/lib/app.d.ts +8 -0
- package/lib/app.js +59 -17
- package/lib/asset.d.ts +1 -1
- package/lib/authentication.js +4 -4
- package/lib/block.js +15 -6
- package/lib/coercers.js +1 -0
- package/lib/config.js +26 -18
- package/lib/createServers.js +3 -1
- package/lib/group.d.ts +1 -1
- package/lib/group.js +7 -6
- package/lib/output.js +3 -1
- package/lib/processCss.js +1 -1
- package/lib/project.js +3 -2
- package/lib/serverImport.d.ts +1 -1
- package/lib/serverImport.js +1 -1
- package/package.json +19 -16
- package/server/db/methods.js +3 -0
- package/server/options/createAppAsset.d.ts +1 -1
- package/server/options/createAppAsset.js +5 -6
- package/server/options/createAppResourcesWithAssets.js +4 -6
- package/server/options/createSettings.js +1 -1
- package/server/options/createTheme.js +2 -0
- package/server/options/getAppAsset.js +5 -10
- package/server/options/getAppAssets.js +5 -9
- package/server/options/getAppScreenshots.js +3 -3
- package/server/options/getBlockAsset.js +3 -0
- package/server/options/getTheme.js +1 -0
- package/server/options/options.js +2 -0
- package/templates/apps/empty/app-definition.yaml +2 -2
- package/templates/blocks/mini-jsx/package.json +4 -1
- package/templates/blocks/mini-jsx/src/index.tsx +1 -1
- package/templates/blocks/preact/package.json +5 -2
- package/templates/blocks/vanilla/package.json +4 -1
- package/vitest.setup.js +11 -2
- package/lib/app.test.d.ts +0 -1
- package/lib/app.test.js +0 -2212
- package/lib/asset.test.d.ts +0 -1
- package/lib/asset.test.js +0 -105
- package/lib/block.test.d.ts +0 -1
- package/lib/block.test.js +0 -235
- package/lib/coercers.test.d.ts +0 -1
- package/lib/coercers.test.js +0 -27
- package/lib/config.test.d.ts +0 -1
- package/lib/config.test.js +0 -239
- package/lib/group.test.d.ts +0 -1
- package/lib/group.test.js +0 -616
- package/lib/organization.test.d.ts +0 -1
- package/lib/organization.test.js +0 -222
- package/lib/resource.test.d.ts +0 -1
- package/lib/resource.test.js +0 -393
- package/server/db/methods.test.d.ts +0 -1
- package/server/db/methods.test.js +0 -366
- package/server/options/parseQuery.test.d.ts +0 -1
- package/server/options/parseQuery.test.js +0 -46
package/README.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
#  Appsemble CLI
|
|
2
2
|
|
|
3
3
|
> Manage apps and blocks from the command line.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@appsemble/cli)
|
|
6
|
-
[](https://gitlab.com/appsemble/appsemble/-/releases/0.32.1-test.15)
|
|
7
7
|
[](https://prettier.io)
|
|
8
8
|
|
|
9
9
|
## Table of Contents
|
|
@@ -323,5 +323,5 @@ appsemble run-cronjobs --interval 30
|
|
|
323
323
|
|
|
324
324
|
## License
|
|
325
325
|
|
|
326
|
-
[LGPL-3.0-only](https://gitlab.com/appsemble/appsemble/-/blob/0.
|
|
326
|
+
[LGPL-3.0-only](https://gitlab.com/appsemble/appsemble/-/blob/0.32.1-test.15/LICENSE.md) ©
|
|
327
327
|
[Appsemble](https://appsemble.com)
|
package/commands/app/create.js
CHANGED
|
@@ -96,7 +96,7 @@ export async function handler(args) {
|
|
|
96
96
|
when: (appOptions) => appOptions.security,
|
|
97
97
|
},
|
|
98
98
|
!args.cronJobs && {
|
|
99
|
-
name: '
|
|
99
|
+
name: 'cronJobs',
|
|
100
100
|
message: 'Would you like to add a cron-job to the definition of the app.',
|
|
101
101
|
type: 'confirm',
|
|
102
102
|
default: false,
|
|
@@ -114,14 +114,19 @@ export async function handler(args) {
|
|
|
114
114
|
const languages = answers.languages || args.languages;
|
|
115
115
|
const resource = answers.resource || args.resource;
|
|
116
116
|
const security = answers.security || args.security;
|
|
117
|
-
const cronJobs = answers
|
|
117
|
+
const cronJobs = answers.cronJobs || args.cronJobs;
|
|
118
118
|
const { groups } = answers;
|
|
119
|
+
// @ts-expect-error 2345 argument of type is not assignable to parameter of type
|
|
120
|
+
// (strictNullChecks)
|
|
119
121
|
const outputDirectory = join(path, name);
|
|
122
|
+
// @ts-expect-error 2345 argument of type is not assignable to parameter of type
|
|
123
|
+
// (strictNullChecks)
|
|
120
124
|
const inputDirectory = join(`${templatesDir}/`, template);
|
|
121
125
|
const appsembleRcPath = join(inputDirectory, '.appsemblerc.yaml');
|
|
122
126
|
const [appsembleRc] = await readData(appsembleRcPath);
|
|
123
127
|
const outputAppsembleRcObject = { ...appsembleRc };
|
|
124
|
-
|
|
128
|
+
outputAppsembleRcObject.context ?? (outputAppsembleRcObject.context = {});
|
|
129
|
+
for (const key of Object.keys(appsembleRc.context ?? {})) {
|
|
125
130
|
outputAppsembleRcObject.context[key].organization = organization;
|
|
126
131
|
}
|
|
127
132
|
const outputAppsembleRc = parse(stringify(outputAppsembleRcObject));
|
|
@@ -187,7 +192,7 @@ export async function handler(args) {
|
|
|
187
192
|
force: false,
|
|
188
193
|
recursive: true,
|
|
189
194
|
});
|
|
190
|
-
for (const language of languages) {
|
|
195
|
+
for (const language of languages ?? []) {
|
|
191
196
|
await writeData(join(outputDirectory, 'i18n', `${language}.json`), {});
|
|
192
197
|
}
|
|
193
198
|
await writeData(join(outputDirectory, '.appsemblerc.yaml'), outputAppsembleRc);
|
package/commands/app/delete.js
CHANGED
|
@@ -8,6 +8,6 @@ export function builder(yargs) {
|
|
|
8
8
|
});
|
|
9
9
|
}
|
|
10
10
|
export async function handler({ clientCredentials, id, remote, }) {
|
|
11
|
-
await deleteApp({ id, remote, clientCredentials });
|
|
11
|
+
await deleteApp({ id, remote, clientCredentials: clientCredentials ?? '' });
|
|
12
12
|
}
|
|
13
13
|
//# sourceMappingURL=delete.js.map
|
package/commands/app/export.js
CHANGED
|
@@ -25,7 +25,7 @@ export async function handler(args) {
|
|
|
25
25
|
const { assets = false, clientCredentials, id: appId, path: outputDirectory, remote, resources = false, } = args;
|
|
26
26
|
const defaultOutputDirectory = join(process.cwd(), 'apps');
|
|
27
27
|
logger.info(`Exporting app with id: ${appId}`);
|
|
28
|
-
await exportAppAsZip(clientCredentials, appId, assets, resources, outputDirectory || defaultOutputDirectory, remote);
|
|
28
|
+
await exportAppAsZip(clientCredentials ?? '', appId, assets, resources, outputDirectory || defaultOutputDirectory, remote);
|
|
29
29
|
logger.info('Export completed successfully');
|
|
30
30
|
}
|
|
31
31
|
//# sourceMappingURL=export.js.map
|
package/commands/app/patch.d.ts
CHANGED
|
@@ -13,6 +13,8 @@ interface PatchAppArguments extends BaseArguments {
|
|
|
13
13
|
locked?: AppLock;
|
|
14
14
|
showAppsembleOAuth2Login?: boolean;
|
|
15
15
|
showAppsembleLogin?: boolean;
|
|
16
|
+
displayAppMemberName?: boolean;
|
|
17
|
+
displayInstallationPrompt?: boolean;
|
|
16
18
|
enableSelfRegistration?: boolean;
|
|
17
19
|
}
|
|
18
20
|
export declare const command = "patch";
|
package/commands/app/patch.js
CHANGED
|
@@ -46,6 +46,14 @@ export function builder(yargs) {
|
|
|
46
46
|
.option('enableSelfRegistration', {
|
|
47
47
|
description: 'Whether new users should be able to register themselves',
|
|
48
48
|
type: 'boolean',
|
|
49
|
+
})
|
|
50
|
+
.option('displayAppMemberName', {
|
|
51
|
+
description: 'Whether to display the app member name in the title bar',
|
|
52
|
+
type: 'boolean',
|
|
53
|
+
})
|
|
54
|
+
.option('displayInstallationPrompt', {
|
|
55
|
+
description: 'Whether to prompt the app users to display the installation prompts',
|
|
56
|
+
type: 'boolean',
|
|
49
57
|
})
|
|
50
58
|
.option('force', {
|
|
51
59
|
description: 'Whether the lock property should be ignored',
|
package/commands/app/update.js
CHANGED
|
@@ -53,7 +53,7 @@ export async function handler({ app, appId, clientCredentials, clonable, context
|
|
|
53
53
|
for (const path of files) {
|
|
54
54
|
logger.info('');
|
|
55
55
|
await publishAsset({
|
|
56
|
-
name: name || (useFileName ? parse(path).name :
|
|
56
|
+
name: name || (useFileName ? parse(path).name : undefined),
|
|
57
57
|
appId: resolvedAppId,
|
|
58
58
|
path,
|
|
59
59
|
seed,
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type Argv } from 'yargs';
|
|
2
|
+
import { type BaseArguments } from '../types.js';
|
|
3
|
+
export declare const command = "cleanup-soft-deleted-records";
|
|
4
|
+
export declare const description = "Permanently deleted soft deleted records that are older than one month";
|
|
5
|
+
export declare function builder(yargs: Argv): Argv<any>;
|
|
6
|
+
export declare function handler(argv: BaseArguments): Promise<void>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { serverImport } from '../lib/serverImport.js';
|
|
2
|
+
export const command = 'cleanup-soft-deleted-records';
|
|
3
|
+
export const description = 'Permanently deleted soft deleted records that are older than one month';
|
|
4
|
+
export function builder(yargs) {
|
|
5
|
+
return yargs
|
|
6
|
+
.option('database-host', {
|
|
7
|
+
desc: 'The host of the database to connect to. This defaults to the connected database container.',
|
|
8
|
+
})
|
|
9
|
+
.option('database-port', {
|
|
10
|
+
desc: 'The port of the database to connect to.',
|
|
11
|
+
type: 'number',
|
|
12
|
+
default: 5432,
|
|
13
|
+
})
|
|
14
|
+
.option('database-ssl', {
|
|
15
|
+
desc: 'Use SSL to connect to the database.',
|
|
16
|
+
type: 'boolean',
|
|
17
|
+
})
|
|
18
|
+
.option('database-name', {
|
|
19
|
+
desc: 'The name of the database to connect to.',
|
|
20
|
+
implies: ['database-user', 'database-password'],
|
|
21
|
+
})
|
|
22
|
+
.option('database-user', {
|
|
23
|
+
desc: 'The user to use to login to the database.',
|
|
24
|
+
implies: ['database-name', 'database-password'],
|
|
25
|
+
})
|
|
26
|
+
.option('database-password', {
|
|
27
|
+
desc: 'The password to use to login to the database.',
|
|
28
|
+
implies: ['database-name', 'database-user'],
|
|
29
|
+
})
|
|
30
|
+
.option('database-url', {
|
|
31
|
+
desc: 'A connection string for the database to connect to. This is an alternative to the separate database related variables.',
|
|
32
|
+
conflicts: ['database-host', 'database-name', 'database-user', 'database-password'],
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
export async function handler(argv) {
|
|
36
|
+
const { cleanupSoftDeletedRecords, setArgv } = await serverImport('setArgv', 'cleanupSoftDeletedRecords');
|
|
37
|
+
setArgv(argv);
|
|
38
|
+
return cleanupSoftDeletedRecords();
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=cleanupSoftDeletedRecords.js.map
|
package/commands/config/get.js
CHANGED
|
@@ -8,11 +8,15 @@ export function builder(yargs) {
|
|
|
8
8
|
});
|
|
9
9
|
}
|
|
10
10
|
export async function handler({ key }) {
|
|
11
|
-
const
|
|
11
|
+
const readResult = await readPackageUp({ normalize: false });
|
|
12
|
+
if (!readResult) {
|
|
13
|
+
throw new Error('Could not find package.json in the current directory or any of its parents');
|
|
14
|
+
}
|
|
15
|
+
const { packageJson } = readResult;
|
|
12
16
|
const pkg = packageJson;
|
|
13
17
|
if (has(pkg, 'appsembleServer')) {
|
|
14
18
|
// eslint-disable-next-line no-console
|
|
15
|
-
console.log(pkg.appsembleServer[key]);
|
|
19
|
+
console.log(pkg.appsembleServer?.[key]);
|
|
16
20
|
}
|
|
17
21
|
}
|
|
18
22
|
//# sourceMappingURL=get.js.map
|
package/commands/config/set.js
CHANGED
|
@@ -14,7 +14,11 @@ export function builder(yargs) {
|
|
|
14
14
|
});
|
|
15
15
|
}
|
|
16
16
|
export async function handler({ key, value }) {
|
|
17
|
-
const
|
|
17
|
+
const readResult = await readPackageUp({ normalize: false });
|
|
18
|
+
if (!readResult) {
|
|
19
|
+
throw new Error('Could not find package.json in the current directory or any of its parents');
|
|
20
|
+
}
|
|
21
|
+
const { packageJson, path } = readResult;
|
|
18
22
|
const pkg = packageJson;
|
|
19
23
|
if (!has(pkg, 'appsembleServer')) {
|
|
20
24
|
pkg.appsembleServer = {};
|
|
@@ -26,6 +30,7 @@ export async function handler({ key, value }) {
|
|
|
26
30
|
catch {
|
|
27
31
|
parsed = value;
|
|
28
32
|
}
|
|
33
|
+
pkg.appsembleServer ?? (pkg.appsembleServer = {});
|
|
29
34
|
pkg.appsembleServer[key] = parsed;
|
|
30
35
|
await writeData(path, packageJson);
|
|
31
36
|
logger.info(`Set option appsembleServer.${key} to ${inspect(parsed, { colors: true })} in ${path}`);
|
package/commands/migrate.js
CHANGED
|
@@ -35,6 +35,25 @@ export function builder(yargs) {
|
|
|
35
35
|
.option('database-url', {
|
|
36
36
|
desc: 'A connection string for the database to connect to. This is an alternative to the separate database related variables.',
|
|
37
37
|
conflicts: ['database-host', 'database-name', 'database-user', 'database-password'],
|
|
38
|
+
})
|
|
39
|
+
.option('s3-host', {
|
|
40
|
+
desc: 'The host of the Amazon S3 compatible object storage server',
|
|
41
|
+
})
|
|
42
|
+
.option('s3-port', {
|
|
43
|
+
desc: 'The port of the Amazon S3 compatible object storage server',
|
|
44
|
+
type: 'number',
|
|
45
|
+
default: 9000,
|
|
46
|
+
})
|
|
47
|
+
.option('s3-secure', {
|
|
48
|
+
desc: 'Whether ssl should be used for the Amazon S3 compatible object storage server',
|
|
49
|
+
type: 'boolean',
|
|
50
|
+
default: true,
|
|
51
|
+
})
|
|
52
|
+
.option('s3-access-key', {
|
|
53
|
+
desc: 'The access key of the Amazon S3 compatible object storage server',
|
|
54
|
+
})
|
|
55
|
+
.option('s3-secret-key', {
|
|
56
|
+
desc: 'The secret key of the Amazon S3 compatible object storage server',
|
|
38
57
|
});
|
|
39
58
|
}
|
|
40
59
|
export async function handler(argv) {
|
package/commands/serve.js
CHANGED
|
@@ -70,6 +70,7 @@ export async function handler(argv) {
|
|
|
70
70
|
name: 'dev',
|
|
71
71
|
email: 'dev@example.com',
|
|
72
72
|
email_verified: true,
|
|
73
|
+
// @ts-expect-error 2322 null is not assignable to type (strictNullChecks)
|
|
73
74
|
role: passedUserRole || appSecurity?.default?.role,
|
|
74
75
|
demo: false,
|
|
75
76
|
zoneinfo: '',
|
|
@@ -155,7 +156,10 @@ export async function handler(argv) {
|
|
|
155
156
|
const localBlocks = await Promise.all(localBlocksPromises);
|
|
156
157
|
const remoteBlocks = await Promise.all(remoteBlocksPromises);
|
|
157
158
|
const appBlocks = [...localBlocks, ...remoteBlocks];
|
|
158
|
-
const webpackConfigs = await Promise.all(localBlocksConfigs.map((blockConfig) => getProjectWebpackConfig(blockConfig, 'development',
|
|
159
|
+
const webpackConfigs = await Promise.all(localBlocksConfigs.map((blockConfig) => getProjectWebpackConfig(blockConfig, 'development',
|
|
160
|
+
// @ts-expect-error 2345 argument of type is not assignable to parameter of type
|
|
161
|
+
// (strictNullChecks)
|
|
162
|
+
join(blockConfig.dir, blockConfig.output))));
|
|
159
163
|
// Get app messages
|
|
160
164
|
const appMessages = [];
|
|
161
165
|
await opendirSafe(join(appPath, 'i18n'), async (path) => {
|
package/commands/start.js
CHANGED
|
@@ -120,6 +120,25 @@ export function builder(yargs) {
|
|
|
120
120
|
.option('ssl-cert', {
|
|
121
121
|
desc: 'The SSL certificate to use, either as a string or as a file path.',
|
|
122
122
|
implies: ['ssl', 'ssl-key'],
|
|
123
|
+
})
|
|
124
|
+
.option('s3-host', {
|
|
125
|
+
desc: 'The host of the Amazon S3 compatible object storage server',
|
|
126
|
+
})
|
|
127
|
+
.option('s3-port', {
|
|
128
|
+
desc: 'The port of the Amazon S3 compatible object storage server',
|
|
129
|
+
type: 'number',
|
|
130
|
+
default: 9000,
|
|
131
|
+
})
|
|
132
|
+
.option('s3-secure', {
|
|
133
|
+
desc: 'Whether ssl should be used for the Amazon S3 compatible object storage server',
|
|
134
|
+
type: 'boolean',
|
|
135
|
+
default: true,
|
|
136
|
+
})
|
|
137
|
+
.option('s3-access-key', {
|
|
138
|
+
desc: 'The access key of the Amazon S3 compatible object storage server',
|
|
139
|
+
})
|
|
140
|
+
.option('s3-secret-key', {
|
|
141
|
+
desc: 'The secret key of the Amazon S3 compatible object storage server',
|
|
123
142
|
});
|
|
124
143
|
}
|
|
125
144
|
export async function handler(argv) {
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type Argv } from 'yargs';
|
|
2
|
+
import { type ServeArguments } from './serve.js';
|
|
3
|
+
export declare const command = "synchronize-trainings";
|
|
4
|
+
export declare const description = "Checks the training folder for training documents and makes sure they are synchronized with the database";
|
|
5
|
+
export declare function builder(yargs: Argv): Argv<any>;
|
|
6
|
+
export declare function handler(argv: ServeArguments): Promise<void>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { serverImport } from '../lib/serverImport.js';
|
|
2
|
+
export const command = 'synchronize-trainings';
|
|
3
|
+
export const description = 'Checks the training folder for training documents and makes sure they are synchronized with the database';
|
|
4
|
+
export function builder(yargs) {
|
|
5
|
+
return yargs
|
|
6
|
+
.option('database-host', {
|
|
7
|
+
desc: 'The host of the database to connect to. This defaults to the connected database container.',
|
|
8
|
+
})
|
|
9
|
+
.option('database-port', {
|
|
10
|
+
desc: 'The port of the database to connect to.',
|
|
11
|
+
type: 'number',
|
|
12
|
+
default: 5432,
|
|
13
|
+
})
|
|
14
|
+
.option('database-ssl', {
|
|
15
|
+
desc: 'Use SSL to connect to the database.',
|
|
16
|
+
type: 'boolean',
|
|
17
|
+
})
|
|
18
|
+
.option('database-name', {
|
|
19
|
+
desc: 'The name of the database to connect to.',
|
|
20
|
+
implies: ['database-user', 'database-password'],
|
|
21
|
+
})
|
|
22
|
+
.option('database-user', {
|
|
23
|
+
desc: 'The user to use to login to the database.',
|
|
24
|
+
implies: ['database-name', 'database-password'],
|
|
25
|
+
})
|
|
26
|
+
.option('database-password', {
|
|
27
|
+
desc: 'The password to use to login to the database.',
|
|
28
|
+
implies: ['database-name', 'database-user'],
|
|
29
|
+
})
|
|
30
|
+
.option('database-url', {
|
|
31
|
+
desc: 'A connection string for the database to connect to. This is an alternative to the separate database related variables.',
|
|
32
|
+
conflicts: ['database-host', 'database-name', 'database-user', 'database-password'],
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
export async function handler(argv) {
|
|
36
|
+
const { setArgv, synchronizeTrainings } = await serverImport('setArgv', 'synchronizeTrainings');
|
|
37
|
+
setArgv(argv);
|
|
38
|
+
return synchronizeTrainings();
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=synchronizeTrainings.js.map
|
package/index.js
CHANGED
|
@@ -10,6 +10,7 @@ import * as checkDownMigrations from './commands/checkDownMigrations.js';
|
|
|
10
10
|
import * as checkMigrations from './commands/checkMigrations.js';
|
|
11
11
|
import * as cleanupDemoAppMembers from './commands/cleanupDemoAppMembers.js';
|
|
12
12
|
import * as cleanupResourcesAndAssets from './commands/cleanupResourcesAndAssets.js';
|
|
13
|
+
import * as cleanupSoftDeletedRecords from './commands/cleanupSoftDeletedRecords.js';
|
|
13
14
|
import * as config from './commands/config/index.js';
|
|
14
15
|
import * as fuzzMigrations from './commands/fuzzMigrations.js';
|
|
15
16
|
import * as group from './commands/group/index.js';
|
|
@@ -23,6 +24,7 @@ import * as runCronJobs from './commands/runCronJobs.js';
|
|
|
23
24
|
import * as scaleContainers from './commands/scaleContainers.js';
|
|
24
25
|
import * as serve from './commands/serve.js';
|
|
25
26
|
import * as start from './commands/start.js';
|
|
27
|
+
import * as synchronizeTrainings from './commands/synchronizeTrainings.js';
|
|
26
28
|
import { coerceRemote } from './lib/coercers.js';
|
|
27
29
|
import { initAxios } from './lib/initAxios.js';
|
|
28
30
|
process.title = 'appsemble';
|
|
@@ -48,12 +50,14 @@ let parser = yargs(process.argv.slice(2))
|
|
|
48
50
|
.option('client-credentials', {
|
|
49
51
|
description: `OAuth2 client credentials formatted as "client_id:client_secret". This may also be defined in the ${CREDENTIALS_ENV_VAR} environment variable.`,
|
|
50
52
|
})
|
|
53
|
+
// @ts-expect-error 2322 ... is not assignable to type (strictNullChecks)
|
|
51
54
|
.middleware([configureLogger, initAxios])
|
|
52
55
|
.command(app)
|
|
53
56
|
.command(asset)
|
|
54
57
|
.command(block)
|
|
55
58
|
.command(cleanupResourcesAndAssets)
|
|
56
59
|
.command(cleanupDemoAppMembers)
|
|
60
|
+
.command(cleanupSoftDeletedRecords)
|
|
57
61
|
.command(checkMigrations)
|
|
58
62
|
.command(checkDownMigrations)
|
|
59
63
|
.command(fuzzMigrations)
|
|
@@ -66,6 +70,7 @@ let parser = yargs(process.argv.slice(2))
|
|
|
66
70
|
.command(resource)
|
|
67
71
|
.command(runCronJobs)
|
|
68
72
|
.command(start)
|
|
73
|
+
.command(synchronizeTrainings)
|
|
69
74
|
.command(serve)
|
|
70
75
|
.command(scaleContainers)
|
|
71
76
|
.command(group)
|
package/lib/app.d.ts
CHANGED
|
@@ -272,6 +272,14 @@ interface PatchAppParams {
|
|
|
272
272
|
* Whether the Appsemble password login method should be shown.
|
|
273
273
|
*/
|
|
274
274
|
showAppsembleLogin?: boolean;
|
|
275
|
+
/**
|
|
276
|
+
* Whether to display the app member name in the title bar.
|
|
277
|
+
*/
|
|
278
|
+
displayAppMemberName?: boolean;
|
|
279
|
+
/**
|
|
280
|
+
* Whether to prompt the app users to display the installation prompts
|
|
281
|
+
*/
|
|
282
|
+
displayInstallationPrompt?: boolean;
|
|
275
283
|
/**
|
|
276
284
|
* Whether the Appsemble OAuth2 login method should be shown.
|
|
277
285
|
*/
|
package/lib/app.js
CHANGED
|
@@ -129,7 +129,8 @@ export async function traverseAppDirectory(path, context, formData) {
|
|
|
129
129
|
controllerPath = join(path, 'controller');
|
|
130
130
|
controllerBuildConfig = await getProjectBuildConfig(controllerPath);
|
|
131
131
|
controllerBuildResult = await buildProject(controllerBuildConfig);
|
|
132
|
-
|
|
132
|
+
// @ts-expect-error 2322 null is not assignable to type (strictNullChecks)
|
|
133
|
+
controllerCode = controllerBuildResult.outputFiles?.[0].text;
|
|
133
134
|
formData.append('controllerCode', controllerCode);
|
|
134
135
|
gatheredData.controllerCode = controllerCode;
|
|
135
136
|
[, controllerImplementations] = await makeProjectPayload(controllerBuildConfig);
|
|
@@ -140,16 +141,18 @@ export async function traverseAppDirectory(path, context, formData) {
|
|
|
140
141
|
break;
|
|
141
142
|
}
|
|
142
143
|
});
|
|
144
|
+
// @ts-expect-error 2454 Variable used before it was assigned
|
|
143
145
|
if (yaml === undefined) {
|
|
144
146
|
throw new AppsembleError('No app definition found');
|
|
145
147
|
}
|
|
146
148
|
discoveredContext || (discoveredContext = {});
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
149
|
+
// @ts-expect-error 2454 Variable used before it was assigned
|
|
150
|
+
// eslint-disable-next-line prettier/prettier
|
|
151
|
+
discoveredContext.icon = discoveredContext.icon ? resolve(path, discoveredContext.icon) : iconPath;
|
|
152
|
+
// @ts-expect-error 2454 Variable used before it was assigned
|
|
153
|
+
// eslint-disable-next-line prettier/prettier
|
|
154
|
+
discoveredContext.maskableIcon = discoveredContext.maskableIcon ? resolve(path, discoveredContext.maskableIcon) : maskableIconPath;
|
|
155
|
+
// @ts-expect-error 2454 Variable used before it was assigned
|
|
153
156
|
return [discoveredContext, rc, yaml, gatheredData];
|
|
154
157
|
}
|
|
155
158
|
function extractFilenameFromContentDisposition(contentDisposition) {
|
|
@@ -186,12 +189,12 @@ async function retrieveContext(path, context) {
|
|
|
186
189
|
}
|
|
187
190
|
});
|
|
188
191
|
discoveredContext || (discoveredContext = {});
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
192
|
+
// @ts-expect-error 2454 Variable used before it was assigned
|
|
193
|
+
// eslint-disable-next-line prettier/prettier
|
|
194
|
+
discoveredContext.icon = discoveredContext.icon ? resolve(path, discoveredContext.icon) : iconPath;
|
|
195
|
+
// @ts-expect-error 2454 Variable used before it was assigned
|
|
196
|
+
// eslint-disable-next-line prettier/prettier
|
|
197
|
+
discoveredContext.maskableIcon = discoveredContext.maskableIcon ? resolve(path, discoveredContext.maskableIcon) : maskableIconPath;
|
|
195
198
|
return discoveredContext;
|
|
196
199
|
}
|
|
197
200
|
/**
|
|
@@ -285,8 +288,10 @@ export async function publishSeedResources(path, app, remote) {
|
|
|
285
288
|
if (resource.isFile()) {
|
|
286
289
|
const { name } = parse(resource.name);
|
|
287
290
|
resourcesToPublish.push({
|
|
291
|
+
// @ts-expect-error 2322 null is not assignable to type (strictNullChecks)
|
|
288
292
|
appId: app.id,
|
|
289
293
|
path: join(resourcesPath, resource.name),
|
|
294
|
+
// @ts-expect-error 2322 null is not assignable to type (strictNullChecks)
|
|
290
295
|
definition: app.definition.resources?.[name],
|
|
291
296
|
type: name,
|
|
292
297
|
});
|
|
@@ -297,8 +302,10 @@ export async function publishSeedResources(path, app, remote) {
|
|
|
297
302
|
});
|
|
298
303
|
for (const subResource of subDirectoryResources.filter((s) => s.isFile())) {
|
|
299
304
|
resourcesToPublish.push({
|
|
305
|
+
// @ts-expect-error 2322 null is not assignable to type (strictNullChecks)
|
|
300
306
|
appId: app.id,
|
|
301
307
|
path: join(resourcesPath, resource.name, subResource.name),
|
|
308
|
+
// @ts-expect-error 2322 null is not assignable to type (strictNullChecks)
|
|
302
309
|
definition: app.definition.resources?.[resource.name],
|
|
303
310
|
type: resource.name,
|
|
304
311
|
});
|
|
@@ -339,6 +346,7 @@ export async function publishSeedAssets(path, app, remote, assetsClonable) {
|
|
|
339
346
|
for (const assetFilePath of files) {
|
|
340
347
|
await publishAsset({
|
|
341
348
|
name: parse(assetFilePath).name,
|
|
349
|
+
// @ts-expect-error 2322 null is not assignable to type (strictNullChecks)
|
|
342
350
|
appId: app.id,
|
|
343
351
|
path: assetFilePath,
|
|
344
352
|
remote,
|
|
@@ -361,6 +369,7 @@ function parseValueFromDefinition(value) {
|
|
|
361
369
|
if (typeof parsed === 'string' && parsed.includes('{{') && parsed.includes('}}')) {
|
|
362
370
|
parsed = parsed.replaceAll(/{{\s*([^\s{}]+)\s*}}/g, (match, variable) => process.env[variable.trim()] || match);
|
|
363
371
|
}
|
|
372
|
+
// @ts-expect-error 2322 null is not assignable to type (strictNullChecks)
|
|
364
373
|
return parsed;
|
|
365
374
|
}
|
|
366
375
|
export function parseValues(type, name, valuesToParse) {
|
|
@@ -413,6 +422,8 @@ export async function publishAppConfig(path, app, remote) {
|
|
|
413
422
|
logger.info(`Publishing ${serviceSecrets.length} app service secret(s)`);
|
|
414
423
|
for (const serviceSecret of serviceSecrets) {
|
|
415
424
|
const { identifier, name, secret, urlPatterns, ...rest } = serviceSecret;
|
|
425
|
+
// @ts-expect-error 2345 argument of type is not assignable to parameter of type
|
|
426
|
+
// (strictNullChecks)
|
|
416
427
|
const [parsedValues, missingValues] = parseValues('service secret', name, [
|
|
417
428
|
{ secret },
|
|
418
429
|
{ identifier },
|
|
@@ -720,6 +731,8 @@ export async function resolveAppIdAndRemote(appPath, name, defaultRemote, defaul
|
|
|
720
731
|
export async function publishApp({ clientCredentials, context, dryRun, modifyContext, path, ...options }) {
|
|
721
732
|
const file = await stat(path);
|
|
722
733
|
const formData = new FormData();
|
|
734
|
+
// @ts-expect-error 2345 argument of type is not assignable to parameter of type
|
|
735
|
+
// (strictNullChecks)
|
|
723
736
|
const appsembleContext = await retrieveContext(path, context);
|
|
724
737
|
let rc;
|
|
725
738
|
let yaml;
|
|
@@ -741,7 +754,9 @@ export async function publishApp({ clientCredentials, context, dryRun, modifyCon
|
|
|
741
754
|
}
|
|
742
755
|
else {
|
|
743
756
|
let appsembleVariantContext;
|
|
744
|
-
[appsembleVariantContext, rc, yaml] = await traverseAppDirectory(appVariantPath,
|
|
757
|
+
[appsembleVariantContext, rc, yaml] = await traverseAppDirectory(appVariantPath,
|
|
758
|
+
// @ts-expect-error 2322 null is not assignable to type (strictNullChecks)
|
|
759
|
+
context, formData);
|
|
745
760
|
if (appsembleVariantContext.icon) {
|
|
746
761
|
appsembleContext.icon = appsembleVariantContext.icon;
|
|
747
762
|
}
|
|
@@ -822,7 +837,7 @@ export async function publishApp({ clientCredentials, context, dryRun, modifyCon
|
|
|
822
837
|
if (error.response?.data?.message !== 'App validation failed') {
|
|
823
838
|
throw error;
|
|
824
839
|
}
|
|
825
|
-
throw new AppsembleError(printAxiosError(filename, yaml, error.response
|
|
840
|
+
throw new AppsembleError(printAxiosError(filename, yaml, (error.response?.data).data.errors));
|
|
826
841
|
}
|
|
827
842
|
if (dryRun) {
|
|
828
843
|
logger.info('Skipped uploading block themes and app messages.');
|
|
@@ -831,7 +846,11 @@ export async function publishApp({ clientCredentials, context, dryRun, modifyCon
|
|
|
831
846
|
}
|
|
832
847
|
if (file.isDirectory() && !dryRun) {
|
|
833
848
|
// After uploading the app, upload block styles, messages if they are available
|
|
849
|
+
// @ts-expect-error 2345 argument of type is not assignable to parameter of type
|
|
850
|
+
// (strictNullChecks)
|
|
834
851
|
await traverseBlockThemes(appVariantPath, data.id, remote, false);
|
|
852
|
+
// @ts-expect-error 2345 argument of type is not assignable to parameter of type
|
|
853
|
+
// (strictNullChecks)
|
|
835
854
|
await uploadMessages(appVariantPath, data.id, remote, false);
|
|
836
855
|
await publishAppConfig(appVariantPath, data, remote);
|
|
837
856
|
// After uploading the app, publish seed resources and assets if they are available
|
|
@@ -843,7 +862,10 @@ export async function publishApp({ clientCredentials, context, dryRun, modifyCon
|
|
|
843
862
|
}
|
|
844
863
|
}
|
|
845
864
|
if (modifyContext && appsembleContext && context && !dryRun) {
|
|
865
|
+
// @ts-expect-error 2345 argument of type is not assignable to parameter of type
|
|
866
|
+
// (strictNullChecks)
|
|
846
867
|
rc.context[context].id = data.id;
|
|
868
|
+
// @ts-expect-error 2454 Variable used before it was assigned
|
|
847
869
|
await writeData(join(appVariantPath, '.appsemblerc.yaml'), rc, { sort: false });
|
|
848
870
|
logger.info(`Updated .appsemblerc: Set context.${context}.id to ${data.id}`);
|
|
849
871
|
}
|
|
@@ -851,6 +873,8 @@ export async function publishApp({ clientCredentials, context, dryRun, modifyCon
|
|
|
851
873
|
logger.info(`Successfully published app ${data.definition.name}! 🙌`);
|
|
852
874
|
logger.info(`App URL: ${protocol}//${data.path}.${data.OrganizationId}.${host}`);
|
|
853
875
|
logger.info(`App store page: ${new URL(`/apps/${data.id}`, remote)}`);
|
|
876
|
+
// eslint-disable-next-line max-len
|
|
877
|
+
// @ts-expect-error 2454 Variable used before it was assigned, 2538 Undefined cannot be used as an index type
|
|
854
878
|
const rcCollections = rc?.context?.[context]?.collections;
|
|
855
879
|
if (Array.isArray(rcCollections)) {
|
|
856
880
|
for (const collectionId of rcCollections) {
|
|
@@ -867,6 +891,7 @@ export async function publishApp({ clientCredentials, context, dryRun, modifyCon
|
|
|
867
891
|
}
|
|
868
892
|
if (appVariantPath !== path && modifyContext && !dryRun) {
|
|
869
893
|
const [defaultAppRc] = await readData(join(path, '.appsemblerc.yaml'));
|
|
894
|
+
// @ts-expect-error 2538 Undefined cannot be used as an index type
|
|
870
895
|
defaultAppRc.context[context] = rc.context[context];
|
|
871
896
|
await writeData(join(path, '.appsemblerc.yaml'), defaultAppRc, { sort: false });
|
|
872
897
|
await rm(appVariantPath, { recursive: true });
|
|
@@ -881,6 +906,8 @@ export async function publishApp({ clientCredentials, context, dryRun, modifyCon
|
|
|
881
906
|
export async function updateApp({ clientCredentials, context, force, path, ...options }) {
|
|
882
907
|
const file = await stat(path);
|
|
883
908
|
const formData = new FormData();
|
|
909
|
+
// @ts-expect-error 2345 argument of type is not assignable to parameter of type
|
|
910
|
+
// (strictNullChecks)
|
|
884
911
|
const appsembleContext = await retrieveContext(path, context);
|
|
885
912
|
let yaml;
|
|
886
913
|
let filename = relative(process.cwd(), path);
|
|
@@ -900,7 +927,10 @@ export async function updateApp({ clientCredentials, context, force, path, ...op
|
|
|
900
927
|
}
|
|
901
928
|
else {
|
|
902
929
|
let appsembleVariantContext;
|
|
903
|
-
[appsembleVariantContext, , yaml] = await traverseAppDirectory(appVariantPath,
|
|
930
|
+
[appsembleVariantContext, , yaml] = await traverseAppDirectory(appVariantPath,
|
|
931
|
+
// @ts-expect-error 2345 argument of type is not assignable to parameter of type
|
|
932
|
+
// (strictNullChecks)
|
|
933
|
+
context, formData);
|
|
904
934
|
if (appsembleVariantContext.icon) {
|
|
905
935
|
appsembleContext.icon = appsembleVariantContext.icon;
|
|
906
936
|
}
|
|
@@ -990,11 +1020,15 @@ export async function updateApp({ clientCredentials, context, force, path, ...op
|
|
|
990
1020
|
if (error.response?.data?.message !== 'App validation failed') {
|
|
991
1021
|
throw error;
|
|
992
1022
|
}
|
|
993
|
-
throw new AppsembleError(printAxiosError(filename, yaml, error.response
|
|
1023
|
+
throw new AppsembleError(printAxiosError(filename, yaml, (error.response?.data).data.errors));
|
|
994
1024
|
}
|
|
995
1025
|
if (file.isDirectory()) {
|
|
996
1026
|
// After uploading the app, upload block styles and messages if they are available
|
|
1027
|
+
// @ts-expect-error 2345 argument of type is not assignable to parameter of type
|
|
1028
|
+
// (strictNullChecks)
|
|
997
1029
|
await traverseBlockThemes(appVariantPath, data.id, remote, force);
|
|
1030
|
+
// @ts-expect-error 2345 argument of type is not assignable to parameter of type
|
|
1031
|
+
// (strictNullChecks)
|
|
998
1032
|
await uploadMessages(appVariantPath, data.id, remote, force);
|
|
999
1033
|
await publishAppConfig(appVariantPath, data, remote);
|
|
1000
1034
|
// After updating the app, publish seed resources and assets if they are available
|
|
@@ -1047,6 +1081,14 @@ export async function patchApp({ id, remote, ...options }) {
|
|
|
1047
1081
|
logger.info(`Setting showAppsembleLogin to ${options.showAppsembleLogin}`);
|
|
1048
1082
|
formData.append('showAppsembleLogin', String(options.showAppsembleLogin));
|
|
1049
1083
|
}
|
|
1084
|
+
if (options.displayAppMemberName !== undefined) {
|
|
1085
|
+
logger.info(`Setting displayAppMemberName to ${options.displayAppMemberName}`);
|
|
1086
|
+
formData.append('displayAppMemberName', String(options.displayAppMemberName));
|
|
1087
|
+
}
|
|
1088
|
+
if (options.displayInstallationPrompt !== undefined) {
|
|
1089
|
+
logger.info(`Setting displayInstallationPrompt to ${options.displayInstallationPrompt}`);
|
|
1090
|
+
formData.append('displayInstallationPrompt', String(options.displayInstallationPrompt));
|
|
1091
|
+
}
|
|
1050
1092
|
if (options.showAppsembleOAuth2Login !== undefined) {
|
|
1051
1093
|
logger.info(`Setting showAppsembleOAuth2Login to ${options.showAppsembleOAuth2Login}`);
|
|
1052
1094
|
formData.append('showAppsembleOAuth2Login', String(options.showAppsembleOAuth2Login));
|
package/lib/asset.d.ts
CHANGED