@appsemble/cli 0.26.0 → 0.27.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/app/publish.js +4 -5
- package/commands/app/update.d.ts +3 -1
- package/commands/app/update.js +15 -5
- package/commands/asset/publish.d.ts +2 -1
- package/commands/asset/publish.js +6 -1
- package/commands/resource/publish.d.ts +2 -1
- package/commands/resource/publish.js +7 -2
- package/lib/app.d.ts +14 -4
- package/lib/app.js +181 -111
- package/lib/asset.d.ts +5 -1
- package/lib/asset.js +3 -2
- package/lib/resource.d.ts +10 -2
- package/lib/resource.js +8 -5
- package/package.json +5 -5
- package/server/options/index.d.ts +0 -1
- package/server/options/index.js +0 -1
- package/server/options/options.js +1 -2
- 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/server/options/checkSeededResources.d.ts +0 -1
- package/server/options/checkSeededResources.js +0 -4
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.27.1)
|
|
7
7
|
[](https://prettier.io)
|
|
8
8
|
|
|
9
9
|
## Table of Contents
|
|
@@ -305,5 +305,5 @@ appsemble run-cronjobs --interval 30
|
|
|
305
305
|
|
|
306
306
|
## License
|
|
307
307
|
|
|
308
|
-
[LGPL-3.0-only](https://gitlab.com/appsemble/appsemble/-/blob/0.
|
|
308
|
+
[LGPL-3.0-only](https://gitlab.com/appsemble/appsemble/-/blob/0.27.1/LICENSE.md) ©
|
|
309
309
|
[Appsemble](https://appsemble.com)
|
package/commands/app/publish.js
CHANGED
|
@@ -40,26 +40,25 @@ export function builder(yargs) {
|
|
|
40
40
|
.option('demo-mode', {
|
|
41
41
|
describe: 'Whether the app should be used in demo mode.',
|
|
42
42
|
type: 'boolean',
|
|
43
|
-
})
|
|
44
|
-
.option('seed', {
|
|
45
|
-
describe: 'Whether to enable seeding for an app or not.',
|
|
46
|
-
implies: ['demo-mode'],
|
|
47
43
|
})
|
|
48
44
|
.option('dry-run', {
|
|
49
45
|
describe: 'Whether the API should be called to run without actually creating the app.',
|
|
50
46
|
type: 'boolean',
|
|
51
47
|
})
|
|
52
48
|
.option('resources', {
|
|
53
|
-
describe: 'Whether the resources from the `resources` directory should be created after publishing the app. The names of
|
|
49
|
+
describe: 'Whether the resources from the `resources` directory should be created after publishing the app. The names of sub-directories are used as the name of the resource, otherwise the names of top level resource .json files are used instead.',
|
|
54
50
|
type: 'boolean',
|
|
55
51
|
})
|
|
56
52
|
.option('assets', {
|
|
57
53
|
describe: 'Whether the assets from the `assets` directory should be created after publishing the app.',
|
|
58
54
|
type: 'boolean',
|
|
55
|
+
default: false,
|
|
59
56
|
})
|
|
60
57
|
.option('assets-clonable', {
|
|
61
58
|
describe: 'Whether published assets should be clonable. Ignored if assets equals false.',
|
|
62
59
|
type: 'boolean',
|
|
60
|
+
default: false,
|
|
61
|
+
implies: 'assets',
|
|
63
62
|
})
|
|
64
63
|
.option('modify-context', {
|
|
65
64
|
describe: 'If the app context is specified, modify it for the current context to include the id of the published app.',
|
package/commands/app/update.d.ts
CHANGED
|
@@ -13,7 +13,9 @@ interface UpdateAppArguments extends BaseArguments {
|
|
|
13
13
|
id: number;
|
|
14
14
|
template: boolean;
|
|
15
15
|
demoMode: boolean;
|
|
16
|
-
|
|
16
|
+
resources: boolean;
|
|
17
|
+
assets: boolean;
|
|
18
|
+
assetsClonable: boolean;
|
|
17
19
|
force: boolean;
|
|
18
20
|
visibility: AppVisibility;
|
|
19
21
|
sentryDsn: string;
|
package/commands/app/update.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AppsembleError,
|
|
1
|
+
import { AppsembleError, logger } from '@appsemble/node-utils';
|
|
2
2
|
import fg from 'fast-glob';
|
|
3
3
|
import normalizePath from 'normalize-path';
|
|
4
4
|
import { updateApp } from '../../lib/app.js';
|
|
@@ -44,9 +44,20 @@ export function builder(yargs) {
|
|
|
44
44
|
describe: 'Whether the app should be used in demo mode.',
|
|
45
45
|
type: 'boolean',
|
|
46
46
|
})
|
|
47
|
-
.option('
|
|
48
|
-
describe: 'Whether
|
|
49
|
-
|
|
47
|
+
.option('resources', {
|
|
48
|
+
describe: 'Whether the resources from the `resources` directory should replace the seed resources of the app being updated. The names of sub-directories are used as the name of the resource, otherwise the names of top level resource .json files are used instead.',
|
|
49
|
+
type: 'boolean',
|
|
50
|
+
})
|
|
51
|
+
.option('assets', {
|
|
52
|
+
describe: 'Whether the assets from the `assets` directory should replace the seed assets of the app being updated.',
|
|
53
|
+
type: 'boolean',
|
|
54
|
+
default: false,
|
|
55
|
+
})
|
|
56
|
+
.option('assets-clonable', {
|
|
57
|
+
describe: 'Whether published assets should be clonable. Ignored if assets equals false.',
|
|
58
|
+
type: 'boolean',
|
|
59
|
+
default: false,
|
|
60
|
+
implies: 'assets',
|
|
50
61
|
})
|
|
51
62
|
.option('force', {
|
|
52
63
|
describe: 'Whether the lock property should be ignored.',
|
|
@@ -70,7 +81,6 @@ export async function handler({ clientCredentials, id, paths, remote, ...args })
|
|
|
70
81
|
}
|
|
71
82
|
const normalizedPaths = paths.map((path) => normalizePath(path));
|
|
72
83
|
const directories = await fg(normalizedPaths, { absolute: true, onlyDirectories: true });
|
|
73
|
-
await authenticate(remote, 'apps:write', clientCredentials);
|
|
74
84
|
logger.info(`Updating ${directories.length} apps`);
|
|
75
85
|
for (const dir of directories) {
|
|
76
86
|
await updateApp({
|
|
@@ -8,9 +8,10 @@ interface PublishAssetArguments extends BaseArguments {
|
|
|
8
8
|
context: string;
|
|
9
9
|
app: string;
|
|
10
10
|
clonable: boolean;
|
|
11
|
+
seed: boolean;
|
|
11
12
|
}
|
|
12
13
|
export declare const command = "publish <paths...>";
|
|
13
14
|
export declare const description = "Publish assets for an existing app.";
|
|
14
15
|
export declare function builder(yargs: Argv): Argv<any>;
|
|
15
|
-
export declare function handler({ app, appId, clientCredentials, clonable, context, name, paths, remote, useFileName, }: PublishAssetArguments): Promise<void>;
|
|
16
|
+
export declare function handler({ app, appId, clientCredentials, clonable, context, name, paths, remote, seed, useFileName, }: PublishAssetArguments): Promise<void>;
|
|
16
17
|
export {};
|
|
@@ -35,9 +35,13 @@ export function builder(yargs) {
|
|
|
35
35
|
type: 'boolean',
|
|
36
36
|
default: false,
|
|
37
37
|
describe: 'If true, all published assets will be clonable',
|
|
38
|
+
})
|
|
39
|
+
.option('seed', {
|
|
40
|
+
describe: 'If true, published resources will be used as seed',
|
|
41
|
+
default: false,
|
|
38
42
|
});
|
|
39
43
|
}
|
|
40
|
-
export async function handler({ app, appId, clientCredentials, clonable, context, name, paths, remote, useFileName, }) {
|
|
44
|
+
export async function handler({ app, appId, clientCredentials, clonable, context, name, paths, remote, seed, useFileName, }) {
|
|
41
45
|
const [resolvedAppId, resolvedRemote] = await resolveAppIdAndRemote(app, context, remote, appId);
|
|
42
46
|
await authenticate(resolvedRemote, 'assets:write', clientCredentials);
|
|
43
47
|
const normalizedPaths = paths.map((path) => normalizePath(path));
|
|
@@ -52,6 +56,7 @@ export async function handler({ app, appId, clientCredentials, clonable, context
|
|
|
52
56
|
name: name || (useFileName ? parse(path).name : null),
|
|
53
57
|
appId: resolvedAppId,
|
|
54
58
|
path,
|
|
59
|
+
seed,
|
|
55
60
|
remote: resolvedRemote,
|
|
56
61
|
clonable,
|
|
57
62
|
});
|
|
@@ -6,9 +6,10 @@ interface PublishResourceArguments extends BaseArguments {
|
|
|
6
6
|
appId: number;
|
|
7
7
|
context: string;
|
|
8
8
|
app: string;
|
|
9
|
+
seed: boolean;
|
|
9
10
|
}
|
|
10
11
|
export declare const command = "publish <resource-name> <paths...>";
|
|
11
12
|
export declare const description = "Publish resources based on a specified JSON file or directory.";
|
|
12
13
|
export declare function builder(yargs: Argv): Argv<any>;
|
|
13
|
-
export declare function handler({ app, appId, clientCredentials, context, paths, remote, resourceName, }: PublishResourceArguments): Promise<void>;
|
|
14
|
+
export declare function handler({ app, appId, clientCredentials, context, paths, remote, resourceName, seed, }: PublishResourceArguments): Promise<void>;
|
|
14
15
|
export {};
|
|
@@ -27,9 +27,13 @@ export function builder(yargs) {
|
|
|
27
27
|
.option('context', {
|
|
28
28
|
describe: 'If specified, use the specified context from .appsemblerc.yaml',
|
|
29
29
|
demandOption: 'app',
|
|
30
|
+
})
|
|
31
|
+
.option('seed', {
|
|
32
|
+
describe: 'If true, published resources will be used as seed',
|
|
33
|
+
default: false,
|
|
30
34
|
});
|
|
31
35
|
}
|
|
32
|
-
export async function handler({ app, appId, clientCredentials, context, paths, remote, resourceName, }) {
|
|
36
|
+
export async function handler({ app, appId, clientCredentials, context, paths, remote, resourceName, seed, }) {
|
|
33
37
|
const [resolvedAppId, resolvedRemote] = await resolveAppIdAndRemote(app, context, remote, appId);
|
|
34
38
|
await authenticate(resolvedRemote, 'resources:write', clientCredentials);
|
|
35
39
|
const normalizedPaths = paths.map((path) => normalizePath(path));
|
|
@@ -43,8 +47,9 @@ export async function handler({ app, appId, clientCredentials, context, paths, r
|
|
|
43
47
|
await publishResource({
|
|
44
48
|
type: resourceName,
|
|
45
49
|
appId: resolvedAppId,
|
|
46
|
-
path,
|
|
47
50
|
remote: resolvedRemote,
|
|
51
|
+
path,
|
|
52
|
+
seed,
|
|
48
53
|
});
|
|
49
54
|
}
|
|
50
55
|
}
|
package/lib/app.d.ts
CHANGED
|
@@ -120,9 +120,17 @@ interface UpdateAppParams {
|
|
|
120
120
|
*/
|
|
121
121
|
demoMode: boolean;
|
|
122
122
|
/**
|
|
123
|
-
* Whether the
|
|
123
|
+
* Whether resources from the `resources` directory should be published after publishing the app.
|
|
124
124
|
*/
|
|
125
|
-
|
|
125
|
+
resources: boolean;
|
|
126
|
+
/**
|
|
127
|
+
* Whether assets from the `assets` directory should be published after publishing the app.
|
|
128
|
+
*/
|
|
129
|
+
assets: boolean;
|
|
130
|
+
/**
|
|
131
|
+
* Whether published assets should be clonable. Ignored if `assets` equals false.
|
|
132
|
+
*/
|
|
133
|
+
assetsClonable: boolean;
|
|
126
134
|
/**
|
|
127
135
|
* Whether the locked property should be ignored.
|
|
128
136
|
*/
|
|
@@ -180,6 +188,8 @@ export declare function exportAppAsZip(appId: number, assets: boolean, resources
|
|
|
180
188
|
* @param force Whether or not to force the update for locked apps.
|
|
181
189
|
*/
|
|
182
190
|
export declare function uploadMessages(path: string, appId: number, remote: string, force: boolean): Promise<void>;
|
|
191
|
+
export declare function publishSeedResources(path: string, app: App, remote: string): Promise<void>;
|
|
192
|
+
export declare function publishSeedAssets(path: string, app: App, remote: string, assetsClonable: boolean): Promise<void>;
|
|
183
193
|
/**
|
|
184
194
|
* @param path The path to the app directory.
|
|
185
195
|
* @param languages A list of languages for which translations should be added in addition to the
|
|
@@ -193,13 +203,13 @@ export declare function writeAppMessages(path: string, languages: string[], veri
|
|
|
193
203
|
*
|
|
194
204
|
* @param argv The command line options used for updating the app.
|
|
195
205
|
*/
|
|
196
|
-
export declare function updateApp({ clientCredentials, context, force, path, ...options }: UpdateAppParams): Promise<void>;
|
|
206
|
+
export declare function updateApp({ assets, clientCredentials, context, force, path, resources, ...options }: UpdateAppParams): Promise<void>;
|
|
197
207
|
/**
|
|
198
208
|
* Publish a new app.
|
|
199
209
|
*
|
|
200
210
|
* @param options The options to use for publishing an app.
|
|
201
211
|
*/
|
|
202
|
-
export declare function publishApp({ assets,
|
|
212
|
+
export declare function publishApp({ assets, clientCredentials, context, dryRun, modifyContext, path, resources, ...options }: PublishAppParams): Promise<void>;
|
|
203
213
|
/**
|
|
204
214
|
* Resolve the app’s ID and remote based on the app context.
|
|
205
215
|
*
|
package/lib/app.js
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { createReadStream, createWriteStream, existsSync } from 'node:fs';
|
|
2
|
-
import { mkdir, readdir, readFile, stat } from 'node:fs/promises';
|
|
3
|
-
import { basename, join, parse, relative, resolve } from 'node:path';
|
|
2
|
+
import { mkdir, readdir, readFile, rm, stat } from 'node:fs/promises';
|
|
3
|
+
import { basename, dirname, join, parse, relative, resolve } from 'node:path';
|
|
4
4
|
import { inspect } from 'node:util';
|
|
5
|
-
import { AppsembleError, authenticate, logger, opendirSafe, readData, writeData, } from '@appsemble/node-utils';
|
|
5
|
+
import { applyAppVariant, AppsembleError, authenticate, logger, opendirSafe, readData, writeData, } from '@appsemble/node-utils';
|
|
6
6
|
import { extractAppMessages, has, normalizeBlockName } from '@appsemble/utils';
|
|
7
7
|
import axios from 'axios';
|
|
8
8
|
import fg from 'fast-glob';
|
|
9
9
|
import FormData from 'form-data';
|
|
10
10
|
import normalizePath from 'normalize-path';
|
|
11
|
-
import { parse as parseYaml } from 'yaml';
|
|
12
11
|
import { publishAsset } from './asset.js';
|
|
13
12
|
import { traverseBlockThemes } from './block.js';
|
|
14
13
|
import { coerceRemote } from './coercers.js';
|
|
@@ -176,6 +175,88 @@ export async function uploadMessages(path, appId, remote, force) {
|
|
|
176
175
|
logger.info(`Successfully uploaded messages for language “${language.language}” 🎉`);
|
|
177
176
|
}
|
|
178
177
|
}
|
|
178
|
+
export async function publishSeedResources(path, app, remote) {
|
|
179
|
+
var _a, _b;
|
|
180
|
+
const resourcesPath = join(path, 'resources');
|
|
181
|
+
logger.info(`Publishing seed resources from ${resourcesPath}`);
|
|
182
|
+
if (existsSync(resourcesPath)) {
|
|
183
|
+
logger.info(`Deleting existing seed resources from app ${app.id}`);
|
|
184
|
+
await axios.delete(`/api/apps/${app.id}/seed-resources`);
|
|
185
|
+
try {
|
|
186
|
+
const resourceFiles = await readdir(resourcesPath, { withFileTypes: true });
|
|
187
|
+
const resourcesToPublish = [];
|
|
188
|
+
const publishedResourcesIds = {};
|
|
189
|
+
for (const resource of resourceFiles) {
|
|
190
|
+
if (resource.isFile()) {
|
|
191
|
+
const { name } = parse(resource.name);
|
|
192
|
+
resourcesToPublish.push({
|
|
193
|
+
appId: app.id,
|
|
194
|
+
path: join(resourcesPath, resource.name),
|
|
195
|
+
definition: (_a = app.definition.resources) === null || _a === void 0 ? void 0 : _a[name],
|
|
196
|
+
type: name,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
else if (resource.isDirectory()) {
|
|
200
|
+
const subDirectoryResources = await readdir(join(resourcesPath, resource.name), {
|
|
201
|
+
withFileTypes: true,
|
|
202
|
+
});
|
|
203
|
+
for (const subResource of subDirectoryResources.filter((s) => s.isFile())) {
|
|
204
|
+
resourcesToPublish.push({
|
|
205
|
+
appId: app.id,
|
|
206
|
+
path: join(resourcesPath, resource.name, subResource.name),
|
|
207
|
+
definition: (_b = app.definition.resources) === null || _b === void 0 ? void 0 : _b[resource.name],
|
|
208
|
+
type: resource.name,
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
await publishResourcesRecursively({
|
|
214
|
+
seed: true,
|
|
215
|
+
remote,
|
|
216
|
+
resourcesToPublish,
|
|
217
|
+
publishedResourcesIds,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
catch (error) {
|
|
221
|
+
logger.error('Something went wrong when publishing seed resources:');
|
|
222
|
+
logger.error(error);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
logger.warn(`Missing resources directory in ${path}. Skipping...`);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
export async function publishSeedAssets(path, app, remote, assetsClonable) {
|
|
230
|
+
const assetsPath = join(path, 'assets');
|
|
231
|
+
logger.info(`Publishing seed assets from ${assetsPath}`);
|
|
232
|
+
if (existsSync(assetsPath)) {
|
|
233
|
+
logger.info(`Deleting existing seed assets from app ${app.id}`);
|
|
234
|
+
await axios.delete(`/api/apps/${app.id}/seed-assets`);
|
|
235
|
+
const assetFiles = await readdir(assetsPath);
|
|
236
|
+
const normalizedPaths = assetFiles.map((assetFile) => normalizePath(join(assetsPath, assetFile)));
|
|
237
|
+
const files = await fg(normalizedPaths, { absolute: true, onlyFiles: true });
|
|
238
|
+
try {
|
|
239
|
+
logger.info(`Publishing ${files.length} asset(s)`);
|
|
240
|
+
for (const assetFilePath of files) {
|
|
241
|
+
await publishAsset({
|
|
242
|
+
name: parse(assetFilePath).name,
|
|
243
|
+
appId: app.id,
|
|
244
|
+
path: assetFilePath,
|
|
245
|
+
remote,
|
|
246
|
+
seed: true,
|
|
247
|
+
clonable: assetsClonable,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
catch (error) {
|
|
252
|
+
logger.error('Something went wrong when creating assets:');
|
|
253
|
+
logger.error(error);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
logger.warn(`Missing assets directory in ${path}. Skipping...`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
179
260
|
/**
|
|
180
261
|
* @param path The path to the app directory.
|
|
181
262
|
* @param languages A list of languages for which translations should be added in addition to the
|
|
@@ -331,32 +412,38 @@ This block version is not used in the app`);
|
|
|
331
412
|
*
|
|
332
413
|
* @param argv The command line options used for updating the app.
|
|
333
414
|
*/
|
|
334
|
-
export async function updateApp({ clientCredentials, context, force, path, ...options }) {
|
|
335
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u
|
|
415
|
+
export async function updateApp({ assets, clientCredentials, context, force, path, resources, ...options }) {
|
|
416
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
|
|
336
417
|
const file = await stat(path);
|
|
337
418
|
const formData = new FormData();
|
|
338
419
|
let appsembleContext;
|
|
420
|
+
let appVariantPath = path;
|
|
421
|
+
if (existsSync(join(path, 'variants', context))) {
|
|
422
|
+
await applyAppVariant(path, context);
|
|
423
|
+
appVariantPath = join(dirname(path), `${basename(path)}-${context}`);
|
|
424
|
+
}
|
|
425
|
+
else {
|
|
426
|
+
logger.warn(`App variant ${context} is not defined. Using default app.`);
|
|
427
|
+
}
|
|
339
428
|
if (file.isFile()) {
|
|
340
|
-
const [, data] = await readData(
|
|
429
|
+
const [, data] = await readData(appVariantPath);
|
|
341
430
|
formData.append('yaml', data);
|
|
342
431
|
}
|
|
343
432
|
else {
|
|
344
|
-
[appsembleContext] = await traverseAppDirectory(
|
|
433
|
+
[appsembleContext] = await traverseAppDirectory(appVariantPath, context, formData);
|
|
345
434
|
}
|
|
346
435
|
const remote = (_a = appsembleContext.remote) !== null && _a !== void 0 ? _a : options.remote;
|
|
347
436
|
const id = (_b = appsembleContext.id) !== null && _b !== void 0 ? _b : options.id;
|
|
348
437
|
const template = (_d = (_c = appsembleContext.template) !== null && _c !== void 0 ? _c : options.template) !== null && _d !== void 0 ? _d : false;
|
|
349
|
-
const
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
const
|
|
353
|
-
const
|
|
354
|
-
const
|
|
355
|
-
const
|
|
356
|
-
const
|
|
357
|
-
const
|
|
358
|
-
const sentryEnvironment = (_q = appsembleContext.sentryEnvironment) !== null && _q !== void 0 ? _q : options.sentryEnvironment;
|
|
359
|
-
const googleAnalyticsId = (_r = appsembleContext.googleAnalyticsId) !== null && _r !== void 0 ? _r : options.googleAnalyticsId;
|
|
438
|
+
const assetsClonable = (_f = (_e = appsembleContext.assetsClonable) !== null && _e !== void 0 ? _e : options.assetsClonable) !== null && _f !== void 0 ? _f : false;
|
|
439
|
+
const demoMode = (_h = (_g = appsembleContext.demoMode) !== null && _g !== void 0 ? _g : options.demoMode) !== null && _h !== void 0 ? _h : false;
|
|
440
|
+
const visibility = (_j = appsembleContext.visibility) !== null && _j !== void 0 ? _j : options.visibility;
|
|
441
|
+
const iconBackground = (_k = appsembleContext.iconBackground) !== null && _k !== void 0 ? _k : options.iconBackground;
|
|
442
|
+
const icon = (_l = options.icon) !== null && _l !== void 0 ? _l : appsembleContext.icon;
|
|
443
|
+
const maskableIcon = (_m = options.maskableIcon) !== null && _m !== void 0 ? _m : appsembleContext.maskableIcon;
|
|
444
|
+
const sentryDsn = (_o = appsembleContext.sentryDsn) !== null && _o !== void 0 ? _o : options.sentryDsn;
|
|
445
|
+
const sentryEnvironment = (_p = appsembleContext.sentryEnvironment) !== null && _p !== void 0 ? _p : options.sentryEnvironment;
|
|
446
|
+
const googleAnalyticsId = (_q = appsembleContext.googleAnalyticsId) !== null && _q !== void 0 ? _q : options.googleAnalyticsId;
|
|
360
447
|
const { appLock } = appsembleContext;
|
|
361
448
|
logger.info(`App id: ${id}`);
|
|
362
449
|
logger.verbose(`App remote: ${remote}`);
|
|
@@ -370,17 +457,16 @@ export async function updateApp({ clientCredentials, context, force, path, ...op
|
|
|
370
457
|
formData.append('force', String(force));
|
|
371
458
|
formData.append('template', String(template));
|
|
372
459
|
formData.append('demoMode', String(demoMode));
|
|
373
|
-
formData.append('seed', String(seed));
|
|
374
460
|
formData.append('visibility', visibility);
|
|
375
461
|
formData.append('iconBackground', iconBackground);
|
|
376
462
|
if (icon) {
|
|
377
463
|
const realIcon = typeof icon === 'string' ? createReadStream(icon) : icon;
|
|
378
|
-
logger.info(`Using icon from ${(
|
|
464
|
+
logger.info(`Using icon from ${(_r = realIcon.path) !== null && _r !== void 0 ? _r : 'stdin'}`);
|
|
379
465
|
formData.append('icon', realIcon);
|
|
380
466
|
}
|
|
381
467
|
if (maskableIcon) {
|
|
382
468
|
const realIcon = typeof maskableIcon === 'string' ? createReadStream(maskableIcon) : maskableIcon;
|
|
383
|
-
logger.info(`Using maskable icon from ${(
|
|
469
|
+
logger.info(`Using maskable icon from ${(_s = realIcon.path) !== null && _s !== void 0 ? _s : 'stdin'}`);
|
|
384
470
|
formData.append('maskableIcon', realIcon);
|
|
385
471
|
}
|
|
386
472
|
if (sentryDsn) {
|
|
@@ -394,7 +480,11 @@ export async function updateApp({ clientCredentials, context, force, path, ...op
|
|
|
394
480
|
logger.info('Using Google Analytics');
|
|
395
481
|
formData.append('googleAnalyticsID', googleAnalyticsId);
|
|
396
482
|
}
|
|
397
|
-
|
|
483
|
+
let authScope = 'apps:write';
|
|
484
|
+
if (resources) {
|
|
485
|
+
authScope += ' resources:write';
|
|
486
|
+
}
|
|
487
|
+
await authenticate(remote, authScope, clientCredentials);
|
|
398
488
|
if (appLock) {
|
|
399
489
|
logger.info(`Setting AppLock to ${appLock}`);
|
|
400
490
|
try {
|
|
@@ -417,7 +507,7 @@ export async function updateApp({ clientCredentials, context, force, path, ...op
|
|
|
417
507
|
if (!axios.isAxiosError(error)) {
|
|
418
508
|
throw error;
|
|
419
509
|
}
|
|
420
|
-
if (((
|
|
510
|
+
if (((_u = (_t = error.response) === null || _t === void 0 ? void 0 : _t.data) === null || _u === void 0 ? void 0 : _u.message) !== 'App validation failed') {
|
|
421
511
|
throw error;
|
|
422
512
|
}
|
|
423
513
|
logger.error(error.response.data);
|
|
@@ -425,51 +515,68 @@ export async function updateApp({ clientCredentials, context, force, path, ...op
|
|
|
425
515
|
}
|
|
426
516
|
if (file.isDirectory()) {
|
|
427
517
|
// After uploading the app, upload block styles and messages if they are available
|
|
428
|
-
await traverseBlockThemes(
|
|
429
|
-
await uploadMessages(
|
|
518
|
+
await traverseBlockThemes(appVariantPath, data.id, remote, force);
|
|
519
|
+
await uploadMessages(appVariantPath, data.id, remote, force);
|
|
520
|
+
// After updating the app, publish seed resources and assets if they are available
|
|
521
|
+
if (assets && (data.locked !== 'fullLock' || force)) {
|
|
522
|
+
await publishSeedAssets(appVariantPath, data, remote, assetsClonable);
|
|
523
|
+
}
|
|
524
|
+
if (resources && (data.locked !== 'fullLock' || force)) {
|
|
525
|
+
await publishSeedResources(appVariantPath, data, remote);
|
|
526
|
+
}
|
|
430
527
|
}
|
|
431
528
|
const { host, protocol } = new URL(remote);
|
|
432
529
|
logger.info(`Successfully updated app ${data.definition.name}! 🙌`);
|
|
433
530
|
logger.info(`App URL: ${protocol}//${data.path}.${data.OrganizationId}.${host}`);
|
|
434
531
|
logger.info(`App store page: ${new URL(`/apps/${data.id}`, remote)}`);
|
|
532
|
+
if (appVariantPath !== path) {
|
|
533
|
+
await rm(appVariantPath, { recursive: true });
|
|
534
|
+
logger.info(`Removed ${appVariantPath}`);
|
|
535
|
+
}
|
|
435
536
|
}
|
|
436
537
|
/**
|
|
437
538
|
* Publish a new app.
|
|
438
539
|
*
|
|
439
540
|
* @param options The options to use for publishing an app.
|
|
440
541
|
*/
|
|
441
|
-
export async function publishApp({ assets,
|
|
442
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u
|
|
542
|
+
export async function publishApp({ assets, clientCredentials, context, dryRun, modifyContext, path, resources, ...options }) {
|
|
543
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
|
|
443
544
|
const file = await stat(path);
|
|
444
545
|
const formData = new FormData();
|
|
445
546
|
let appsembleContext;
|
|
446
547
|
let rc;
|
|
447
548
|
let yaml;
|
|
448
549
|
let filename = relative(process.cwd(), path);
|
|
550
|
+
let appVariantPath = path;
|
|
551
|
+
if (existsSync(join(path, 'variants', context))) {
|
|
552
|
+
await applyAppVariant(path, context);
|
|
553
|
+
appVariantPath = join(dirname(path), `${basename(path)}-${context}`);
|
|
554
|
+
}
|
|
555
|
+
else {
|
|
556
|
+
logger.warn(`App variant ${context} is not defined. Using default app.`);
|
|
557
|
+
}
|
|
449
558
|
if (file.isFile()) {
|
|
450
559
|
// Assuming file is App YAML
|
|
451
|
-
const [, data] = await readData(
|
|
560
|
+
const [, data] = await readData(appVariantPath);
|
|
452
561
|
yaml = data;
|
|
453
562
|
formData.append('yaml', data);
|
|
454
563
|
}
|
|
455
564
|
else {
|
|
456
|
-
[appsembleContext, rc, yaml] = await traverseAppDirectory(
|
|
565
|
+
[appsembleContext, rc, yaml] = await traverseAppDirectory(appVariantPath, context, formData);
|
|
457
566
|
filename = join(filename, 'app-definition.yaml');
|
|
458
567
|
}
|
|
459
568
|
const remote = (_a = appsembleContext.remote) !== null && _a !== void 0 ? _a : options.remote;
|
|
460
569
|
const organizationId = (_b = appsembleContext.organization) !== null && _b !== void 0 ? _b : options.organization;
|
|
461
570
|
const template = (_d = (_c = appsembleContext.template) !== null && _c !== void 0 ? _c : options.template) !== null && _d !== void 0 ? _d : false;
|
|
462
|
-
const
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
const
|
|
466
|
-
const
|
|
467
|
-
const
|
|
468
|
-
const
|
|
469
|
-
const
|
|
470
|
-
const
|
|
471
|
-
const sentryEnvironment = (_q = appsembleContext.sentryEnvironment) !== null && _q !== void 0 ? _q : options.sentryEnvironment;
|
|
472
|
-
const googleAnalyticsId = (_r = appsembleContext.googleAnalyticsId) !== null && _r !== void 0 ? _r : options.googleAnalyticsId;
|
|
571
|
+
const assetsClonable = (_f = (_e = appsembleContext.assetsClonable) !== null && _e !== void 0 ? _e : options.assetsClonable) !== null && _f !== void 0 ? _f : false;
|
|
572
|
+
const demoMode = (_h = (_g = appsembleContext.demoMode) !== null && _g !== void 0 ? _g : options.demoMode) !== null && _h !== void 0 ? _h : false;
|
|
573
|
+
const visibility = (_j = appsembleContext.visibility) !== null && _j !== void 0 ? _j : options.visibility;
|
|
574
|
+
const iconBackground = (_k = appsembleContext.iconBackground) !== null && _k !== void 0 ? _k : options.iconBackground;
|
|
575
|
+
const icon = (_l = options.icon) !== null && _l !== void 0 ? _l : appsembleContext.icon;
|
|
576
|
+
const maskableIcon = (_m = options.maskableIcon) !== null && _m !== void 0 ? _m : appsembleContext.maskableIcon;
|
|
577
|
+
const sentryDsn = (_o = appsembleContext.sentryDsn) !== null && _o !== void 0 ? _o : options.sentryDsn;
|
|
578
|
+
const sentryEnvironment = (_p = appsembleContext.sentryEnvironment) !== null && _p !== void 0 ? _p : options.sentryEnvironment;
|
|
579
|
+
const googleAnalyticsId = (_q = appsembleContext.googleAnalyticsId) !== null && _q !== void 0 ? _q : options.googleAnalyticsId;
|
|
473
580
|
const appLock = appsembleContext.appLock || 'unlocked';
|
|
474
581
|
logger.verbose(`App remote: ${remote}`);
|
|
475
582
|
logger.verbose(`App organization: ${organizationId}`);
|
|
@@ -482,18 +589,17 @@ export async function publishApp({ assets, assetsClonable, clientCredentials, co
|
|
|
482
589
|
formData.append('OrganizationId', organizationId);
|
|
483
590
|
formData.append('template', String(template));
|
|
484
591
|
formData.append('demoMode', String(demoMode));
|
|
485
|
-
formData.append('seed', String(seed));
|
|
486
592
|
formData.append('visibility', visibility);
|
|
487
593
|
formData.append('iconBackground', iconBackground);
|
|
488
594
|
formData.append('locked', appLock);
|
|
489
595
|
if (icon) {
|
|
490
596
|
const realIcon = typeof icon === 'string' ? createReadStream(icon) : icon;
|
|
491
|
-
logger.info(`Using icon from ${(
|
|
597
|
+
logger.info(`Using icon from ${(_r = realIcon.path) !== null && _r !== void 0 ? _r : 'stdin'}`);
|
|
492
598
|
formData.append('icon', realIcon);
|
|
493
599
|
}
|
|
494
600
|
if (maskableIcon) {
|
|
495
601
|
const realIcon = typeof maskableIcon === 'string' ? createReadStream(maskableIcon) : maskableIcon;
|
|
496
|
-
logger.info(`Using maskable icon from ${(
|
|
602
|
+
logger.info(`Using maskable icon from ${(_s = realIcon.path) !== null && _s !== void 0 ? _s : 'stdin'}`);
|
|
497
603
|
formData.append('maskableIcon', realIcon);
|
|
498
604
|
}
|
|
499
605
|
if (sentryDsn) {
|
|
@@ -523,7 +629,7 @@ export async function publishApp({ assets, assetsClonable, clientCredentials, co
|
|
|
523
629
|
if (!axios.isAxiosError(error)) {
|
|
524
630
|
throw error;
|
|
525
631
|
}
|
|
526
|
-
if (((
|
|
632
|
+
if (((_u = (_t = error.response) === null || _t === void 0 ? void 0 : _t.data) === null || _u === void 0 ? void 0 : _u.message) !== 'App validation failed') {
|
|
527
633
|
throw error;
|
|
528
634
|
}
|
|
529
635
|
throw new AppsembleError(printAxiosError(filename, yaml, error.response.data.data.errors));
|
|
@@ -534,83 +640,47 @@ export async function publishApp({ assets, assetsClonable, clientCredentials, co
|
|
|
534
640
|
return;
|
|
535
641
|
}
|
|
536
642
|
if (file.isDirectory() && !dryRun) {
|
|
537
|
-
// After uploading the app, upload block styles
|
|
538
|
-
await traverseBlockThemes(
|
|
539
|
-
await uploadMessages(
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
const normalizedPaths = assetFiles.map((assetFile) => normalizePath(join(assetsPath, assetFile)));
|
|
544
|
-
const files = await fg(normalizedPaths, { absolute: true, onlyFiles: true });
|
|
545
|
-
try {
|
|
546
|
-
logger.info(`Publishing ${files.length} asset(s)`);
|
|
547
|
-
for (const assetFilePath of files) {
|
|
548
|
-
await publishAsset({
|
|
549
|
-
name: parse(assetFilePath).name,
|
|
550
|
-
appId: data.id,
|
|
551
|
-
path: assetFilePath,
|
|
552
|
-
remote,
|
|
553
|
-
clonable: assetsClonable,
|
|
554
|
-
});
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
catch (error) {
|
|
558
|
-
logger.error('Something went wrong when creating assets:');
|
|
559
|
-
logger.error(error);
|
|
560
|
-
}
|
|
643
|
+
// After uploading the app, upload block styles, messages if they are available
|
|
644
|
+
await traverseBlockThemes(appVariantPath, data.id, remote, false);
|
|
645
|
+
await uploadMessages(appVariantPath, data.id, remote, false);
|
|
646
|
+
// After uploading the app, publish seed resources and assets if they are available
|
|
647
|
+
if (assets) {
|
|
648
|
+
await publishSeedAssets(appVariantPath, data, remote, assetsClonable);
|
|
561
649
|
}
|
|
562
|
-
if (resources
|
|
563
|
-
|
|
564
|
-
const resourcePath = join(path, 'resources');
|
|
565
|
-
try {
|
|
566
|
-
const resourceFiles = await readdir(resourcePath, { withFileTypes: true });
|
|
567
|
-
const resourcesToPublish = [];
|
|
568
|
-
const publishedResourcesIds = {};
|
|
569
|
-
for (const resource of resourceFiles) {
|
|
570
|
-
if (resource.isFile()) {
|
|
571
|
-
const { name } = parse(resource.name);
|
|
572
|
-
resourcesToPublish.push({
|
|
573
|
-
appId: data.id,
|
|
574
|
-
path: join(resourcePath, resource.name),
|
|
575
|
-
definition: appDefinition.resources[name],
|
|
576
|
-
type: name,
|
|
577
|
-
});
|
|
578
|
-
}
|
|
579
|
-
else if (resource.isDirectory()) {
|
|
580
|
-
const subDirectoryResources = await readdir(join(resourcePath, resource.name), {
|
|
581
|
-
withFileTypes: true,
|
|
582
|
-
});
|
|
583
|
-
for (const subResource of subDirectoryResources.filter((s) => s.isFile())) {
|
|
584
|
-
resourcesToPublish.push({
|
|
585
|
-
appId: data.id,
|
|
586
|
-
path: join(resourcePath, resource.name, subResource.name),
|
|
587
|
-
definition: appDefinition.resources[resource.name],
|
|
588
|
-
type: resource.name,
|
|
589
|
-
});
|
|
590
|
-
}
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
await publishResourcesRecursively({
|
|
594
|
-
remote,
|
|
595
|
-
resourcesToPublish,
|
|
596
|
-
publishedResourcesIds,
|
|
597
|
-
});
|
|
598
|
-
}
|
|
599
|
-
catch (error) {
|
|
600
|
-
logger.error('Something went wrong when creating resources:');
|
|
601
|
-
logger.error(error);
|
|
602
|
-
}
|
|
650
|
+
if (resources) {
|
|
651
|
+
await publishSeedResources(appVariantPath, data, remote);
|
|
603
652
|
}
|
|
604
653
|
}
|
|
605
654
|
if (modifyContext && appsembleContext && context && !dryRun) {
|
|
606
655
|
rc.context[context].id = data.id;
|
|
607
|
-
await writeData(join(
|
|
656
|
+
await writeData(join(appVariantPath, '.appsemblerc.yaml'), rc, { sort: false });
|
|
608
657
|
logger.info(`Updated .appsemblerc: Set context.${context}.id to ${data.id}`);
|
|
609
658
|
}
|
|
610
659
|
const { host, protocol } = new URL(remote);
|
|
611
660
|
logger.info(`Successfully published app ${data.definition.name}! 🙌`);
|
|
612
661
|
logger.info(`App URL: ${protocol}//${data.path}.${data.OrganizationId}.${host}`);
|
|
613
662
|
logger.info(`App store page: ${new URL(`/apps/${data.id}`, remote)}`);
|
|
663
|
+
const rcCollections = rc.context[context].collections;
|
|
664
|
+
if (Array.isArray(rcCollections)) {
|
|
665
|
+
for (const collectionId of rcCollections) {
|
|
666
|
+
try {
|
|
667
|
+
await axios.post(`/api/appCollections/${collectionId}/apps`, { AppId: data.id }, {
|
|
668
|
+
baseURL: remote,
|
|
669
|
+
});
|
|
670
|
+
logger.info(`Successfully added app to collection ${collectionId}`);
|
|
671
|
+
}
|
|
672
|
+
catch (error) {
|
|
673
|
+
logger.error(error);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
if (appVariantPath !== path) {
|
|
678
|
+
const [defaultAppRc] = await readData(join(path, '.appsemblerc.yaml'));
|
|
679
|
+
defaultAppRc.context[context] = rc.context[context];
|
|
680
|
+
await writeData(join(path, '.appsemblerc.yaml'), defaultAppRc, { sort: false });
|
|
681
|
+
await rm(appVariantPath, { recursive: true });
|
|
682
|
+
logger.info(`Removed ${appVariantPath}`);
|
|
683
|
+
}
|
|
614
684
|
}
|
|
615
685
|
/**
|
|
616
686
|
* Resolve the app’s ID and remote based on the app context.
|
package/lib/asset.d.ts
CHANGED
|
@@ -16,10 +16,14 @@ interface PublishAssetParams {
|
|
|
16
16
|
* The remote server to publish the asset on.
|
|
17
17
|
*/
|
|
18
18
|
remote: string;
|
|
19
|
+
/**
|
|
20
|
+
* Whether the published asset should be used as seed.
|
|
21
|
+
*/
|
|
22
|
+
seed: boolean;
|
|
19
23
|
/**
|
|
20
24
|
* Whether the asset should be clonable.
|
|
21
25
|
*/
|
|
22
26
|
clonable: boolean;
|
|
23
27
|
}
|
|
24
|
-
export declare function publishAsset({ appId, clonable, name, path, remote, }: PublishAssetParams): Promise<void>;
|
|
28
|
+
export declare function publishAsset({ appId, clonable, name, path, remote, seed, }: PublishAssetParams): Promise<void>;
|
|
25
29
|
export {};
|
package/lib/asset.js
CHANGED
|
@@ -3,7 +3,7 @@ import { logger } from '@appsemble/node-utils';
|
|
|
3
3
|
import { normalize } from '@appsemble/utils';
|
|
4
4
|
import axios from 'axios';
|
|
5
5
|
import FormData from 'form-data';
|
|
6
|
-
export async function publishAsset({ appId, clonable, name, path, remote, }) {
|
|
6
|
+
export async function publishAsset({ appId, clonable, name, path, remote, seed, }) {
|
|
7
7
|
const formData = new FormData();
|
|
8
8
|
const file = createReadStream(path);
|
|
9
9
|
formData.append('file', file);
|
|
@@ -11,7 +11,8 @@ export async function publishAsset({ appId, clonable, name, path, remote, }) {
|
|
|
11
11
|
if (name) {
|
|
12
12
|
formData.append('name', normalize(name));
|
|
13
13
|
}
|
|
14
|
-
const
|
|
14
|
+
const endpoint = `/api/apps/${appId}/${seed ? 'seed-' : ''}assets`;
|
|
15
|
+
const { data: { id }, } = await axios.post(endpoint, formData, { baseURL: remote });
|
|
15
16
|
logger.info(`Published asset ${id}${name ? ` with name ${normalize(name)}` : ''}`);
|
|
16
17
|
}
|
|
17
18
|
//# sourceMappingURL=asset.js.map
|
package/lib/resource.d.ts
CHANGED
|
@@ -34,6 +34,10 @@ interface PublishResourceParams {
|
|
|
34
34
|
* The remote server to publish the resource on.
|
|
35
35
|
*/
|
|
36
36
|
remote: string;
|
|
37
|
+
/**
|
|
38
|
+
* Whether the published resource should be used as seed.
|
|
39
|
+
*/
|
|
40
|
+
seed: boolean;
|
|
37
41
|
/**
|
|
38
42
|
* The definition of the resource.
|
|
39
43
|
*/
|
|
@@ -54,6 +58,10 @@ interface PublishResourcesRecursivelyParams {
|
|
|
54
58
|
* The remote server to publish the resource on.
|
|
55
59
|
*/
|
|
56
60
|
remote: string;
|
|
61
|
+
/**
|
|
62
|
+
* Whether the published resources should be used as seed.
|
|
63
|
+
*/
|
|
64
|
+
seed: boolean;
|
|
57
65
|
/**
|
|
58
66
|
* All resources that need to be published.
|
|
59
67
|
*/
|
|
@@ -63,7 +71,7 @@ interface PublishResourcesRecursivelyParams {
|
|
|
63
71
|
*/
|
|
64
72
|
publishedResourcesIds: Record<string, number[]>;
|
|
65
73
|
}
|
|
66
|
-
export declare function publishResource({ appId, definition, path, publishedResourcesIds, remote, type, }: PublishResourceParams): Promise<number[]>;
|
|
67
|
-
export declare function publishResourcesRecursively({ publishedResourcesIds, remote, resourcesToPublish, }: PublishResourcesRecursivelyParams): Promise<Record<string, number[]>>;
|
|
74
|
+
export declare function publishResource({ appId, definition, path, publishedResourcesIds, remote, seed, type, }: PublishResourceParams): Promise<number[]>;
|
|
75
|
+
export declare function publishResourcesRecursively({ publishedResourcesIds, remote, resourcesToPublish, seed, }: PublishResourcesRecursivelyParams): Promise<Record<string, number[]>>;
|
|
68
76
|
export declare function updateResource({ appId, path, remote, resourceName, }: UpdateResourceParams): Promise<void>;
|
|
69
77
|
export {};
|
package/lib/resource.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
import { AppsembleError, logger, readData } from '@appsemble/node-utils';
|
|
3
3
|
import axios from 'axios';
|
|
4
|
-
export async function publishResource({ appId, definition, path, publishedResourcesIds = {}, remote, type, }) {
|
|
4
|
+
export async function publishResource({ appId, definition, path, publishedResourcesIds = {}, remote, seed, type, }) {
|
|
5
5
|
const csv = path.endsWith('.csv');
|
|
6
6
|
let resources;
|
|
7
7
|
if (csv) {
|
|
@@ -16,15 +16,16 @@ export async function publishResource({ appId, definition, path, publishedResour
|
|
|
16
16
|
}
|
|
17
17
|
logger.info(`Publishing resource(s) from ${path}`);
|
|
18
18
|
let data;
|
|
19
|
+
const endpoint = `/api/apps/${appId}/${seed ? 'seed-' : ''}resources/${type}`;
|
|
19
20
|
if (csv) {
|
|
20
|
-
const response = await axios.post(
|
|
21
|
+
const response = await axios.post(endpoint, resources, {
|
|
21
22
|
baseURL: remote,
|
|
22
23
|
headers: { 'content-type': 'text/csv' },
|
|
23
24
|
});
|
|
24
25
|
data = response.data;
|
|
25
26
|
}
|
|
26
27
|
else {
|
|
27
|
-
const response = await axios.post(
|
|
28
|
+
const response = await axios.post(endpoint, resources.map((resource) => {
|
|
28
29
|
var _a, _b, _c;
|
|
29
30
|
const resourceWithReferences = { ...resource };
|
|
30
31
|
for (const [referencedProperty, resourceReference] of Object.entries((_a = definition === null || definition === void 0 ? void 0 : definition.references) !== null && _a !== void 0 ? _a : {})) {
|
|
@@ -45,7 +46,7 @@ export async function publishResource({ appId, definition, path, publishedResour
|
|
|
45
46
|
.join('\n')}`);
|
|
46
47
|
return ids;
|
|
47
48
|
}
|
|
48
|
-
export async function publishResourcesRecursively({ publishedResourcesIds, remote, resourcesToPublish, }) {
|
|
49
|
+
export async function publishResourcesRecursively({ publishedResourcesIds, remote, resourcesToPublish, seed, }) {
|
|
49
50
|
let updatedPublishedResourcesIds = { ...publishedResourcesIds };
|
|
50
51
|
for (const resourceToPublish of resourcesToPublish) {
|
|
51
52
|
const resourceReferences = resourceToPublish.definition.references;
|
|
@@ -56,9 +57,10 @@ export async function publishResourcesRecursively({ publishedResourcesIds, remot
|
|
|
56
57
|
if (referencedResourcesToPublish.length &&
|
|
57
58
|
!updatedPublishedResourcesIds[referencedResourceType]) {
|
|
58
59
|
const referencedPublishedResourcesIds = await publishResourcesRecursively({
|
|
59
|
-
remote,
|
|
60
60
|
resourcesToPublish: referencedResourcesToPublish,
|
|
61
61
|
publishedResourcesIds: updatedPublishedResourcesIds,
|
|
62
|
+
remote,
|
|
63
|
+
seed,
|
|
62
64
|
});
|
|
63
65
|
updatedPublishedResourcesIds = {
|
|
64
66
|
...updatedPublishedResourcesIds,
|
|
@@ -72,6 +74,7 @@ export async function publishResourcesRecursively({ publishedResourcesIds, remot
|
|
|
72
74
|
...resourceToPublish,
|
|
73
75
|
publishedResourcesIds: updatedPublishedResourcesIds,
|
|
74
76
|
remote,
|
|
77
|
+
seed,
|
|
75
78
|
});
|
|
76
79
|
}
|
|
77
80
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appsemble/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.1",
|
|
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.
|
|
46
|
-
"@appsemble/types": "0.
|
|
47
|
-
"@appsemble/utils": "0.
|
|
45
|
+
"@appsemble/node-utils": "0.27.1",
|
|
46
|
+
"@appsemble/types": "0.27.1",
|
|
47
|
+
"@appsemble/utils": "0.27.1",
|
|
48
48
|
"@fortawesome/fontawesome-common-types": "^6.0.0",
|
|
49
49
|
"@koa/cors": "^4.0.0",
|
|
50
50
|
"@odata/parser": "^0.2.0",
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
"yargs": "^17.0.0"
|
|
88
88
|
},
|
|
89
89
|
"devDependencies": {
|
|
90
|
-
"@appsemble/types": "0.
|
|
90
|
+
"@appsemble/types": "0.27.1",
|
|
91
91
|
"@types/concat-stream": "^2.0.0",
|
|
92
92
|
"@types/inquirer": "^9.0.0",
|
|
93
93
|
"@types/normalize-path": "^3.0.0",
|
package/server/options/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { applyAppServiceSecrets, checkRole,
|
|
1
|
+
import { applyAppServiceSecrets, checkRole, createAppAsset, createAppResourcesWithAssets, createSettings, createTheme, deleteAppAsset, deleteAppResource, email, getApp, getAppAssets, getAppBlockStyles, getAppDetails, getAppIcon, getAppMembers, getAppMessages, getAppResource, getAppResources, getAppScreenshots, getAppStyles, getAppTeams, getAppUrl, getAppUserInfo, getBlockAsset, getBlockMessages, getBlocksAssetsPaths, getCsp, getDbUpdated, getHost, getTheme, parseQuery, reloadUser, sendNotifications, updateAppResource, verifyResourceActionPermission, } from './index.js';
|
|
2
2
|
export const options = {
|
|
3
3
|
applyAppServiceSecrets,
|
|
4
4
|
checkRole,
|
|
5
|
-
checkSeededResources,
|
|
6
5
|
createAppAsset,
|
|
7
6
|
createAppResourcesWithAssets,
|
|
8
7
|
createSettings,
|
|
@@ -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.27.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.27.1
|
|
21
21
|
parameters:
|
|
22
22
|
icon: arrow-left
|
|
23
23
|
actions:
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function checkSeededResources(): Promise<boolean>;
|