@fedify/cli 1.8.12 → 2.0.0-dev.1761

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.
Files changed (130) hide show
  1. package/deno.json +71 -0
  2. package/dist/cache.js +17 -0
  3. package/dist/deno.js +71 -0
  4. package/dist/docloader.js +52 -0
  5. package/dist/globals.js +49 -0
  6. package/dist/imagerenderer.js +105 -0
  7. package/dist/inbox/rendercode.js +57 -0
  8. package/dist/inbox/view.js +508 -0
  9. package/dist/inbox.js +315 -0
  10. package/dist/init/action/configs.js +81 -0
  11. package/dist/init/action/deps.js +52 -0
  12. package/dist/init/action/dir.js +16 -0
  13. package/dist/init/action/env.js +13 -0
  14. package/dist/init/action/install.js +22 -0
  15. package/dist/init/action/mod.js +39 -0
  16. package/dist/init/action/notice.js +62 -0
  17. package/dist/init/action/patch.js +141 -0
  18. package/dist/init/action/precommand.js +23 -0
  19. package/dist/init/action/recommend.js +24 -0
  20. package/dist/init/action/set.js +31 -0
  21. package/dist/init/action/templates.js +57 -0
  22. package/dist/init/action/utils.js +50 -0
  23. package/dist/init/ask/dir.js +82 -0
  24. package/dist/init/ask/kv.js +33 -0
  25. package/dist/init/ask/mod.js +16 -0
  26. package/dist/init/ask/mq.js +33 -0
  27. package/dist/init/ask/pm.js +49 -0
  28. package/dist/init/ask/wf.js +29 -0
  29. package/dist/init/command.js +25 -0
  30. package/dist/init/const.js +31 -0
  31. package/dist/init/json/biome.js +24 -0
  32. package/dist/init/json/kv.js +53 -0
  33. package/dist/init/json/mq.js +72 -0
  34. package/dist/init/json/pm.js +44 -0
  35. package/dist/init/json/rt.js +39 -0
  36. package/dist/init/json/vscode-settings-for-deno.js +53 -0
  37. package/dist/init/json/vscode-settings.js +49 -0
  38. package/dist/init/lib.js +129 -0
  39. package/dist/init/mod.js +5 -0
  40. package/dist/init/webframeworks.js +133 -0
  41. package/dist/kv.bun.js +17 -0
  42. package/dist/kv.node.js +17 -0
  43. package/dist/log.js +52 -0
  44. package/dist/lookup.js +287 -0
  45. package/dist/mod.js +34 -0
  46. package/dist/nodeinfo.js +261 -0
  47. package/dist/table.js +24 -0
  48. package/dist/tempserver.js +71 -0
  49. package/dist/tunnel.js +21 -0
  50. package/dist/utils.js +67 -0
  51. package/dist/webfinger/action.js +44 -0
  52. package/dist/webfinger/command.js +20 -0
  53. package/dist/webfinger/error.js +47 -0
  54. package/dist/webfinger/lib.js +45 -0
  55. package/dist/webfinger/mod.js +5 -0
  56. package/package.json +64 -24
  57. package/scripts/pack.ts +64 -0
  58. package/src/cache.ts +17 -0
  59. package/src/docloader.ts +67 -0
  60. package/src/globals.ts +43 -0
  61. package/src/imagerenderer.ts +149 -0
  62. package/src/inbox/entry.ts +10 -0
  63. package/src/inbox/rendercode.ts +68 -0
  64. package/src/inbox/view.tsx +598 -0
  65. package/src/inbox.tsx +535 -0
  66. package/src/init/action/configs.ts +88 -0
  67. package/src/init/action/deps.ts +93 -0
  68. package/src/init/action/dir.ts +11 -0
  69. package/src/init/action/env.ts +14 -0
  70. package/src/init/action/install.ts +59 -0
  71. package/src/init/action/mod.ts +66 -0
  72. package/src/init/action/notice.ts +101 -0
  73. package/src/init/action/patch.ts +212 -0
  74. package/src/init/action/precommand.ts +22 -0
  75. package/src/init/action/recommend.ts +38 -0
  76. package/src/init/action/set.ts +78 -0
  77. package/src/init/action/templates.ts +95 -0
  78. package/src/init/action/utils.ts +64 -0
  79. package/src/init/ask/dir.ts +98 -0
  80. package/src/init/ask/kv.ts +39 -0
  81. package/src/init/ask/mod.ts +23 -0
  82. package/src/init/ask/mq.ts +37 -0
  83. package/src/init/ask/pm.ts +58 -0
  84. package/src/init/ask/wf.ts +27 -0
  85. package/src/init/command.ts +64 -0
  86. package/src/init/const.ts +4 -0
  87. package/src/init/json/biome.json +17 -0
  88. package/src/init/json/kv.json +39 -0
  89. package/src/init/json/mq.json +95 -0
  90. package/src/init/json/pm.json +47 -0
  91. package/src/init/json/rt.json +42 -0
  92. package/src/init/json/vscode-settings-for-deno.json +43 -0
  93. package/src/init/json/vscode-settings.json +41 -0
  94. package/src/init/lib.ts +220 -0
  95. package/src/init/mod.ts +2 -0
  96. package/src/init/templates/defaults/federation.ts.tpl +23 -0
  97. package/src/init/templates/defaults/logging.ts.tpl +23 -0
  98. package/src/init/templates/express/app.ts.tpl +16 -0
  99. package/src/init/templates/express/index.ts.tpl +6 -0
  100. package/src/init/templates/hono/app.tsx.tpl +14 -0
  101. package/src/init/templates/hono/index/bun.ts.tpl +10 -0
  102. package/src/init/templates/hono/index/deno.ts.tpl +13 -0
  103. package/src/init/templates/hono/index/node.ts.tpl +14 -0
  104. package/src/init/templates/next/middleware.ts.tpl +45 -0
  105. package/src/init/templates/nitro/nitro.config.ts.tpl +5 -0
  106. package/src/init/templates/nitro/server/error.ts.tpl +3 -0
  107. package/src/init/templates/nitro/server/middleware/federation.ts.tpl +8 -0
  108. package/src/init/types.ts +88 -0
  109. package/src/init/webframeworks.ts +151 -0
  110. package/src/kv.bun.ts +12 -0
  111. package/src/kv.node.ts +11 -0
  112. package/src/log.ts +64 -0
  113. package/src/lookup.test.ts +182 -0
  114. package/src/lookup.ts +558 -0
  115. package/src/mod.ts +45 -0
  116. package/src/nodeinfo.test.ts +229 -0
  117. package/src/nodeinfo.ts +447 -0
  118. package/src/table.ts +17 -0
  119. package/src/tempserver.ts +87 -0
  120. package/src/tunnel.ts +32 -0
  121. package/src/utils.ts +136 -0
  122. package/src/webfinger/action.ts +50 -0
  123. package/src/webfinger/command.ts +59 -0
  124. package/src/webfinger/error.ts +47 -0
  125. package/src/webfinger/lib.ts +37 -0
  126. package/src/webfinger/mod.test.ts +79 -0
  127. package/src/webfinger/mod.ts +2 -0
  128. package/tsdown.config.ts +24 -0
  129. package/src/install.mjs +0 -189
  130. package/src/run.mjs +0 -22
@@ -0,0 +1,149 @@
1
+ import { encodeBase64 } from "byte-encodings/base64";
2
+ import fs from "node:fs/promises";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import process from "node:process";
6
+ import { Jimp } from "./nodeinfo.ts";
7
+
8
+ export type TerminalType = "kitty" | "iterm2" | "none";
9
+
10
+ const KITTY_IDENTIFIERS: string[] = [
11
+ "kitty",
12
+ "wezterm",
13
+ "konsole",
14
+ "warp",
15
+ "wayst",
16
+ "st",
17
+ "ghostty",
18
+ ];
19
+
20
+ type KittyCommand = Record<string, string | number>;
21
+
22
+ export function detectTerminalCapabilities(): TerminalType {
23
+ const termProgram = (process.env.TERM_PROGRAM || "").toLowerCase();
24
+
25
+ if (KITTY_IDENTIFIERS.includes(termProgram)) return "kitty";
26
+
27
+ if (termProgram === "iterm.app") return "iterm2";
28
+
29
+ return "none";
30
+ }
31
+
32
+ function serializeGrCommand(
33
+ cmd: KittyCommand,
34
+ payload?: string,
35
+ ): Uint8Array {
36
+ const cmdString = Object.entries(cmd)
37
+ .map(([k, v]) => `${k}=${v}`)
38
+ .join(",");
39
+
40
+ const encoder = new TextEncoder();
41
+ const parts: Uint8Array[] = [];
42
+
43
+ parts.push(encoder.encode("\x1b_G"));
44
+ parts.push(encoder.encode(cmdString));
45
+
46
+ if (payload) {
47
+ parts.push(encoder.encode(";"));
48
+ parts.push(encoder.encode(payload));
49
+ }
50
+
51
+ parts.push(encoder.encode("\x1b\\"));
52
+
53
+ const totalLength = parts.reduce((sum, part) => sum + part.length, 0);
54
+ const result = new Uint8Array(totalLength);
55
+ let offset = 0;
56
+
57
+ for (const part of parts) {
58
+ result.set(part, offset);
59
+ offset += part.length;
60
+ }
61
+
62
+ return result;
63
+ }
64
+
65
+ export async function renderImageKitty(
66
+ imagePath: string,
67
+ cmd: KittyCommand,
68
+ ): Promise<void> {
69
+ const imageData = await fs.readFile(imagePath);
70
+ const base64Data = encodeBase64(imageData);
71
+ let remaining = base64Data;
72
+ let isFirst = true;
73
+
74
+ while (remaining.length > 0) {
75
+ const chunk = remaining.slice(0, 4096);
76
+ remaining = remaining.slice(4096);
77
+
78
+ const chunkCmd = {
79
+ ...(isFirst ? cmd : {}),
80
+ m: remaining.length > 0 ? 1 : 0,
81
+ };
82
+
83
+ const command = serializeGrCommand(chunkCmd, chunk);
84
+
85
+ process.stderr.write(command);
86
+
87
+ isFirst = false;
88
+ }
89
+ }
90
+
91
+ export async function renderImageITerm2(
92
+ imagePath: string,
93
+ ): Promise<void> {
94
+ const imageData = await fs.readFile(imagePath);
95
+ const base64Data = encodeBase64(imageData);
96
+
97
+ const encoder = new TextEncoder();
98
+ const command = encoder.encode(
99
+ `\x1b]1337;File=inline=1preserveAspectRatio=1:${base64Data}\x07\n`,
100
+ );
101
+ process.stderr.write(command);
102
+ }
103
+
104
+ export async function downloadImage(url: string): Promise<string | null> {
105
+ try {
106
+ const response = await fetch(url);
107
+ const imageData = new Uint8Array(await response.arrayBuffer());
108
+ const extension = new URL(url).pathname.split(".").pop() || "jpg";
109
+ const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "fedify"));
110
+ const tempPath = path.join(tempDir, `image.${extension}`);
111
+
112
+ await fs.writeFile(tempPath, imageData);
113
+
114
+ return tempPath;
115
+ } catch (_error) {
116
+ return null;
117
+ }
118
+ }
119
+
120
+ export async function renderImages(
121
+ imageUrls: URL[],
122
+ ): Promise<void> {
123
+ const graphicsProtocol = detectTerminalCapabilities();
124
+ for (const url of imageUrls) {
125
+ const tempPath = await downloadImage(url.href);
126
+ if (!tempPath) continue;
127
+
128
+ const convertedImagePath: `${string}.png` = `${tempPath}.converted.png`;
129
+ const image = await Jimp.read(tempPath);
130
+ await image.write(convertedImagePath);
131
+ await fs.rm(tempPath);
132
+
133
+ console.error(); // clear the line before rendering image
134
+
135
+ if (graphicsProtocol === "kitty") {
136
+ await renderImageKitty(convertedImagePath, {
137
+ a: "T",
138
+ f: 100, // specify the image format is png
139
+ });
140
+ } else if (graphicsProtocol === "iterm2") {
141
+ await renderImageITerm2(convertedImagePath);
142
+ } else {
143
+ continue;
144
+ }
145
+ console.error(); // clear the line after rendering image
146
+ }
147
+ }
148
+
149
+ // cSpell: ignore ghostty iterm konsole magick wezterm wayst
@@ -0,0 +1,10 @@
1
+ import type { Activity } from "@fedify/fedify";
2
+ import type { LogRecord } from "@logtape/logtape";
3
+
4
+ export interface ActivityEntry {
5
+ timestamp: Temporal.Instant;
6
+ request: Request;
7
+ response?: Response;
8
+ activity?: Activity;
9
+ logs: LogRecord[];
10
+ }
@@ -0,0 +1,68 @@
1
+ import type { Activity } from "@fedify/fedify";
2
+ import { getStatusText } from "@poppanator/http-constants";
3
+ import { getContextLoader } from "../docloader.ts";
4
+
5
+ export async function renderRequest(request: Request): Promise<string> {
6
+ // @ts-ignore: Work around `deno publish --dry-run` bug
7
+ request = request.clone();
8
+ const url = new URL(request.url);
9
+ let code = `${request.method} ${url.pathname + url.search}\n`;
10
+ for (const [key, value] of request.headers.entries()) {
11
+ code += `${capitalize(key)}: ${value}\n`;
12
+ }
13
+ let body: string;
14
+ try {
15
+ body = await request.text();
16
+ } catch (_) {
17
+ body = "[Failed to decode body; it may be binary.]";
18
+ }
19
+ code += `\n${body}`;
20
+ return code;
21
+ }
22
+
23
+ export async function renderResponse(response: Response): Promise<string> {
24
+ response = response.clone();
25
+ let code = `${response.status} ${
26
+ response.statusText === ""
27
+ ? getStatusText(response.status)
28
+ : response.statusText
29
+ }\n`;
30
+ for (const [key, value] of response.headers.entries()) {
31
+ code += `${capitalize(key)}: ${value}\n`;
32
+ }
33
+ let body: string;
34
+ try {
35
+ body = await response.text();
36
+ } catch (_) {
37
+ body = "[Failed to decode body; it may be binary.]";
38
+ }
39
+ code += `\n${body}`;
40
+ return code;
41
+ }
42
+
43
+ export async function renderRawActivity(request: Request): Promise<string> {
44
+ // @ts-ignore: Work around `deno publish --dry-run` bug
45
+ request = request.clone();
46
+ try {
47
+ const activity = await request.json();
48
+ return JSON.stringify(activity, null, 2);
49
+ } catch {
50
+ return "[Failed to decode body; it may not be JSON.]";
51
+ }
52
+ }
53
+
54
+ export async function renderActivity(
55
+ activity: Activity,
56
+ expand: boolean = false,
57
+ ): Promise<string> {
58
+ const contextLoader = await getContextLoader();
59
+ const jsonLd = await activity.toJsonLd({
60
+ contextLoader,
61
+ format: expand ? "expand" : "compact",
62
+ });
63
+ return JSON.stringify(jsonLd, null, 2);
64
+ }
65
+
66
+ function capitalize(name: string): string {
67
+ return name.replace(/(^|-)./g, (match) => match.toUpperCase());
68
+ }