asljs-appbase 0.0.0-stage → 0.1.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/LICENSE.md +51 -0
- package/README.md +81 -2
- package/dist/browser-modules.d.ts +36 -0
- package/dist/browser-modules.js +148 -0
- package/dist/editor-app.d.ts +199 -0
- package/dist/editor-app.js +201 -0
- package/dist/files.d.ts +25 -0
- package/dist/files.js +48 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +8 -0
- package/dist/markdown.d.ts +27 -0
- package/dist/markdown.js +84 -0
- package/dist/post-process.d.ts +50 -0
- package/dist/post-process.js +84 -0
- package/dist/server.d.ts +152 -0
- package/dist/server.js +354 -0
- package/dist/state-folder.d.ts +20 -0
- package/dist/state-folder.js +21 -0
- package/docs/appbase.md +182 -0
- package/package.json +62 -4
package/docs/appbase.md
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# appbase
|
|
2
|
+
|
|
3
|
+
The exports of `asljs-appbase`, by module.
|
|
4
|
+
|
|
5
|
+
## Logging
|
|
6
|
+
|
|
7
|
+
The functions that run something take an optional `Logger` of `asljs-logging`
|
|
8
|
+
from their caller, and log nothing without one: they never create a provider.
|
|
9
|
+
What they log is listed with each of them.
|
|
10
|
+
|
|
11
|
+
Asking an AI agent and running commands are in `asljs-agents`, and the MCP
|
|
12
|
+
server core in `asljs-mcp`.
|
|
13
|
+
|
|
14
|
+
## Markdown
|
|
15
|
+
|
|
16
|
+
- `parseMarkdown(text)` - the mdast tree.
|
|
17
|
+
- `findSectionHeading(root, name)`, `getSection(root, name)` - a level 2
|
|
18
|
+
section: its heading, or its nodes up to the next level 1 or 2 heading.
|
|
19
|
+
- `plainText(node)` - the text of a node.
|
|
20
|
+
- `splitLocalUrl(url)` - a local link target split into a decoded path and its
|
|
21
|
+
`#` fragment; `null` for a URL with a scheme.
|
|
22
|
+
- `formatUrl(url)` - a link target in angle brackets when it has spaces or
|
|
23
|
+
parentheses.
|
|
24
|
+
|
|
25
|
+
## Files
|
|
26
|
+
|
|
27
|
+
- `findMarkdownFiles(folder, { skip })` - the `.md` files of a folder and its
|
|
28
|
+
subfolders, any case of the extension, by absolute path, sorted, as the
|
|
29
|
+
`LocationResolver` of `asljs-locator` finds them, skipping folders whose name
|
|
30
|
+
starts with `.`, `node_modules`, and the `skip` names.
|
|
31
|
+
- `listFiles(folder)` - every file of a folder and its subfolders, relative to
|
|
32
|
+
it with `/` separators, sorted, as the `LocationResolver` of `asljs-locator`
|
|
33
|
+
finds them; what `.gitignore` files ignore, `.git` and `node_modules` are left
|
|
34
|
+
out.
|
|
35
|
+
- `toDisplayPath(folder, file)` - a path relative to `folder` with `/`
|
|
36
|
+
separators.
|
|
37
|
+
|
|
38
|
+
## Post-processing
|
|
39
|
+
|
|
40
|
+
- `writeMarkdown(file, text)` - writes a markdown file and remembers it.
|
|
41
|
+
- `takeWritten()` - the files written since the last call, and forgets them.
|
|
42
|
+
- `findConfig(folder, name)` - the nearest configuration file `name`, e.g.
|
|
43
|
+
`rq.json`, of `folder` or a parent; an error when it is not valid JSON or its
|
|
44
|
+
`markdownPostProcessing` is not a string.
|
|
45
|
+
- `postProcess(io, files, name)` - runs the `markdownPostProcessing` command of
|
|
46
|
+
the nearest `name` with the files that still exist, relative to the
|
|
47
|
+
configuration file's folder, where it runs. Returns 1 and writes the output to
|
|
48
|
+
`io.stderr` when the command fails, 0 otherwise. The command line and its exit
|
|
49
|
+
code go to `io.logger` at `debug`.
|
|
50
|
+
|
|
51
|
+
## Configuration and executables
|
|
52
|
+
|
|
53
|
+
The configuration readers, `loadConfig` and the `config*` functions, and the
|
|
54
|
+
entry point of an executable, `runMain`, `commandLine` and the helpers beside
|
|
55
|
+
them, are in [asljs-cmdbase][CMB], and this package re-exports them. The rules
|
|
56
|
+
of the configuration file are in [Configuration][CFG] at the repository root.
|
|
57
|
+
`findConfig` is `loadConfig` with the check of `markdownPostProcessing`.
|
|
58
|
+
|
|
59
|
+
## State folder
|
|
60
|
+
|
|
61
|
+
- `stateFolder(folder, app, config, given?)` - where application `app` keeps
|
|
62
|
+
what it stores between runs for the project in `folder`: `given`, a command
|
|
63
|
+
line's `{ option, variable, env, cwd }`, the option, else the variable, e.g.
|
|
64
|
+
`KB_STATE_DIR`, both against `cwd`; else `stateDir` of `config`, against the
|
|
65
|
+
folder of the file; else `.<app>` in `folder`, e.g. `.kb`. A service passes no
|
|
66
|
+
`given`: its projects are configured by their own files.
|
|
67
|
+
|
|
68
|
+
## Server
|
|
69
|
+
|
|
70
|
+
A server sends data, never a rendering of it: rendering is the page's, e.g. the
|
|
71
|
+
plugin of an editor application. It serves a markdown file as its text, and JSON
|
|
72
|
+
values; the only HTML it sends is `index`, a page that loads its data.
|
|
73
|
+
|
|
74
|
+
- `startServer({ folder, index?, json?, port?, host?, post?, allow?, modules?,
|
|
75
|
+
logger? })` - serves `/` with `index()`, made again on every request, and not
|
|
76
|
+
found without it; a path of `json` with its value; and any file of `folder` as
|
|
77
|
+
it is, a `.md` file as `text/markdown`. Nothing outside `folder`, or that
|
|
78
|
+
`allow(relative)` refuses, is served. The files of each of `modules` are
|
|
79
|
+
served under `MODULES_PREFIX`, `/modules/<name>/<file>`, and nothing outside
|
|
80
|
+
their folders. It listens on `host`, `127.0.0.1` by default, on `port`, or
|
|
81
|
+
without one on the first free port from `DEFAULT_PORT`, 3000, up to 3099.
|
|
82
|
+
`logger` is told that it listens, with its URL, at `information`, each request
|
|
83
|
+
at `trace`, and a request that failed at `error`. A `POST` is answered by
|
|
84
|
+
`post(url, body)` with the parsed JSON body; it returns a `PostReply`, `{
|
|
85
|
+
status, body }`, sent back as JSON. Without `post` a `POST` is not found. Only
|
|
86
|
+
a `POST` with `Content-Type: application/json`, sent to a local name
|
|
87
|
+
(`localhost`, `127.0.0.1`, `[::1]` or `host`) and, when it has an `Origin`,
|
|
88
|
+
from the server's own pages is answered; any other gets 403, a body that is
|
|
89
|
+
not JSON 400, and one over 10 MB 413.
|
|
90
|
+
- `json` of `startServer`, by path, gives values sent as JSON, e.g.
|
|
91
|
+
`/_/data.json`, made from the request URL with its query; a value made with
|
|
92
|
+
`jsonReply(status, body)` is sent with that status, e.g. 422. `methods`, e.g.
|
|
93
|
+
`[ 'GET', 'HEAD' ]`, refuses any other method with 405, and `moduleTypes`,
|
|
94
|
+
e.g. `[ '.js', '.mjs', '.map' ]`, limits the module files served by their
|
|
95
|
+
extensions.
|
|
96
|
+
- `createHandler(options)` - the `RequestHandler` of `startServer` without
|
|
97
|
+
listening: `(request, response, url)`, whose `url` path is relative to where
|
|
98
|
+
it is mounted. `serve(handler, { port?, host?, logger? })` listens with any
|
|
99
|
+
handler, as `startServer` does; `send(response, status, type, body)` answers.
|
|
100
|
+
- `mountHandlers(mounts, fallback?)` - passes a request for `/<name>/...` to
|
|
101
|
+
`mounts[name]` with the path relative to it, redirects `/<name>` to
|
|
102
|
+
`/<name>/`, and passes any other request to `fallback`, or answers 404.
|
|
103
|
+
- `untilStopped(server, signals?)` - resolves once the server has closed; the
|
|
104
|
+
first of `signals`, `SIGINT` and `SIGTERM` by default, closes it and its open
|
|
105
|
+
connections. A command that serves awaits it, so that it releases what the
|
|
106
|
+
server used, such as its logger provider, only after the server.
|
|
107
|
+
- `serverUrl(server)` - its address, e.g. `http://127.0.0.1:3000/`, an IPv6
|
|
108
|
+
address in brackets.
|
|
109
|
+
- `page(title, body, style?)` - an HTML page with the shared style and `style`,
|
|
110
|
+
e.g. the editor page, or a page printed to PDF.
|
|
111
|
+
- `scriptJson(value)` - JSON that is safe inside a `<script>` element.
|
|
112
|
+
- `versionConflict()` - the 409 reply to a save of a document that changed since
|
|
113
|
+
its editor read it.
|
|
114
|
+
- `escapeHtml(text)` - the text with `&`, `<`, `>` and `"` escaped.
|
|
115
|
+
|
|
116
|
+
## Editor applications
|
|
117
|
+
|
|
118
|
+
An application served as a plugin of the editor of `asljs-ui-editor`, with a
|
|
119
|
+
selector of its projects; one server can serve one application, or several.
|
|
120
|
+
|
|
121
|
+
- `findProjects(folder, name, files?)` - the projects of an application by its
|
|
122
|
+
configuration file `name`, e.g. `kb.json`: `folder` itself when it has the
|
|
123
|
+
file; else every folder below it that has one, by id; else `folder` itself
|
|
124
|
+
with the nearest file of a parent, or none. It looks for the file in `files`,
|
|
125
|
+
the files of `folder` as `listFiles` gives them, so that a server of several
|
|
126
|
+
applications lists them once; it lists them itself without. A `Project` is `{
|
|
127
|
+
id, title, folder, config }`; `id` is the folder relative to `folder`, `.` for
|
|
128
|
+
itself.
|
|
129
|
+
- `createEditorApp({ id, title, icon, base?, projects, project, plugin, modules,
|
|
130
|
+
style? })` - an `EditorApp`, whose `handler` answers, relative to `base`, `/`
|
|
131
|
+
with the editor whose only plugin is the application, `/_/app.json` with an
|
|
132
|
+
`EditorAppDescriptor` - `{ id, title, icon, plugin, projects }`, each project
|
|
133
|
+
`{ id, title, base }` - `/_/plugin/...` with the folder of `plugin`, the path
|
|
134
|
+
of the plugin's browser module, its scripts and source maps only, so that it
|
|
135
|
+
imports the modules beside it, `plugin` being `/_/plugin/<file>` in the
|
|
136
|
+
descriptor; `/modules/...` with the modules, and `/p/<project>/...` with the
|
|
137
|
+
handler of that project, `~` naming `.`. `project(project, { base, onClose })`
|
|
138
|
+
makes that handler when the project is first requested; it answers data, which
|
|
139
|
+
the plugin renders. `base` is where it is served, e.g. `/kb/p/docs/`, the
|
|
140
|
+
prefix of the URLs its plugin reads, and `onClose` registers what `close()` of
|
|
141
|
+
the application runs. `projectSegment(id)` is the segment of a project in a
|
|
142
|
+
path.
|
|
143
|
+
- `EditorAppContext` - `{ cwd, base, env, loggerProvider, files?, host? }`, what
|
|
144
|
+
the `createApp` of an application server makes its `EditorApp` with, alone or
|
|
145
|
+
in an aggregating server; `files`, the files of `cwd` an aggregating server
|
|
146
|
+
listed once, go to `findProjects`, and `host`, the address the server listens
|
|
147
|
+
on, to the `host` of each project's handler.
|
|
148
|
+
- `combineEditorApps(title, apps)` - a handler that mounts each application at
|
|
149
|
+
`/<id>/`, the `base` it was made with, and answers `/` with the editor whose
|
|
150
|
+
plugins are all of them and `/modules/...` with the modules of them all.
|
|
151
|
+
- `editorPage({ title, apps, modules, style? })` - the editor page: the import
|
|
152
|
+
map of `modules`, an `asljs-editor` and `mountEditorApps` of the applications
|
|
153
|
+
whose `/_/app.json` URLs are `apps`, and `style`; the editor adds its own
|
|
154
|
+
style, `EDITOR_STYLE` of `asljs-ui-editor`, when it mounts.
|
|
155
|
+
- `serveApp(app, { io, cwd, port?, host?, loggerProvider })` - serves an
|
|
156
|
+
`EditorApp`, prints `Serving <cwd> at <url>`, waits until SIGINT or SIGTERM,
|
|
157
|
+
and closes the application.
|
|
158
|
+
|
|
159
|
+
## Browser modules
|
|
160
|
+
|
|
161
|
+
A page served by `startServer` can import installed packages, such as
|
|
162
|
+
`asljs-ui-diagram`, without a bundler.
|
|
163
|
+
|
|
164
|
+
- `findBrowserModules(name, from)` - the package `name`, or each package of an
|
|
165
|
+
array of names, looked up from the folder `from`, and every package it depends
|
|
166
|
+
on at runtime, each a `BrowserModule`: its `name`, its folder `root`, and its
|
|
167
|
+
ES module `entry`, picked from the `browser`, `import`, `module` and `default`
|
|
168
|
+
conditions of `exports`, else `module`, else `main`, else `index.js`, and its
|
|
169
|
+
`subpaths`, the module of each other subpath of `exports`, e.g. `wiki` of
|
|
170
|
+
`asljs-kb/wiki`, a pattern with `*` left out. It throws for a package it
|
|
171
|
+
cannot find.
|
|
172
|
+
- `createImportMap(modules, prefix)` - the import map that points each name at
|
|
173
|
+
`<prefix><name>/<entry>`, each `<name>/<subpath>` at its module, and `<name>/`
|
|
174
|
+
at `<prefix><name>/`, for a module that imports a file of a package, as lit
|
|
175
|
+
imports `lit/decorators.js`. Pass it to `startServer` as `modules` and put the
|
|
176
|
+
map, with `MODULES_PREFIX`, in a `<script type="importmap">` of the page.
|
|
177
|
+
- `findModuleFile(rest, modules)` - the file of a module that a path after
|
|
178
|
+
`MODULES_PREFIX` names, or `null` for an unknown module or a path that leaves
|
|
179
|
+
its folder.
|
|
180
|
+
|
|
181
|
+
[CFG]: ../../../docs/Configuration.md
|
|
182
|
+
[CMB]: ../../cmdbase/docs/cmdbase.md
|
package/package.json
CHANGED
|
@@ -1,6 +1,64 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "asljs-appbase",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.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
|
+
"type": "module",
|
|
6
|
+
"asljs": {
|
|
7
|
+
"type": "lib"
|
|
8
|
+
},
|
|
9
|
+
"main": "dist/index.js",
|
|
10
|
+
"types": "dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist/**",
|
|
19
|
+
"docs/**",
|
|
20
|
+
"README.md",
|
|
21
|
+
"LICENSE.md"
|
|
22
|
+
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"flint": "toolkit flint",
|
|
25
|
+
"clean": "toolkit clean",
|
|
26
|
+
"build": "npm run codegen --if-present && tsc -p tsconfig.build.json",
|
|
27
|
+
"build:dist": "npm run codegen --if-present && tsc -p tsconfig.dist.json",
|
|
28
|
+
"typecheck": "npm run codegen --if-present && tsc -p tsconfig.build.json --noEmit",
|
|
29
|
+
"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",
|
|
31
|
+
"postpublish": "toolkit tag-release-revision",
|
|
32
|
+
"test": "node --test --enable-source-maps \"build/**/*.test.js\"",
|
|
33
|
+
"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\"",
|
|
35
|
+
"release:patch": "toolkit release-patch",
|
|
36
|
+
"all": "npm run clean && npm run build:dist && npm run flint && npm run typecheck && npm run build && npm run test"
|
|
37
|
+
},
|
|
38
|
+
"keywords": [
|
|
39
|
+
"markdown",
|
|
40
|
+
"cli"
|
|
41
|
+
],
|
|
42
|
+
"homepage": "https://github.com/AlexandriteSoftware/asljs#readme",
|
|
43
|
+
"bugs": {
|
|
44
|
+
"url": "https://github.com/AlexandriteSoftware/asljs/issues"
|
|
45
|
+
},
|
|
46
|
+
"repository": {
|
|
47
|
+
"type": "git",
|
|
48
|
+
"url": "git+https://github.com/AlexandriteSoftware/asljs.git"
|
|
49
|
+
},
|
|
50
|
+
"author": "\"Alex Netkachov\" <alex.netkachov@gmail.com>",
|
|
51
|
+
"license": "SEE LICENSE IN LICENSE.md",
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"asljs-agents": "^0.1.0",
|
|
54
|
+
"asljs-cmdbase": "^0.1.0",
|
|
55
|
+
"asljs-locator": "^0.1.0",
|
|
56
|
+
"asljs-logging": "^0.1.2",
|
|
57
|
+
"remark-parse": "^11.0.0",
|
|
58
|
+
"unified": "^11.0.5"
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"asljs-tmpdir": "^0.1.13",
|
|
62
|
+
"asljs-toolkit": "^0.1.0"
|
|
63
|
+
}
|
|
64
|
+
}
|