asljs-appbase 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/editor-app.d.ts +34 -1
- package/dist/editor-app.js +70 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/docs/appbase.md +24 -13
- package/package.json +18 -8
package/dist/editor-app.d.ts
CHANGED
|
@@ -32,8 +32,35 @@ export interface Project {
|
|
|
32
32
|
* nearest file of a parent, or with none (`loadConfig`). The files are
|
|
33
33
|
* `files`, the files of `folder` as `listFiles` gives them, so that a server
|
|
34
34
|
* of several applications lists them once; `listFiles(folder)` when absent.
|
|
35
|
+
*
|
|
36
|
+
* With `required`, a project needs the file: when the folder, the folders
|
|
37
|
+
* below it and those above it have none, it throws, for an application whose
|
|
38
|
+
* projects cannot be told without it, e.g. which artefacts a part project
|
|
39
|
+
* supports.
|
|
35
40
|
*/
|
|
36
|
-
export declare function findProjects(folder: string, name: string, files?: readonly string[]
|
|
41
|
+
export declare function findProjects(folder: string, name: string, files?: readonly string[], options?: {
|
|
42
|
+
required?: boolean;
|
|
43
|
+
}): Promise<Project[]>;
|
|
44
|
+
/**
|
|
45
|
+
* The projects of an application in the folders of `context` by its
|
|
46
|
+
* configuration file `name`: `findProjects` of `cwd` and `files` alone, or of
|
|
47
|
+
* each of `folders` when there are several. Then the id of a project starts
|
|
48
|
+
* with the name of its folder, `docs/notes` for `notes` of `docs`, the name
|
|
49
|
+
* alone for the folder itself, and a name that two folders share gets `-2`,
|
|
50
|
+
* `-3` and so on after the first. With `required`, a folder without the file
|
|
51
|
+
* has no project, and an error is thrown only when no folder has one.
|
|
52
|
+
*/
|
|
53
|
+
export declare function findAppProjects(context: Pick<EditorAppContext, 'cwd' | 'files' | 'folders'>, name: string, options?: {
|
|
54
|
+
required?: boolean;
|
|
55
|
+
}): Promise<Project[]>;
|
|
56
|
+
/**
|
|
57
|
+
* A folder whose projects an application serves, and its files as `listFiles`
|
|
58
|
+
* gives them, when they are listed already.
|
|
59
|
+
*/
|
|
60
|
+
export interface WorkingFolder {
|
|
61
|
+
cwd: string;
|
|
62
|
+
files?: readonly string[];
|
|
63
|
+
}
|
|
37
64
|
/**
|
|
38
65
|
* What the `createApp` of an application server, e.g. `asljs-kb-srv`, makes
|
|
39
66
|
* its `EditorApp` with, whether it serves alone or in an aggregating server.
|
|
@@ -61,6 +88,12 @@ export interface EditorAppContext {
|
|
|
61
88
|
* `host` of `createHandler`, which a `POST` must be sent to.
|
|
62
89
|
*/
|
|
63
90
|
host?: string;
|
|
91
|
+
/**
|
|
92
|
+
* The folders whose projects are served, when an aggregating server serves
|
|
93
|
+
* several, `cwd` and `files` being those of the first: `findAppProjects`
|
|
94
|
+
* finds the projects of them all.
|
|
95
|
+
*/
|
|
96
|
+
folders?: readonly WorkingFolder[];
|
|
64
97
|
}
|
|
65
98
|
/**
|
|
66
99
|
* What a project handler is made with.
|
package/dist/editor-app.js
CHANGED
|
@@ -2,7 +2,7 @@ import { loadConfig } from 'asljs-cmdbase';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { createImportMap, MODULES_PREFIX } from './browser-modules.js';
|
|
4
4
|
import { listFiles } from './files.js';
|
|
5
|
-
import { createHandler, mountHandlers, page, scriptJson, serve, serverUrl, untilStopped
|
|
5
|
+
import { createHandler, mountHandlers, page, scriptJson, send, serve, serverUrl, untilStopped } from './server.js';
|
|
6
6
|
/**
|
|
7
7
|
* The path an application serves its plugin's folder at.
|
|
8
8
|
*/
|
|
@@ -14,8 +14,13 @@ const PLUGIN_PREFIX = '/_/plugin/';
|
|
|
14
14
|
* nearest file of a parent, or with none (`loadConfig`). The files are
|
|
15
15
|
* `files`, the files of `folder` as `listFiles` gives them, so that a server
|
|
16
16
|
* of several applications lists them once; `listFiles(folder)` when absent.
|
|
17
|
+
*
|
|
18
|
+
* With `required`, a project needs the file: when the folder, the folders
|
|
19
|
+
* below it and those above it have none, it throws, for an application whose
|
|
20
|
+
* projects cannot be told without it, e.g. which artefacts a part project
|
|
21
|
+
* supports.
|
|
17
22
|
*/
|
|
18
|
-
export async function findProjects(folder, name, files) {
|
|
23
|
+
export async function findProjects(folder, name, files, options = {}) {
|
|
19
24
|
const root = path.resolve(folder);
|
|
20
25
|
const listed = files
|
|
21
26
|
?? await listFiles(root);
|
|
@@ -30,7 +35,69 @@ export async function findProjects(folder, name, files) {
|
|
|
30
35
|
return (await Promise.all(folders.map(found => toProject(root, found, name))))
|
|
31
36
|
.sort((a, b) => a.id.localeCompare(b.id));
|
|
32
37
|
}
|
|
33
|
-
|
|
38
|
+
const project = await toProject(root, root, name);
|
|
39
|
+
if (options.required === true
|
|
40
|
+
&& project.config.file === null) {
|
|
41
|
+
throw new Error(`No ${name} in ${root}, in a folder below it, or in a folder above it.`);
|
|
42
|
+
}
|
|
43
|
+
return [project];
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The projects of an application in the folders of `context` by its
|
|
47
|
+
* configuration file `name`: `findProjects` of `cwd` and `files` alone, or of
|
|
48
|
+
* each of `folders` when there are several. Then the id of a project starts
|
|
49
|
+
* with the name of its folder, `docs/notes` for `notes` of `docs`, the name
|
|
50
|
+
* alone for the folder itself, and a name that two folders share gets `-2`,
|
|
51
|
+
* `-3` and so on after the first. With `required`, a folder without the file
|
|
52
|
+
* has no project, and an error is thrown only when no folder has one.
|
|
53
|
+
*/
|
|
54
|
+
export async function findAppProjects(context, name, options = {}) {
|
|
55
|
+
const folders = context.folders
|
|
56
|
+
?? [{ cwd: context.cwd,
|
|
57
|
+
files: context.files }];
|
|
58
|
+
if (folders.length === 1) {
|
|
59
|
+
return await findProjects(folders[0].cwd, name, folders[0].files, options);
|
|
60
|
+
}
|
|
61
|
+
const labels = folderLabels(folders.map(folder => folder.cwd));
|
|
62
|
+
const projects = [];
|
|
63
|
+
for (const [index, folder] of folders.entries()) {
|
|
64
|
+
for (const project of await findProjects(folder.cwd, name, folder.files)) {
|
|
65
|
+
if (options.required === true
|
|
66
|
+
&& project.config.file === null) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
const id = project.id === '.'
|
|
70
|
+
? labels[index]
|
|
71
|
+
: `${labels[index]}/${project.id}`;
|
|
72
|
+
projects.push({ ...project,
|
|
73
|
+
id,
|
|
74
|
+
title: id });
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (projects.length === 0) {
|
|
78
|
+
throw new Error(`No ${name} in ${folders
|
|
79
|
+
.map(folder => path.resolve(folder.cwd))
|
|
80
|
+
.join(', ')}, in a folder below them, or in a folder above them.`);
|
|
81
|
+
}
|
|
82
|
+
return projects;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* The name of each folder, by its base name, `-2`, `-3` and so on added to a
|
|
86
|
+
* name an earlier folder has.
|
|
87
|
+
*/
|
|
88
|
+
function folderLabels(folders) {
|
|
89
|
+
const labels = [];
|
|
90
|
+
for (const folder of folders) {
|
|
91
|
+
const resolved = path.resolve(folder);
|
|
92
|
+
const base = path.basename(resolved)
|
|
93
|
+
|| resolved;
|
|
94
|
+
let label = base;
|
|
95
|
+
for (let n = 2; labels.includes(label); n++) {
|
|
96
|
+
label = `${base}-${n}`;
|
|
97
|
+
}
|
|
98
|
+
labels.push(label);
|
|
99
|
+
}
|
|
100
|
+
return labels;
|
|
34
101
|
}
|
|
35
102
|
async function toProject(root, folder, name) {
|
|
36
103
|
const id = path.relative(root, folder)
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export { createImportMap, findBrowserModules, findModuleFile, MODULES_PREFIX, type BrowserModule } from './browser-modules.js';
|
|
2
2
|
export { commandLine, configBoolean, configLogging, configPath, configPaths, configPort, configString, configStrings, loadCommandLineConfig, loadConfig, messageOf, packageVersion, parsePort, readOptionValue, runMain, workingFolder, type CommandIo, type Config } from 'asljs-cmdbase';
|
|
3
|
-
export { combineEditorApps, createEditorApp, editorPage, findProjects, projectSegment, serveApp, type EditorApp, type EditorAppContext, type EditorAppDescriptor, type EditorAppOptions, type Project, type ProjectContext } from './editor-app.js';
|
|
3
|
+
export { combineEditorApps, createEditorApp, editorPage, findAppProjects, findProjects, projectSegment, serveApp, type EditorApp, type EditorAppContext, type EditorAppDescriptor, type EditorAppOptions, type Project, type ProjectContext, type WorkingFolder } from './editor-app.js';
|
|
4
4
|
export { findMarkdownFiles, listFiles, toDisplayPath, type FindOptions } from './files.js';
|
|
5
5
|
export { findSectionHeading, formatUrl, getSection, parseMarkdown, plainText, splitLocalUrl, type MarkdownNode } from './markdown.js';
|
|
6
6
|
export { findConfig, postProcess, takeWritten, writeMarkdown, type PostProcessIo, type ToolConfig } from './post-process.js';
|
|
7
|
-
export { createHandler, DEFAULT_PORT, escapeHtml,
|
|
7
|
+
export { createHandler, DEFAULT_PORT, escapeHtml, jsonReply, mountHandlers, page, scriptJson, send, serve, serverUrl, startServer, untilStopped, versionConflict, type HandlerOptions, type JsonReply, type ListenOptions, type PostReply, type RequestHandler, type ServerOptions } from './server.js';
|
|
8
8
|
export { stateFolder, type GivenStateFolder } from './state-folder.js';
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export { createImportMap, findBrowserModules, findModuleFile, MODULES_PREFIX } from './browser-modules.js';
|
|
2
2
|
export { commandLine, configBoolean, configLogging, configPath, configPaths, configPort, configString, configStrings, loadCommandLineConfig, loadConfig, messageOf, packageVersion, parsePort, readOptionValue, runMain, workingFolder } from 'asljs-cmdbase';
|
|
3
|
-
export { combineEditorApps, createEditorApp, editorPage, findProjects, projectSegment, serveApp } from './editor-app.js';
|
|
3
|
+
export { combineEditorApps, createEditorApp, editorPage, findAppProjects, findProjects, projectSegment, serveApp } from './editor-app.js';
|
|
4
4
|
export { findMarkdownFiles, listFiles, toDisplayPath } from './files.js';
|
|
5
5
|
export { findSectionHeading, formatUrl, getSection, parseMarkdown, plainText, splitLocalUrl } from './markdown.js';
|
|
6
6
|
export { findConfig, postProcess, takeWritten, writeMarkdown } from './post-process.js';
|
|
7
|
-
export { createHandler, DEFAULT_PORT, escapeHtml,
|
|
7
|
+
export { createHandler, DEFAULT_PORT, escapeHtml, jsonReply, mountHandlers, page, scriptJson, send, serve, serverUrl, startServer, untilStopped, versionConflict } from './server.js';
|
|
8
8
|
export { stateFolder } from './state-folder.js';
|
package/docs/appbase.md
CHANGED
|
@@ -118,14 +118,21 @@ values; the only HTML it sends is `index`, a page that loads its data.
|
|
|
118
118
|
An application served as a plugin of the editor of `asljs-ui-editor`, with a
|
|
119
119
|
selector of its projects; one server can serve one application, or several.
|
|
120
120
|
|
|
121
|
-
- `findProjects(folder, name, files?)` - the projects of an
|
|
122
|
-
configuration file `name`, e.g. `kb.json`: `folder` itself
|
|
123
|
-
file; else every folder below it that has one, by id; else
|
|
124
|
-
with the nearest file of a parent, or none
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
itself.
|
|
121
|
+
- `findProjects(folder, name, files?, { required? })` - the projects of an
|
|
122
|
+
application by its configuration file `name`, e.g. `kb.json`: `folder` itself
|
|
123
|
+
when it has the file; else every folder below it that has one, by id; else
|
|
124
|
+
`folder` itself with the nearest file of a parent, or none; with `required`,
|
|
125
|
+
none throws. It looks for the file in `files`, the files of `folder` as
|
|
126
|
+
`listFiles` gives them, so that a server of several applications lists them
|
|
127
|
+
once; it lists them itself without. A `Project` is `{ id, title, folder,
|
|
128
|
+
config }`; `id` is the folder relative to `folder`, `.` for itself.
|
|
129
|
+
- `findAppProjects(context, name, { required? })` - the projects of an
|
|
130
|
+
application in the folders of an `EditorAppContext`: `findProjects` of its
|
|
131
|
+
`cwd` and `files`, or, with several `folders`, the projects of each, whose ids
|
|
132
|
+
start with the folder's name, such as `docs/notes`, the name alone for the
|
|
133
|
+
folder itself; a name two folders share gets `-2`, `-3` after the first. With
|
|
134
|
+
`required`, a folder without the file has no project, and it throws only when
|
|
135
|
+
no folder has one.
|
|
129
136
|
- `createEditorApp({ id, title, icon, base?, projects, project, plugin, modules,
|
|
130
137
|
style? })` - an `EditorApp`, whose `handler` answers, relative to `base`, `/`
|
|
131
138
|
with the editor whose only plugin is the application, `/_/app.json` with an
|
|
@@ -140,11 +147,15 @@ selector of its projects; one server can serve one application, or several.
|
|
|
140
147
|
prefix of the URLs its plugin reads, and `onClose` registers what `close()` of
|
|
141
148
|
the application runs. `projectSegment(id)` is the segment of a project in a
|
|
142
149
|
path.
|
|
143
|
-
- `EditorAppContext` - `{ cwd, base, env, loggerProvider, files?, host
|
|
144
|
-
the `createApp` of an application server makes its
|
|
145
|
-
in an aggregating server; `files`, the files of
|
|
146
|
-
listed once, go to `findProjects`, and `host`, the
|
|
147
|
-
on, to the `host` of each project's handler.
|
|
150
|
+
- `EditorAppContext` - `{ cwd, base, env, loggerProvider, files?, host?,
|
|
151
|
+
folders? }`, what the `createApp` of an application server makes its
|
|
152
|
+
`EditorApp` with, alone or in an aggregating server; `files`, the files of
|
|
153
|
+
`cwd` an aggregating server listed once, go to `findProjects`, and `host`, the
|
|
154
|
+
address the server listens on, to the `host` of each project's handler.
|
|
155
|
+
`folders`, each a `WorkingFolder` `{ cwd, files? }`, are the folders of an
|
|
156
|
+
aggregating server that serves several, `cwd` and `files` being the first's;
|
|
157
|
+
`createApp` finds its projects with `findAppProjects`, in one folder or in
|
|
158
|
+
all.
|
|
148
159
|
- `combineEditorApps(title, apps)` - a handler that mounts each application at
|
|
149
160
|
`/<id>/`, the `base` it was made with, and answers `/` with the editor whose
|
|
150
161
|
plugins are all of them and `/modules/...` with the modules of them all.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "asljs-appbase",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "The base of the applications: configuration files and state folders, the entry point of an executable, markdown, the document server and editor applications.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"asljs": {
|
|
@@ -18,23 +18,33 @@
|
|
|
18
18
|
"dist/**",
|
|
19
19
|
"docs/**",
|
|
20
20
|
"README.md",
|
|
21
|
-
"LICENSE.md"
|
|
21
|
+
"LICENSE.md",
|
|
22
|
+
"!dist/*.tsbuildinfo"
|
|
22
23
|
],
|
|
23
24
|
"scripts": {
|
|
24
25
|
"flint": "toolkit flint",
|
|
25
|
-
"clean": "
|
|
26
|
-
"
|
|
27
|
-
"build
|
|
26
|
+
"clean:build": "node ../../scripts/cleanBuildOutDir.js",
|
|
27
|
+
"clean:dist": "node ../../scripts/cleanDistOutDir.js",
|
|
28
|
+
"compile:build": "npm run codegen --if-present && tsc -p tsconfig.build.json",
|
|
29
|
+
"compile:dist": "npm run codegen --if-present && tsc -p tsconfig.dist.json",
|
|
30
|
+
"build:dist": "node ../../scripts/buildDistDeps.js && npm run compile:dist",
|
|
28
31
|
"typecheck": "npm run codegen --if-present && tsc -p tsconfig.build.json --noEmit",
|
|
29
32
|
"guard:clean-git": "toolkit ensure-clean-working-directory",
|
|
30
|
-
"prepack": "npm run clean && npm run build:dist && npm run build && npm run test && npm run guard:clean-git",
|
|
33
|
+
"prepack": "npm run clean:build && npm run clean:dist && npm run build:dist && npm run compile:build && npm run test && npm run guard:clean-git",
|
|
31
34
|
"postpublish": "toolkit tag-release-revision",
|
|
32
35
|
"test": "node --test --enable-source-maps \"build/**/*.test.js\"",
|
|
33
36
|
"test:watch": "node --watch --test \"build/**/*.test.js\"",
|
|
34
|
-
"coverage": "npm run build && node --test --experimental-test-coverage --enable-source-maps --test-coverage-exclude=\"**/*.test.js\" \"build/**/*.test.js\"",
|
|
37
|
+
"coverage": "npm run compile:build && node --test --experimental-test-coverage --enable-source-maps --test-coverage-exclude=\"**/*.test.js\" \"build/**/*.test.js\"",
|
|
35
38
|
"release:patch": "toolkit release-patch",
|
|
36
|
-
"
|
|
39
|
+
"build": "npm run clean:build && npm run flint && npm run typecheck && npm run compile:build && npm run test"
|
|
37
40
|
},
|
|
41
|
+
"distDependencies": [
|
|
42
|
+
"asljs-agents",
|
|
43
|
+
"asljs-cmdbase",
|
|
44
|
+
"asljs-locator",
|
|
45
|
+
"asljs-logging",
|
|
46
|
+
"asljs-tmpdir"
|
|
47
|
+
],
|
|
38
48
|
"keywords": [
|
|
39
49
|
"markdown",
|
|
40
50
|
"cli"
|