tangled
alpha
login
or
join now
kris.darkworld.download
/
darkworld
1
fork
atom
The code for darkworld.download
darkworld.download
1
fork
atom
overview
issues
pulls
pipelines
feat: dangerous atproto sync, part 2
kris.darkworld.download
6 days ago
ccb365a2
af5612e7
verified
This commit was signed with the committer's
known signature
.
kris.darkworld.download
SSH Key Fingerprint:
SHA256:4iiUkypaBzJPnEeVlazWCFBrJncWXreVhtJPB4DlswE=
+241
-39
14 changed files
expand all
collapse all
unified
split
build.ts
lexicons
download.darkworld.site.getState.json
download.darkworld.state.json
scripts
publish-lexicons.ts
src
frontend.tsx
index.html
index.template.html
index.tsx
lib
currentStateSync.ts
prophecy.ts
runtime
generated
island-loaders.ts
island-loaders.ts
islands-client.tsx
server
renderPage.tsx
+9
-2
build.ts
···
13
};
14
15
const outdir = path.join(process.cwd(), "dist");
0
16
const generatedDir = path.join(process.cwd(), "src", "runtime", "generated");
17
const generatedLoadersPath = path.join(generatedDir, "island-loaders.ts");
18
const manifestPath = path.join(outdir, "build-manifest.json");
···
92
await mkdir(generatedDir, { recursive: true });
93
94
const lines = [
95
-
"export const islandLoaders: Record<string, () => Promise<Record<string, unknown>>> = {",
0
0
96
...modules.map((moduleId) => {
97
const importPath = "../" + path.relative(path.join(process.cwd(), "src", "runtime"), path.join(process.cwd(), moduleId)).replaceAll("\\", "/");
98
return `\t${JSON.stringify(moduleId)}: () => import(${JSON.stringify(importPath)}),`;
99
}),
100
"};",
101
"",
0
0
0
0
102
];
103
104
await writeFile(generatedLoadersPath, lines.join("\n"), "utf8");
···
106
107
function outputHref(outputPath: string): string {
108
const relative = path.relative(outdir, outputPath).replaceAll("\\", "/");
109
-
return `/${relative}`;
110
}
111
112
async function buildCss(): Promise<string | null> {
···
13
};
14
15
const outdir = path.join(process.cwd(), "dist");
16
+
const DIST_PUBLIC_PREFIX = "/.dist";
17
const generatedDir = path.join(process.cwd(), "src", "runtime", "generated");
18
const generatedLoadersPath = path.join(generatedDir, "island-loaders.ts");
19
const manifestPath = path.join(outdir, "build-manifest.json");
···
93
await mkdir(generatedDir, { recursive: true });
94
95
const lines = [
96
+
"type IslandLoader = () => Promise<Record<string, unknown>>;",
97
+
"",
98
+
"const generatedIslandLoaders: Record<string, IslandLoader> = {",
99
...modules.map((moduleId) => {
100
const importPath = "../" + path.relative(path.join(process.cwd(), "src", "runtime"), path.join(process.cwd(), moduleId)).replaceAll("\\", "/");
101
return `\t${JSON.stringify(moduleId)}: () => import(${JSON.stringify(importPath)}),`;
102
}),
103
"};",
104
"",
105
+
"export function getGeneratedIslandLoaders(): Record<string, IslandLoader> {",
106
+
"\treturn generatedIslandLoaders;",
107
+
"}",
108
+
"",
109
];
110
111
await writeFile(generatedLoadersPath, lines.join("\n"), "utf8");
···
113
114
function outputHref(outputPath: string): string {
115
const relative = path.relative(outdir, outputPath).replaceAll("\\", "/");
116
+
return `${DIST_PUBLIC_PREFIX}/${relative}`;
117
}
118
119
async function buildCss(): Promise<string | null> {
+67
lexicons/download.darkworld.site.getState.json
···
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
···
1
+
{
2
+
"id": "download.darkworld.site.getState",
3
+
"defs": {
4
+
"main": {
5
+
"type": "query",
6
+
"description": "Return the normalized website state used by darkworld.download clients.",
7
+
"output": {
8
+
"encoding": "application/json",
9
+
"schema": {
10
+
"type": "ref",
11
+
"ref": "#output"
12
+
}
13
+
}
14
+
},
15
+
"output": {
16
+
"type": "object",
17
+
"required": [
18
+
"useSusieProphecy",
19
+
"titleColors",
20
+
"favoriteGames",
21
+
"favoriteArtists",
22
+
"favoriteAlbums",
23
+
"favoriteDeltaruneCharacters"
24
+
],
25
+
"properties": {
26
+
"useSusieProphecy": {
27
+
"type": "boolean",
28
+
"description": "Whether to show Susie instead of Kris in prophecy content."
29
+
},
30
+
"titleColors": {
31
+
"type": "string",
32
+
"description": "Named title color mode for the site.",
33
+
"knownValues": [
34
+
"none",
35
+
"enby",
36
+
"trans"
37
+
]
38
+
},
39
+
"favoriteGames": {
40
+
"type": "array",
41
+
"items": {
42
+
"type": "string"
43
+
}
44
+
},
45
+
"favoriteArtists": {
46
+
"type": "array",
47
+
"items": {
48
+
"type": "string"
49
+
}
50
+
},
51
+
"favoriteAlbums": {
52
+
"type": "array",
53
+
"items": {
54
+
"type": "string"
55
+
}
56
+
},
57
+
"favoriteDeltaruneCharacters": {
58
+
"type": "array",
59
+
"items": {
60
+
"type": "string"
61
+
}
62
+
}
63
+
}
64
+
}
65
+
},
66
+
"lexicon": 1
67
+
}
+4
-12
lexicons/download.darkworld.state.json
···
39
"properties": {
40
"titleColors": {
41
"description": "TBD",
42
-
"refs": [
43
-
"#titleColorsEnby",
44
-
"#titleColorsTrans"
45
],
46
-
"type": "union"
47
},
48
"susieProphecy": {
49
"description": "Swap out Kris with Susie in the prophecy panel.",
···
85
}
86
}
87
}
88
-
},
89
-
"titleColorsEnby": {
90
-
"type": "object",
91
-
"properties": {}
92
-
},
93
-
"titleColorsTrans": {
94
-
"type": "object",
95
-
"properties": {}
96
}
97
},
98
"lexicon": 1
···
39
"properties": {
40
"titleColors": {
41
"description": "TBD",
42
+
"knownValues": [
43
+
"enby",
44
+
"trans"
45
],
46
+
"type": "string"
47
},
48
"susieProphecy": {
49
"description": "Swap out Kris with Susie in the prophecy panel.",
···
85
}
86
}
87
}
0
0
0
0
0
0
0
0
88
}
89
},
90
"lexicon": 1
+1
-1
scripts/publish-lexicons.ts
···
32
password: a?.password!
33
})
34
35
-
console.log(`Logged in as ${c.data.handle} (${process.env.MASK_EMAIL || c.data.email || "unknown-email"}), account status: ${c.data.active}`);
36
37
const status = (await b.com.atproto.sync.getRepoStatus({ did: c.data.did! })).data;
38
console.log(`Repository status: ${status.status}, current rev: ${status.rev}`);
···
32
password: a?.password!
33
})
34
35
+
console.log(`Logged in as ${c.data.handle} (${process.env.MASK_EMAIL || c.data.email || "unknown-email"}), account status: ${c.data.active ? "active" : c.data.status}`);
36
37
const status = (await b.com.atproto.sync.getRepoStatus({ did: c.data.did! })).data;
38
console.log(`Repository status: ${status.status}, current rev: ${status.rev}`);
+2
-4
src/frontend.tsx
···
8
import { createRoot, hydrateRoot } from "react-dom/client";
9
import "./index.css";
10
import { App } from "./App";
11
-
import { getLatestState } from "./lib/currentStateSync";
12
13
-
type DebugState = {
14
-
swapOutKrisWithSusie: boolean;
15
-
};
16
17
function mountDevStateWrench() {
18
if (document.getElementById("dev-state-wrench")) {
···
8
import { createRoot, hydrateRoot } from "react-dom/client";
9
import "./index.css";
10
import { App } from "./App";
11
+
import { getLatestState, type State } from "./lib/currentStateSync";
12
13
+
type DebugState = State;
0
0
14
15
function mountDevStateWrench() {
16
if (document.getElementById("dev-state-wrench")) {
+1
-1
src/index.html
···
7
<!-- <link rel="icon" type="image/svg+xml" href="./logo.svg" /> -->
8
<title>DARK WORLD</title>
9
<meta property="og:title" content="DARKWORLD (download)" />
10
-
<meta property="og:description" content="KRIS, YOU SERIOUSLY NEED DELTARUNE REFERENCES ON ATPROTO? " />
11
<meta property="og:locale" content="en_US" />
12
<meta property="og:url" content="https://darkworld.download/" />
13
</head>
···
7
<!-- <link rel="icon" type="image/svg+xml" href="./logo.svg" /> -->
8
<title>DARK WORLD</title>
9
<meta property="og:title" content="DARKWORLD (download)" />
10
+
<meta property="og:description" content="KRIS, YOU SERIOUSLY NEED DELTARUNE REFERENCES ON ATPROTO?" />
11
<meta property="og:locale" content="en_US" />
12
<meta property="og:url" content="https://darkworld.download/" />
13
</head>
+1
-1
src/index.template.html
···
6
<meta name="robots" content="noindex, nofollow" />
7
<title>DARK WORLD</title>
8
<meta property="og:title" content="DARKWORLD (download)" />
9
-
<meta property="og:description" content="KRIS, YOU SERIOUSLY NEED DELTARUNE REFERENCES ON ATPROTO? " />
10
<meta property="og:locale" content="en_US" />
11
<meta property="og:url" content="https://darkworld.download/" />
12
<!--app-head-->
···
6
<meta name="robots" content="noindex, nofollow" />
7
<title>DARK WORLD</title>
8
<meta property="og:title" content="DARKWORLD (download)" />
9
+
<meta property="og:description" content="KRIS, YOU SERIOUSLY NEED DELTARUNE REFERENCES ON ATPROTO?" />
10
<meta property="og:locale" content="en_US" />
11
<meta property="og:url" content="https://darkworld.download/" />
12
<!--app-head-->
+22
src/index.tsx
···
25
return assetPath;
26
}
27
0
0
0
0
0
0
0
0
28
function loadBuildManifest(): BuildManifest {
29
if (!isProduction) {
30
return {
···
83
84
const prodOnlyRoutes = isProduction
85
? {
0
0
0
0
0
0
0
0
0
0
0
0
0
0
86
"/*": async (req: Request) => {
87
const pathname = new URL(req.url).pathname;
88
const relative = safeRelativePath(pathname);
···
25
return assetPath;
26
}
27
28
+
function safeDistPath(pathname: string): string | null {
29
+
const distPath = pathname.replace(/^\/\.dist\//, "");
30
+
if (!distPath || distPath.includes("..") || distPath.includes("\\")) {
31
+
return null;
32
+
}
33
+
return distPath;
34
+
}
35
+
36
function loadBuildManifest(): BuildManifest {
37
if (!isProduction) {
38
return {
···
91
92
const prodOnlyRoutes = isProduction
93
? {
94
+
"/.dist/*": async (req: Request) => {
95
+
const pathname = new URL(req.url).pathname;
96
+
const relative = safeDistPath(pathname);
97
+
if (!relative) {
98
+
return new Response("Not Found", { status: 404 });
99
+
}
100
+
101
+
const file = Bun.file(path.join(distDir, relative));
102
+
if (!(await file.exists())) {
103
+
return new Response("Not Found", { status: 404 });
104
+
}
105
+
106
+
return new Response(file);
107
+
},
108
"/*": async (req: Request) => {
109
const pathname = new URL(req.url).pathname;
110
const relative = safeRelativePath(pathname);
+102
-10
src/lib/currentStateSync.ts
···
1
-
type State = {
2
-
swapOutKrisWithSusie: boolean;
0
0
0
0
0
0
0
3
};
4
5
declare global {
···
9
}
10
11
const DEFAULT_STATE: State = {
12
-
swapOutKrisWithSusie: false,
0
0
0
0
0
13
};
14
15
const STATE_TTL_MS = 10_000;
···
31
let didServiceCache: { did: string; endpoint: string; cachedAtMs: number } | null = null;
32
let lastSyncError = "";
33
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
34
function parseState(input: unknown): State | null {
35
if (!input || typeof input !== "object") {
36
return null;
37
}
38
39
-
const value = input as { swapOutKrisWithSusie?: unknown };
40
-
if (typeof value.swapOutKrisWithSusie !== "boolean") {
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
41
return null;
42
}
43
44
-
return { swapOutKrisWithSusie: value.swapOutKrisWithSusie };
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
45
}
46
47
function getServerState(): State {
···
55
56
const record = input as {
57
swapOutKrisWithSusie?: unknown;
58
-
site?: { susieProphecy?: unknown };
0
0
0
0
0
0
59
};
0
60
61
if (typeof record.swapOutKrisWithSusie === "boolean") {
62
-
return { swapOutKrisWithSusie: record.swapOutKrisWithSusie };
0
0
0
0
0
0
0
63
}
64
65
if (typeof record.site?.susieProphecy === "boolean") {
66
-
return { swapOutKrisWithSusie: record.site.susieProphecy };
0
0
0
0
0
0
0
67
}
68
69
return null;
···
90
const body = (await response.json()) as { value?: unknown };
91
const parsed = parseAtprotoStateRecord(body.value);
92
if (!parsed) {
93
-
throw new Error("State record is missing `site.susieProphecy` or `swapOutKrisWithSusie`");
94
}
95
96
return parsed;
···
1
+
type TitleColor = "none" | "enby" | "trans";
2
+
3
+
export type State = {
4
+
useSusieProphecy: boolean;
5
+
titleColors: TitleColor;
6
+
favoriteGames: string[];
7
+
favoriteArtists: string[];
8
+
favoriteAlbums: string[];
9
+
favoriteDeltaruneCharacters: string[];
10
};
11
12
declare global {
···
16
}
17
18
const DEFAULT_STATE: State = {
19
+
useSusieProphecy: false,
20
+
titleColors: "none",
21
+
favoriteGames: [],
22
+
favoriteArtists: [],
23
+
favoriteAlbums: [],
24
+
favoriteDeltaruneCharacters: [],
25
};
26
27
const STATE_TTL_MS = 10_000;
···
43
let didServiceCache: { did: string; endpoint: string; cachedAtMs: number } | null = null;
44
let lastSyncError = "";
45
46
+
function parseKnownTitleColors(input: unknown): Exclude<TitleColor, "none"> | null {
47
+
if (input === "enby" || input === "trans") {
48
+
return input;
49
+
}
50
+
51
+
return null;
52
+
}
53
+
54
+
function parseStringArray(input: unknown): string[] {
55
+
if (!Array.isArray(input)) {
56
+
return [];
57
+
}
58
+
59
+
return input.filter((entry): entry is string => typeof entry === "string");
60
+
}
61
+
62
function parseState(input: unknown): State | null {
63
if (!input || typeof input !== "object") {
64
return null;
65
}
66
67
+
const value = input as {
68
+
useSusieProphecy?: unknown;
69
+
titleColors?: unknown;
70
+
favoriteGames?: unknown;
71
+
favoriteArtists?: unknown;
72
+
favoriteAlbums?: unknown;
73
+
favoriteDeltaruneCharacters?: unknown;
74
+
swapOutKrisWithSusie?: unknown;
75
+
site?: { susieProphecy?: unknown; titleColors?: unknown };
76
+
favorite?: {
77
+
game?: unknown;
78
+
artist?: unknown;
79
+
album?: unknown;
80
+
deltaruneCharacter?: unknown;
81
+
};
82
+
};
83
+
84
+
const useSusieProphecy =
85
+
typeof value.useSusieProphecy === "boolean"
86
+
? value.useSusieProphecy
87
+
: typeof value.swapOutKrisWithSusie === "boolean"
88
+
? value.swapOutKrisWithSusie
89
+
: typeof value.site?.susieProphecy === "boolean"
90
+
? value.site.susieProphecy
91
+
: null;
92
+
93
+
if (useSusieProphecy === null) {
94
return null;
95
}
96
97
+
const titleColorsFromSite = parseKnownTitleColors(value.site?.titleColors);
98
+
99
+
let titleColors: TitleColor = "none";
100
+
if (value.titleColors === "none" || value.titleColors === "enby" || value.titleColors === "trans") {
101
+
titleColors = value.titleColors;
102
+
} else if (titleColorsFromSite) {
103
+
titleColors = titleColorsFromSite;
104
+
}
105
+
106
+
return {
107
+
useSusieProphecy,
108
+
titleColors,
109
+
favoriteGames: parseStringArray(value.favoriteGames ?? value.favorite?.game),
110
+
favoriteArtists: parseStringArray(value.favoriteArtists ?? value.favorite?.artist),
111
+
favoriteAlbums: parseStringArray(value.favoriteAlbums ?? value.favorite?.album),
112
+
favoriteDeltaruneCharacters: parseStringArray(
113
+
value.favoriteDeltaruneCharacters ?? value.favorite?.deltaruneCharacter,
114
+
),
115
+
};
116
}
117
118
function getServerState(): State {
···
126
127
const record = input as {
128
swapOutKrisWithSusie?: unknown;
129
+
site?: { susieProphecy?: unknown; titleColors?: unknown };
130
+
favorite?: {
131
+
game?: unknown;
132
+
artist?: unknown;
133
+
album?: unknown;
134
+
deltaruneCharacter?: unknown;
135
+
};
136
};
137
+
const titleColors = parseKnownTitleColors(record.site?.titleColors) ?? "none";
138
139
if (typeof record.swapOutKrisWithSusie === "boolean") {
140
+
return {
141
+
useSusieProphecy: record.swapOutKrisWithSusie,
142
+
titleColors,
143
+
favoriteGames: parseStringArray(record.favorite?.game),
144
+
favoriteArtists: parseStringArray(record.favorite?.artist),
145
+
favoriteAlbums: parseStringArray(record.favorite?.album),
146
+
favoriteDeltaruneCharacters: parseStringArray(record.favorite?.deltaruneCharacter),
147
+
};
148
}
149
150
if (typeof record.site?.susieProphecy === "boolean") {
151
+
return {
152
+
useSusieProphecy: record.site.susieProphecy,
153
+
titleColors,
154
+
favoriteGames: parseStringArray(record.favorite?.game),
155
+
favoriteArtists: parseStringArray(record.favorite?.artist),
156
+
favoriteAlbums: parseStringArray(record.favorite?.album),
157
+
favoriteDeltaruneCharacters: parseStringArray(record.favorite?.deltaruneCharacter),
158
+
};
159
}
160
161
return null;
···
182
const body = (await response.json()) as { value?: unknown };
183
const parsed = parseAtprotoStateRecord(body.value);
184
if (!parsed) {
185
+
throw new Error("State record is missing `site.susieProphecy` or `useSusieProphecy`");
186
}
187
188
return parsed;
+3
-3
src/lib/prophecy.ts
···
52
image: "/assets/prophecy/deltarune.png",
53
} satisfies ProphecyPanelProps,
54
krisOrSusie: {
55
-
text: state.swapOutKrisWithSusie
56
? "THE SECOND HERO.\nTHE GIRL, WITH HOPE CROSSED ON HER HEART."
57
: `THE FIRST HERO.\nTHE CAGE, WITH HUMAN SOUL AND PARTS.`,
58
-
image: state.swapOutKrisWithSusie
59
? "/assets/prophecy/susie.png"
60
: "/assets/prophecy/kris.png",
61
-
variant: state.swapOutKrisWithSusie
62
? ProphecyPanelVariant.SUSIE_DARKWORLD
63
: ProphecyPanelVariant.DEFAULT,
64
} satisfies ProphecyPanelProps,
···
52
image: "/assets/prophecy/deltarune.png",
53
} satisfies ProphecyPanelProps,
54
krisOrSusie: {
55
+
text: state.useSusieProphecy
56
? "THE SECOND HERO.\nTHE GIRL, WITH HOPE CROSSED ON HER HEART."
57
: `THE FIRST HERO.\nTHE CAGE, WITH HUMAN SOUL AND PARTS.`,
58
+
image: state.useSusieProphecy
59
? "/assets/prophecy/susie.png"
60
: "/assets/prophecy/kris.png",
61
+
variant: state.useSusieProphecy
62
? ProphecyPanelVariant.SUSIE_DARKWORLD
63
: ProphecyPanelVariant.DEFAULT,
64
} satisfies ProphecyPanelProps,
+7
-1
src/runtime/generated/island-loaders.ts
···
1
-
export const islandLoaders: Record<string, () => Promise<Record<string, unknown>>> = {
0
0
2
};
0
0
0
0
···
1
+
type IslandLoader = () => Promise<Record<string, unknown>>;
2
+
3
+
const generatedIslandLoaders: Record<string, IslandLoader> = {
4
};
5
+
6
+
export function getGeneratedIslandLoaders(): Record<string, IslandLoader> {
7
+
return generatedIslandLoaders;
8
+
}
+18
src/runtime/island-loaders.ts
···
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
···
1
+
import { getGeneratedIslandLoaders } from "./generated/island-loaders";
2
+
3
+
export type IslandLoader = () => Promise<Record<string, unknown>>;
4
+
export type IslandLoaders = Record<string, IslandLoader>;
5
+
6
+
let cachedIslandLoaders: IslandLoaders | null = null;
7
+
8
+
export function getIslandLoaders(): IslandLoaders {
9
+
if (!cachedIslandLoaders) {
10
+
cachedIslandLoaders = getGeneratedIslandLoaders();
11
+
}
12
+
13
+
return cachedIslandLoaders;
14
+
}
15
+
16
+
export function getIslandLoader(moduleId: string): IslandLoader | undefined {
17
+
return getIslandLoaders()[moduleId];
18
+
}
+2
-2
src/runtime/islands-client.tsx
···
2
import { hydrateRoot } from "react-dom/client";
3
import { decodeJsonProps, type JsonValue } from "./jsonSafe";
4
import { islandAttrs } from "./server-islands";
5
-
import { islandLoaders } from "./generated/island-loaders";
6
7
type ModuleRecord = Record<string, unknown>;
8
9
async function loadModule(moduleId: string): Promise<ModuleRecord | null> {
10
-
const loader = islandLoaders[moduleId];
11
if (!loader) {
12
console.warn(`[islands] Missing loader for module: ${moduleId}`);
13
return null;
···
2
import { hydrateRoot } from "react-dom/client";
3
import { decodeJsonProps, type JsonValue } from "./jsonSafe";
4
import { islandAttrs } from "./server-islands";
5
+
import { getIslandLoader } from "./island-loaders";
6
7
type ModuleRecord = Record<string, unknown>;
8
9
async function loadModule(moduleId: string): Promise<ModuleRecord | null> {
10
+
const loader = getIslandLoader(moduleId);
11
if (!loader) {
12
console.warn(`[islands] Missing loader for module: ${moduleId}`);
13
return null;
+2
-2
src/server/renderPage.tsx
···
34
35
const scripts: string[] = [];
36
if (manifest.fullClient && manifest.fullClientScriptHref) {
37
-
scripts.push(`<script type="module" src="${manifest.fullClientScriptHref}"></script>`);
38
} else if (!manifest.fullClient && manifest.islandsScriptHref) {
39
-
scripts.push(`<script type="module" src="${manifest.islandsScriptHref}"></script>`);
40
}
41
scripts.unshift(stateScript);
42
···
34
35
const scripts: string[] = [];
36
if (manifest.fullClient && manifest.fullClientScriptHref) {
37
+
scripts.push(`<script type="module" src="${manifest.fullClientScriptHref}" async defer></script>`);
38
} else if (!manifest.fullClient && manifest.islandsScriptHref) {
39
+
scripts.push(`<script type="module" src="${manifest.islandsScriptHref}" defer></script>`);
40
}
41
scripts.unshift(stateScript);
42