@appsemble/cli 0.40.3 → 0.40.4
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 -74
- package/index.js +0 -2
- package/lib/app.d.ts +1 -2
- package/lib/app.js +1 -1
- package/package.json +7 -22
- 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/commands/serve.d.ts +0 -14
- package/commands/serve.js +0 -305
- package/lib/createServers.d.ts +0 -15
- package/lib/createServers.js +0 -62
- package/server/argv.d.ts +0 -117
- package/server/argv.js +0 -25
- package/server/controllers/apps/actions/index.d.ts +0 -5
- package/server/controllers/apps/actions/index.js +0 -6
- package/server/controllers/apps/actions/proxyDelete.d.ts +0 -2
- package/server/controllers/apps/actions/proxyDelete.js +0 -4
- package/server/controllers/apps/actions/proxyGet.d.ts +0 -2
- package/server/controllers/apps/actions/proxyGet.js +0 -4
- package/server/controllers/apps/actions/proxyPatch.d.ts +0 -2
- package/server/controllers/apps/actions/proxyPatch.js +0 -4
- package/server/controllers/apps/actions/proxyPost.d.ts +0 -2
- package/server/controllers/apps/actions/proxyPost.js +0 -4
- package/server/controllers/apps/actions/proxyPut.d.ts +0 -2
- package/server/controllers/apps/actions/proxyPut.js +0 -4
- package/server/controllers/apps/index.d.ts +0 -2
- package/server/controllers/apps/index.js +0 -3
- package/server/controllers/apps/members/current/getCurrentAppMember.d.ts +0 -2
- package/server/controllers/apps/members/current/getCurrentAppMember.js +0 -4
- package/server/controllers/apps/members/current/groups/getCurrentAppMemberGroups.d.ts +0 -2
- package/server/controllers/apps/members/current/groups/getCurrentAppMemberGroups.js +0 -4
- package/server/controllers/apps/members/current/groups/index.d.ts +0 -1
- package/server/controllers/apps/members/current/groups/index.js +0 -2
- package/server/controllers/apps/members/current/index.d.ts +0 -2
- package/server/controllers/apps/members/current/index.js +0 -3
- package/server/controllers/apps/members/index.d.ts +0 -1
- package/server/controllers/apps/members/index.js +0 -2
- package/server/controllers/common/apps/assets/getAppAssetById.d.ts +0 -2
- package/server/controllers/common/apps/assets/getAppAssetById.js +0 -4
- package/server/controllers/common/apps/assets/index.d.ts +0 -1
- package/server/controllers/common/apps/assets/index.js +0 -2
- package/server/controllers/common/apps/groups/getAppGroups.d.ts +0 -2
- package/server/controllers/common/apps/groups/getAppGroups.js +0 -4
- package/server/controllers/common/apps/groups/index.d.ts +0 -1
- package/server/controllers/common/apps/groups/index.js +0 -2
- package/server/controllers/common/apps/index.d.ts +0 -5
- package/server/controllers/common/apps/index.js +0 -6
- package/server/controllers/common/apps/messages/getAppMessages.d.ts +0 -2
- package/server/controllers/common/apps/messages/getAppMessages.js +0 -4
- package/server/controllers/common/apps/messages/index.d.ts +0 -1
- package/server/controllers/common/apps/messages/index.js +0 -2
- package/server/controllers/common/apps/resources/countAppResources.d.ts +0 -2
- package/server/controllers/common/apps/resources/countAppResources.js +0 -4
- package/server/controllers/common/apps/resources/createAppResource.d.ts +0 -2
- package/server/controllers/common/apps/resources/createAppResource.js +0 -4
- package/server/controllers/common/apps/resources/deleteAppResource.d.ts +0 -2
- package/server/controllers/common/apps/resources/deleteAppResource.js +0 -4
- package/server/controllers/common/apps/resources/getAppResourceById.d.ts +0 -2
- package/server/controllers/common/apps/resources/getAppResourceById.js +0 -4
- package/server/controllers/common/apps/resources/index.d.ts +0 -6
- package/server/controllers/common/apps/resources/index.js +0 -7
- package/server/controllers/common/apps/resources/queryAppResources.d.ts +0 -2
- package/server/controllers/common/apps/resources/queryAppResources.js +0 -4
- package/server/controllers/common/apps/resources/updateAppResource.d.ts +0 -2
- package/server/controllers/common/apps/resources/updateAppResource.js +0 -4
- package/server/controllers/common/apps/variables/getAppVariables.d.ts +0 -2
- package/server/controllers/common/apps/variables/getAppVariables.js +0 -4
- package/server/controllers/common/apps/variables/index.d.ts +0 -1
- package/server/controllers/common/apps/variables/index.js +0 -2
- package/server/controllers/common/index.d.ts +0 -1
- package/server/controllers/common/index.js +0 -2
- package/server/controllers/index.d.ts +0 -3
- package/server/controllers/index.js +0 -4
- package/server/controllers/main/apps/assets/createAppAsset.d.ts +0 -2
- package/server/controllers/main/apps/assets/createAppAsset.js +0 -4
- package/server/controllers/main/apps/assets/index.d.ts +0 -1
- package/server/controllers/main/apps/assets/index.js +0 -2
- package/server/controllers/main/apps/index.d.ts +0 -1
- package/server/controllers/main/apps/index.js +0 -2
- package/server/controllers/main/index.d.ts +0 -1
- package/server/controllers/main/index.js +0 -2
- package/server/db/index.d.ts +0 -2
- package/server/db/index.js +0 -10
- package/server/db/methods.d.ts +0 -11
- package/server/db/methods.js +0 -241
- package/server/models/Resource.d.ts +0 -16
- package/server/models/Resource.js +0 -23
- package/server/models/Theme.d.ts +0 -17
- package/server/models/Theme.js +0 -11
- package/server/options/applyAppServiceSecrets.d.ts +0 -3
- package/server/options/applyAppServiceSecrets.js +0 -2
- package/server/options/checkAppMemberAppPermissions.d.ts +0 -1
- package/server/options/checkAppMemberAppPermissions.js +0 -4
- package/server/options/checkAppPermissions.d.ts +0 -1
- package/server/options/checkAppPermissions.js +0 -4
- package/server/options/checkAuthSubjectAppPermissions.d.ts +0 -1
- package/server/options/checkAuthSubjectAppPermissions.js +0 -4
- package/server/options/checkUserOrganizationPermissions.d.ts +0 -1
- package/server/options/checkUserOrganizationPermissions.js +0 -4
- package/server/options/createAppAsset.d.ts +0 -2
- package/server/options/createAppAsset.js +0 -14
- package/server/options/createAppResourcesWithAssets.d.ts +0 -3
- package/server/options/createAppResourcesWithAssets.js +0 -16
- package/server/options/createSettings.d.ts +0 -2
- package/server/options/createSettings.js +0 -34
- package/server/options/createTheme.d.ts +0 -2
- package/server/options/createTheme.js +0 -7
- package/server/options/deleteAppAsset.d.ts +0 -2
- package/server/options/deleteAppAsset.js +0 -15
- package/server/options/deleteAppResource.d.ts +0 -2
- package/server/options/deleteAppResource.js +0 -16
- package/server/options/email.d.ts +0 -1
- package/server/options/email.js +0 -2
- package/server/options/getApp.d.ts +0 -3
- package/server/options/getApp.js +0 -5
- package/server/options/getAppAsset.d.ts +0 -2
- package/server/options/getAppAsset.js +0 -8
- package/server/options/getAppAssets.d.ts +0 -2
- package/server/options/getAppAssets.js +0 -8
- package/server/options/getAppBlockStyles.d.ts +0 -2
- package/server/options/getAppBlockStyles.js +0 -27
- package/server/options/getAppDetails.d.ts +0 -2
- package/server/options/getAppDetails.js +0 -8
- package/server/options/getAppGroups.d.ts +0 -2
- package/server/options/getAppGroups.js +0 -4
- package/server/options/getAppIcon.d.ts +0 -2
- package/server/options/getAppIcon.js +0 -6
- package/server/options/getAppMessages.d.ts +0 -3
- package/server/options/getAppMessages.js +0 -4
- package/server/options/getAppReadmes.d.ts +0 -2
- package/server/options/getAppReadmes.js +0 -11
- package/server/options/getAppResource.d.ts +0 -3
- package/server/options/getAppResource.js +0 -5
- package/server/options/getAppResources.d.ts +0 -3
- package/server/options/getAppResources.js +0 -5
- package/server/options/getAppScreenshots.d.ts +0 -2
- package/server/options/getAppScreenshots.js +0 -20
- package/server/options/getAppStyles.d.ts +0 -2
- package/server/options/getAppStyles.js +0 -10
- package/server/options/getAppUrl.d.ts +0 -2
- package/server/options/getAppUrl.js +0 -5
- package/server/options/getAppVariables.d.ts +0 -3
- package/server/options/getAppVariables.js +0 -4
- package/server/options/getBlockAsset.d.ts +0 -2
- package/server/options/getBlockAsset.js +0 -33
- package/server/options/getBlockAssetsPaths.d.ts +0 -2
- package/server/options/getBlockAssetsPaths.js +0 -8
- package/server/options/getBlockMessages.d.ts +0 -2
- package/server/options/getBlockMessages.js +0 -4
- package/server/options/getCsp.d.ts +0 -2
- package/server/options/getCsp.js +0 -14
- package/server/options/getCurrentAppMember.d.ts +0 -3
- package/server/options/getCurrentAppMember.js +0 -4
- package/server/options/getCurrentAppMemberGroups.d.ts +0 -3
- package/server/options/getCurrentAppMemberGroups.js +0 -2
- package/server/options/getDbUpdated.d.ts +0 -1
- package/server/options/getDbUpdated.js +0 -2
- package/server/options/getHost.d.ts +0 -2
- package/server/options/getHost.js +0 -5
- package/server/options/getTheme.d.ts +0 -2
- package/server/options/getTheme.js +0 -6
- package/server/options/index.d.ts +0 -40
- package/server/options/index.js +0 -41
- package/server/options/options.d.ts +0 -2
- package/server/options/options.js +0 -46
- package/server/options/parseQuery.d.ts +0 -2
- package/server/options/parseQuery.js +0 -86
- package/server/options/reloadUser.d.ts +0 -1
- package/server/options/reloadUser.js +0 -2
- package/server/options/sendNotifications.d.ts +0 -1
- package/server/options/sendNotifications.js +0 -2
- package/server/options/updateAppResource.d.ts +0 -3
- package/server/options/updateAppResource.js +0 -16
- package/server/routes/appRouter/index.d.ts +0 -2
- package/server/routes/appRouter/index.js +0 -4
- package/server/utils/resourceLock.d.ts +0 -11
- package/server/utils/resourceLock.js +0 -23
package/README.md
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
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.40.4)
|
|
7
7
|
[](https://prettier.io)
|
|
8
8
|
|
|
9
9
|
## Table of Contents
|
|
10
10
|
|
|
11
11
|
- [Installation](#installation)
|
|
12
12
|
- [Usage](#usage)
|
|
13
|
-
- [Development server](#development-server)
|
|
14
13
|
- [Authentication](#authentication)
|
|
15
14
|
- [Organizations](#organizations)
|
|
16
15
|
- [Apps](#apps)
|
|
@@ -38,76 +37,6 @@ appsemble --help
|
|
|
38
37
|
|
|
39
38
|
Every subcommand also supports the `--help` flag.
|
|
40
39
|
|
|
41
|
-
### Development server
|
|
42
|
-
|
|
43
|
-
The development server can create an app from a specified folder containing an `app-definition.yml`
|
|
44
|
-
file. It will check what blocks are needed for the app and will try to load them from the local
|
|
45
|
-
workspaces, listed in the `package.json` file in the root of the project, if they are present. This
|
|
46
|
-
way, all default Appsemble blocks shipped with Appsemble are loaded automatically.
|
|
47
|
-
|
|
48
|
-
Once the development server is started, making a change to a block’s code or styles will reflect in
|
|
49
|
-
the browser immediately after refreshing the page, without the need of increasing the block’s
|
|
50
|
-
version. Running docker database containers, creating a user account and creating an organization
|
|
51
|
-
are not needed.
|
|
52
|
-
|
|
53
|
-
The Appsemble CLI can be used to start the development server. For example, the following command
|
|
54
|
-
serves `my-app`:
|
|
55
|
-
|
|
56
|
-
```sh
|
|
57
|
-
appsemble serve <path-to-app-directory>
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
This will serve the app on `http://localhost:9090`.
|
|
61
|
-
|
|
62
|
-
A different port can be specified with the `--port` parameter.
|
|
63
|
-
|
|
64
|
-
The following option allows you to view the app with a specified role:
|
|
65
|
-
|
|
66
|
-
```sh
|
|
67
|
-
appsemble serve <path-to-app-directory> --user-role test
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
The following option allows you to view the app as a Manager of a group:
|
|
71
|
-
|
|
72
|
-
```sh
|
|
73
|
-
appsemble serve <path-to-app-directory> --group-role Manager
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
App data is stored within a `db.json` file in your machine’s cache directory. Each app has their own
|
|
77
|
-
directory `<my-app>`.
|
|
78
|
-
|
|
79
|
-
```sh
|
|
80
|
-
MacOS - /Users/<my-name>/Library/Caches/appsemble/<my-app>
|
|
81
|
-
Linux - /home/<my-name>/.cache/appsemble/<my-app>
|
|
82
|
-
Windows - C:\Users\<my-name>\AppData\Local\appsemble\Cache\<my-app>
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
App assets will be served from the local file system.
|
|
86
|
-
|
|
87
|
-
The development server will automatically fetch all blocks that are needed for the served app but
|
|
88
|
-
are missing from the local workspaces. These are typically third-party or proprietary blocks. The
|
|
89
|
-
development server will use `http://localhost:9999` as the default remote server to fetch blocks
|
|
90
|
-
from. The following option allows you to specify a different remote (e.g. `https://appsemble.app`):
|
|
91
|
-
|
|
92
|
-
```sh
|
|
93
|
-
appsemble serve <path-to-app-directory> --remote <remote>
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
The development server will use the corresponding block directory in your machine’s cache directory
|
|
97
|
-
to store and read block manifests and assets.
|
|
98
|
-
|
|
99
|
-
```sh
|
|
100
|
-
MacOS - /Users/<my-name>/Library/Caches/appsemble/blocks/<organisation>/<block-name>/<block-version>
|
|
101
|
-
Linux - /home/<my-name>/.cache/appsemble/blocks/<organisation>/<block-name>/<block-version>
|
|
102
|
-
Windows - C:\Users\<my-name>\AppData\Local\appsemble\Cache\blocks\<organisation>\<block-name>\<block-version>
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
You can overwrite the existing block cache with the following option:
|
|
106
|
-
|
|
107
|
-
```sh
|
|
108
|
-
appsemble serve <path-to-app-directory> --remote <remote> --overwrite-block-cache
|
|
109
|
-
```
|
|
110
|
-
|
|
111
40
|
### Authentication
|
|
112
41
|
|
|
113
42
|
The Appsemble CLI uses OAuth2 client credentials to authenticate to the Appsemble server.
|
|
@@ -342,5 +271,5 @@ appsemble run-cronjobs --interval 30
|
|
|
342
271
|
|
|
343
272
|
## License
|
|
344
273
|
|
|
345
|
-
[LGPL-3.0-only](https://gitlab.com/appsemble/appsemble/-/blob/0.40.
|
|
274
|
+
[LGPL-3.0-only](https://gitlab.com/appsemble/appsemble/-/blob/0.40.4/LICENSE.md) ©
|
|
346
275
|
[Appsemble](https://appsemble.com)
|
package/index.js
CHANGED
|
@@ -27,7 +27,6 @@ import * as resource from './commands/resource/index.js';
|
|
|
27
27
|
import * as restoreDataFromBackup from './commands/restoreDataFromBackup.js';
|
|
28
28
|
import * as runCronJobs from './commands/runCronJobs.js';
|
|
29
29
|
import * as scaleContainers from './commands/scaleContainers.js';
|
|
30
|
-
import * as serve from './commands/serve.js';
|
|
31
30
|
import * as start from './commands/start.js';
|
|
32
31
|
import { coerceRemote } from './lib/coercers.js';
|
|
33
32
|
import { initAxios } from './lib/initAxios.js';
|
|
@@ -79,7 +78,6 @@ let parser = yargs(process.argv.slice(2))
|
|
|
79
78
|
.command(resource)
|
|
80
79
|
.command(runCronJobs)
|
|
81
80
|
.command(start)
|
|
82
|
-
.command(serve)
|
|
83
81
|
.command(scaleContainers)
|
|
84
82
|
.command(chargeOrganizationSubscriptions)
|
|
85
83
|
.command(group)
|
package/lib/app.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ReadStream } from 'node:fs';
|
|
2
|
-
import { type App, type AppLock, type AppsembleContext, type AppsembleRC, type AppTotp, type AppVisibility
|
|
2
|
+
import { type App, type AppLock, type AppsembleContext, type AppsembleRC, type AppTotp, type AppVisibility } from '@appsemble/types';
|
|
3
3
|
import FormData from 'form-data';
|
|
4
4
|
/**
|
|
5
5
|
* Traverses an app directory and appends the files it finds to the given FormData object.
|
|
@@ -39,7 +39,6 @@ export declare function deleteApp({ clientCredentials, id, remote }: DeleteAppAr
|
|
|
39
39
|
export declare function publishSeedResources(path: string, app: App, remote: string): Promise<void>;
|
|
40
40
|
export declare function publishSeedAppMembers(path: string, app: App, remote: string): Promise<void>;
|
|
41
41
|
export declare function publishSeedAssets(path: string, app: App, remote: string, assetsClonable: boolean): Promise<void>;
|
|
42
|
-
export declare function parseValues(type: string, name: string, valuesToParse: Record<string, ValueFromDefinition>[]): [Record<string, ValueFromProcess>, boolean];
|
|
43
42
|
export declare function publishAppConfig(path: string, app: App, remote: string): Promise<void>;
|
|
44
43
|
/**
|
|
45
44
|
* @param path The path to the app directory.
|
package/lib/app.js
CHANGED
|
@@ -407,7 +407,7 @@ function parseValueFromDefinition(value) {
|
|
|
407
407
|
// @ts-expect-error 2322 null is not assignable to type (strictNullChecks)
|
|
408
408
|
return parsed;
|
|
409
409
|
}
|
|
410
|
-
|
|
410
|
+
function parseValues(type, name, valuesToParse) {
|
|
411
411
|
const parsedValues = {};
|
|
412
412
|
let missingValues = false;
|
|
413
413
|
for (const valueToParse of valuesToParse) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appsemble/cli",
|
|
3
|
-
"version": "0.40.
|
|
3
|
+
"version": "0.40.4",
|
|
4
4
|
"description": "The CLI for developing with Appsemble apps and blocks",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"app",
|
|
@@ -43,14 +43,12 @@
|
|
|
43
43
|
"test": "vitest"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@appsemble/node-utils": "0.40.
|
|
47
|
-
"@appsemble/types": "0.40.
|
|
48
|
-
"@appsemble/lang-sdk": "0.40.
|
|
49
|
-
"@appsemble/utils": "0.40.
|
|
46
|
+
"@appsemble/node-utils": "0.40.4",
|
|
47
|
+
"@appsemble/types": "0.40.4",
|
|
48
|
+
"@appsemble/lang-sdk": "0.40.4",
|
|
49
|
+
"@appsemble/utils": "0.40.4",
|
|
50
50
|
"@fortawesome/fontawesome-common-types": "^6.0.0",
|
|
51
51
|
"@inquirer/prompts": "^8.0.0",
|
|
52
|
-
"@koa/cors": "^5.0.0",
|
|
53
|
-
"@odata/parser": "^0.2.0",
|
|
54
52
|
"axios": "^1.0.0",
|
|
55
53
|
"chalk": "^5.0.0",
|
|
56
54
|
"comment-parser": "^1.0.0",
|
|
@@ -59,17 +57,8 @@
|
|
|
59
57
|
"esbuild": "^0.28.0",
|
|
60
58
|
"fast-glob": "^3.0.0",
|
|
61
59
|
"form-data": "^4.0.4",
|
|
62
|
-
"global-cache-dir": "^6.0.0",
|
|
63
60
|
"jsonschema": "~1.4.1",
|
|
64
61
|
"koa": "^3.0.0",
|
|
65
|
-
"koa-compose": "^4.0.0",
|
|
66
|
-
"koa-compress": "^5.0.0",
|
|
67
|
-
"koa-range": "^0.3.0",
|
|
68
|
-
"koas-core": "^0.7.0",
|
|
69
|
-
"koas-operations": "^0.7.0",
|
|
70
|
-
"koas-status-code": "^0.7.0",
|
|
71
|
-
"mime-types": "^2.0.0",
|
|
72
|
-
"node-json-db": "^2.0.0",
|
|
73
62
|
"normalize-path": "^3.0.0",
|
|
74
63
|
"open": "^9.0.0",
|
|
75
64
|
"postcss": "^8.0.0",
|
|
@@ -80,7 +69,6 @@
|
|
|
80
69
|
"prettier": "^3.0.0",
|
|
81
70
|
"raw-body": "^2.0.0",
|
|
82
71
|
"read-package-up": "^11.0.0",
|
|
83
|
-
"sharp": "0.35.4",
|
|
84
72
|
"ts-json-schema-generator": "^1.0.0",
|
|
85
73
|
"type-fest": "^4.0.0",
|
|
86
74
|
"url": "0.11.4",
|
|
@@ -89,12 +77,9 @@
|
|
|
89
77
|
"yargs": "^17.0.0"
|
|
90
78
|
},
|
|
91
79
|
"devDependencies": {
|
|
92
|
-
"@appsemble/types": "0.40.
|
|
93
|
-
"@appsemble/server": "0.40.
|
|
80
|
+
"@appsemble/types": "0.40.4",
|
|
81
|
+
"@appsemble/server": "0.40.4",
|
|
94
82
|
"@types/concat-stream": "2.0.3",
|
|
95
|
-
"@types/koa__cors": "5.0.1",
|
|
96
|
-
"@types/koa-compress": "4.0.7",
|
|
97
|
-
"@types/koa-range": "0.3.6",
|
|
98
83
|
"@types/normalize-path": "3.0.2",
|
|
99
84
|
"@types/postcss-import": "14.0.3",
|
|
100
85
|
"@types/postcss-url": "10.0.4",
|
|
@@ -6,7 +6,7 @@ pages:
|
|
|
6
6
|
- name: Example Page A
|
|
7
7
|
blocks:
|
|
8
8
|
- type: action-button
|
|
9
|
-
version: 0.40.
|
|
9
|
+
version: 0.40.4
|
|
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.40.
|
|
20
|
+
version: 0.40.4
|
|
21
21
|
parameters:
|
|
22
22
|
icon: arrow-left
|
|
23
23
|
actions:
|
package/commands/serve.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { type Argv } from 'yargs';
|
|
2
|
-
export interface ServeArguments {
|
|
3
|
-
remote: string;
|
|
4
|
-
path: string;
|
|
5
|
-
port: number;
|
|
6
|
-
'api-port': number;
|
|
7
|
-
'user-role': string;
|
|
8
|
-
'group-role': string;
|
|
9
|
-
'overwrite-block-cache': boolean;
|
|
10
|
-
}
|
|
11
|
-
export declare const command = "serve path";
|
|
12
|
-
export declare const description = "Serve an app with a local development server.";
|
|
13
|
-
export declare function builder(yargs: Argv): Argv<any>;
|
|
14
|
-
export declare function handler(argv: ServeArguments): Promise<void>;
|
package/commands/serve.js
DELETED
|
@@ -1,305 +0,0 @@
|
|
|
1
|
-
import { createWriteStream, existsSync } from 'node:fs';
|
|
2
|
-
import { mkdir, readFile } from 'node:fs/promises';
|
|
3
|
-
import http from 'node:http';
|
|
4
|
-
import { basename, dirname, extname, join, parse } from 'node:path';
|
|
5
|
-
import { Readable } from 'node:stream';
|
|
6
|
-
import { pipeline } from 'node:stream/promises';
|
|
7
|
-
import { getAppBlocks, getAppRoles, normalize, parseBlockName, } from '@appsemble/lang-sdk';
|
|
8
|
-
import { AppsembleError, getBlockAssetDownloadUrl, isValidBlockAssetFilename, logger, opendirSafe, readData, writeData, } from '@appsemble/node-utils';
|
|
9
|
-
import { asciiLogo } from '@appsemble/utils';
|
|
10
|
-
import axios from 'axios';
|
|
11
|
-
import csvToJson from 'csvtojson';
|
|
12
|
-
import FormData from 'form-data';
|
|
13
|
-
import globalCacheDir from 'global-cache-dir';
|
|
14
|
-
import { parseValues, traverseAppDirectory } from '../lib/app.js';
|
|
15
|
-
import { buildBlock } from '../lib/block.js';
|
|
16
|
-
import { getProjectBuildConfig, getProjectWebpackConfig } from '../lib/config.js';
|
|
17
|
-
import { createApiServer, createStaticServer } from '../lib/createServers.js';
|
|
18
|
-
import { makeProjectPayload } from '../lib/project.js';
|
|
19
|
-
import { setArgv } from '../server/argv.js';
|
|
20
|
-
import { setAppName } from '../server/db/methods.js';
|
|
21
|
-
import { Resource } from '../server/models/Resource.js';
|
|
22
|
-
export const command = 'serve path';
|
|
23
|
-
export const description = 'Serve an app with a local development server.';
|
|
24
|
-
export function builder(yargs) {
|
|
25
|
-
return yargs
|
|
26
|
-
.positional('path', {
|
|
27
|
-
describe: 'The path to the app to publish.',
|
|
28
|
-
})
|
|
29
|
-
.option('port', {
|
|
30
|
-
desc: 'The static HTTP server port to use. This is the port where the app is accessible.',
|
|
31
|
-
type: 'number',
|
|
32
|
-
default: 9090,
|
|
33
|
-
})
|
|
34
|
-
.option('api-port', {
|
|
35
|
-
desc: 'The Appsemble development HTTP server port to use. This is the port where the Appsemble development API endpoints are available.',
|
|
36
|
-
type: 'number',
|
|
37
|
-
default: 9191,
|
|
38
|
-
})
|
|
39
|
-
.option('user-role', {
|
|
40
|
-
desc: 'The role to set to the mocked authenticated user.',
|
|
41
|
-
type: 'string',
|
|
42
|
-
})
|
|
43
|
-
.option('group-role', {
|
|
44
|
-
desc: 'The role to set to the mocked authenticated user in the group.',
|
|
45
|
-
type: 'string',
|
|
46
|
-
default: 'member',
|
|
47
|
-
})
|
|
48
|
-
.option('remote', {
|
|
49
|
-
desc: 'The address to fetch remote blocks from.',
|
|
50
|
-
type: 'string',
|
|
51
|
-
})
|
|
52
|
-
.option('overwrite-block-cache', {
|
|
53
|
-
desc: 'Whether to overwrite remote blocks cache if it exists.',
|
|
54
|
-
type: 'boolean',
|
|
55
|
-
default: false,
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
export async function handler(argv) {
|
|
59
|
-
setArgv(argv);
|
|
60
|
-
const appPath = join(process.cwd(), argv.path);
|
|
61
|
-
const [, , , appsembleApp] = await traverseAppDirectory(appPath, 'development', new FormData());
|
|
62
|
-
const appRoles = getAppRoles(appsembleApp.definition.security);
|
|
63
|
-
const passedUserRole = argv['user-role'];
|
|
64
|
-
if (passedUserRole && !appRoles?.includes(passedUserRole)) {
|
|
65
|
-
throw appRoles
|
|
66
|
-
? new AppsembleError(`The specified role "${passedUserRole}" is not supported by this app. Supported roles are [${appRoles}]`)
|
|
67
|
-
: new AppsembleError('This app does not support roles');
|
|
68
|
-
}
|
|
69
|
-
const appSecurity = appsembleApp.definition.security;
|
|
70
|
-
const appMemberRole = passedUserRole || appSecurity?.default?.role;
|
|
71
|
-
const appMemberInfo = {
|
|
72
|
-
sub: '1',
|
|
73
|
-
name: 'dev',
|
|
74
|
-
email: 'dev@example.com',
|
|
75
|
-
email_verified: true,
|
|
76
|
-
...(appMemberRole ? { role: appMemberRole } : {}),
|
|
77
|
-
roles: appMemberRole ? [appMemberRole] : [],
|
|
78
|
-
demo: false,
|
|
79
|
-
zoneinfo: '',
|
|
80
|
-
properties: {},
|
|
81
|
-
$seed: false,
|
|
82
|
-
$ephemeral: false,
|
|
83
|
-
};
|
|
84
|
-
const appMembers = [appMemberInfo];
|
|
85
|
-
const allowedGroupRoles = ['manager', 'member'];
|
|
86
|
-
const passedGroupRole = argv['group-role'];
|
|
87
|
-
if (passedGroupRole && !allowedGroupRoles.includes(passedGroupRole)) {
|
|
88
|
-
throw new AppsembleError(`The specified group role ${passedGroupRole} is not supported. Allowed roles are [member,manager]`);
|
|
89
|
-
}
|
|
90
|
-
const appGroups = [
|
|
91
|
-
{
|
|
92
|
-
id: 1,
|
|
93
|
-
name: 'group',
|
|
94
|
-
size: 1,
|
|
95
|
-
annotations: {},
|
|
96
|
-
},
|
|
97
|
-
];
|
|
98
|
-
const appName = normalize(appsembleApp.definition.name);
|
|
99
|
-
const appId = 1;
|
|
100
|
-
setAppName(appName);
|
|
101
|
-
const identifiableBlocks = getAppBlocks(appsembleApp.definition);
|
|
102
|
-
const localIdentifiableBlocks = [];
|
|
103
|
-
const remoteIdentifiableBlocks = [];
|
|
104
|
-
for (const identifiableBlock of identifiableBlocks) {
|
|
105
|
-
const [, blockName] = parseBlockName(identifiableBlock.type);
|
|
106
|
-
if (existsSync(join(process.cwd(), 'blocks', blockName))) {
|
|
107
|
-
localIdentifiableBlocks.push(identifiableBlock);
|
|
108
|
-
}
|
|
109
|
-
else {
|
|
110
|
-
remoteIdentifiableBlocks.push(identifiableBlock);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
const localBlocksConfigs = await Promise.all(localIdentifiableBlocks.map(async (identifiableBlock) => {
|
|
114
|
-
const [organization, blockName] = parseBlockName(identifiableBlock.type);
|
|
115
|
-
const buildConfig = await getProjectBuildConfig(join(process.cwd(), 'blocks', blockName));
|
|
116
|
-
return {
|
|
117
|
-
...buildConfig,
|
|
118
|
-
OrganizationId: organization,
|
|
119
|
-
};
|
|
120
|
-
}));
|
|
121
|
-
const localBlocksPromises = localBlocksConfigs.map(async (blockConfig) => {
|
|
122
|
-
await buildBlock(blockConfig, 'development');
|
|
123
|
-
const [, blockImplementations] = await makeProjectPayload(blockConfig);
|
|
124
|
-
return {
|
|
125
|
-
...blockImplementations,
|
|
126
|
-
...blockConfig,
|
|
127
|
-
};
|
|
128
|
-
});
|
|
129
|
-
const cacheDir = await globalCacheDir('appsemble');
|
|
130
|
-
const remoteBlocksPromises = remoteIdentifiableBlocks.map(async (identifiableBlock) => {
|
|
131
|
-
const [organization, blockName] = parseBlockName(identifiableBlock.type);
|
|
132
|
-
const blockCacheDir = join(cacheDir, 'blocks', organization, blockName, identifiableBlock.version);
|
|
133
|
-
const cachedBlockManifest = join(blockCacheDir, 'manifest.json');
|
|
134
|
-
const cacheExists = existsSync(cachedBlockManifest);
|
|
135
|
-
if (!cacheExists || (cacheExists && argv['overwrite-block-cache'])) {
|
|
136
|
-
const blockUrl = String(new URL(`/api/blocks/@${organization}/${blockName}/versions/${identifiableBlock.version}`, argv.remote));
|
|
137
|
-
try {
|
|
138
|
-
const { data: blockManifest } = await axios.get(blockUrl);
|
|
139
|
-
const assetsDir = join(blockCacheDir, 'assets');
|
|
140
|
-
if (!existsSync(assetsDir)) {
|
|
141
|
-
await mkdir(assetsDir);
|
|
142
|
-
}
|
|
143
|
-
const blockFilesPromises = blockManifest.files.map(async (filename) => {
|
|
144
|
-
if (!isValidBlockAssetFilename(filename)) {
|
|
145
|
-
throw new AppsembleError(`Invalid block asset filename: ${filename}`);
|
|
146
|
-
}
|
|
147
|
-
const target = join(assetsDir, filename);
|
|
148
|
-
await mkdir(dirname(target), { recursive: true });
|
|
149
|
-
const { data: content } = await axios.get(getBlockAssetDownloadUrl(blockUrl, blockManifest.fileUrls, filename), {
|
|
150
|
-
responseType: 'stream',
|
|
151
|
-
});
|
|
152
|
-
await pipeline(content, createWriteStream(target));
|
|
153
|
-
});
|
|
154
|
-
await Promise.all(blockFilesPromises);
|
|
155
|
-
const localBlockManifest = { ...blockManifest };
|
|
156
|
-
delete localBlockManifest.fileUrls;
|
|
157
|
-
await writeData(cachedBlockManifest, localBlockManifest);
|
|
158
|
-
return localBlockManifest;
|
|
159
|
-
}
|
|
160
|
-
catch {
|
|
161
|
-
throw new AppsembleError(`The server was unable to fetch the "${blockName}" block\nThis could be due to a misconfigured remote\nMake sure the passed remote supports fetching blocks such as https://appsemble.app`);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
const [blockManifest] = (await readData(cachedBlockManifest));
|
|
165
|
-
delete blockManifest.fileUrls;
|
|
166
|
-
return blockManifest;
|
|
167
|
-
});
|
|
168
|
-
const localBlocks = await Promise.all(localBlocksPromises);
|
|
169
|
-
const remoteBlocks = await Promise.all(remoteBlocksPromises);
|
|
170
|
-
const appBlocks = [...localBlocks, ...remoteBlocks];
|
|
171
|
-
const webpackConfigs = await Promise.all(localBlocksConfigs.map((blockConfig) => getProjectWebpackConfig(blockConfig, 'development',
|
|
172
|
-
// @ts-expect-error 2345 argument of type is not assignable to parameter of type
|
|
173
|
-
// (strictNullChecks)
|
|
174
|
-
join(blockConfig.dir, blockConfig.output))));
|
|
175
|
-
// Get app messages
|
|
176
|
-
const appMessages = [];
|
|
177
|
-
await opendirSafe(join(appPath, 'i18n'), async (path) => {
|
|
178
|
-
logger.verbose(`Processing ${path} ⚙️`);
|
|
179
|
-
const { name: language } = parse(path);
|
|
180
|
-
if (appMessages.some((entry) => entry.language === language)) {
|
|
181
|
-
throw new AppsembleError(`Found duplicate language “${language}”. Make sure each language only exists once in the directory.`);
|
|
182
|
-
}
|
|
183
|
-
const [messages] = await readData(path);
|
|
184
|
-
appMessages.push({ language, messages });
|
|
185
|
-
}, { allowMissing: true });
|
|
186
|
-
// Get app assets
|
|
187
|
-
const appAssets = [];
|
|
188
|
-
await opendirSafe(join(appPath, 'assets'), (path) => {
|
|
189
|
-
logger.verbose(`Processing ${path} ⚙️`);
|
|
190
|
-
const extension = extname(path);
|
|
191
|
-
const name = basename(path, extension);
|
|
192
|
-
appAssets.push({
|
|
193
|
-
id: name,
|
|
194
|
-
mime: extension,
|
|
195
|
-
filename: path,
|
|
196
|
-
name,
|
|
197
|
-
});
|
|
198
|
-
}, { allowMissing: true });
|
|
199
|
-
// Get app resources
|
|
200
|
-
await opendirSafe(join(appPath, 'resources'), async (path, stat) => {
|
|
201
|
-
logger.verbose(`Processing ${path} ⚙️`);
|
|
202
|
-
let resources;
|
|
203
|
-
if (path.endsWith('.csv')) {
|
|
204
|
-
const data = await readFile(path);
|
|
205
|
-
const stream = Readable.from(data);
|
|
206
|
-
resources = await csvToJson({}).fromStream(stream);
|
|
207
|
-
}
|
|
208
|
-
else {
|
|
209
|
-
const [resource] = await readData(path);
|
|
210
|
-
if (typeof resource !== 'object') {
|
|
211
|
-
throw new AppsembleError(`File at ${path} does not contain an object or array of objects`);
|
|
212
|
-
}
|
|
213
|
-
resources = [].concat(resource);
|
|
214
|
-
}
|
|
215
|
-
logger.info(`Creating resource(s) from ${path}`);
|
|
216
|
-
const { name } = parse(stat.name);
|
|
217
|
-
await Resource.bulkCreate(resources, name, true);
|
|
218
|
-
}, { allowMissing: true });
|
|
219
|
-
const appVariables = [];
|
|
220
|
-
const configPath = join(appPath, 'config');
|
|
221
|
-
if (existsSync(configPath)) {
|
|
222
|
-
const variablesPath = join(configPath, 'variables.json');
|
|
223
|
-
if (existsSync(variablesPath)) {
|
|
224
|
-
const [readAppVariables] = (await readData(variablesPath));
|
|
225
|
-
if (readAppVariables.length) {
|
|
226
|
-
for (const appVariable of readAppVariables) {
|
|
227
|
-
const { name, value } = appVariable;
|
|
228
|
-
const [parsedValues, missingValues] = parseValues('variable', name, [{ value }]);
|
|
229
|
-
if (missingValues) {
|
|
230
|
-
continue;
|
|
231
|
-
}
|
|
232
|
-
appVariables.push({ name, ...parsedValues });
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
const stubbedApp = {
|
|
238
|
-
...appsembleApp,
|
|
239
|
-
id: appId,
|
|
240
|
-
path: appPath,
|
|
241
|
-
coreStyle: appsembleApp.coreStyle || '',
|
|
242
|
-
sharedStyle: appsembleApp.sharedStyle || '',
|
|
243
|
-
$updated: new Date().toISOString(),
|
|
244
|
-
};
|
|
245
|
-
const appsembleApiServer = createApiServer({
|
|
246
|
-
context: {
|
|
247
|
-
appHost: `http://localhost:${argv.port}`,
|
|
248
|
-
appsembleApp: stubbedApp,
|
|
249
|
-
appBlocks,
|
|
250
|
-
appMessages,
|
|
251
|
-
appVariables,
|
|
252
|
-
...(appSecurity
|
|
253
|
-
? {
|
|
254
|
-
appMembers,
|
|
255
|
-
appMemberInfo,
|
|
256
|
-
appGroups,
|
|
257
|
-
}
|
|
258
|
-
: {}),
|
|
259
|
-
appAssets,
|
|
260
|
-
blockConfigs: localBlocksConfigs,
|
|
261
|
-
},
|
|
262
|
-
});
|
|
263
|
-
appsembleApiServer.on('error', (err) => {
|
|
264
|
-
if (err.expose) {
|
|
265
|
-
return;
|
|
266
|
-
}
|
|
267
|
-
logger.error(err);
|
|
268
|
-
});
|
|
269
|
-
const api = http.createServer(appsembleApiServer.callback());
|
|
270
|
-
const staticServer = await createStaticServer({
|
|
271
|
-
context: {
|
|
272
|
-
appPath,
|
|
273
|
-
apiUrl: `http://localhost:${argv['api-port']}`,
|
|
274
|
-
appHost: `http://localhost:${argv.port}`,
|
|
275
|
-
appsembleApp: stubbedApp,
|
|
276
|
-
appBlocks,
|
|
277
|
-
appMessages,
|
|
278
|
-
...(appSecurity
|
|
279
|
-
? {
|
|
280
|
-
appMembers,
|
|
281
|
-
appMemberInfo,
|
|
282
|
-
appGroups,
|
|
283
|
-
}
|
|
284
|
-
: {}),
|
|
285
|
-
appAssets,
|
|
286
|
-
blockConfigs: localBlocksConfigs,
|
|
287
|
-
},
|
|
288
|
-
webpackConfigs,
|
|
289
|
-
});
|
|
290
|
-
staticServer.on('error', (err) => {
|
|
291
|
-
if (err.expose) {
|
|
292
|
-
return;
|
|
293
|
-
}
|
|
294
|
-
logger.error(err);
|
|
295
|
-
});
|
|
296
|
-
const app = http.createServer(staticServer.callback());
|
|
297
|
-
api.listen(argv['api-port'], '::', () => {
|
|
298
|
-
logger.info(asciiLogo);
|
|
299
|
-
logger.info(`The api can be found on\n> http://localhost:${argv['api-port']}`);
|
|
300
|
-
});
|
|
301
|
-
app.listen(argv.port, '::', () => {
|
|
302
|
-
logger.info(`\nThe app can be found on\n> http://localhost:${argv.port}`);
|
|
303
|
-
});
|
|
304
|
-
}
|
|
305
|
-
//# sourceMappingURL=serve.js.map
|
package/lib/createServers.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import Koa from 'koa';
|
|
2
|
-
import { type Configuration } from 'webpack';
|
|
3
|
-
interface CreateServerOptions {
|
|
4
|
-
/**
|
|
5
|
-
* Additional context to append to the server.
|
|
6
|
-
*/
|
|
7
|
-
context?: Record<string, any>;
|
|
8
|
-
/**
|
|
9
|
-
* Webpack configurations to serve using Webpack dev server middleware.
|
|
10
|
-
*/
|
|
11
|
-
webpackConfigs?: Configuration[];
|
|
12
|
-
}
|
|
13
|
-
export declare function createStaticServer({ context, webpackConfigs, }: CreateServerOptions): Promise<Koa>;
|
|
14
|
-
export declare function createApiServer({ context }: CreateServerOptions): Koa;
|
|
15
|
-
export {};
|
package/lib/createServers.js
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { bodyParser, conditional, errorMiddleware, frontend, loggerMiddleware, parameters, serializer, throwKoaError, version, } from '@appsemble/node-utils';
|
|
2
|
-
import { api } from '@appsemble/utils';
|
|
3
|
-
import cors from '@koa/cors';
|
|
4
|
-
import Koa from 'koa';
|
|
5
|
-
import compose from 'koa-compose';
|
|
6
|
-
import compress from 'koa-compress';
|
|
7
|
-
import range from 'koa-range';
|
|
8
|
-
import { koas } from 'koas-core';
|
|
9
|
-
import { operations } from 'koas-operations';
|
|
10
|
-
import { statusCode } from 'koas-status-code';
|
|
11
|
-
import { argv } from '../server/argv.js';
|
|
12
|
-
import * as controllers from '../server/controllers/index.js';
|
|
13
|
-
import { appRouter } from '../server/routes/appRouter/index.js';
|
|
14
|
-
export async function createStaticServer({ context, webpackConfigs, }) {
|
|
15
|
-
const app = new Koa();
|
|
16
|
-
app.use(loggerMiddleware());
|
|
17
|
-
app.use(errorMiddleware());
|
|
18
|
-
app.use(range);
|
|
19
|
-
Object.assign(app.context, context);
|
|
20
|
-
if (process.env.NODE_ENV === 'production') {
|
|
21
|
-
app.use(compress());
|
|
22
|
-
}
|
|
23
|
-
if (!['test', 'production'].includes(process.env.NODE_ENV ?? '')) {
|
|
24
|
-
// @ts-expect-error 2345 argument of type is not assignable to parameter of type
|
|
25
|
-
// (strictNullChecks)
|
|
26
|
-
app.use(await frontend(webpackConfigs, argv));
|
|
27
|
-
}
|
|
28
|
-
app.use(appRouter);
|
|
29
|
-
return app;
|
|
30
|
-
}
|
|
31
|
-
export function createApiServer({ context }) {
|
|
32
|
-
const app = new Koa();
|
|
33
|
-
app.use(loggerMiddleware());
|
|
34
|
-
app.use(errorMiddleware());
|
|
35
|
-
app.use(range);
|
|
36
|
-
Object.assign(app.context, context);
|
|
37
|
-
if (process.env.NODE_ENV === 'production') {
|
|
38
|
-
app.use(compress());
|
|
39
|
-
}
|
|
40
|
-
app.use(compose([
|
|
41
|
-
conditional((ctx) => ctx.path.startsWith('/api') ||
|
|
42
|
-
ctx.path === '/auth/oauth2/token' ||
|
|
43
|
-
/\/apps\/\d+\/auth\/oauth2\/token/.test(ctx.path),
|
|
44
|
-
// Reflect the origin instead of '*', so credentialed app requests pass CORS.
|
|
45
|
-
cors({ origin: (ctx) => ctx.get('Origin') || '*', credentials: true })),
|
|
46
|
-
koas(api(version, argv), [
|
|
47
|
-
parameters(),
|
|
48
|
-
bodyParser(),
|
|
49
|
-
serializer(),
|
|
50
|
-
statusCode(),
|
|
51
|
-
operations({ controllers, throwOnNotImplemented: false }),
|
|
52
|
-
]),
|
|
53
|
-
(ctx, next) => {
|
|
54
|
-
if (ctx.path.startsWith('/api/')) {
|
|
55
|
-
throwKoaError(ctx, 404, 'URL not found');
|
|
56
|
-
}
|
|
57
|
-
return next();
|
|
58
|
-
},
|
|
59
|
-
]));
|
|
60
|
-
return app;
|
|
61
|
-
}
|
|
62
|
-
//# sourceMappingURL=createServers.js.map
|