@fedify/cli 2.0.0-pr.479.1922 → 2.0.1
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 +1 -1
- package/README.md +3 -3
- package/dist/cache.js +17 -3
- package/dist/config.js +105 -0
- package/dist/deno.js +18 -8
- package/dist/generate-vocab/action.js +1 -1
- package/dist/imagerenderer.js +1 -1
- package/dist/inbox/rendercode.js +11 -21
- package/dist/inbox.js +162 -132
- package/dist/init/mod.js +3 -3
- package/dist/log.js +35 -1
- package/dist/lookup.js +55 -23
- package/dist/mod.js +95 -18
- package/dist/nodeinfo.js +39 -22
- package/dist/options.js +84 -0
- package/dist/relay.js +136 -0
- package/dist/tempserver.js +15 -8
- package/dist/tunnel.js +6 -10
- package/dist/utils.js +19 -108
- package/dist/webfinger/action.js +1 -1
- package/dist/webfinger/command.js +17 -9
- package/dist/webfinger/lib.js +3 -3
- package/package.json +50 -28
- package/deno.json +0 -71
- package/dist/globals.js +0 -49
- package/dist/init/action/configs.js +0 -91
- package/dist/init/action/const.js +0 -10
- package/dist/init/action/deps.js +0 -50
- package/dist/init/action/dir.js +0 -16
- package/dist/init/action/env.js +0 -13
- package/dist/init/action/install.js +0 -20
- package/dist/init/action/mod.js +0 -39
- package/dist/init/action/notice.js +0 -55
- package/dist/init/action/patch.js +0 -147
- package/dist/init/action/precommand.js +0 -28
- package/dist/init/action/recommend.js +0 -24
- package/dist/init/action/set.js +0 -31
- package/dist/init/action/templates.js +0 -58
- package/dist/init/action/utils.js +0 -50
- package/dist/init/ask/dir.js +0 -82
- package/dist/init/ask/kv.js +0 -44
- package/dist/init/ask/mod.js +0 -16
- package/dist/init/ask/mq.js +0 -46
- package/dist/init/ask/pm.js +0 -49
- package/dist/init/ask/wf.js +0 -29
- package/dist/init/command.js +0 -50
- package/dist/init/const.js +0 -31
- package/dist/init/json/biome.js +0 -24
- package/dist/init/json/kv.js +0 -53
- package/dist/init/json/mq.js +0 -72
- package/dist/init/json/pm.js +0 -44
- package/dist/init/json/rt.js +0 -39
- package/dist/init/json/vscode-settings-for-deno.js +0 -53
- package/dist/init/json/vscode-settings.js +0 -49
- package/dist/init/lib.js +0 -136
- package/dist/init/templates/defaults/federation.ts.tpl +0 -23
- package/dist/init/templates/defaults/logging.ts.tpl +0 -23
- package/dist/init/templates/express/app.ts.tpl +0 -16
- package/dist/init/templates/express/index.ts.tpl +0 -6
- package/dist/init/templates/hono/app.tsx.tpl +0 -14
- package/dist/init/templates/hono/index/bun.ts.tpl +0 -10
- package/dist/init/templates/hono/index/deno.ts.tpl +0 -13
- package/dist/init/templates/hono/index/node.ts.tpl +0 -14
- package/dist/init/templates/next/middleware.ts.tpl +0 -45
- package/dist/init/templates/nitro/.env.test.tpl +0 -1
- package/dist/init/templates/nitro/nitro.config.ts.tpl +0 -14
- package/dist/init/templates/nitro/server/error.ts.tpl +0 -3
- package/dist/init/templates/nitro/server/middleware/federation.ts.tpl +0 -8
- package/dist/init/test/action.js +0 -17
- package/dist/init/test/create.js +0 -100
- package/dist/init/test/fill.js +0 -32
- package/dist/init/test/lookup.js +0 -190
- package/dist/init/test/run.js +0 -25
- package/dist/init/test/utils.js +0 -17
- package/dist/init/webframeworks.js +0 -136
- package/scripts/pack.ts +0 -71
- package/src/cache.ts +0 -17
- package/src/docloader.ts +0 -67
- package/src/generate-vocab/action.ts +0 -17
- package/src/generate-vocab/command.ts +0 -44
- package/src/generate-vocab/mod.ts +0 -2
- package/src/globals.ts +0 -43
- package/src/imagerenderer.ts +0 -149
- package/src/inbox/entry.ts +0 -10
- package/src/inbox/rendercode.ts +0 -68
- package/src/inbox/view.tsx +0 -598
- package/src/inbox.tsx +0 -536
- package/src/init/action/configs.ts +0 -133
- package/src/init/action/const.ts +0 -9
- package/src/init/action/deps.ts +0 -161
- package/src/init/action/dir.ts +0 -11
- package/src/init/action/env.ts +0 -14
- package/src/init/action/install.ts +0 -24
- package/src/init/action/mod.ts +0 -66
- package/src/init/action/notice.ts +0 -103
- package/src/init/action/patch.ts +0 -233
- package/src/init/action/precommand.ts +0 -29
- package/src/init/action/recommend.ts +0 -38
- package/src/init/action/set.ts +0 -65
- package/src/init/action/templates.ts +0 -96
- package/src/init/action/utils.ts +0 -64
- package/src/init/ask/dir.ts +0 -98
- package/src/init/ask/kv.ts +0 -82
- package/src/init/ask/mod.ts +0 -23
- package/src/init/ask/mq.ts +0 -86
- package/src/init/ask/pm.ts +0 -58
- package/src/init/ask/wf.ts +0 -27
- package/src/init/command.ts +0 -135
- package/src/init/const.ts +0 -4
- package/src/init/json/biome.json +0 -17
- package/src/init/json/kv.json +0 -39
- package/src/init/json/mq.json +0 -95
- package/src/init/json/pm.json +0 -47
- package/src/init/json/rt.json +0 -42
- package/src/init/json/vscode-settings-for-deno.json +0 -43
- package/src/init/json/vscode-settings.json +0 -41
- package/src/init/lib.ts +0 -223
- package/src/init/mod.ts +0 -3
- package/src/init/templates/defaults/federation.ts.tpl +0 -23
- package/src/init/templates/defaults/logging.ts.tpl +0 -23
- package/src/init/templates/express/app.ts.tpl +0 -16
- package/src/init/templates/express/index.ts.tpl +0 -6
- package/src/init/templates/hono/app.tsx.tpl +0 -14
- package/src/init/templates/hono/index/bun.ts.tpl +0 -10
- package/src/init/templates/hono/index/deno.ts.tpl +0 -13
- package/src/init/templates/hono/index/node.ts.tpl +0 -14
- package/src/init/templates/next/middleware.ts.tpl +0 -45
- package/src/init/templates/nitro/.env.test.tpl +0 -1
- package/src/init/templates/nitro/nitro.config.ts.tpl +0 -14
- package/src/init/templates/nitro/server/error.ts.tpl +0 -3
- package/src/init/templates/nitro/server/middleware/federation.ts.tpl +0 -8
- package/src/init/test/action.ts +0 -28
- package/src/init/test/create.ts +0 -137
- package/src/init/test/fill.ts +0 -67
- package/src/init/test/lookup.ts +0 -254
- package/src/init/test/run.ts +0 -39
- package/src/init/test/types.ts +0 -27
- package/src/init/test/utils.ts +0 -21
- package/src/init/types.ts +0 -89
- package/src/init/webframeworks.ts +0 -168
- package/src/kv.bun.ts +0 -12
- package/src/kv.node.ts +0 -11
- package/src/log.ts +0 -64
- package/src/lookup.test.ts +0 -182
- package/src/lookup.ts +0 -563
- package/src/mod.ts +0 -62
- package/src/nodeinfo.test.ts +0 -229
- package/src/nodeinfo.ts +0 -454
- package/src/table.ts +0 -17
- package/src/tempserver.ts +0 -87
- package/src/tunnel.test.ts +0 -157
- package/src/tunnel.ts +0 -94
- package/src/utils.ts +0 -254
- package/src/webfinger/action.ts +0 -50
- package/src/webfinger/command.ts +0 -64
- package/src/webfinger/error.ts +0 -47
- package/src/webfinger/lib.ts +0 -37
- package/src/webfinger/mod.test.ts +0 -79
- package/src/webfinger/mod.ts +0 -2
- package/tsdown.config.ts +0 -35
package/src/lookup.ts
DELETED
|
@@ -1,563 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Application,
|
|
3
|
-
Collection,
|
|
4
|
-
CryptographicKey,
|
|
5
|
-
generateCryptoKeyPair,
|
|
6
|
-
getAuthenticatedDocumentLoader,
|
|
7
|
-
type Link,
|
|
8
|
-
lookupObject,
|
|
9
|
-
Object as APObject,
|
|
10
|
-
type ResourceDescriptor,
|
|
11
|
-
respondWithObject,
|
|
12
|
-
traverseCollection,
|
|
13
|
-
} from "@fedify/fedify";
|
|
14
|
-
import type { DocumentLoader } from "@fedify/vocab-runtime";
|
|
15
|
-
import { getLogger } from "@logtape/logtape";
|
|
16
|
-
import {
|
|
17
|
-
argument,
|
|
18
|
-
choice,
|
|
19
|
-
command,
|
|
20
|
-
constant,
|
|
21
|
-
flag,
|
|
22
|
-
float,
|
|
23
|
-
type InferValue,
|
|
24
|
-
map,
|
|
25
|
-
merge,
|
|
26
|
-
message,
|
|
27
|
-
multiple,
|
|
28
|
-
object,
|
|
29
|
-
option,
|
|
30
|
-
optional,
|
|
31
|
-
optionNames,
|
|
32
|
-
or,
|
|
33
|
-
string,
|
|
34
|
-
withDefault,
|
|
35
|
-
} from "@optique/core";
|
|
36
|
-
import { path, print, printError } from "@optique/run";
|
|
37
|
-
import { createWriteStream, type WriteStream } from "node:fs";
|
|
38
|
-
import process from "node:process";
|
|
39
|
-
import ora from "ora";
|
|
40
|
-
import { getContextLoader, getDocumentLoader } from "./docloader.ts";
|
|
41
|
-
import { configureLogging, debugOption } from "./globals.ts";
|
|
42
|
-
import { renderImages } from "./imagerenderer.ts";
|
|
43
|
-
import { spawnTemporaryServer, type TemporaryServer } from "./tempserver.ts";
|
|
44
|
-
import { colorEnabled, colors, formatObject } from "./utils.ts";
|
|
45
|
-
|
|
46
|
-
const logger = getLogger(["fedify", "cli", "lookup"]);
|
|
47
|
-
|
|
48
|
-
export const authorizedFetchOption = withDefault(
|
|
49
|
-
object({
|
|
50
|
-
authorizedFetch: flag("-a", "--authorized-fetch", {
|
|
51
|
-
description: message`Sign the request with an one-time key.`,
|
|
52
|
-
}),
|
|
53
|
-
firstKnock: withDefault(
|
|
54
|
-
option(
|
|
55
|
-
"--first-knock",
|
|
56
|
-
choice(["draft-cavage-http-signatures-12", "rfc9421"]),
|
|
57
|
-
{
|
|
58
|
-
description: message`The first-knock spec for ${
|
|
59
|
-
optionNames(["-a", "--authorized-fetch"])
|
|
60
|
-
}. It is used for the double-knocking technique.`,
|
|
61
|
-
},
|
|
62
|
-
),
|
|
63
|
-
"draft-cavage-http-signatures-12" as const,
|
|
64
|
-
),
|
|
65
|
-
}),
|
|
66
|
-
{ authorizedFetch: false } as const,
|
|
67
|
-
);
|
|
68
|
-
|
|
69
|
-
const traverseOption = withDefault(
|
|
70
|
-
object({
|
|
71
|
-
traverse: flag("-t", "--traverse", {
|
|
72
|
-
description:
|
|
73
|
-
message`Traverse the given collection(s) to fetch all items.`,
|
|
74
|
-
}),
|
|
75
|
-
suppressErrors: option("-S", "--suppress-errors", {
|
|
76
|
-
description:
|
|
77
|
-
message`Suppress partial errors while traversing the collection.`,
|
|
78
|
-
}),
|
|
79
|
-
}),
|
|
80
|
-
{ traverse: false } as const,
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
export const lookupCommand = command(
|
|
84
|
-
"lookup",
|
|
85
|
-
merge(
|
|
86
|
-
"Looking up options",
|
|
87
|
-
object({ command: constant("lookup") }),
|
|
88
|
-
traverseOption,
|
|
89
|
-
authorizedFetchOption,
|
|
90
|
-
debugOption,
|
|
91
|
-
object({
|
|
92
|
-
urls: multiple(
|
|
93
|
-
argument(string({ metavar: "URL_OR_HANDLE" }), {
|
|
94
|
-
description: message`One or more URLs or handles to look up.`,
|
|
95
|
-
}),
|
|
96
|
-
{ min: 1 },
|
|
97
|
-
),
|
|
98
|
-
format: withDefault(
|
|
99
|
-
or(
|
|
100
|
-
map(
|
|
101
|
-
option("-r", "--raw", {
|
|
102
|
-
description: message`Print the fetched JSON-LD document as is.`,
|
|
103
|
-
}),
|
|
104
|
-
() => "raw" as const,
|
|
105
|
-
),
|
|
106
|
-
map(
|
|
107
|
-
option("-C", "--compact", {
|
|
108
|
-
description: message`Compact the fetched JSON-LD document.`,
|
|
109
|
-
}),
|
|
110
|
-
() => "compact" as const,
|
|
111
|
-
),
|
|
112
|
-
map(
|
|
113
|
-
option("-e", "--expand", {
|
|
114
|
-
description: message`Expand the fetched JSON-LD document.`,
|
|
115
|
-
}),
|
|
116
|
-
() => "expand" as const,
|
|
117
|
-
),
|
|
118
|
-
),
|
|
119
|
-
"default" as const,
|
|
120
|
-
),
|
|
121
|
-
userAgent: optional(
|
|
122
|
-
option("-u", "--user-agent", string({ metavar: "USER_AGENT" }), {
|
|
123
|
-
description: message`The custom User-Agent header value.`,
|
|
124
|
-
}),
|
|
125
|
-
),
|
|
126
|
-
separator: withDefault(
|
|
127
|
-
option("-s", "--separator", string({ metavar: "SEPARATOR" }), {
|
|
128
|
-
description:
|
|
129
|
-
message`Specify the separator between adjacent output objects or collection items.`,
|
|
130
|
-
}),
|
|
131
|
-
"----",
|
|
132
|
-
),
|
|
133
|
-
output: optional(option(
|
|
134
|
-
"-o",
|
|
135
|
-
"--output",
|
|
136
|
-
path({
|
|
137
|
-
metavar: "OUTPUT_PATH",
|
|
138
|
-
type: "file",
|
|
139
|
-
allowCreate: true,
|
|
140
|
-
}),
|
|
141
|
-
{ description: message`Specify the output file path.` },
|
|
142
|
-
)),
|
|
143
|
-
timeout: optional(option(
|
|
144
|
-
"-T",
|
|
145
|
-
"--timeout",
|
|
146
|
-
float({ min: 0, metavar: "SECONDS" }),
|
|
147
|
-
{ description: message`Set timeout for network requests in seconds.` },
|
|
148
|
-
)),
|
|
149
|
-
}),
|
|
150
|
-
),
|
|
151
|
-
{
|
|
152
|
-
brief: message`Look up Activity Streams objects.`,
|
|
153
|
-
description:
|
|
154
|
-
message`Look up Activity Streams objects by URL or actor handle.
|
|
155
|
-
|
|
156
|
-
The arguments can be either URLs or actor handles (e.g., ${"@username@domain"}), and they can be multiple.`,
|
|
157
|
-
},
|
|
158
|
-
);
|
|
159
|
-
|
|
160
|
-
export class TimeoutError extends Error {
|
|
161
|
-
override name = "TimeoutError";
|
|
162
|
-
constructor(message: string) {
|
|
163
|
-
super(message);
|
|
164
|
-
this.name = "TimeoutError";
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
async function findAllImages(obj: APObject): Promise<URL[]> {
|
|
169
|
-
const result: URL[] = [];
|
|
170
|
-
const icon = await obj.getIcon();
|
|
171
|
-
const image = await obj.getImage();
|
|
172
|
-
|
|
173
|
-
if (icon && icon.url instanceof URL) {
|
|
174
|
-
result.push(icon.url);
|
|
175
|
-
}
|
|
176
|
-
if (image && image.url instanceof URL) {
|
|
177
|
-
result.push(image.url);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return result;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
export async function writeObjectToStream(
|
|
184
|
-
object: APObject | Link,
|
|
185
|
-
outputPath: string | undefined,
|
|
186
|
-
format: string | undefined,
|
|
187
|
-
contextLoader: DocumentLoader,
|
|
188
|
-
): Promise<void> {
|
|
189
|
-
const stream: WriteStream | NodeJS.WritableStream = outputPath
|
|
190
|
-
? createWriteStream(outputPath)
|
|
191
|
-
: process.stdout;
|
|
192
|
-
|
|
193
|
-
let content;
|
|
194
|
-
let json = true;
|
|
195
|
-
let imageUrls: URL[] = [];
|
|
196
|
-
|
|
197
|
-
if (format) {
|
|
198
|
-
if (format === "raw") {
|
|
199
|
-
content = await object.toJsonLd({ contextLoader });
|
|
200
|
-
} else if (format === "compact") {
|
|
201
|
-
content = await object.toJsonLd({ format: "compact", contextLoader });
|
|
202
|
-
} else if (format === "expand") {
|
|
203
|
-
content = await object.toJsonLd({ format: "expand", contextLoader });
|
|
204
|
-
} else {
|
|
205
|
-
content = object;
|
|
206
|
-
json = false;
|
|
207
|
-
}
|
|
208
|
-
} else {
|
|
209
|
-
content = object;
|
|
210
|
-
json = false;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
const enableColors = colorEnabled && outputPath === undefined;
|
|
214
|
-
content = formatObject(content, enableColors, json);
|
|
215
|
-
|
|
216
|
-
const encoder = new TextEncoder();
|
|
217
|
-
const bytes = encoder.encode(content + "\n");
|
|
218
|
-
|
|
219
|
-
stream.write(bytes);
|
|
220
|
-
|
|
221
|
-
if (object instanceof APObject) {
|
|
222
|
-
imageUrls = await findAllImages(object);
|
|
223
|
-
}
|
|
224
|
-
if (!outputPath && imageUrls.length > 0) {
|
|
225
|
-
await renderImages(imageUrls);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
const signalTimers = new WeakMap<AbortSignal, number>();
|
|
230
|
-
|
|
231
|
-
export function createTimeoutSignal(
|
|
232
|
-
timeoutSeconds?: number,
|
|
233
|
-
): AbortSignal | undefined {
|
|
234
|
-
if (timeoutSeconds == null) return undefined;
|
|
235
|
-
const controller = new AbortController();
|
|
236
|
-
const timerId = setTimeout(() => {
|
|
237
|
-
controller.abort(
|
|
238
|
-
new TimeoutError(`Request timed out after ${timeoutSeconds} seconds`),
|
|
239
|
-
);
|
|
240
|
-
}, timeoutSeconds * 1000);
|
|
241
|
-
|
|
242
|
-
signalTimers.set(controller.signal, timerId);
|
|
243
|
-
|
|
244
|
-
return controller.signal;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
export function clearTimeoutSignal(signal?: AbortSignal): void {
|
|
248
|
-
if (!signal) return;
|
|
249
|
-
const timerId = signalTimers.get(signal);
|
|
250
|
-
if (timerId !== undefined) {
|
|
251
|
-
clearTimeout(timerId);
|
|
252
|
-
signalTimers.delete(signal);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
function wrapDocumentLoaderWithTimeout(
|
|
257
|
-
loader: DocumentLoader,
|
|
258
|
-
timeoutSeconds?: number,
|
|
259
|
-
): DocumentLoader {
|
|
260
|
-
if (timeoutSeconds == null) return loader;
|
|
261
|
-
|
|
262
|
-
return (url: string, options?) => {
|
|
263
|
-
const signal = createTimeoutSignal(timeoutSeconds);
|
|
264
|
-
return loader(url, { ...options, signal }).finally(() =>
|
|
265
|
-
clearTimeoutSignal(signal)
|
|
266
|
-
);
|
|
267
|
-
};
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
function handleTimeoutError(
|
|
271
|
-
spinner: { fail: (text: string) => void },
|
|
272
|
-
timeoutSeconds?: number,
|
|
273
|
-
url?: string,
|
|
274
|
-
): void {
|
|
275
|
-
const urlText = url ? ` for: ${colors.red(url)}` : "";
|
|
276
|
-
spinner.fail(`Request timed out after ${timeoutSeconds} seconds${urlText}.`);
|
|
277
|
-
printError(
|
|
278
|
-
message`Try increasing the timeout with -T/--timeout option or check network connectivity.`,
|
|
279
|
-
);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
export async function runLookup(command: InferValue<typeof lookupCommand>) {
|
|
283
|
-
if (command.urls.length < 1) {
|
|
284
|
-
printError(message`At least one URL or actor handle must be provided.`);
|
|
285
|
-
process.exit(1);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// Enable Debug mode if requested
|
|
289
|
-
if (command.debug) {
|
|
290
|
-
await configureLogging();
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
const spinner = ora({
|
|
294
|
-
text: `Looking up the ${
|
|
295
|
-
command.traverse
|
|
296
|
-
? "collection"
|
|
297
|
-
: command.urls.length > 1
|
|
298
|
-
? "objects"
|
|
299
|
-
: "object"
|
|
300
|
-
}...`,
|
|
301
|
-
discardStdin: false,
|
|
302
|
-
}).start();
|
|
303
|
-
|
|
304
|
-
let server: TemporaryServer | undefined = undefined;
|
|
305
|
-
const baseDocumentLoader = await getDocumentLoader({
|
|
306
|
-
userAgent: command.userAgent,
|
|
307
|
-
});
|
|
308
|
-
const documentLoader = wrapDocumentLoaderWithTimeout(
|
|
309
|
-
baseDocumentLoader,
|
|
310
|
-
command.timeout,
|
|
311
|
-
);
|
|
312
|
-
const baseContextLoader = await getContextLoader({
|
|
313
|
-
userAgent: command.userAgent,
|
|
314
|
-
});
|
|
315
|
-
const contextLoader = wrapDocumentLoaderWithTimeout(
|
|
316
|
-
baseContextLoader,
|
|
317
|
-
command.timeout,
|
|
318
|
-
);
|
|
319
|
-
|
|
320
|
-
let authLoader: DocumentLoader | undefined = undefined;
|
|
321
|
-
|
|
322
|
-
if (command.authorizedFetch) {
|
|
323
|
-
spinner.text = "Generating a one-time key pair...";
|
|
324
|
-
const key = await generateCryptoKeyPair();
|
|
325
|
-
spinner.text = "Spinning up a temporary ActivityPub server...";
|
|
326
|
-
server = await spawnTemporaryServer((req) => {
|
|
327
|
-
const serverUrl = server?.url ?? new URL("http://localhost/");
|
|
328
|
-
if (new URL(req.url).pathname == "/.well-known/webfinger") {
|
|
329
|
-
const jrd: ResourceDescriptor = {
|
|
330
|
-
subject: `acct:${serverUrl.hostname}@${serverUrl.hostname}`,
|
|
331
|
-
aliases: [serverUrl.href],
|
|
332
|
-
links: [
|
|
333
|
-
{
|
|
334
|
-
rel: "self",
|
|
335
|
-
href: serverUrl.href,
|
|
336
|
-
type: "application/activity+json",
|
|
337
|
-
},
|
|
338
|
-
],
|
|
339
|
-
};
|
|
340
|
-
return new Response(JSON.stringify(jrd), {
|
|
341
|
-
headers: { "Content-Type": "application/jrd+json" },
|
|
342
|
-
});
|
|
343
|
-
}
|
|
344
|
-
return respondWithObject(
|
|
345
|
-
new Application({
|
|
346
|
-
id: serverUrl,
|
|
347
|
-
preferredUsername: serverUrl?.hostname,
|
|
348
|
-
publicKey: new CryptographicKey({
|
|
349
|
-
id: new URL("#main-key", serverUrl),
|
|
350
|
-
owner: serverUrl,
|
|
351
|
-
publicKey: key.publicKey,
|
|
352
|
-
}),
|
|
353
|
-
manuallyApprovesFollowers: true,
|
|
354
|
-
inbox: new URL("/inbox", serverUrl),
|
|
355
|
-
outbox: new URL("/outbox", serverUrl),
|
|
356
|
-
}),
|
|
357
|
-
{ contextLoader },
|
|
358
|
-
);
|
|
359
|
-
});
|
|
360
|
-
const baseAuthLoader = getAuthenticatedDocumentLoader(
|
|
361
|
-
{
|
|
362
|
-
keyId: new URL("#main-key", server.url),
|
|
363
|
-
privateKey: key.privateKey,
|
|
364
|
-
},
|
|
365
|
-
{
|
|
366
|
-
specDeterminer: {
|
|
367
|
-
determineSpec() {
|
|
368
|
-
return command.firstKnock;
|
|
369
|
-
},
|
|
370
|
-
rememberSpec() {
|
|
371
|
-
},
|
|
372
|
-
},
|
|
373
|
-
},
|
|
374
|
-
);
|
|
375
|
-
authLoader = wrapDocumentLoaderWithTimeout(
|
|
376
|
-
baseAuthLoader,
|
|
377
|
-
command.timeout,
|
|
378
|
-
);
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
spinner.text = `Looking up the ${
|
|
382
|
-
command.traverse
|
|
383
|
-
? "collection"
|
|
384
|
-
: command.urls.length > 1
|
|
385
|
-
? "objects"
|
|
386
|
-
: "object"
|
|
387
|
-
}...`;
|
|
388
|
-
|
|
389
|
-
if (command.traverse) {
|
|
390
|
-
let totalItems = 0;
|
|
391
|
-
|
|
392
|
-
for (let urlIndex = 0; urlIndex < command.urls.length; urlIndex++) {
|
|
393
|
-
const url = command.urls[urlIndex];
|
|
394
|
-
|
|
395
|
-
if (urlIndex > 0) {
|
|
396
|
-
spinner.text = `Looking up collection ${
|
|
397
|
-
urlIndex + 1
|
|
398
|
-
}/${command.urls.length}...`;
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
let collection: APObject | null;
|
|
402
|
-
try {
|
|
403
|
-
collection = await lookupObject(url, {
|
|
404
|
-
documentLoader: authLoader ?? documentLoader,
|
|
405
|
-
contextLoader,
|
|
406
|
-
userAgent: command.userAgent,
|
|
407
|
-
});
|
|
408
|
-
} catch (error) {
|
|
409
|
-
if (error instanceof TimeoutError) {
|
|
410
|
-
handleTimeoutError(spinner, command.timeout, url);
|
|
411
|
-
} else {
|
|
412
|
-
spinner.fail(`Failed to fetch object: ${colors.red(url)}.`);
|
|
413
|
-
if (authLoader == null) {
|
|
414
|
-
printError(
|
|
415
|
-
message`It may be a private object. Try with -a/--authorized-fetch.`,
|
|
416
|
-
);
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
await server?.close();
|
|
420
|
-
process.exit(1);
|
|
421
|
-
}
|
|
422
|
-
if (collection == null) {
|
|
423
|
-
spinner.fail(`Failed to fetch object: ${colors.red(url)}.`);
|
|
424
|
-
if (authLoader == null) {
|
|
425
|
-
printError(
|
|
426
|
-
message`It may be a private object. Try with -a/--authorized-fetch.`,
|
|
427
|
-
);
|
|
428
|
-
}
|
|
429
|
-
await server?.close();
|
|
430
|
-
process.exit(1);
|
|
431
|
-
}
|
|
432
|
-
if (!(collection instanceof Collection)) {
|
|
433
|
-
spinner.fail(
|
|
434
|
-
`Not a collection: ${colors.red(url)}. ` +
|
|
435
|
-
"The -t/--traverse option requires a collection.",
|
|
436
|
-
);
|
|
437
|
-
await server?.close();
|
|
438
|
-
process.exit(1);
|
|
439
|
-
}
|
|
440
|
-
spinner.succeed(`Fetched collection: ${colors.green(url)}.`);
|
|
441
|
-
|
|
442
|
-
try {
|
|
443
|
-
let collectionItems = 0;
|
|
444
|
-
for await (
|
|
445
|
-
const item of traverseCollection(collection, {
|
|
446
|
-
documentLoader: authLoader ?? documentLoader,
|
|
447
|
-
contextLoader,
|
|
448
|
-
suppressError: command.suppressErrors,
|
|
449
|
-
})
|
|
450
|
-
) {
|
|
451
|
-
if (!command.output && (totalItems > 0 || collectionItems > 0)) {
|
|
452
|
-
print(message`${command.separator}`);
|
|
453
|
-
}
|
|
454
|
-
await writeObjectToStream(
|
|
455
|
-
item,
|
|
456
|
-
command.output,
|
|
457
|
-
command.format,
|
|
458
|
-
contextLoader,
|
|
459
|
-
);
|
|
460
|
-
collectionItems++;
|
|
461
|
-
totalItems++;
|
|
462
|
-
}
|
|
463
|
-
} catch (error) {
|
|
464
|
-
logger.error("Failed to complete the traversal for {url}: {error}", {
|
|
465
|
-
url,
|
|
466
|
-
error,
|
|
467
|
-
});
|
|
468
|
-
if (error instanceof TimeoutError) {
|
|
469
|
-
handleTimeoutError(spinner, command.timeout, url);
|
|
470
|
-
} else {
|
|
471
|
-
spinner.fail(
|
|
472
|
-
`Failed to complete the traversal for: ${colors.red(url)}.`,
|
|
473
|
-
);
|
|
474
|
-
if (authLoader == null) {
|
|
475
|
-
printError(
|
|
476
|
-
message`It may be a private object. Try with -a/--authorized-fetch.`,
|
|
477
|
-
);
|
|
478
|
-
} else {
|
|
479
|
-
printError(
|
|
480
|
-
message`Use the -S/--suppress-errors option to suppress partial errors.`,
|
|
481
|
-
);
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
await server?.close();
|
|
485
|
-
process.exit(1);
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
spinner.succeed("Successfully fetched all items in the collection.");
|
|
489
|
-
|
|
490
|
-
await server?.close();
|
|
491
|
-
process.exit(0);
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
const promises: Promise<APObject | null>[] = [];
|
|
495
|
-
|
|
496
|
-
for (const url of command.urls) {
|
|
497
|
-
promises.push(
|
|
498
|
-
lookupObject(url, {
|
|
499
|
-
documentLoader: authLoader ?? documentLoader,
|
|
500
|
-
contextLoader,
|
|
501
|
-
userAgent: command.userAgent,
|
|
502
|
-
}).catch((error) => {
|
|
503
|
-
if (error instanceof TimeoutError) {
|
|
504
|
-
handleTimeoutError(spinner, command.timeout, url);
|
|
505
|
-
}
|
|
506
|
-
throw error;
|
|
507
|
-
}),
|
|
508
|
-
);
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
let objects: (APObject | null)[];
|
|
512
|
-
try {
|
|
513
|
-
objects = await Promise.all(promises);
|
|
514
|
-
} catch (_error) {
|
|
515
|
-
await server?.close();
|
|
516
|
-
process.exit(1);
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
spinner.stop();
|
|
520
|
-
let success = true;
|
|
521
|
-
let i = 0;
|
|
522
|
-
for (const obj of objects) {
|
|
523
|
-
const url = command.urls[i];
|
|
524
|
-
if (i > 0) print(message`${command.separator}`);
|
|
525
|
-
i++;
|
|
526
|
-
if (obj == null) {
|
|
527
|
-
spinner.fail(`Failed to fetch ${colors.red(url)}`);
|
|
528
|
-
if (authLoader == null) {
|
|
529
|
-
printError(
|
|
530
|
-
message`It may be a private object. Try with -a/--authorized-fetch.`,
|
|
531
|
-
);
|
|
532
|
-
}
|
|
533
|
-
success = false;
|
|
534
|
-
} else {
|
|
535
|
-
spinner.succeed(`Fetched object: ${colors.green(url)}`);
|
|
536
|
-
await writeObjectToStream(
|
|
537
|
-
obj,
|
|
538
|
-
command.output,
|
|
539
|
-
command.format,
|
|
540
|
-
contextLoader,
|
|
541
|
-
);
|
|
542
|
-
if (i < command.urls.length - 1) {
|
|
543
|
-
print(message`${command.separator}`);
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
if (success) {
|
|
548
|
-
spinner.succeed(
|
|
549
|
-
command.urls.length > 1
|
|
550
|
-
? "Successfully fetched all objects."
|
|
551
|
-
: "Successfully fetched the object.",
|
|
552
|
-
);
|
|
553
|
-
}
|
|
554
|
-
await server?.close();
|
|
555
|
-
if (!success) {
|
|
556
|
-
process.exit(1);
|
|
557
|
-
}
|
|
558
|
-
if (success && command.output) {
|
|
559
|
-
spinner.succeed(
|
|
560
|
-
`Successfully wrote output to ${colors.green(command.output)}.`,
|
|
561
|
-
);
|
|
562
|
-
}
|
|
563
|
-
}
|
package/src/mod.ts
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { or } from "@optique/core";
|
|
3
|
-
import { run } from "@optique/run";
|
|
4
|
-
import {
|
|
5
|
-
generateVocabCommand,
|
|
6
|
-
runGenerateVocab,
|
|
7
|
-
} from "./generate-vocab/mod.ts";
|
|
8
|
-
import { inboxCommand, runInbox } from "./inbox.tsx";
|
|
9
|
-
import {
|
|
10
|
-
initCommand,
|
|
11
|
-
runInit,
|
|
12
|
-
runTestInit,
|
|
13
|
-
testInitCommand,
|
|
14
|
-
} from "./init/mod.ts";
|
|
15
|
-
import { lookupCommand, runLookup } from "./lookup.ts";
|
|
16
|
-
import { nodeInfoCommand, runNodeInfo } from "./nodeinfo.ts";
|
|
17
|
-
import { runTunnel, tunnelCommand } from "./tunnel.ts";
|
|
18
|
-
import { runWebFinger, webFingerCommand } from "./webfinger/mod.ts";
|
|
19
|
-
|
|
20
|
-
const command = or(
|
|
21
|
-
initCommand,
|
|
22
|
-
webFingerCommand,
|
|
23
|
-
lookupCommand,
|
|
24
|
-
inboxCommand,
|
|
25
|
-
nodeInfoCommand,
|
|
26
|
-
tunnelCommand,
|
|
27
|
-
generateVocabCommand,
|
|
28
|
-
testInitCommand,
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
async function main() {
|
|
32
|
-
const result = run(command, {
|
|
33
|
-
programName: "fedify",
|
|
34
|
-
help: "both",
|
|
35
|
-
});
|
|
36
|
-
if (result.command === "init") {
|
|
37
|
-
await runInit(result);
|
|
38
|
-
}
|
|
39
|
-
if (result.command === "lookup") {
|
|
40
|
-
await runLookup(result);
|
|
41
|
-
}
|
|
42
|
-
if (result.command === "webfinger") {
|
|
43
|
-
await runWebFinger(result);
|
|
44
|
-
}
|
|
45
|
-
if (result.command === "inbox") {
|
|
46
|
-
runInbox(result);
|
|
47
|
-
}
|
|
48
|
-
if (result.command === "nodeinfo") {
|
|
49
|
-
runNodeInfo(result);
|
|
50
|
-
}
|
|
51
|
-
if (result.command === "tunnel") {
|
|
52
|
-
await runTunnel(result);
|
|
53
|
-
}
|
|
54
|
-
if (result.command === "generate-vocab") {
|
|
55
|
-
await runGenerateVocab(result);
|
|
56
|
-
}
|
|
57
|
-
if (result.command === "test-init") {
|
|
58
|
-
await runTestInit(result);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
await main();
|