@fedify/cli 1.8.12 → 2.0.0-dev.1757
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/deno.json +72 -0
- package/dist/cache.js +17 -0
- package/dist/deno.js +72 -0
- package/dist/docloader.js +52 -0
- package/dist/globals.js +49 -0
- package/dist/imagerenderer.js +105 -0
- package/dist/inbox/rendercode.js +57 -0
- package/dist/inbox/view.js +508 -0
- package/dist/inbox.js +315 -0
- package/dist/init/action/configs.js +81 -0
- package/dist/init/action/deps.js +52 -0
- package/dist/init/action/dir.js +16 -0
- package/dist/init/action/env.js +13 -0
- package/dist/init/action/install.js +22 -0
- package/dist/init/action/mod.js +39 -0
- package/dist/init/action/notice.js +62 -0
- package/dist/init/action/patch.js +141 -0
- package/dist/init/action/precommand.js +23 -0
- package/dist/init/action/recommend.js +24 -0
- package/dist/init/action/set.js +31 -0
- package/dist/init/action/templates.js +57 -0
- package/dist/init/action/utils.js +50 -0
- package/dist/init/ask/dir.js +82 -0
- package/dist/init/ask/kv.js +33 -0
- package/dist/init/ask/mod.js +16 -0
- package/dist/init/ask/mq.js +33 -0
- package/dist/init/ask/pm.js +49 -0
- package/dist/init/ask/wf.js +29 -0
- package/dist/init/command.js +25 -0
- package/dist/init/const.js +31 -0
- package/dist/init/json/biome.js +24 -0
- package/dist/init/json/kv.js +53 -0
- package/dist/init/json/mq.js +72 -0
- package/dist/init/json/pm.js +44 -0
- package/dist/init/json/rt.js +39 -0
- package/dist/init/json/vscode-settings-for-deno.js +53 -0
- package/dist/init/json/vscode-settings.js +49 -0
- package/dist/init/lib.js +129 -0
- package/dist/init/mod.js +5 -0
- package/dist/init/webframeworks.js +133 -0
- package/dist/kv.bun.js +17 -0
- package/dist/kv.node.js +17 -0
- package/dist/log.js +52 -0
- package/dist/lookup.js +287 -0
- package/dist/mod.js +34 -0
- package/dist/nodeinfo.js +261 -0
- package/dist/table.js +24 -0
- package/dist/tempserver.js +71 -0
- package/dist/tunnel.js +21 -0
- package/dist/utils.js +67 -0
- package/dist/webfinger/action.js +44 -0
- package/dist/webfinger/command.js +20 -0
- package/dist/webfinger/error.js +47 -0
- package/dist/webfinger/lib.js +45 -0
- package/dist/webfinger/mod.js +5 -0
- package/package.json +64 -24
- package/scripts/pack.ts +64 -0
- package/src/cache.ts +17 -0
- package/src/docloader.ts +67 -0
- package/src/globals.ts +43 -0
- package/src/imagerenderer.ts +149 -0
- package/src/inbox/entry.ts +10 -0
- package/src/inbox/rendercode.ts +68 -0
- package/src/inbox/view.tsx +598 -0
- package/src/inbox.tsx +535 -0
- package/src/init/action/configs.ts +88 -0
- package/src/init/action/deps.ts +93 -0
- package/src/init/action/dir.ts +11 -0
- package/src/init/action/env.ts +14 -0
- package/src/init/action/install.ts +59 -0
- package/src/init/action/mod.ts +66 -0
- package/src/init/action/notice.ts +101 -0
- package/src/init/action/patch.ts +212 -0
- package/src/init/action/precommand.ts +22 -0
- package/src/init/action/recommend.ts +38 -0
- package/src/init/action/set.ts +78 -0
- package/src/init/action/templates.ts +95 -0
- package/src/init/action/utils.ts +64 -0
- package/src/init/ask/dir.ts +98 -0
- package/src/init/ask/kv.ts +39 -0
- package/src/init/ask/mod.ts +23 -0
- package/src/init/ask/mq.ts +37 -0
- package/src/init/ask/pm.ts +58 -0
- package/src/init/ask/wf.ts +27 -0
- package/src/init/command.ts +64 -0
- package/src/init/const.ts +4 -0
- package/src/init/json/biome.json +17 -0
- package/src/init/json/kv.json +39 -0
- package/src/init/json/mq.json +95 -0
- package/src/init/json/pm.json +47 -0
- package/src/init/json/rt.json +42 -0
- package/src/init/json/vscode-settings-for-deno.json +43 -0
- package/src/init/json/vscode-settings.json +41 -0
- package/src/init/lib.ts +220 -0
- package/src/init/mod.ts +2 -0
- package/src/init/templates/defaults/federation.ts.tpl +23 -0
- package/src/init/templates/defaults/logging.ts.tpl +23 -0
- package/src/init/templates/express/app.ts.tpl +16 -0
- package/src/init/templates/express/index.ts.tpl +6 -0
- package/src/init/templates/hono/app.tsx.tpl +14 -0
- package/src/init/templates/hono/index/bun.ts.tpl +10 -0
- package/src/init/templates/hono/index/deno.ts.tpl +13 -0
- package/src/init/templates/hono/index/node.ts.tpl +14 -0
- package/src/init/templates/next/middleware.ts.tpl +45 -0
- package/src/init/templates/nitro/nitro.config.ts.tpl +5 -0
- package/src/init/templates/nitro/server/error.ts.tpl +3 -0
- package/src/init/templates/nitro/server/middleware/federation.ts.tpl +8 -0
- package/src/init/types.ts +88 -0
- package/src/init/webframeworks.ts +151 -0
- package/src/kv.bun.ts +12 -0
- package/src/kv.node.ts +11 -0
- package/src/log.ts +64 -0
- package/src/lookup.test.ts +182 -0
- package/src/lookup.ts +558 -0
- package/src/mod.ts +45 -0
- package/src/nodeinfo.test.ts +229 -0
- package/src/nodeinfo.ts +447 -0
- package/src/table.ts +17 -0
- package/src/tempserver.ts +87 -0
- package/src/tunnel.ts +32 -0
- package/src/utils.ts +136 -0
- package/src/webfinger/action.ts +50 -0
- package/src/webfinger/command.ts +59 -0
- package/src/webfinger/error.ts +47 -0
- package/src/webfinger/lib.ts +37 -0
- package/src/webfinger/mod.test.ts +79 -0
- package/src/webfinger/mod.ts +2 -0
- package/tsdown.config.ts +24 -0
- package/src/install.mjs +0 -189
- package/src/run.mjs +0 -22
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { pipe } from "@fxts/core";
|
|
2
|
+
import { replace } from "../utils.ts";
|
|
3
|
+
import { PACKAGE_MANAGER } from "./const.ts";
|
|
4
|
+
import {
|
|
5
|
+
getInstruction,
|
|
6
|
+
getNextInitCommand,
|
|
7
|
+
getNitroInitCommand,
|
|
8
|
+
PACKAGE_VERSION,
|
|
9
|
+
readTemplate,
|
|
10
|
+
} from "./lib.ts";
|
|
11
|
+
import type { WebFrameworks } from "./types.ts";
|
|
12
|
+
|
|
13
|
+
const webFrameworks: WebFrameworks = {
|
|
14
|
+
hono: {
|
|
15
|
+
label: "Hono",
|
|
16
|
+
packageManagers: PACKAGE_MANAGER,
|
|
17
|
+
init: (projectName, pm) => ({
|
|
18
|
+
dependencies: pm === "deno"
|
|
19
|
+
? {
|
|
20
|
+
"@std/dotenv": "^0.225.2",
|
|
21
|
+
"@hono/hono": "^4.5.0",
|
|
22
|
+
"@hongminhee/x-forwarded-fetch": "^0.2.0",
|
|
23
|
+
}
|
|
24
|
+
: pm === "bun"
|
|
25
|
+
? { hono: "^4.5.0", "x-forwarded-fetch": "^0.2.0" }
|
|
26
|
+
: {
|
|
27
|
+
"@dotenvx/dotenvx": "^1.14.1",
|
|
28
|
+
hono: "^4.5.0",
|
|
29
|
+
"@hono/node-server": "^1.12.0",
|
|
30
|
+
tsx: "^4.17.0",
|
|
31
|
+
"x-forwarded-fetch": "^0.2.0",
|
|
32
|
+
},
|
|
33
|
+
devDependencies: pm === "bun" ? { "@types/bun": "^1.1.6" } : {},
|
|
34
|
+
federationFile: "src/federation.ts",
|
|
35
|
+
loggingFile: "src/logging.ts",
|
|
36
|
+
files: {
|
|
37
|
+
"src/app.tsx": pipe(
|
|
38
|
+
"hono/app.tsx",
|
|
39
|
+
readTemplate,
|
|
40
|
+
replace(
|
|
41
|
+
/\/\* hono \*\//,
|
|
42
|
+
pm === "deno" ? "@hono/hono" : "hono",
|
|
43
|
+
),
|
|
44
|
+
)
|
|
45
|
+
.replace(/\/\* logger \*\//, projectName),
|
|
46
|
+
"src/index.ts": readTemplate(`hono/index/${pm}.ts`),
|
|
47
|
+
},
|
|
48
|
+
compilerOptions: pm === "deno" ? undefined : {
|
|
49
|
+
"lib": ["ESNext", "DOM"],
|
|
50
|
+
"target": "ESNext",
|
|
51
|
+
"module": "NodeNext",
|
|
52
|
+
"moduleResolution": "NodeNext",
|
|
53
|
+
"allowImportingTsExtensions": true,
|
|
54
|
+
"verbatimModuleSyntax": true,
|
|
55
|
+
"noEmit": true,
|
|
56
|
+
"strict": true,
|
|
57
|
+
"jsx": "react-jsx",
|
|
58
|
+
"jsxImportSource": "hono/jsx",
|
|
59
|
+
},
|
|
60
|
+
tasks: {
|
|
61
|
+
"dev": pm === "deno"
|
|
62
|
+
? "deno run -A --watch ./src/index.ts"
|
|
63
|
+
: pm === "bun"
|
|
64
|
+
? "bun run --hot ./src/index.ts"
|
|
65
|
+
: "dotenvx run -- tsx watch ./src/index.ts",
|
|
66
|
+
"prod": pm === "deno"
|
|
67
|
+
? "deno run -A ./src/index.ts"
|
|
68
|
+
: pm === "bun"
|
|
69
|
+
? "bun run ./src/index.ts"
|
|
70
|
+
: "dotenvx run -- node --import tsx ./src/index.ts",
|
|
71
|
+
},
|
|
72
|
+
instruction: getInstruction(pm),
|
|
73
|
+
}),
|
|
74
|
+
},
|
|
75
|
+
express: {
|
|
76
|
+
label: "Express",
|
|
77
|
+
packageManagers: ["bun", "npm", "yarn", "pnpm"] as const,
|
|
78
|
+
init: (projectName, pm) => ({
|
|
79
|
+
dependencies: {
|
|
80
|
+
express: "^4.19.2",
|
|
81
|
+
"@fedify/express": PACKAGE_VERSION,
|
|
82
|
+
...(pm !== "deno" && pm !== "bun"
|
|
83
|
+
? { "@dotenvx/dotenvx": "^1.14.1", tsx: "^4.17.0" }
|
|
84
|
+
: {}),
|
|
85
|
+
},
|
|
86
|
+
devDependencies: {
|
|
87
|
+
"@types/express": "^4.17.21",
|
|
88
|
+
...(pm === "bun" ? { "@types/bun": "^1.1.6" } : {}),
|
|
89
|
+
},
|
|
90
|
+
federationFile: "src/federation.ts",
|
|
91
|
+
loggingFile: "src/logging.ts",
|
|
92
|
+
files: {
|
|
93
|
+
"src/app.ts": readTemplate("express/app.ts")
|
|
94
|
+
.replace(/\/\* logger \*\//, projectName),
|
|
95
|
+
"src/index.ts": readTemplate("express/index.ts"),
|
|
96
|
+
},
|
|
97
|
+
compilerOptions: pm === "deno" ? undefined : {
|
|
98
|
+
"lib": ["ESNext", "DOM"],
|
|
99
|
+
"target": "ESNext",
|
|
100
|
+
"module": "NodeNext",
|
|
101
|
+
"moduleResolution": "NodeNext",
|
|
102
|
+
"allowImportingTsExtensions": true,
|
|
103
|
+
"verbatimModuleSyntax": true,
|
|
104
|
+
"noEmit": true,
|
|
105
|
+
"strict": true,
|
|
106
|
+
},
|
|
107
|
+
tasks: {
|
|
108
|
+
"dev": pm === "bun"
|
|
109
|
+
? "bun run --hot ./src/index.ts"
|
|
110
|
+
: "dotenvx run -- tsx watch ./src/index.ts",
|
|
111
|
+
"prod": pm === "bun"
|
|
112
|
+
? "bun run ./src/index.ts"
|
|
113
|
+
: "dotenvx run -- node --import tsx ./src/index.ts",
|
|
114
|
+
},
|
|
115
|
+
instruction: getInstruction(pm),
|
|
116
|
+
}),
|
|
117
|
+
},
|
|
118
|
+
nitro: {
|
|
119
|
+
label: "Nitro",
|
|
120
|
+
packageManagers: PACKAGE_MANAGER,
|
|
121
|
+
init: (_, pm) => ({
|
|
122
|
+
command: getNitroInitCommand(pm),
|
|
123
|
+
dependencies: { "@fedify/h3": PACKAGE_VERSION },
|
|
124
|
+
federationFile: "server/federation.ts",
|
|
125
|
+
loggingFile: "server/logging.ts",
|
|
126
|
+
files: {
|
|
127
|
+
"server/middleware/federation.ts": readTemplate(
|
|
128
|
+
"nitro/server/middleware/federation.ts",
|
|
129
|
+
),
|
|
130
|
+
"server/error.ts": readTemplate("nitro/server/error.ts"),
|
|
131
|
+
"nitro.config.ts": readTemplate("nitro/nitro.config.ts"),
|
|
132
|
+
},
|
|
133
|
+
instruction: getInstruction(pm),
|
|
134
|
+
}),
|
|
135
|
+
},
|
|
136
|
+
next: {
|
|
137
|
+
label: "Next.js",
|
|
138
|
+
packageManagers: PACKAGE_MANAGER,
|
|
139
|
+
init: (_, pm) => ({
|
|
140
|
+
label: "Next.js",
|
|
141
|
+
command: getNextInitCommand(pm),
|
|
142
|
+
dependencies: { "@fedify/next": PACKAGE_VERSION },
|
|
143
|
+
devDependencies: { "@types/node": "^20.11.2" },
|
|
144
|
+
federationFile: "federation/index.ts",
|
|
145
|
+
loggingFile: "logging.ts",
|
|
146
|
+
files: { "middleware.ts": readTemplate("next/middleware.ts") },
|
|
147
|
+
instruction: getInstruction(pm),
|
|
148
|
+
}),
|
|
149
|
+
},
|
|
150
|
+
} as const;
|
|
151
|
+
export default webFrameworks;
|
package/src/kv.bun.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { KvStore } from "@fedify/fedify/federation";
|
|
2
|
+
import { SqliteKvStore } from "@fedify/sqlite";
|
|
3
|
+
import { Database } from "bun:sqlite";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import type { DatabaseSync } from "node:sqlite";
|
|
6
|
+
import { getCacheDir } from "./cache.ts";
|
|
7
|
+
|
|
8
|
+
export async function getKvStore(): Promise<KvStore> {
|
|
9
|
+
const path = join(await getCacheDir(), "sqlite");
|
|
10
|
+
const sqlite = new Database(path);
|
|
11
|
+
return new SqliteKvStore(sqlite as unknown as DatabaseSync);
|
|
12
|
+
}
|
package/src/kv.node.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { KvStore } from "@fedify/fedify/federation";
|
|
2
|
+
import { SqliteKvStore } from "@fedify/sqlite";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { DatabaseSync } from "node:sqlite";
|
|
5
|
+
import { getCacheDir } from "./cache.ts";
|
|
6
|
+
|
|
7
|
+
export async function getKvStore(): Promise<KvStore> {
|
|
8
|
+
const path = join(await getCacheDir(), "sqlite");
|
|
9
|
+
const sqlite = new DatabaseSync(path);
|
|
10
|
+
return new SqliteKvStore(sqlite);
|
|
11
|
+
}
|
package/src/log.ts
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { getFileSink } from "@logtape/file";
|
|
2
|
+
import {
|
|
3
|
+
configure,
|
|
4
|
+
getConsoleSink,
|
|
5
|
+
type LogRecord,
|
|
6
|
+
type Sink,
|
|
7
|
+
} from "@logtape/logtape";
|
|
8
|
+
import { dirname } from "node:path";
|
|
9
|
+
import process from "node:process";
|
|
10
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
11
|
+
import { mkdir } from "node:fs/promises";
|
|
12
|
+
|
|
13
|
+
export interface RecordingSink extends Sink {
|
|
14
|
+
startRecording(): void;
|
|
15
|
+
stopRecording(): void;
|
|
16
|
+
getRecords(): LogRecord[];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function getRecordingSink(): RecordingSink {
|
|
20
|
+
let records: LogRecord[] = [];
|
|
21
|
+
let recording = false;
|
|
22
|
+
const sink: RecordingSink = (record: LogRecord) => {
|
|
23
|
+
if (recording) records.push(record);
|
|
24
|
+
};
|
|
25
|
+
sink.startRecording = () => {
|
|
26
|
+
records = [];
|
|
27
|
+
recording = true;
|
|
28
|
+
};
|
|
29
|
+
sink.stopRecording = () => {
|
|
30
|
+
recording = false;
|
|
31
|
+
};
|
|
32
|
+
sink.getRecords = () => [...records];
|
|
33
|
+
return sink;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const recordingSink = getRecordingSink();
|
|
37
|
+
|
|
38
|
+
export const logFile = process.env["FEDIFY_LOG_FILE"];
|
|
39
|
+
if (logFile != null) {
|
|
40
|
+
await mkdir(dirname(logFile), { recursive: true });
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
await configure({
|
|
44
|
+
sinks: {
|
|
45
|
+
console: getConsoleSink(),
|
|
46
|
+
recording: recordingSink,
|
|
47
|
+
file: logFile == null ? () => undefined : getFileSink(logFile),
|
|
48
|
+
},
|
|
49
|
+
filters: {},
|
|
50
|
+
loggers: [
|
|
51
|
+
{
|
|
52
|
+
category: "fedify",
|
|
53
|
+
lowestLevel: "debug",
|
|
54
|
+
sinks: ["recording", "file"],
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
category: ["logtape", "meta"],
|
|
58
|
+
lowestLevel: "warning",
|
|
59
|
+
sinks: ["console", "file"],
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
contextLocalStorage: new AsyncLocalStorage(),
|
|
63
|
+
reset: true,
|
|
64
|
+
});
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { Activity, Note } from "@fedify/fedify";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import test from "node:test";
|
|
4
|
+
import { mkdir, readFile, rm } from "node:fs/promises";
|
|
5
|
+
import { getContextLoader } from "./docloader.ts";
|
|
6
|
+
import {
|
|
7
|
+
clearTimeoutSignal,
|
|
8
|
+
createTimeoutSignal,
|
|
9
|
+
TimeoutError,
|
|
10
|
+
writeObjectToStream,
|
|
11
|
+
} from "./lookup.ts";
|
|
12
|
+
|
|
13
|
+
test("writeObjectToStream - writes Note object with default options", async () => {
|
|
14
|
+
const testDir = "./test_output_note";
|
|
15
|
+
const testFile = `${testDir}/note.txt`;
|
|
16
|
+
|
|
17
|
+
await mkdir(testDir, { recursive: true });
|
|
18
|
+
|
|
19
|
+
const note = new Note({
|
|
20
|
+
id: new URL("https://example.com/notes/1"),
|
|
21
|
+
content: "Hello, fediverse!",
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const contextLoader = await getContextLoader({});
|
|
25
|
+
await writeObjectToStream(note, testFile, undefined, contextLoader);
|
|
26
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
27
|
+
|
|
28
|
+
const content = await readFile(testFile, { encoding: "utf8" });
|
|
29
|
+
|
|
30
|
+
assert.ok(content);
|
|
31
|
+
assert.match(content, /Hello, fediverse!/);
|
|
32
|
+
assert.match(content, /id/);
|
|
33
|
+
|
|
34
|
+
await rm(testDir, { recursive: true });
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test("writeObjectToStream - writes Activity object in raw JSON-LD format", async () => {
|
|
38
|
+
const testDir = "./test_output_activity";
|
|
39
|
+
const testFile = `${testDir}/raw.json`;
|
|
40
|
+
|
|
41
|
+
await mkdir(testDir, { recursive: true });
|
|
42
|
+
|
|
43
|
+
const activity = new Activity({
|
|
44
|
+
id: new URL("https://example.com/activities/1"),
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const contextLoader = await getContextLoader({});
|
|
48
|
+
await writeObjectToStream(activity, testFile, "raw", contextLoader);
|
|
49
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
50
|
+
|
|
51
|
+
// Verify file exists and contains JSON-LD
|
|
52
|
+
const content = await readFile(testFile);
|
|
53
|
+
|
|
54
|
+
assert.ok(content);
|
|
55
|
+
assert.ok(content.includes("@context"));
|
|
56
|
+
assert.ok(content.includes("id"));
|
|
57
|
+
|
|
58
|
+
await rm(testDir, { recursive: true });
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test("writeObjectToStream - writes object in compact JSON-LD format", async () => {
|
|
62
|
+
const testDir = "./test_output_compact";
|
|
63
|
+
const testFile = `${testDir}/compact.json`;
|
|
64
|
+
|
|
65
|
+
await mkdir(testDir, { recursive: true });
|
|
66
|
+
|
|
67
|
+
const note = new Note({
|
|
68
|
+
id: new URL("https://example.com/notes/1"),
|
|
69
|
+
content: "Test note",
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const contextLoader = await getContextLoader({});
|
|
73
|
+
await writeObjectToStream(note, testFile, "compact", contextLoader);
|
|
74
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
75
|
+
|
|
76
|
+
// Verify file exists and contains compacted JSON-LD
|
|
77
|
+
const content = await readFile(testFile);
|
|
78
|
+
assert.ok(content);
|
|
79
|
+
assert.ok(content.includes("Test note"));
|
|
80
|
+
|
|
81
|
+
await rm(testDir, { recursive: true });
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test("writeObjectToStream - writes object in expanded JSON-LD format", async () => {
|
|
85
|
+
const testDir = "./test_output_expand";
|
|
86
|
+
const testFile = `${testDir}/expand.json`;
|
|
87
|
+
|
|
88
|
+
await mkdir(testDir, { recursive: true });
|
|
89
|
+
|
|
90
|
+
const note = new Note({
|
|
91
|
+
id: new URL("https://example.com/notes/1"),
|
|
92
|
+
content: "Test note for expansion",
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
const contextLoader = await getContextLoader({});
|
|
96
|
+
await writeObjectToStream(note, testFile, "expand", contextLoader);
|
|
97
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
98
|
+
|
|
99
|
+
const content = await readFile(testFile);
|
|
100
|
+
assert.ok(content);
|
|
101
|
+
assert.ok(content.includes("Test note for expansion"));
|
|
102
|
+
|
|
103
|
+
await rm(testDir, { recursive: true });
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
test("writeObjectToStream - writes to stdout when no output file specified", async () => {
|
|
107
|
+
const note = new Note({
|
|
108
|
+
id: new URL("https://example.com/notes/1"),
|
|
109
|
+
content: "Test stdout note",
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const contextLoader = await getContextLoader({});
|
|
113
|
+
|
|
114
|
+
await writeObjectToStream(note, undefined, undefined, contextLoader);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test("writeObjectToStream - handles empty content properly", async () => {
|
|
118
|
+
const testDir = "./test_output_empty";
|
|
119
|
+
const testFile = `${testDir}/empty.txt`;
|
|
120
|
+
|
|
121
|
+
await mkdir(testDir, { recursive: true });
|
|
122
|
+
|
|
123
|
+
const note = new Note({
|
|
124
|
+
id: new URL("https://example.com/notes/1"),
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
const contextLoader = await getContextLoader({});
|
|
128
|
+
|
|
129
|
+
await writeObjectToStream(note, testFile, undefined, contextLoader);
|
|
130
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
131
|
+
|
|
132
|
+
const content = await readFile(testFile);
|
|
133
|
+
assert.ok(content);
|
|
134
|
+
assert.ok(content.includes("Note"));
|
|
135
|
+
|
|
136
|
+
await rm(testDir, { recursive: true });
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test("createTimeoutSignal - returns undefined when no timeout specified", () => {
|
|
140
|
+
const signal = createTimeoutSignal();
|
|
141
|
+
assert.strictEqual(signal, undefined);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test("createTimeoutSignal - returns undefined when timeout is null", () => {
|
|
145
|
+
const signal = createTimeoutSignal(undefined);
|
|
146
|
+
assert.strictEqual(signal, undefined);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
test("createTimeoutSignal - creates AbortSignal that aborts after timeout", async () => {
|
|
150
|
+
const signal = createTimeoutSignal(0.1);
|
|
151
|
+
assert.ok(signal);
|
|
152
|
+
assert.ok(!signal.aborted);
|
|
153
|
+
|
|
154
|
+
await new Promise((resolve) => setTimeout(resolve, 150));
|
|
155
|
+
|
|
156
|
+
assert.ok(signal.aborted);
|
|
157
|
+
assert.ok(signal.reason instanceof TimeoutError);
|
|
158
|
+
assert.equal(
|
|
159
|
+
(signal.reason as TimeoutError).message,
|
|
160
|
+
"Request timed out after 0.1 seconds",
|
|
161
|
+
);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
test("createTimeoutSignal - signal is not aborted before timeout", () => {
|
|
165
|
+
const signal = createTimeoutSignal(1); // 1 second timeout
|
|
166
|
+
assert.ok(signal);
|
|
167
|
+
assert.ok(!signal.aborted);
|
|
168
|
+
|
|
169
|
+
clearTimeoutSignal(signal);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
test("clearTimeoutSignal - cleans up timer properly", async () => {
|
|
173
|
+
const signal = createTimeoutSignal(0.05); // 50ms timeout
|
|
174
|
+
assert.ok(signal);
|
|
175
|
+
assert.ok(!signal.aborted);
|
|
176
|
+
|
|
177
|
+
clearTimeoutSignal(signal);
|
|
178
|
+
|
|
179
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
180
|
+
|
|
181
|
+
assert.ok(!signal.aborted);
|
|
182
|
+
});
|