@appsemble/cli 0.23.3 → 0.23.5
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 +21 -5
- package/commands/app/export.d.ts +12 -0
- package/commands/app/export.js +29 -0
- package/commands/app/import.d.ts +11 -0
- package/commands/app/import.js +36 -0
- package/commands/app/index.js +4 -0
- package/commands/config/get.js +1 -1
- package/commands/config/set.js +1 -1
- package/lib/app.d.ts +9 -0
- package/lib/app.js +21 -1
- package/lib/authentication.js +1 -1
- package/lib/block.d.ts +1 -1
- package/lib/block.js +1 -1
- package/package.json +7 -7
- package/templates/apps/empty/app-definition.yaml +2 -2
- package/templates/blocks/mini-jsx/package.json +1 -1
- package/templates/blocks/preact/package.json +2 -2
- package/templates/blocks/vanilla/package.json +1 -1
- package/types.d.ts +1 -1
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.23.5)
|
|
7
7
|
[](https://prettier.io)
|
|
8
8
|
|
|
9
9
|
## Table of Contents
|
|
@@ -144,8 +144,8 @@ arguments.
|
|
|
144
144
|
appsemble app create
|
|
145
145
|
```
|
|
146
146
|
|
|
147
|
-
The Appsemble CLI can be used to create,
|
|
148
|
-
the `apps/my-app` directory, run:
|
|
147
|
+
The Appsemble CLI can be used to create, export, import and update apps. For example, to create an
|
|
148
|
+
app in the `apps/my-app` directory, run:
|
|
149
149
|
|
|
150
150
|
```sh
|
|
151
151
|
appsemble app publish apps/my-app
|
|
@@ -163,6 +163,22 @@ To delete an app using the CLI use the following command:
|
|
|
163
163
|
appsemble app delete --id <appId>
|
|
164
164
|
```
|
|
165
165
|
|
|
166
|
+
To export an app as a zip file, run the following:
|
|
167
|
+
|
|
168
|
+
```sh
|
|
169
|
+
appsemble app export --id <app-id>
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Supported arguments for this app are `resources` and `path`. Resources is used to specify whether to
|
|
173
|
+
include the resources in the exported file and path is the path of the folder where you want to put
|
|
174
|
+
your downloaded file. Path is `./apps` by default and resources is set to `false`.
|
|
175
|
+
|
|
176
|
+
To import an app from a zip file, use the following command:
|
|
177
|
+
|
|
178
|
+
```sh
|
|
179
|
+
appsemble app import <path-of-zip-file> --organization <organizationId>
|
|
180
|
+
```
|
|
181
|
+
|
|
166
182
|
For a more in depth explanation of how to build apps, use our
|
|
167
183
|
[app building guide](https://appsemble.app/docs/guide).
|
|
168
184
|
|
|
@@ -288,5 +304,5 @@ appsemble run-cronjobs --interval 30
|
|
|
288
304
|
|
|
289
305
|
## License
|
|
290
306
|
|
|
291
|
-
[LGPL-3.0-only](https://gitlab.com/appsemble/appsemble/-/blob/0.23.
|
|
307
|
+
[LGPL-3.0-only](https://gitlab.com/appsemble/appsemble/-/blob/0.23.5/LICENSE.md) ©
|
|
292
308
|
[Appsemble](https://appsemble.com)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type Argv } from 'yargs';
|
|
2
|
+
import { type BaseArguments } from '../../types.js';
|
|
3
|
+
interface ExportAppArgs extends BaseArguments {
|
|
4
|
+
id: number;
|
|
5
|
+
resources: boolean;
|
|
6
|
+
path?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare const command = "export";
|
|
9
|
+
export declare const description = "Export an app as a zip file using app id.\n App definition, styles and messages are exported by default, to export resources, make sure you have suitable permissions and use the '--resources' flag.";
|
|
10
|
+
export declare function builder(yargs: Argv): Argv<any>;
|
|
11
|
+
export declare function handler(args: ExportAppArgs): Promise<void>;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { authenticate, logger } from '@appsemble/node-utils';
|
|
3
|
+
import { exportAppAsZip } from '../../lib/app.js';
|
|
4
|
+
export const command = 'export';
|
|
5
|
+
export const description = `Export an app as a zip file using app id.
|
|
6
|
+
App definition, styles and messages are exported by default, to export resources, make sure you have suitable permissions and use the '--resources' flag.`;
|
|
7
|
+
export function builder(yargs) {
|
|
8
|
+
return yargs
|
|
9
|
+
.option('id', {
|
|
10
|
+
describe: 'Id of the app to be exported as a zip file',
|
|
11
|
+
demandOption: true,
|
|
12
|
+
})
|
|
13
|
+
.option('resources', {
|
|
14
|
+
describe: 'Boolean representing whether the resources should be exported or not',
|
|
15
|
+
default: false,
|
|
16
|
+
})
|
|
17
|
+
.option('path', {
|
|
18
|
+
describe: 'Path of the folder where you want to put your exported file.',
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
export async function handler(args) {
|
|
22
|
+
const { clientCredentials, id: appId, path: outputDirectory, remote, resources } = args;
|
|
23
|
+
const defaultOutputDirectory = join(process.cwd(), 'apps');
|
|
24
|
+
await authenticate(remote, 'apps:export', clientCredentials);
|
|
25
|
+
logger.info(`Exporting app with id: ${appId}`);
|
|
26
|
+
await exportAppAsZip(appId, resources, outputDirectory || defaultOutputDirectory, remote);
|
|
27
|
+
logger.info('Export completed successfully');
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=export.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type Argv } from 'yargs';
|
|
2
|
+
import { type BaseArguments } from '../../types.js';
|
|
3
|
+
interface ImportAppArgs extends BaseArguments {
|
|
4
|
+
organization: string;
|
|
5
|
+
path: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const command = "import <path>";
|
|
8
|
+
export declare const description = "Import an app from a zip file using organization id. App definition, styles, resources and messages can be imported from the zip file.";
|
|
9
|
+
export declare function builder(yargs: Argv): Argv<any>;
|
|
10
|
+
export declare function handler(args: ImportAppArgs): Promise<void>;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { authenticate, logger } from '@appsemble/node-utils';
|
|
3
|
+
import axios from 'axios';
|
|
4
|
+
export const command = 'import <path>';
|
|
5
|
+
export const description = 'Import an app from a zip file using organization id. App definition, styles, resources and messages can be imported from the zip file.';
|
|
6
|
+
export function builder(yargs) {
|
|
7
|
+
return yargs
|
|
8
|
+
.positional('path', {
|
|
9
|
+
describe: 'Path of the zip file you want to import.',
|
|
10
|
+
required: true,
|
|
11
|
+
})
|
|
12
|
+
.option('organization', {
|
|
13
|
+
describe: 'Id of the organization to which app will be imported.',
|
|
14
|
+
demandOption: true,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
export async function handler(args) {
|
|
18
|
+
const { clientCredentials, organization, path: inputFile, remote } = args;
|
|
19
|
+
const [, extName] = inputFile.split('.');
|
|
20
|
+
if (extName !== 'zip') {
|
|
21
|
+
logger.error('Input file must be a zip file.');
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
await authenticate(remote, 'apps:write', clientCredentials);
|
|
25
|
+
logger.info(`Importing app to organization: ${organization}`);
|
|
26
|
+
const zipFile = await readFile(inputFile);
|
|
27
|
+
const config = {
|
|
28
|
+
base: remote,
|
|
29
|
+
headers: {
|
|
30
|
+
'Content-Type': 'application/zip',
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
await axios.post(`/api/apps/import/organization/${organization}`, zipFile, config);
|
|
34
|
+
logger.info('Importing app completed successfully');
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=import.js.map
|
package/commands/app/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import * as create from './create.js';
|
|
2
2
|
import * as remove from './delete.js';
|
|
3
|
+
import * as exportApp from './export.js';
|
|
3
4
|
import * as extractMessages from './extract-messages.js';
|
|
5
|
+
import * as importApp from './import.js';
|
|
4
6
|
import * as publish from './publish.js';
|
|
5
7
|
import * as update from './update.js';
|
|
6
8
|
export { noop as handler } from '@appsemble/utils';
|
|
@@ -11,7 +13,9 @@ export function builder(yargs) {
|
|
|
11
13
|
.command(publish)
|
|
12
14
|
.command(create)
|
|
13
15
|
.command(remove)
|
|
16
|
+
.command(exportApp)
|
|
14
17
|
.command(extractMessages)
|
|
18
|
+
.command(importApp)
|
|
15
19
|
.command(update)
|
|
16
20
|
.demandCommand(1);
|
|
17
21
|
}
|
package/commands/config/get.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { has } from '@appsemble/utils';
|
|
2
|
-
import { readPackageUp } from 'read-
|
|
2
|
+
import { readPackageUp } from 'read-package-up';
|
|
3
3
|
export const command = 'get <key>';
|
|
4
4
|
export const description = 'Get an Appsemble configuration option from package.json.';
|
|
5
5
|
export function builder(yargs) {
|
package/commands/config/set.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { inspect } from 'node:util';
|
|
2
2
|
import { logger, writeData } from '@appsemble/node-utils';
|
|
3
3
|
import { has } from '@appsemble/utils';
|
|
4
|
-
import { readPackageUp } from 'read-
|
|
4
|
+
import { readPackageUp } from 'read-package-up';
|
|
5
5
|
export const command = 'set <key> <value>';
|
|
6
6
|
export const description = 'Set an Appsemble configuration option in package.json.';
|
|
7
7
|
export function builder(yargs) {
|
package/lib/app.d.ts
CHANGED
|
@@ -145,6 +145,15 @@ interface UpdateAppParams {
|
|
|
145
145
|
* @returns The context from `.appsemblerc.yaml` if a match was found.
|
|
146
146
|
*/
|
|
147
147
|
export declare function traverseAppDirectory(path: string, context: string, formData: FormData): Promise<[AppsembleContext, AppsembleRC, string, App]>;
|
|
148
|
+
/**
|
|
149
|
+
* Export an app as a zip file.
|
|
150
|
+
*
|
|
151
|
+
* @param appId Id of the app to be exported.
|
|
152
|
+
* @param resources Boolean representing whether to include resources in the zip file.
|
|
153
|
+
* @param path Path of the folder where you want to put your downloaded file.
|
|
154
|
+
* @param remote The remote to fetch the app from.
|
|
155
|
+
*/
|
|
156
|
+
export declare function exportAppAsZip(appId: number, resources: boolean, path: string, remote: string): Promise<void>;
|
|
148
157
|
/**
|
|
149
158
|
* Upload messages for an app.
|
|
150
159
|
*
|
package/lib/app.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createReadStream, existsSync } from 'node:fs';
|
|
1
|
+
import { createReadStream, createWriteStream, existsSync } from 'node:fs';
|
|
2
2
|
import { mkdir, readdir, readFile, stat } from 'node:fs/promises';
|
|
3
3
|
import { basename, join, parse, relative, resolve } from 'node:path';
|
|
4
4
|
import { inspect } from 'node:util';
|
|
@@ -105,6 +105,26 @@ export async function traverseAppDirectory(path, context, formData) {
|
|
|
105
105
|
: maskableIconPath;
|
|
106
106
|
return [discoveredContext, rc, yaml, gatheredData];
|
|
107
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* Export an app as a zip file.
|
|
110
|
+
*
|
|
111
|
+
* @param appId Id of the app to be exported.
|
|
112
|
+
* @param resources Boolean representing whether to include resources in the zip file.
|
|
113
|
+
* @param path Path of the folder where you want to put your downloaded file.
|
|
114
|
+
* @param remote The remote to fetch the app from.
|
|
115
|
+
*/
|
|
116
|
+
export async function exportAppAsZip(appId, resources, path, remote) {
|
|
117
|
+
const app = await axios.get(`/api/apps/${appId}`);
|
|
118
|
+
const { name } = app.data.definition;
|
|
119
|
+
const response = await axios.get(`/api/apps/${appId}/export?resources=${resources}`, {
|
|
120
|
+
baseURL: remote,
|
|
121
|
+
responseType: 'stream',
|
|
122
|
+
});
|
|
123
|
+
const zipFileName = join(path, `${name}_${appId}.zip`);
|
|
124
|
+
const writeStream = createWriteStream(zipFileName);
|
|
125
|
+
response.data.pipe(writeStream);
|
|
126
|
+
logger.info(`Successfully downloaded file: ${zipFileName}`);
|
|
127
|
+
}
|
|
108
128
|
/**
|
|
109
129
|
* Upload messages for an app.
|
|
110
130
|
*
|
package/lib/authentication.js
CHANGED
|
@@ -31,7 +31,7 @@ function waitForCredentials(url) {
|
|
|
31
31
|
catch {
|
|
32
32
|
throwKoaError(ctx, 400, 'Invalid JSON');
|
|
33
33
|
}
|
|
34
|
-
assertKoaError(typeof credentials === 'string' && validate(credentials), ctx, 400, 'Invalid client credentials');
|
|
34
|
+
assertKoaError(typeof credentials === 'string' && !validate(credentials), ctx, 400, 'Invalid client credentials');
|
|
35
35
|
ctx.status = 204;
|
|
36
36
|
server.close();
|
|
37
37
|
resolve(credentials);
|
package/lib/block.d.ts
CHANGED
|
@@ -25,7 +25,7 @@ export declare function getBlockConfig(dir: string): Promise<BlockConfig>;
|
|
|
25
25
|
/**
|
|
26
26
|
* Discover Appsemble blocks based on workspaces in a monorepo.
|
|
27
27
|
*
|
|
28
|
-
*
|
|
28
|
+
* npm workspaces are supported.
|
|
29
29
|
*
|
|
30
30
|
* @param root The project root in which to find workspaces.
|
|
31
31
|
* @returns Discovered Appsemble blocks.
|
package/lib/block.js
CHANGED
|
@@ -78,7 +78,7 @@ export async function getBlockConfig(dir) {
|
|
|
78
78
|
/**
|
|
79
79
|
* Discover Appsemble blocks based on workspaces in a monorepo.
|
|
80
80
|
*
|
|
81
|
-
*
|
|
81
|
+
* npm workspaces are supported.
|
|
82
82
|
*
|
|
83
83
|
* @param root The project root in which to find workspaces.
|
|
84
84
|
* @returns Discovered Appsemble blocks.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appsemble/cli",
|
|
3
|
-
"version": "0.23.
|
|
3
|
+
"version": "0.23.5",
|
|
4
4
|
"description": "The CLI for developing with Appsemble apps and blocks",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"app",
|
|
@@ -42,9 +42,9 @@
|
|
|
42
42
|
"test": "vitest"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@appsemble/node-utils": "0.23.
|
|
46
|
-
"@appsemble/types": "0.23.
|
|
47
|
-
"@appsemble/utils": "0.23.
|
|
45
|
+
"@appsemble/node-utils": "0.23.5",
|
|
46
|
+
"@appsemble/types": "0.23.5",
|
|
47
|
+
"@appsemble/utils": "0.23.5",
|
|
48
48
|
"@fortawesome/fontawesome-common-types": "^6.0.0",
|
|
49
49
|
"@koa/cors": "^4.0.0",
|
|
50
50
|
"@odata/parser": "^0.2.0",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"csvtojson": "^2.0.0",
|
|
56
56
|
"fast-glob": "^3.0.0",
|
|
57
57
|
"form-data": "^4.0.0",
|
|
58
|
-
"global-cache-dir": "^
|
|
58
|
+
"global-cache-dir": "^6.0.0",
|
|
59
59
|
"inquirer": "^9.0.0",
|
|
60
60
|
"jsonschema": "^1.0.0",
|
|
61
61
|
"koa": "^2.0.0",
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"postcss-load-config": "^4.0.0",
|
|
77
77
|
"postcss-url": "^10.0.0",
|
|
78
78
|
"raw-body": "^2.0.0",
|
|
79
|
-
"read-
|
|
79
|
+
"read-package-up": "^11.0.0",
|
|
80
80
|
"sharp": "^0.32.0",
|
|
81
81
|
"ts-json-schema-generator": "^1.0.0",
|
|
82
82
|
"type-fest": "^4.0.0",
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
"yargs": "^17.0.0"
|
|
86
86
|
},
|
|
87
87
|
"devDependencies": {
|
|
88
|
-
"@appsemble/types": "0.23.
|
|
88
|
+
"@appsemble/types": "0.23.5",
|
|
89
89
|
"@types/concat-stream": "^2.0.0",
|
|
90
90
|
"@types/inquirer": "^9.0.0",
|
|
91
91
|
"@types/normalize-path": "^3.0.0",
|
|
@@ -6,7 +6,7 @@ pages:
|
|
|
6
6
|
- name: Example Page A
|
|
7
7
|
blocks:
|
|
8
8
|
- type: action-button
|
|
9
|
-
version: 0.23.
|
|
9
|
+
version: 0.23.5
|
|
10
10
|
parameters:
|
|
11
11
|
icon: arrow-right
|
|
12
12
|
actions:
|
|
@@ -17,7 +17,7 @@ pages:
|
|
|
17
17
|
- name: Example Page B
|
|
18
18
|
blocks:
|
|
19
19
|
- type: action-button
|
|
20
|
-
version: 0.23.
|
|
20
|
+
version: 0.23.5
|
|
21
21
|
parameters:
|
|
22
22
|
icon: arrow-left
|
|
23
23
|
actions:
|
package/types.d.ts
CHANGED