datanotes 0.0.0-stage → 1.1.0
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 +202 -0
- package/NOTICE +4 -0
- package/README.md +65 -2
- package/SECURITY.md +51 -0
- package/dist/api/catalog.d.ts +19 -0
- package/dist/api/client.d.ts +100 -0
- package/dist/api/index.cjs +3161 -0
- package/dist/api/index.d.ts +9 -0
- package/dist/api/index.js +3138 -0
- package/dist/api/local.cjs +68 -0
- package/dist/api/local.d.ts +31 -0
- package/dist/api/local.js +31 -0
- package/dist/api/requests.d.ts +28 -0
- package/dist/api/results.d.ts +15 -0
- package/dist/api/tokens.d.ts +7 -0
- package/dist/datanotes.cjs +22272 -0
- package/package.json +81 -4
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/api/local.ts
|
|
31
|
+
var local_exports = {};
|
|
32
|
+
__export(local_exports, {
|
|
33
|
+
LOCK_STALE_MS: () => LOCK_STALE_MS,
|
|
34
|
+
localEngine: () => localEngine,
|
|
35
|
+
vaultSettingsPath: () => vaultSettingsPath
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(local_exports);
|
|
38
|
+
var import_node_fs = __toESM(require("node:fs"), 1);
|
|
39
|
+
var import_node_os = __toESM(require("node:os"), 1);
|
|
40
|
+
var import_node_path = __toESM(require("node:path"), 1);
|
|
41
|
+
var LOCK_STALE_MS = 3e4;
|
|
42
|
+
function vaultSettingsPath(vault) {
|
|
43
|
+
const plugin = import_node_path.default.join(vault, ".obsidian", "plugins", "datanotes", "data.json");
|
|
44
|
+
return import_node_fs.default.existsSync(plugin) ? plugin : import_node_path.default.join(vault, ".datanotes", "service.json");
|
|
45
|
+
}
|
|
46
|
+
function readJson(file) {
|
|
47
|
+
try {
|
|
48
|
+
return JSON.parse(import_node_fs.default.readFileSync(file, "utf8"));
|
|
49
|
+
} catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function localEngine(vault, opts = {}) {
|
|
54
|
+
const settings = readJson(opts.settingsFile ?? vaultSettingsPath(vault)) ?? {};
|
|
55
|
+
const store = typeof settings.storeFolder === "string" && settings.storeFolder ? settings.storeFolder : ".datanotes";
|
|
56
|
+
const lock = readJson(import_node_path.default.join(vault, store.replace(/\/+$/, ""), "engine.lock"));
|
|
57
|
+
if (!lock || (opts.now ?? Date.now()) - Date.parse(lock.heartbeat) >= LOCK_STALE_MS) return null;
|
|
58
|
+
if (lock.host !== import_node_os.default.hostname()) throw new Error(`the vault is held by an engine on ${lock.host}; connect to it by its address`);
|
|
59
|
+
const token = typeof settings.httpServerToken === "string" ? settings.httpServerToken : "";
|
|
60
|
+
if (!token) return null;
|
|
61
|
+
return { url: `http://${opts.host ?? "127.0.0.1"}:${lock.port}`, token, lock };
|
|
62
|
+
}
|
|
63
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
64
|
+
0 && (module.exports = {
|
|
65
|
+
LOCK_STALE_MS,
|
|
66
|
+
localEngine,
|
|
67
|
+
vaultSettingsPath
|
|
68
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Find the engine running on a vault of this machine (Node only): its address and the owner's
|
|
3
|
+
* token, read from the vault's settings and from the lock the engine holds while it runs.
|
|
4
|
+
*/
|
|
5
|
+
/** The lock an engine writes in its store folder (`<vault>/.datanotes/engine.lock`). */
|
|
6
|
+
export interface EngineLock {
|
|
7
|
+
kind: "service" | "plugin";
|
|
8
|
+
pid: number;
|
|
9
|
+
host: string;
|
|
10
|
+
port: number;
|
|
11
|
+
startedAt: string;
|
|
12
|
+
heartbeat: string;
|
|
13
|
+
}
|
|
14
|
+
/** A lock whose heartbeat is older than this belongs to an engine that stopped. */
|
|
15
|
+
export declare const LOCK_STALE_MS = 30000;
|
|
16
|
+
export interface LocalEngine {
|
|
17
|
+
url: string;
|
|
18
|
+
token: string;
|
|
19
|
+
lock: EngineLock;
|
|
20
|
+
}
|
|
21
|
+
/** The settings file of a vault: the Obsidian plugin's when present, else the service's. */
|
|
22
|
+
export declare function vaultSettingsPath(vault: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* The engine holding `vault`, or null when none runs. Throws when the lock is fresh but held on
|
|
25
|
+
* another machine (a synced or shared folder): that engine is not reachable from here.
|
|
26
|
+
*/
|
|
27
|
+
export declare function localEngine(vault: string, opts?: {
|
|
28
|
+
settingsFile?: string;
|
|
29
|
+
host?: string;
|
|
30
|
+
now?: number;
|
|
31
|
+
}): LocalEngine | null;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// src/api/local.ts
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
var LOCK_STALE_MS = 3e4;
|
|
6
|
+
function vaultSettingsPath(vault) {
|
|
7
|
+
const plugin = path.join(vault, ".obsidian", "plugins", "datanotes", "data.json");
|
|
8
|
+
return fs.existsSync(plugin) ? plugin : path.join(vault, ".datanotes", "service.json");
|
|
9
|
+
}
|
|
10
|
+
function readJson(file) {
|
|
11
|
+
try {
|
|
12
|
+
return JSON.parse(fs.readFileSync(file, "utf8"));
|
|
13
|
+
} catch {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function localEngine(vault, opts = {}) {
|
|
18
|
+
const settings = readJson(opts.settingsFile ?? vaultSettingsPath(vault)) ?? {};
|
|
19
|
+
const store = typeof settings.storeFolder === "string" && settings.storeFolder ? settings.storeFolder : ".datanotes";
|
|
20
|
+
const lock = readJson(path.join(vault, store.replace(/\/+$/, ""), "engine.lock"));
|
|
21
|
+
if (!lock || (opts.now ?? Date.now()) - Date.parse(lock.heartbeat) >= LOCK_STALE_MS) return null;
|
|
22
|
+
if (lock.host !== os.hostname()) throw new Error(`the vault is held by an engine on ${lock.host}; connect to it by its address`);
|
|
23
|
+
const token = typeof settings.httpServerToken === "string" ? settings.httpServerToken : "";
|
|
24
|
+
if (!token) return null;
|
|
25
|
+
return { url: `http://${opts.host ?? "127.0.0.1"}:${lock.port}`, token, lock };
|
|
26
|
+
}
|
|
27
|
+
export {
|
|
28
|
+
LOCK_STALE_MS,
|
|
29
|
+
localEngine,
|
|
30
|
+
vaultSettingsPath
|
|
31
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The HTTP request behind each operation of the catalogue (`catalog.ts`): most are
|
|
3
|
+
* `POST /datanotes/<route>` with a JSON body built from the operation's arguments (renamed where
|
|
4
|
+
* the route names them differently); the note operations read the vault routes.
|
|
5
|
+
*/
|
|
6
|
+
type Args = Record<string, unknown>;
|
|
7
|
+
export declare class OperationInputError extends Error {
|
|
8
|
+
readonly name = "OperationInputError";
|
|
9
|
+
}
|
|
10
|
+
export declare const ROUTE_PREFIX = "/datanotes";
|
|
11
|
+
export interface OperationRequest {
|
|
12
|
+
method: "GET" | "POST";
|
|
13
|
+
/** Path from the server root, query string included. */
|
|
14
|
+
path: string;
|
|
15
|
+
body?: unknown;
|
|
16
|
+
/** Accept header, when the route answers in more than one format. */
|
|
17
|
+
accept?: string;
|
|
18
|
+
}
|
|
19
|
+
/** The request for an operation and its arguments; throws OperationInputError on bad arguments. */
|
|
20
|
+
export declare function operationRequest(name: string, args?: Args): OperationRequest;
|
|
21
|
+
/** Operations this module can build a request for (to check the catalogue against). */
|
|
22
|
+
export declare const CALLABLE_OPERATIONS: Set<string>;
|
|
23
|
+
/** The route an operation calls (without the prefix) and the body fields it fixes (e.g. `op` for DDL), or null. */
|
|
24
|
+
export declare function operationRoute(name: string): {
|
|
25
|
+
path: string;
|
|
26
|
+
fixed: Args;
|
|
27
|
+
} | null;
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What an operation returned, for its caller: the value of a success, or an agent-readable text
|
|
3
|
+
* for a refusal (what was refused; nothing was written) or an error.
|
|
4
|
+
*/
|
|
5
|
+
/** Agent-readable summary of conflicts / violations / failures in a refused result. */
|
|
6
|
+
export declare function describeRefusal(data: Record<string, unknown>): string;
|
|
7
|
+
/** Agent-readable summary of a refused batch: the failing operation and the rollback. */
|
|
8
|
+
export declare function describeBatch(data: Record<string, unknown>): string;
|
|
9
|
+
export interface OperationResult {
|
|
10
|
+
ok: boolean;
|
|
11
|
+
/** The result (JSON, or the text of a note) or, when `ok` is false, the reason. */
|
|
12
|
+
value: unknown;
|
|
13
|
+
}
|
|
14
|
+
/** The result of an HTTP answer: `json` when the body was JSON, else its `text`. */
|
|
15
|
+
export declare function resultOf(status: number, json: unknown, text: string): OperationResult;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A tokenizer-free estimate of how many tokens a text costs a model: words count about one token
|
|
3
|
+
* per 4 letters, numbers one per 3 digits, every other symbol (JSON punctuation, quotes, …) one.
|
|
4
|
+
* Close to real tokenizers on JSON and on Italian/English prose (within ~15%); good for telling
|
|
5
|
+
* which tools and sessions fill the context, not for billing.
|
|
6
|
+
*/
|
|
7
|
+
export declare function estimateTokens(text: string): number;
|