@appsemble/node-utils 0.27.9 → 0.27.10
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/app.d.ts +17 -1
- package/app.js +23 -3
- package/package.json +3 -3
- package/server/routes/appRouter/index.js +5 -0
- package/server/routes/appRouter/readmeHandler.d.ts +3 -0
- package/server/routes/appRouter/readmeHandler.js +15 -0
- package/server/types.d.ts +9 -0
package/README.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
#  Appsemble Node Utilities
|
|
2
2
|
|
|
3
3
|
> NodeJS utilities used by Appsemble internally.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@appsemble/node-utils)
|
|
6
|
-
[](https://gitlab.com/appsemble/appsemble/-/releases/0.27.10)
|
|
7
7
|
[](https://prettier.io)
|
|
8
8
|
|
|
9
9
|
## Table of Contents
|
|
@@ -26,5 +26,5 @@ compatibility is not guaranteed.
|
|
|
26
26
|
|
|
27
27
|
## License
|
|
28
28
|
|
|
29
|
-
[LGPL-3.0-only](https://gitlab.com/appsemble/appsemble/-/blob/0.27.
|
|
29
|
+
[LGPL-3.0-only](https://gitlab.com/appsemble/appsemble/-/blob/0.27.10/LICENSE.md) ©
|
|
30
30
|
[Appsemble](https://appsemble.com)
|
package/app.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type App, type UserInfo } from '@appsemble/types';
|
|
1
|
+
import { type App, type AppsembleMessages, type UserInfo } from '@appsemble/types';
|
|
2
2
|
import { type RemapperContext } from '@appsemble/utils';
|
|
3
3
|
import { type DefaultContext, type DefaultState, type ParameterizedContext } from 'koa';
|
|
4
4
|
import { type Options } from './server/types.js';
|
|
@@ -15,4 +15,20 @@ import { type Options } from './server/types.js';
|
|
|
15
15
|
* @returns A localized remapper context for the app.
|
|
16
16
|
*/
|
|
17
17
|
export declare function getRemapperContext(app: App, language: string, userInfo: UserInfo, options: Options, context: ParameterizedContext<DefaultState, DefaultContext, any>): Promise<RemapperContext>;
|
|
18
|
+
/**
|
|
19
|
+
* Patch an app definition of an app inside the `apps` folder.
|
|
20
|
+
*
|
|
21
|
+
* @param appPath The path to the app to patch.
|
|
22
|
+
* @param patches Patches to apply to the YAML.
|
|
23
|
+
*/
|
|
24
|
+
export declare function patchDefinition(appPath: string, patches: [key: (number | string)[], value: unknown][]): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Patch app messages.
|
|
27
|
+
*
|
|
28
|
+
* The replacements will be deep merged into the original content.
|
|
29
|
+
*
|
|
30
|
+
* @param appPath The name of the app to patch.
|
|
31
|
+
* @param replacements Replacements for the original messages.
|
|
32
|
+
*/
|
|
33
|
+
export declare function patchMessages(appPath: string, replacements: Record<string, Partial<AppsembleMessages>>): Promise<void>;
|
|
18
34
|
export declare function applyAppVariant(appPath: string, appVariant: string): Promise<void>;
|
package/app.js
CHANGED
|
@@ -9,7 +9,7 @@ import { IntlMessageFormat } from 'intl-messageformat';
|
|
|
9
9
|
import lodash from 'lodash';
|
|
10
10
|
import { format, resolveConfig } from 'prettier';
|
|
11
11
|
import { parseDocument } from 'yaml';
|
|
12
|
-
import { readData, writeData } from './fs.js';
|
|
12
|
+
import { opendirSafe, readData, writeData } from './fs.js';
|
|
13
13
|
import { logger } from './logger.js';
|
|
14
14
|
const getNumberFormat = memoize((locale, opts) => new Intl.NumberFormat(locale, opts));
|
|
15
15
|
const getPluralRules = memoize((locale, opts) => new Intl.PluralRules(locale, opts));
|
|
@@ -87,7 +87,7 @@ function replaceStyle(stylesheet, selector, property, value) {
|
|
|
87
87
|
* @param appPath The path to the app to patch.
|
|
88
88
|
* @param patches Patches to apply to the YAML.
|
|
89
89
|
*/
|
|
90
|
-
async function patchDefinition(appPath, patches) {
|
|
90
|
+
export async function patchDefinition(appPath, patches) {
|
|
91
91
|
try {
|
|
92
92
|
const path = join(appPath, 'app-definition.yaml');
|
|
93
93
|
logger.verbose(`Updating ${path}`);
|
|
@@ -118,11 +118,15 @@ async function patchDefinition(appPath, patches) {
|
|
|
118
118
|
* @param appPath The name of the app to patch.
|
|
119
119
|
* @param replacements Replacements for the original messages.
|
|
120
120
|
*/
|
|
121
|
-
async function patchMessages(appPath, replacements) {
|
|
121
|
+
export async function patchMessages(appPath, replacements) {
|
|
122
122
|
try {
|
|
123
123
|
const i18nPath = join(appPath, 'i18n');
|
|
124
124
|
for (const [language, replacementMessages] of Object.entries(replacements)) {
|
|
125
125
|
const originalMessagesPath = join(i18nPath, `${language}.json`);
|
|
126
|
+
if (!existsSync(originalMessagesPath)) {
|
|
127
|
+
logger.warn(`Missing translation file at ${originalMessagesPath}`);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
126
130
|
logger.verbose(`Updating ${originalMessagesPath}`);
|
|
127
131
|
const [originalMessages] = await readData(originalMessagesPath);
|
|
128
132
|
await (replacementMessages
|
|
@@ -201,6 +205,21 @@ async function transferAppVariantFiles(appPath, appVariantDefDir, appVariantDest
|
|
|
201
205
|
logger.error(error);
|
|
202
206
|
}
|
|
203
207
|
}
|
|
208
|
+
async function transferReadmes(appPath, appVariantDefDir, appVariantDestDir) {
|
|
209
|
+
try {
|
|
210
|
+
await opendirSafe(appVariantDefDir, async (filePath, fileStat) => {
|
|
211
|
+
if (fileStat.isFile()) {
|
|
212
|
+
const fileBasename = basename(filePath);
|
|
213
|
+
if (fileBasename.toLowerCase().startsWith('readme')) {
|
|
214
|
+
await transferAppVariantFiles(appPath, appVariantDefDir, appVariantDestDir, fileBasename);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
catch (error) {
|
|
220
|
+
logger.error(error);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
204
223
|
export async function applyAppVariant(appPath, appVariant) {
|
|
205
224
|
try {
|
|
206
225
|
logger.info(`Applying ${appVariant} variant to ${appPath}`);
|
|
@@ -214,6 +233,7 @@ export async function applyAppVariant(appPath, appVariant) {
|
|
|
214
233
|
await transferAppVariantFiles(appPath, appVariantDefDir, appVariantDestDir, 'resources');
|
|
215
234
|
await transferAppVariantFiles(appPath, appVariantDefDir, appVariantDestDir, 'screenshots');
|
|
216
235
|
await transferAppVariantFiles(appPath, appVariantDefDir, appVariantDestDir, 'icon.png');
|
|
236
|
+
await transferReadmes(appPath, appVariantDefDir, appVariantDestDir);
|
|
217
237
|
const patchesPath = join(appVariantDefDir, 'patches');
|
|
218
238
|
try {
|
|
219
239
|
const definitionPath = join(patchesPath, 'app-definition.json');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appsemble/node-utils",
|
|
3
|
-
"version": "0.27.
|
|
3
|
+
"version": "0.27.10",
|
|
4
4
|
"description": "NodeJS utilities used by Appsemble internally.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"app",
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
"test": "vitest"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@appsemble/types": "0.27.
|
|
42
|
-
"@appsemble/utils": "0.27.
|
|
41
|
+
"@appsemble/types": "0.27.10",
|
|
42
|
+
"@appsemble/utils": "0.27.10",
|
|
43
43
|
"@formatjs/fast-memoize": "^2.0.0",
|
|
44
44
|
"@fortawesome/fontawesome-free": "^6.0.0",
|
|
45
45
|
"@koa/cors": "^4.0.0",
|
|
@@ -11,6 +11,7 @@ import { createCssHandler } from './cssHandler.js';
|
|
|
11
11
|
import { createIconHandler } from './iconHandler.js';
|
|
12
12
|
import { createIndexHandler } from './indexHandler.js';
|
|
13
13
|
import { createManifestHandler } from './manifestHandler.js';
|
|
14
|
+
import { createReadmeHandler } from './readmeHandler.js';
|
|
14
15
|
import { createRobotsHandler } from './robotsHandler.js';
|
|
15
16
|
import { createScreenshotHandler } from './screenshotHandler.js';
|
|
16
17
|
import { createServiceWorkerHandler } from './serviceWorkerHandler.js';
|
|
@@ -39,6 +40,10 @@ export function createAppRouter(options) {
|
|
|
39
40
|
route: /^\/screenshots\/(?<id>\d+)\.(?<ext>[a-z]+)$/,
|
|
40
41
|
get: createScreenshotHandler(options),
|
|
41
42
|
},
|
|
43
|
+
{
|
|
44
|
+
route: /^\/readmes\/(?<id>\d+)\.md$/,
|
|
45
|
+
get: createReadmeHandler(options),
|
|
46
|
+
},
|
|
42
47
|
{
|
|
43
48
|
route: new RegExp(`^/api/blocks/${blockName}/versions/(?<version>${partialSemver.source})/(?<filename>.+)$`),
|
|
44
49
|
get: createBlockAssetHandler(options),
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { assertKoaError } from '@appsemble/node-utils';
|
|
2
|
+
export function createReadmeHandler({ getApp, getAppReadmes }) {
|
|
3
|
+
return async (ctx) => {
|
|
4
|
+
const { id } = ctx.params;
|
|
5
|
+
const app = await getApp({ context: ctx });
|
|
6
|
+
assertKoaError(!app, ctx, 404, 'App not found');
|
|
7
|
+
const appReadmes = await getAppReadmes({ app, context: ctx });
|
|
8
|
+
const appReadme = appReadmes.find((readme) => readme.id === Number.parseInt(id));
|
|
9
|
+
assertKoaError(!appReadme, ctx, 404, 'Readme not found');
|
|
10
|
+
const { file } = appReadme;
|
|
11
|
+
ctx.type = 'text/markdown';
|
|
12
|
+
ctx.body = file;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=readmeHandler.js.map
|
package/server/types.d.ts
CHANGED
|
@@ -28,6 +28,7 @@ declare module 'koa' {
|
|
|
28
28
|
appUserInfo: UserInfo;
|
|
29
29
|
appTeams: ExtendedTeam[];
|
|
30
30
|
appAssets: AppAsset[];
|
|
31
|
+
appReadmes: AppReadme[];
|
|
31
32
|
blockConfigs: ContextBlockConfig[];
|
|
32
33
|
params?: Record<string, string>;
|
|
33
34
|
}
|
|
@@ -73,6 +74,7 @@ declare module 'koas-parameters' {
|
|
|
73
74
|
resourceTypeId: string;
|
|
74
75
|
schemaId: string;
|
|
75
76
|
screenshotId: number;
|
|
77
|
+
readmeId: number;
|
|
76
78
|
snapshotId: number;
|
|
77
79
|
teamId: string;
|
|
78
80
|
token: string;
|
|
@@ -96,6 +98,8 @@ declare module 'koas-parameters' {
|
|
|
96
98
|
view: string;
|
|
97
99
|
resources: boolean;
|
|
98
100
|
assets: boolean;
|
|
101
|
+
screenshots: boolean;
|
|
102
|
+
readmes: boolean;
|
|
99
103
|
roles: string[];
|
|
100
104
|
}
|
|
101
105
|
}
|
|
@@ -313,6 +317,10 @@ export interface AppScreenshot {
|
|
|
313
317
|
height: number;
|
|
314
318
|
width: number;
|
|
315
319
|
}
|
|
320
|
+
export interface AppReadme {
|
|
321
|
+
id: number;
|
|
322
|
+
file: Buffer;
|
|
323
|
+
}
|
|
316
324
|
export interface AppBlockStyle {
|
|
317
325
|
style: string;
|
|
318
326
|
}
|
|
@@ -344,6 +352,7 @@ export interface Options {
|
|
|
344
352
|
getAppTeams: (params: GetAppTeamsParams) => Promise<ExtendedTeam[]>;
|
|
345
353
|
getAppStyles: (params: GetAppParams | GetAppSubEntityParams) => Promise<AppStyles>;
|
|
346
354
|
getAppScreenshots: (params: GetAppSubEntityParams) => Promise<AppScreenshot[]>;
|
|
355
|
+
getAppReadmes: (params: GetAppSubEntityParams) => Promise<AppReadme[]>;
|
|
347
356
|
getAppBlockStyles: (params: GetAppBlockStylesParams) => Promise<AppBlockStyle[]>;
|
|
348
357
|
getAppIcon: (params: GetAppSubEntityParams) => Promise<Buffer>;
|
|
349
358
|
getAppUrl: (params: GetAppSubEntityParams) => Promise<URL>;
|