data-of-loathing 2.6.2 → 3.0.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/dist/BaseClient.d.ts +14 -0
- package/dist/BaseClient.js +30 -0
- package/dist/browser-client.d.ts +17 -0
- package/dist/browser-client.js +58 -0
- package/dist/browser-strategies.d.ts +9 -0
- package/dist/browser-strategies.js +37 -0
- package/dist/browser.d.ts +15 -0
- package/dist/browser.js +35 -0
- package/dist/client.d.ts +11 -0
- package/dist/client.js +29 -0
- package/dist/http-range-worker.d.ts +1 -0
- package/dist/http-range-worker.js +25844 -0
- package/dist/http-vfs-dialect.d.ts +9 -0
- package/dist/http-vfs-dialect.js +93 -0
- package/dist/index.d.ts +3 -25
- package/dist/index.js +5 -40
- package/dist/node.d.ts +18 -0
- package/dist/node.js +52 -0
- package/dist/sqlite3.wasm +0 -0
- package/dist/strategies.d.ts +15 -0
- package/dist/strategies.js +46 -0
- package/package.json +30 -8
- package/dist/runtime/batcher.d.ts +0 -105
- package/dist/runtime/batcher.js +0 -204
- package/dist/runtime/createClient.d.ts +0 -17
- package/dist/runtime/createClient.js +0 -40
- package/dist/runtime/error.d.ts +0 -18
- package/dist/runtime/error.js +0 -19
- package/dist/runtime/fetcher.d.ts +0 -10
- package/dist/runtime/fetcher.js +0 -84
- package/dist/runtime/generateGraphqlOperation.d.ts +0 -30
- package/dist/runtime/generateGraphqlOperation.js +0 -129
- package/dist/runtime/index.d.ts +0 -11
- package/dist/runtime/index.js +0 -18
- package/dist/runtime/linkTypeMap.d.ts +0 -9
- package/dist/runtime/linkTypeMap.js +0 -101
- package/dist/runtime/typeSelection.d.ts +0 -28
- package/dist/runtime/typeSelection.js +0 -4
- package/dist/runtime/types.d.ts +0 -55
- package/dist/runtime/types.js +0 -3
- package/dist/schema.d.ts +0 -10053
- package/dist/schema.js +0 -1668
- package/dist/types.d.ts +0 -3537
- package/dist/types.js +0 -9258
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type EntityManager, MikroORM } from "@mikro-orm/core";
|
|
2
|
+
export declare const DEFAULT_URL = "https://data.loathers.net/dol.sqlite";
|
|
3
|
+
export declare const ETAG_KEY = "dol-etag";
|
|
4
|
+
export declare abstract class BaseClient<S> {
|
|
5
|
+
protected _orm?: MikroORM;
|
|
6
|
+
protected readonly _strategy: S;
|
|
7
|
+
constructor(strategy: S);
|
|
8
|
+
get query(): EntityManager;
|
|
9
|
+
abstract load(): Promise<void>;
|
|
10
|
+
protected fetchDb(url: string): Promise<ArrayBuffer>;
|
|
11
|
+
protected abstract getStoredEtag(key: string): Promise<string | null>;
|
|
12
|
+
protected abstract storeEtag(key: string, etag: string): Promise<void>;
|
|
13
|
+
protected syncIfNeeded(url: string, key: string, apply: (data: ArrayBuffer) => Promise<void>, force?: boolean): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export const DEFAULT_URL = "https://data.loathers.net/dol.sqlite";
|
|
2
|
+
export const ETAG_KEY = "dol-etag";
|
|
3
|
+
export class BaseClient {
|
|
4
|
+
_orm;
|
|
5
|
+
_strategy;
|
|
6
|
+
constructor(strategy) {
|
|
7
|
+
this._strategy = strategy;
|
|
8
|
+
}
|
|
9
|
+
get query() {
|
|
10
|
+
if (!this._orm)
|
|
11
|
+
throw new Error("Call await client.load() before querying");
|
|
12
|
+
return this._orm.em;
|
|
13
|
+
}
|
|
14
|
+
async fetchDb(url) {
|
|
15
|
+
const response = await fetch(url);
|
|
16
|
+
if (!response.ok)
|
|
17
|
+
throw new Error(`Failed to fetch database: ${response.status}`);
|
|
18
|
+
return response.arrayBuffer();
|
|
19
|
+
}
|
|
20
|
+
async syncIfNeeded(url, key, apply, force = false) {
|
|
21
|
+
const storedEtag = force ? null : await this.getStoredEtag(key);
|
|
22
|
+
const head = await fetch(url, { method: "HEAD" });
|
|
23
|
+
const remoteEtag = head.headers.get("etag");
|
|
24
|
+
if (force || storedEtag !== remoteEtag) {
|
|
25
|
+
await apply(await this.fetchDb(url));
|
|
26
|
+
if (remoteEtag)
|
|
27
|
+
await this.storeEtag(key, remoteEtag);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type EntityManager } from "@mikro-orm/core";
|
|
2
|
+
export type Strategy = {
|
|
3
|
+
strategy?: "cache";
|
|
4
|
+
url?: string;
|
|
5
|
+
} | {
|
|
6
|
+
strategy: "remote";
|
|
7
|
+
url?: string;
|
|
8
|
+
};
|
|
9
|
+
export declare class Client {
|
|
10
|
+
private _orm?;
|
|
11
|
+
private readonly _strategy;
|
|
12
|
+
constructor(strategy?: Strategy);
|
|
13
|
+
get em(): EntityManager;
|
|
14
|
+
load(): Promise<void>;
|
|
15
|
+
private _db?;
|
|
16
|
+
}
|
|
17
|
+
export declare function createClient(strategy?: Strategy): Client;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { SqlMikroORM, SqliteDriver } from "@mikro-orm/sql";
|
|
2
|
+
import { HttpVFSDialect } from "./http-vfs-dialect.js";
|
|
3
|
+
import { entities } from "data-of-loathing-schema";
|
|
4
|
+
const DEFAULT_URL = "https://data.loathers.net/dol.sqlite";
|
|
5
|
+
const ETAG_KEY = "dol-etag";
|
|
6
|
+
export class Client {
|
|
7
|
+
_orm;
|
|
8
|
+
_strategy;
|
|
9
|
+
constructor(strategy = {}) {
|
|
10
|
+
this._strategy = strategy;
|
|
11
|
+
}
|
|
12
|
+
get em() {
|
|
13
|
+
if (!this._orm)
|
|
14
|
+
throw new Error("Call await client.load() before querying");
|
|
15
|
+
return this._orm.em;
|
|
16
|
+
}
|
|
17
|
+
async load() {
|
|
18
|
+
await this._orm?.close();
|
|
19
|
+
const url = this._strategy.url ?? DEFAULT_URL;
|
|
20
|
+
if (this._strategy.strategy === "remote") {
|
|
21
|
+
this._orm = await SqlMikroORM.init({
|
|
22
|
+
driver: SqliteDriver,
|
|
23
|
+
driverOptions: new HttpVFSDialect(url),
|
|
24
|
+
dbName: url,
|
|
25
|
+
entities,
|
|
26
|
+
allowGlobalContext: true,
|
|
27
|
+
});
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const { SQLocalKysely } = await import("sqlocal/kysely");
|
|
31
|
+
if (!this._db) {
|
|
32
|
+
this._db = new SQLocalKysely("dol.sqlite");
|
|
33
|
+
}
|
|
34
|
+
const storedEtag = localStorage.getItem(ETAG_KEY);
|
|
35
|
+
const head = await fetch(url, { method: "HEAD" });
|
|
36
|
+
const remoteEtag = head.headers.get("etag");
|
|
37
|
+
if (!storedEtag || storedEtag !== remoteEtag) {
|
|
38
|
+
const response = await fetch(url);
|
|
39
|
+
if (!response.ok)
|
|
40
|
+
throw new Error(`Failed to fetch database: ${response.status}`);
|
|
41
|
+
await this._db.overwriteDatabaseFile(await response.arrayBuffer());
|
|
42
|
+
if (remoteEtag)
|
|
43
|
+
localStorage.setItem(ETAG_KEY, remoteEtag);
|
|
44
|
+
}
|
|
45
|
+
this._orm = await SqlMikroORM.init({
|
|
46
|
+
driver: SqliteDriver,
|
|
47
|
+
driverOptions: this._db.dialect,
|
|
48
|
+
dbName: "dol.sqlite",
|
|
49
|
+
entities,
|
|
50
|
+
allowGlobalContext: true,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
// sqlocal instance kept across load() calls to preserve OPFS connection
|
|
54
|
+
_db;
|
|
55
|
+
}
|
|
56
|
+
export function createClient(strategy = {}) {
|
|
57
|
+
return new Client(strategy);
|
|
58
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const DEFAULT_URL = "https://data.loathers.net/data-of-loathing.sqlite";
|
|
2
|
+
export type BrowserStrategy = {
|
|
3
|
+
strategy?: "cache";
|
|
4
|
+
url?: string;
|
|
5
|
+
} | {
|
|
6
|
+
strategy: "remote";
|
|
7
|
+
url?: string;
|
|
8
|
+
};
|
|
9
|
+
export declare function resolveDbPath(opts: BrowserStrategy): Promise<string>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export const DEFAULT_URL = "https://data.loathers.net/data-of-loathing.sqlite";
|
|
2
|
+
const OPFS_FILENAME = "data-of-loathing.sqlite";
|
|
3
|
+
const ETAG_KEY = "data-of-loathing-etag";
|
|
4
|
+
async function writeToOpfs(data) {
|
|
5
|
+
const root = await navigator.storage.getDirectory();
|
|
6
|
+
const handle = await root.getFileHandle(OPFS_FILENAME, { create: true });
|
|
7
|
+
const writable = await handle.createWritable();
|
|
8
|
+
await writable.write(data);
|
|
9
|
+
await writable.close();
|
|
10
|
+
}
|
|
11
|
+
async function opfsFileExists() {
|
|
12
|
+
try {
|
|
13
|
+
const root = await navigator.storage.getDirectory();
|
|
14
|
+
await root.getFileHandle(OPFS_FILENAME);
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export async function resolveDbPath(opts) {
|
|
22
|
+
if (opts.strategy === "remote")
|
|
23
|
+
throw new Error("HTTP range request strategy not yet implemented");
|
|
24
|
+
const url = opts.url ?? DEFAULT_URL;
|
|
25
|
+
const storedEtag = localStorage.getItem(ETAG_KEY);
|
|
26
|
+
const head = await fetch(url, { method: "HEAD" });
|
|
27
|
+
const remoteEtag = head.headers.get("etag");
|
|
28
|
+
if (!(await opfsFileExists()) || storedEtag !== remoteEtag) {
|
|
29
|
+
const response = await fetch(url);
|
|
30
|
+
if (!response.ok)
|
|
31
|
+
throw new Error(`Failed to fetch database: ${response.status}`);
|
|
32
|
+
await writeToOpfs(await response.arrayBuffer());
|
|
33
|
+
if (remoteEtag)
|
|
34
|
+
localStorage.setItem(ETAG_KEY, remoteEtag);
|
|
35
|
+
}
|
|
36
|
+
return OPFS_FILENAME;
|
|
37
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BaseClient } from "./BaseClient.js";
|
|
2
|
+
export type Strategy = {
|
|
3
|
+
strategy?: "url";
|
|
4
|
+
url?: string;
|
|
5
|
+
force?: boolean;
|
|
6
|
+
};
|
|
7
|
+
export declare class Client extends BaseClient<Strategy> {
|
|
8
|
+
private _db?;
|
|
9
|
+
constructor(strategy?: Strategy);
|
|
10
|
+
protected getStoredEtag(_key: string): Promise<string | null>;
|
|
11
|
+
protected storeEtag(_key: string, etag: string): Promise<void>;
|
|
12
|
+
load(): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
export declare function createClient(strategy?: Strategy): Client;
|
|
15
|
+
export * from "data-of-loathing-schema";
|
package/dist/browser.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { SqlMikroORM, SqliteDriver } from "@mikro-orm/sql";
|
|
2
|
+
import { SQLocalKysely } from "sqlocal/kysely";
|
|
3
|
+
import { entities } from "data-of-loathing-schema";
|
|
4
|
+
import { BaseClient, DEFAULT_URL, ETAG_KEY } from "./BaseClient.js";
|
|
5
|
+
export class Client extends BaseClient {
|
|
6
|
+
_db;
|
|
7
|
+
constructor(strategy = {}) {
|
|
8
|
+
super(strategy);
|
|
9
|
+
}
|
|
10
|
+
async getStoredEtag(_key) {
|
|
11
|
+
return localStorage.getItem(ETAG_KEY);
|
|
12
|
+
}
|
|
13
|
+
async storeEtag(_key, etag) {
|
|
14
|
+
localStorage.setItem(ETAG_KEY, etag);
|
|
15
|
+
}
|
|
16
|
+
async load() {
|
|
17
|
+
await this._orm?.close();
|
|
18
|
+
const url = this._strategy.url ?? DEFAULT_URL;
|
|
19
|
+
if (!this._db) {
|
|
20
|
+
this._db = new SQLocalKysely("dol.sqlite");
|
|
21
|
+
}
|
|
22
|
+
await this.syncIfNeeded(url, ETAG_KEY, (data) => this._db.overwriteDatabaseFile(data), this._strategy.force);
|
|
23
|
+
this._orm = await SqlMikroORM.init({
|
|
24
|
+
driver: SqliteDriver,
|
|
25
|
+
driverOptions: this._db.dialect,
|
|
26
|
+
dbName: "dol.sqlite",
|
|
27
|
+
entities,
|
|
28
|
+
allowGlobalContext: true,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export function createClient(strategy = {}) {
|
|
33
|
+
return new Client(strategy);
|
|
34
|
+
}
|
|
35
|
+
export * from "data-of-loathing-schema";
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { EntityManager } from "@mikro-orm/core";
|
|
2
|
+
import { type Strategy } from "./strategies.js";
|
|
3
|
+
export type { Strategy };
|
|
4
|
+
export declare class Client {
|
|
5
|
+
private _orm?;
|
|
6
|
+
private readonly _strategy;
|
|
7
|
+
constructor(strategy?: Strategy);
|
|
8
|
+
get em(): EntityManager;
|
|
9
|
+
load(): Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
export declare function createClient(strategy?: Strategy): Client;
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { NodeSqliteDialect, SqliteDriver, SqlMikroORM } from "@mikro-orm/sql";
|
|
2
|
+
import { entities } from "data-of-loathing-schema";
|
|
3
|
+
import { resolveDbPath } from "./strategies.js";
|
|
4
|
+
export class Client {
|
|
5
|
+
_orm;
|
|
6
|
+
_strategy;
|
|
7
|
+
constructor(strategy = {}) {
|
|
8
|
+
this._strategy = strategy;
|
|
9
|
+
}
|
|
10
|
+
get em() {
|
|
11
|
+
if (!this._orm)
|
|
12
|
+
throw new Error("Call await client.load() before querying");
|
|
13
|
+
return this._orm.em;
|
|
14
|
+
}
|
|
15
|
+
async load() {
|
|
16
|
+
await this._orm?.close();
|
|
17
|
+
const path = await resolveDbPath(this._strategy);
|
|
18
|
+
this._orm = await SqlMikroORM.init({
|
|
19
|
+
driver: SqliteDriver,
|
|
20
|
+
driverOptions: new NodeSqliteDialect(path),
|
|
21
|
+
dbName: path,
|
|
22
|
+
entities,
|
|
23
|
+
allowGlobalContext: true,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export function createClient(strategy = {}) {
|
|
28
|
+
return new Client(strategy);
|
|
29
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|