asljs-appbase 0.0.0-stage → 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.
@@ -0,0 +1,193 @@
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?, { 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.
136
+ - `createEditorApp({ id, title, icon, base?, projects, project, plugin, modules,
137
+ style? })` - an `EditorApp`, whose `handler` answers, relative to `base`, `/`
138
+ with the editor whose only plugin is the application, `/_/app.json` with an
139
+ `EditorAppDescriptor` - `{ id, title, icon, plugin, projects }`, each project
140
+ `{ id, title, base }` - `/_/plugin/...` with the folder of `plugin`, the path
141
+ of the plugin's browser module, its scripts and source maps only, so that it
142
+ imports the modules beside it, `plugin` being `/_/plugin/<file>` in the
143
+ descriptor; `/modules/...` with the modules, and `/p/<project>/...` with the
144
+ handler of that project, `~` naming `.`. `project(project, { base, onClose })`
145
+ makes that handler when the project is first requested; it answers data, which
146
+ the plugin renders. `base` is where it is served, e.g. `/kb/p/docs/`, the
147
+ prefix of the URLs its plugin reads, and `onClose` registers what `close()` of
148
+ the application runs. `projectSegment(id)` is the segment of a project in a
149
+ path.
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.
159
+ - `combineEditorApps(title, apps)` - a handler that mounts each application at
160
+ `/<id>/`, the `base` it was made with, and answers `/` with the editor whose
161
+ plugins are all of them and `/modules/...` with the modules of them all.
162
+ - `editorPage({ title, apps, modules, style? })` - the editor page: the import
163
+ map of `modules`, an `asljs-editor` and `mountEditorApps` of the applications
164
+ whose `/_/app.json` URLs are `apps`, and `style`; the editor adds its own
165
+ style, `EDITOR_STYLE` of `asljs-ui-editor`, when it mounts.
166
+ - `serveApp(app, { io, cwd, port?, host?, loggerProvider })` - serves an
167
+ `EditorApp`, prints `Serving <cwd> at <url>`, waits until SIGINT or SIGTERM,
168
+ and closes the application.
169
+
170
+ ## Browser modules
171
+
172
+ A page served by `startServer` can import installed packages, such as
173
+ `asljs-ui-diagram`, without a bundler.
174
+
175
+ - `findBrowserModules(name, from)` - the package `name`, or each package of an
176
+ array of names, looked up from the folder `from`, and every package it depends
177
+ on at runtime, each a `BrowserModule`: its `name`, its folder `root`, and its
178
+ ES module `entry`, picked from the `browser`, `import`, `module` and `default`
179
+ conditions of `exports`, else `module`, else `main`, else `index.js`, and its
180
+ `subpaths`, the module of each other subpath of `exports`, e.g. `wiki` of
181
+ `asljs-kb/wiki`, a pattern with `*` left out. It throws for a package it
182
+ cannot find.
183
+ - `createImportMap(modules, prefix)` - the import map that points each name at
184
+ `<prefix><name>/<entry>`, each `<name>/<subpath>` at its module, and `<name>/`
185
+ at `<prefix><name>/`, for a module that imports a file of a package, as lit
186
+ imports `lit/decorators.js`. Pass it to `startServer` as `modules` and put the
187
+ map, with `MODULES_PREFIX`, in a `<script type="importmap">` of the page.
188
+ - `findModuleFile(rest, modules)` - the file of a module that a path after
189
+ `MODULES_PREFIX` names, or `null` for an unknown module or a path that leaves
190
+ its folder.
191
+
192
+ [CFG]: ../../../docs/Configuration.md
193
+ [CMB]: ../../cmdbase/docs/cmdbase.md
package/package.json CHANGED
@@ -1,6 +1,74 @@
1
1
  {
2
2
  "name": "asljs-appbase",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.5",
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
+ "!dist/*.tsbuildinfo"
23
+ ],
24
+ "scripts": {
25
+ "flint": "toolkit flint",
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",
31
+ "typecheck": "npm run codegen --if-present && tsc -p tsconfig.build.json --noEmit",
32
+ "guard:clean-git": "toolkit ensure-clean-working-directory",
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",
34
+ "postpublish": "toolkit tag-release-revision",
35
+ "test": "node --test --enable-source-maps \"build/**/*.test.js\"",
36
+ "test:watch": "node --watch --test \"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\"",
38
+ "release:patch": "toolkit release-patch",
39
+ "build": "npm run clean:build && npm run flint && npm run typecheck && npm run compile:build && npm run test"
40
+ },
41
+ "distDependencies": [
42
+ "asljs-agents",
43
+ "asljs-cmdbase",
44
+ "asljs-locator",
45
+ "asljs-logging",
46
+ "asljs-tmpdir"
47
+ ],
48
+ "keywords": [
49
+ "markdown",
50
+ "cli"
51
+ ],
52
+ "homepage": "https://github.com/AlexandriteSoftware/asljs#readme",
53
+ "bugs": {
54
+ "url": "https://github.com/AlexandriteSoftware/asljs/issues"
55
+ },
56
+ "repository": {
57
+ "type": "git",
58
+ "url": "git+https://github.com/AlexandriteSoftware/asljs.git"
59
+ },
60
+ "author": "\"Alex Netkachov\" <alex.netkachov@gmail.com>",
61
+ "license": "SEE LICENSE IN LICENSE.md",
62
+ "dependencies": {
63
+ "asljs-agents": "^0.1.0",
64
+ "asljs-cmdbase": "^0.1.0",
65
+ "asljs-locator": "^0.1.0",
66
+ "asljs-logging": "^0.1.2",
67
+ "remark-parse": "^11.0.0",
68
+ "unified": "^11.0.5"
69
+ },
70
+ "devDependencies": {
71
+ "asljs-tmpdir": "^0.1.13",
72
+ "asljs-toolkit": "^0.1.0"
73
+ }
74
+ }