@appsemble/cli 0.36.10 → 0.37.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/commands/start.js +5 -0
- package/lib/config.js +4 -2
- package/package.json +7 -7
- package/server/options/deleteAppResource.d.ts +1 -1
- package/server/options/deleteAppResource.js +13 -2
- package/server/options/getTheme.d.ts +1 -1
- package/server/options/getTheme.js +1 -4
- package/server/options/updateAppResource.d.ts +1 -1
- package/server/options/updateAppResource.js +13 -2
- package/server/utils/resourceLock.d.ts +11 -0
- package/server/utils/resourceLock.js +23 -0
- 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/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.37.1)
|
|
7
7
|
[](https://prettier.io)
|
|
8
8
|
|
|
9
9
|
## Table of Contents
|
|
@@ -342,5 +342,5 @@ appsemble run-cronjobs --interval 30
|
|
|
342
342
|
|
|
343
343
|
## License
|
|
344
344
|
|
|
345
|
-
[LGPL-3.0-only](https://gitlab.com/appsemble/appsemble/-/blob/0.
|
|
345
|
+
[LGPL-3.0-only](https://gitlab.com/appsemble/appsemble/-/blob/0.37.1/LICENSE.md) ©
|
|
346
346
|
[Appsemble](https://appsemble.com)
|
package/commands/start.js
CHANGED
|
@@ -159,6 +159,11 @@ export function builder(yargs) {
|
|
|
159
159
|
desc: 'Use TLS when connecting to the Valkey server.',
|
|
160
160
|
type: 'boolean',
|
|
161
161
|
default: false,
|
|
162
|
+
})
|
|
163
|
+
.option('app-serving-cache-ttl', {
|
|
164
|
+
desc: 'The TTL in seconds for cached app-serving metadata. Set to 0 to disable the cache.',
|
|
165
|
+
type: 'number',
|
|
166
|
+
default: 300,
|
|
162
167
|
});
|
|
163
168
|
}
|
|
164
169
|
export async function handler(argv) {
|
package/lib/config.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
2
|
import { readFile, stat } from 'node:fs/promises';
|
|
3
|
-
import { dirname, join, relative } from 'node:path';
|
|
3
|
+
import { dirname, isAbsolute, join, relative } from 'node:path';
|
|
4
|
+
import { pathToFileURL } from 'node:url';
|
|
4
5
|
import { inspect } from 'node:util';
|
|
5
6
|
import { prefixBlockURL } from '@appsemble/lang-sdk';
|
|
6
7
|
import { AppsembleError, getWorkspaces, logger, readData } from '@appsemble/node-utils';
|
|
@@ -396,7 +397,8 @@ export async function getProjectWebpackConfig(buildConfig, mode, outputPath) {
|
|
|
396
397
|
}
|
|
397
398
|
logger.info(`Using webpack config from ${configPath}`);
|
|
398
399
|
const publicPath = prefixBlockURL({ type: buildConfig.name, version: buildConfig.version }, '');
|
|
399
|
-
|
|
400
|
+
const configSpecifier = isAbsolute(configPath) ? pathToFileURL(configPath).href : configPath;
|
|
401
|
+
let config = await import(configSpecifier);
|
|
400
402
|
config = await (config.default || config);
|
|
401
403
|
config = config instanceof Function ? await config(buildConfig, { mode, publicPath }) : config;
|
|
402
404
|
// Koa-webpack serves assets on the `output.path` path. Normally this field describes where to
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appsemble/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.37.1",
|
|
4
4
|
"description": "The CLI for developing with Appsemble apps and blocks",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"app",
|
|
@@ -44,10 +44,10 @@
|
|
|
44
44
|
"test": "vitest"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@appsemble/node-utils": "0.
|
|
48
|
-
"@appsemble/types": "0.
|
|
49
|
-
"@appsemble/lang-sdk": "0.
|
|
50
|
-
"@appsemble/utils": "0.
|
|
47
|
+
"@appsemble/node-utils": "0.37.1",
|
|
48
|
+
"@appsemble/types": "0.37.1",
|
|
49
|
+
"@appsemble/lang-sdk": "0.37.1",
|
|
50
|
+
"@appsemble/utils": "0.37.1",
|
|
51
51
|
"@fortawesome/fontawesome-common-types": "^6.0.0",
|
|
52
52
|
"@inquirer/prompts": "^8.0.0",
|
|
53
53
|
"@koa/cors": "^5.0.0",
|
|
@@ -89,8 +89,8 @@
|
|
|
89
89
|
"yargs": "^17.0.0"
|
|
90
90
|
},
|
|
91
91
|
"devDependencies": {
|
|
92
|
-
"@appsemble/types": "0.
|
|
93
|
-
"@appsemble/server": "0.
|
|
92
|
+
"@appsemble/types": "0.37.1",
|
|
93
|
+
"@appsemble/server": "0.37.1",
|
|
94
94
|
"@types/concat-stream": "2.0.3",
|
|
95
95
|
"@types/koa__cors": "5.0.1",
|
|
96
96
|
"@types/koa-compress": "4.0.7",
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { type DeleteAppResourceParams } from '@appsemble/node-utils';
|
|
2
|
-
export declare function deleteAppResource({ id, type }: DeleteAppResourceParams): Promise<void>;
|
|
2
|
+
export declare function deleteAppResource({ context, id, ifMatch, type, }: DeleteAppResourceParams): Promise<void>;
|
|
@@ -1,5 +1,16 @@
|
|
|
1
|
+
import { createResourceEtag, matchesResourceIfMatch, throwResourcePreconditionFailedKoaError, } from '@appsemble/node-utils';
|
|
1
2
|
import { Resource } from '../models/Resource.js';
|
|
2
|
-
|
|
3
|
-
|
|
3
|
+
import { withResourceLock } from '../utils/resourceLock.js';
|
|
4
|
+
export function deleteAppResource({ context, id, ifMatch, type, }) {
|
|
5
|
+
return withResourceLock(type, id, async () => {
|
|
6
|
+
if (ifMatch) {
|
|
7
|
+
const existing = await Resource.findById(id, type);
|
|
8
|
+
if (!existing ||
|
|
9
|
+
!matchesResourceIfMatch(ifMatch, createResourceEtag(existing))) {
|
|
10
|
+
throwResourcePreconditionFailedKoaError(context, type, id);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return Resource.deleteOne(id, type);
|
|
14
|
+
});
|
|
4
15
|
}
|
|
5
16
|
//# sourceMappingURL=deleteAppResource.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { type GetThemeParams, type Theme as ThemeInterface } from '@appsemble/node-utils';
|
|
2
|
-
export declare function getTheme({ theme }: GetThemeParams): Promise<ThemeInterface>;
|
|
2
|
+
export declare function getTheme({ theme }: GetThemeParams): Promise<ThemeInterface | null>;
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { Theme } from '../models/Theme.js';
|
|
2
2
|
export async function getTheme({ theme }) {
|
|
3
3
|
const persistedTheme = await Theme.findOne({ where: theme });
|
|
4
|
-
return {
|
|
5
|
-
// @ts-expect-error 2322 null is not assignable to type (strictNullChecks)
|
|
6
|
-
css: persistedTheme ? persistedTheme.css : null,
|
|
7
|
-
};
|
|
4
|
+
return persistedTheme && { css: persistedTheme.css };
|
|
8
5
|
}
|
|
9
6
|
//# sourceMappingURL=getTheme.js.map
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { type UpdateAppResourceParams } from '@appsemble/node-utils';
|
|
2
2
|
import { type Resource as ResourceInterface } from '@appsemble/types';
|
|
3
|
-
export declare function updateAppResource({ id, resource, type, }: UpdateAppResourceParams): Promise<ResourceInterface | null>;
|
|
3
|
+
export declare function updateAppResource({ context, id, ifMatch, resource, type, }: UpdateAppResourceParams): Promise<ResourceInterface | null>;
|
|
@@ -1,5 +1,16 @@
|
|
|
1
|
+
import { createResourceEtag, matchesResourceIfMatch, throwResourcePreconditionFailedKoaError, } from '@appsemble/node-utils';
|
|
1
2
|
import { Resource } from '../models/Resource.js';
|
|
2
|
-
|
|
3
|
-
|
|
3
|
+
import { withResourceLock } from '../utils/resourceLock.js';
|
|
4
|
+
export function updateAppResource({ context, id, ifMatch, resource, type, }) {
|
|
5
|
+
return withResourceLock(type, id, async () => {
|
|
6
|
+
if (ifMatch) {
|
|
7
|
+
const existing = await Resource.findById(id, type);
|
|
8
|
+
if (!existing ||
|
|
9
|
+
!matchesResourceIfMatch(ifMatch, createResourceEtag(existing))) {
|
|
10
|
+
throwResourcePreconditionFailedKoaError(context, type, id);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return Resource.updateOne(id, resource, type);
|
|
14
|
+
});
|
|
4
15
|
}
|
|
5
16
|
//# sourceMappingURL=updateAppResource.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serialize file-backed resource operations against the same (type, id) pair so
|
|
3
|
+
* the read-then-write pattern used by `updateAppResource`/`deleteAppResource`
|
|
4
|
+
* cannot interleave with a concurrent writer.
|
|
5
|
+
*
|
|
6
|
+
* @param type Resource type, used as part of the lock key.
|
|
7
|
+
* @param id Resource id, used as part of the lock key.
|
|
8
|
+
* @param fn Async operation to run while holding the lock.
|
|
9
|
+
* @returns The resolved value of `fn`.
|
|
10
|
+
*/
|
|
11
|
+
export declare function withResourceLock<T>(type: string, id: number | string, fn: () => Promise<T>): Promise<T>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const queues = new Map();
|
|
2
|
+
/**
|
|
3
|
+
* Serialize file-backed resource operations against the same (type, id) pair so
|
|
4
|
+
* the read-then-write pattern used by `updateAppResource`/`deleteAppResource`
|
|
5
|
+
* cannot interleave with a concurrent writer.
|
|
6
|
+
*
|
|
7
|
+
* @param type Resource type, used as part of the lock key.
|
|
8
|
+
* @param id Resource id, used as part of the lock key.
|
|
9
|
+
* @param fn Async operation to run while holding the lock.
|
|
10
|
+
* @returns The resolved value of `fn`.
|
|
11
|
+
*/
|
|
12
|
+
export function withResourceLock(type, id, fn) {
|
|
13
|
+
const key = `${type}#${id}`;
|
|
14
|
+
const previous = queues.get(key) ?? Promise.resolve();
|
|
15
|
+
const next = previous.then(fn, fn);
|
|
16
|
+
queues.set(key, next.finally(() => {
|
|
17
|
+
if (queues.get(key) === next) {
|
|
18
|
+
queues.delete(key);
|
|
19
|
+
}
|
|
20
|
+
}));
|
|
21
|
+
return next;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=resourceLock.js.map
|
|
@@ -6,7 +6,7 @@ pages:
|
|
|
6
6
|
- name: Example Page A
|
|
7
7
|
blocks:
|
|
8
8
|
- type: action-button
|
|
9
|
-
version: 0.
|
|
9
|
+
version: 0.37.1
|
|
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.
|
|
20
|
+
version: 0.37.1
|
|
21
21
|
parameters:
|
|
22
22
|
icon: arrow-left
|
|
23
23
|
actions:
|