@ankinize/sdk 0.0.0-stage → 1.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/README.md +78 -2
- package/dist/batch.d.ts +157 -0
- package/dist/batch.js +263 -0
- package/dist/gen/client/client.gen.d.ts +2 -0
- package/dist/gen/client/client.gen.js +216 -0
- package/dist/gen/client/index.d.ts +10 -0
- package/dist/gen/client/index.js +6 -0
- package/dist/gen/client/types.gen.d.ts +120 -0
- package/dist/gen/client/types.gen.js +2 -0
- package/dist/gen/client/utils.gen.d.ts +37 -0
- package/dist/gen/client/utils.gen.js +228 -0
- package/dist/gen/client.gen.d.ts +12 -0
- package/dist/gen/client.gen.js +4 -0
- package/dist/gen/core/auth.gen.d.ts +25 -0
- package/dist/gen/core/auth.gen.js +14 -0
- package/dist/gen/core/bodySerializer.gen.d.ts +25 -0
- package/dist/gen/core/bodySerializer.gen.js +57 -0
- package/dist/gen/core/params.gen.d.ts +43 -0
- package/dist/gen/core/params.gen.js +109 -0
- package/dist/gen/core/pathSerializer.gen.d.ts +33 -0
- package/dist/gen/core/pathSerializer.gen.js +106 -0
- package/dist/gen/core/queryKeySerializer.gen.d.ts +18 -0
- package/dist/gen/core/queryKeySerializer.gen.js +92 -0
- package/dist/gen/core/serverSentEvents.gen.d.ts +71 -0
- package/dist/gen/core/serverSentEvents.gen.js +132 -0
- package/dist/gen/core/types.gen.d.ts +83 -0
- package/dist/gen/core/types.gen.js +2 -0
- package/dist/gen/core/utils.gen.d.ts +19 -0
- package/dist/gen/core/utils.gen.js +87 -0
- package/dist/gen/public.gen.d.ts +1 -0
- package/dist/gen/public.gen.js +2 -0
- package/dist/gen/sdk.gen.d.ts +504 -0
- package/dist/gen/sdk.gen.js +880 -0
- package/dist/gen/types.gen.d.ts +3452 -0
- package/dist/gen/types.gen.js +2 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +5 -0
- package/dist/runtime.d.ts +19 -0
- package/dist/runtime.js +57 -0
- package/dist/typed.d.ts +90 -0
- package/dist/typed.js +51 -0
- package/package.json +43 -5
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { BATCH_LIMITS, type BatchOptions, type CreateNotesResult, type CreateTagsResult, createNotes, createTags, type DeleteCardsResult, type DeleteNotesResult, type DeleteTagsResult, deleteCards, deleteNotes, deleteTags, PartialBatchError, type UpdateCardsResult, type UpdateNotesResult, type UpdateTagsResult, updateCards, updateNotes, updateTags, } from "./batch.js";
|
|
2
|
+
export { client } from "./gen/client.gen.js";
|
|
3
|
+
export * from "./gen/public.gen.js";
|
|
4
|
+
export type * from "./gen/types.gen.js";
|
|
5
|
+
export { AnkinizeError } from "./runtime.js";
|
|
6
|
+
export { createNote, type DeckName, generateTypes, type NoteFields, type NoteInput, type Register, } from "./typed.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { BATCH_LIMITS, createNotes, createTags, deleteCards, deleteNotes, deleteTags, PartialBatchError, updateCards, updateNotes, updateTags, } from "./batch.js";
|
|
2
|
+
export { client } from "./gen/client.gen.js";
|
|
3
|
+
export * from "./gen/public.gen.js";
|
|
4
|
+
export { AnkinizeError } from "./runtime.js";
|
|
5
|
+
export { createNote, generateTypes, } from "./typed.js";
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { CreateClientConfig } from "./gen/client.gen.js";
|
|
2
|
+
/** Thrown for every answer that is not 2xx. */
|
|
3
|
+
export declare class AnkinizeError extends Error {
|
|
4
|
+
/** HTTP status, for example 404 or 429. */
|
|
5
|
+
readonly status: number;
|
|
6
|
+
/** Machine-readable reason, for example `not_found` or `rate_limited`. */
|
|
7
|
+
readonly code: string;
|
|
8
|
+
/** The raw answer, for headers such as `Retry-After`. Its body is already read. */
|
|
9
|
+
readonly response: Response;
|
|
10
|
+
readonly name = "AnkinizeError";
|
|
11
|
+
constructor(
|
|
12
|
+
/** HTTP status, for example 404 or 429. */
|
|
13
|
+
status: number,
|
|
14
|
+
/** Machine-readable reason, for example `not_found` or `rate_limited`. */
|
|
15
|
+
code: string, message: string,
|
|
16
|
+
/** The raw answer, for headers such as `Retry-After`. Its body is already read. */
|
|
17
|
+
response: Response);
|
|
18
|
+
}
|
|
19
|
+
export declare const createClientConfig: CreateClientConfig;
|
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/** Thrown for every answer that is not 2xx. */
|
|
2
|
+
export class AnkinizeError extends Error {
|
|
3
|
+
status;
|
|
4
|
+
code;
|
|
5
|
+
response;
|
|
6
|
+
name = "AnkinizeError";
|
|
7
|
+
constructor(
|
|
8
|
+
/** HTTP status, for example 404 or 429. */
|
|
9
|
+
status,
|
|
10
|
+
/** Machine-readable reason, for example `not_found` or `rate_limited`. */
|
|
11
|
+
code, message,
|
|
12
|
+
/** The raw answer, for headers such as `Retry-After`. Its body is already read. */
|
|
13
|
+
response) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.status = status;
|
|
16
|
+
this.code = code;
|
|
17
|
+
this.response = response;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
async function toError(response) {
|
|
21
|
+
const text = await response.text();
|
|
22
|
+
let body;
|
|
23
|
+
try {
|
|
24
|
+
body = JSON.parse(text);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// Not from the API (a proxy's error page, say): fall through to the status.
|
|
28
|
+
}
|
|
29
|
+
return new AnkinizeError(response.status, body?.error?.code ?? `http_${response.status}`, body?.error?.message ?? (text || response.statusText), response);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The generated client picks how to read a body from its Content-Type, and
|
|
33
|
+
* reads a type it does not know as JSON. Media files can be fonts, which it
|
|
34
|
+
* does not know, so they are handed over as plain bytes (a Blob).
|
|
35
|
+
*/
|
|
36
|
+
function asBytes(response) {
|
|
37
|
+
if (!response.headers.get("Content-Type")?.startsWith("font/"))
|
|
38
|
+
return response;
|
|
39
|
+
const headers = new Headers(response.headers);
|
|
40
|
+
headers.set("Content-Type", "application/octet-stream");
|
|
41
|
+
return new Response(response.body, {
|
|
42
|
+
status: response.status,
|
|
43
|
+
statusText: response.statusText,
|
|
44
|
+
headers,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/** Looks `fetch` up per call, so a test double or a polyfill installed later still applies. */
|
|
48
|
+
const apiFetch = async (input, init) => {
|
|
49
|
+
const response = await globalThis.fetch(input, init);
|
|
50
|
+
if (!response.ok)
|
|
51
|
+
throw await toError(response);
|
|
52
|
+
return asBytes(response);
|
|
53
|
+
};
|
|
54
|
+
export const createClientConfig = (config) => ({
|
|
55
|
+
...config,
|
|
56
|
+
fetch: apiFetch,
|
|
57
|
+
});
|
package/dist/typed.d.ts
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type-safe names. Out of the box a note is made by `notetypeName` and
|
|
3
|
+
* `deckName` strings and a `fields` object of strings. Describe your own
|
|
4
|
+
* collection once, with {@link generateTypes}, and the compiler also knows
|
|
5
|
+
* which note types and decks exist and which field keys each note type has.
|
|
6
|
+
*/
|
|
7
|
+
import { createNote as generatedCreateNote, listDecks } from "./gen/sdk.gen.js";
|
|
8
|
+
import type { CreateNoteInput } from "./gen/types.gen.js";
|
|
9
|
+
/**
|
|
10
|
+
* Filled in by your own declaration, usually the file {@link generateTypes}
|
|
11
|
+
* writes. Without it every name is a plain `string`.
|
|
12
|
+
*
|
|
13
|
+
* ```ts
|
|
14
|
+
* declare module "@ankinize/sdk" {
|
|
15
|
+
* interface Register {
|
|
16
|
+
* noteTypes: { Basic: "front" | "back"; "Cloze": "text" | "backExtra" };
|
|
17
|
+
* decks: "Default" | "Languages::German";
|
|
18
|
+
* }
|
|
19
|
+
* }
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export interface Register {
|
|
23
|
+
}
|
|
24
|
+
/** Note type name to the union of its field keys. */
|
|
25
|
+
type NoteTypes = Register extends {
|
|
26
|
+
noteTypes: infer T extends Record<string, string>;
|
|
27
|
+
} ? T : never;
|
|
28
|
+
/** The names of your decks, or `string`. */
|
|
29
|
+
export type DeckName = Register extends {
|
|
30
|
+
decks: infer D extends string;
|
|
31
|
+
} ? D : string;
|
|
32
|
+
/** The `fields` of a note by key; `Record<string, string>` until note types are registered. */
|
|
33
|
+
export type NoteFields<Name extends string = string> = [NoteTypes] extends [
|
|
34
|
+
never
|
|
35
|
+
] ? Record<string, string> : Name extends keyof NoteTypes ? {
|
|
36
|
+
[K in NoteTypes[Name]]?: string;
|
|
37
|
+
} : Record<string, string>;
|
|
38
|
+
type Base = Omit<CreateNoteInput, "notetypeName" | "notetypeId" | "deckName" | "deckId" | "fields">;
|
|
39
|
+
type ByName = [NoteTypes] extends [never] ? {
|
|
40
|
+
notetypeName: string;
|
|
41
|
+
fields: NoteFields;
|
|
42
|
+
} : {
|
|
43
|
+
[N in keyof NoteTypes & string]: {
|
|
44
|
+
notetypeName: N;
|
|
45
|
+
fields: NoteFields<N>;
|
|
46
|
+
};
|
|
47
|
+
}[keyof NoteTypes & string];
|
|
48
|
+
/** The id path is not checked against your note types; its fields are by key. */
|
|
49
|
+
type ById = {
|
|
50
|
+
notetypeId: number;
|
|
51
|
+
fields: Record<string, string>;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* A note to create: a note type by `notetypeName` (or `notetypeId`), at most
|
|
55
|
+
* one of `deckName` and `deckId`, and `fields` keyed by the note type's field
|
|
56
|
+
* keys.
|
|
57
|
+
*/
|
|
58
|
+
export type NoteInput = Base & ((ByName & {
|
|
59
|
+
notetypeId?: never;
|
|
60
|
+
}) | (ById & {
|
|
61
|
+
notetypeName?: never;
|
|
62
|
+
})) & ({
|
|
63
|
+
deckName?: DeckName;
|
|
64
|
+
deckId?: never;
|
|
65
|
+
} | {
|
|
66
|
+
deckId?: number;
|
|
67
|
+
deckName?: never;
|
|
68
|
+
});
|
|
69
|
+
/**
|
|
70
|
+
* Creates a note and its cards. Same call as the generated operation, with
|
|
71
|
+
* `notetypeName`, `deckName` and `fields` checked against {@link Register}.
|
|
72
|
+
* Send `idempotencyKey` to make a retry safe.
|
|
73
|
+
*/
|
|
74
|
+
export declare const createNote: <ThrowOnError extends boolean = true>(parameters: NoteInput & {
|
|
75
|
+
idempotencyKey?: string;
|
|
76
|
+
}, options?: Parameters<typeof generatedCreateNote<ThrowOnError>>[1]) => import("./gen/client/types.gen.js").RequestResult<import("./index.js").CreateNoteResponses, import("./index.js").CreateNoteErrors, ThrowOnError, "data">;
|
|
77
|
+
/**
|
|
78
|
+
* The text of a declaration file that registers this collection's note types,
|
|
79
|
+
* their field keys and its decks. Write it anywhere the compiler reads:
|
|
80
|
+
*
|
|
81
|
+
* ```ts
|
|
82
|
+
* await Bun.write("ankinize.d.ts", await generateTypes());
|
|
83
|
+
* ```
|
|
84
|
+
*
|
|
85
|
+
* Run it again after you add a note type, a field or a deck.
|
|
86
|
+
*/
|
|
87
|
+
export declare function generateTypes(options?: {
|
|
88
|
+
client?: NonNullable<Parameters<typeof listDecks>[0]>["client"];
|
|
89
|
+
}): Promise<string>;
|
|
90
|
+
export {};
|
package/dist/typed.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type-safe names. Out of the box a note is made by `notetypeName` and
|
|
3
|
+
* `deckName` strings and a `fields` object of strings. Describe your own
|
|
4
|
+
* collection once, with {@link generateTypes}, and the compiler also knows
|
|
5
|
+
* which note types and decks exist and which field keys each note type has.
|
|
6
|
+
*/
|
|
7
|
+
import { createNote as generatedCreateNote, getNoteType, listDecks, listNoteTypes, } from "./gen/sdk.gen.js";
|
|
8
|
+
/**
|
|
9
|
+
* Creates a note and its cards. Same call as the generated operation, with
|
|
10
|
+
* `notetypeName`, `deckName` and `fields` checked against {@link Register}.
|
|
11
|
+
* Send `idempotencyKey` to make a retry safe.
|
|
12
|
+
*/
|
|
13
|
+
export const createNote = (parameters, options) => generatedCreateNote(parameters, options);
|
|
14
|
+
/**
|
|
15
|
+
* The text of a declaration file that registers this collection's note types,
|
|
16
|
+
* their field keys and its decks. Write it anywhere the compiler reads:
|
|
17
|
+
*
|
|
18
|
+
* ```ts
|
|
19
|
+
* await Bun.write("ankinize.d.ts", await generateTypes());
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* Run it again after you add a note type, a field or a deck.
|
|
23
|
+
*/
|
|
24
|
+
export async function generateTypes(options = {}) {
|
|
25
|
+
const request = { client: options.client };
|
|
26
|
+
const { decks } = await listDecks(request);
|
|
27
|
+
const { noteTypes } = await listNoteTypes(request);
|
|
28
|
+
const lines = [];
|
|
29
|
+
for (const { id, name } of noteTypes) {
|
|
30
|
+
if (id === undefined || name === undefined)
|
|
31
|
+
continue;
|
|
32
|
+
const { fields } = await getNoteType({ id }, request);
|
|
33
|
+
const keys = fields.map((f) => JSON.stringify(f.key)).join(" | ");
|
|
34
|
+
lines.push(`\t\t${JSON.stringify(name)}: ${keys || "never"};`);
|
|
35
|
+
}
|
|
36
|
+
const deckNames = decks.map((d) => JSON.stringify(d.name)).join(" | ");
|
|
37
|
+
return [
|
|
38
|
+
"// Generated by generateTypes() from @ankinize/sdk. Do not edit.",
|
|
39
|
+
"export {};",
|
|
40
|
+
"",
|
|
41
|
+
'declare module "@ankinize/sdk" {',
|
|
42
|
+
"\tinterface Register {",
|
|
43
|
+
"\t\tnoteTypes: {",
|
|
44
|
+
...lines.map((l) => `\t${l}`),
|
|
45
|
+
"\t\t};",
|
|
46
|
+
`\t\tdecks: ${deckNames || "never"};`,
|
|
47
|
+
"\t}",
|
|
48
|
+
"}",
|
|
49
|
+
"",
|
|
50
|
+
].join("\n");
|
|
51
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,44 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
"name": "@ankinize/sdk",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Official TypeScript SDK for the Ankinize REST API. Plain fetch, no runtime dependencies.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/0x0501/Ankinize.git",
|
|
9
|
+
"directory": "packages/sdk"
|
|
10
|
+
},
|
|
11
|
+
"publishConfig": {
|
|
12
|
+
"access": "public"
|
|
13
|
+
},
|
|
14
|
+
"type": "module",
|
|
15
|
+
"sideEffects": false,
|
|
16
|
+
"main": "./dist/index.js",
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"default": "./dist/index.js"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"README.md"
|
|
27
|
+
],
|
|
28
|
+
"scripts": {
|
|
29
|
+
"generate": "bun install --cwd generator --frozen-lockfile && bun run --cwd generator generate && bun run scripts/idempotency-key.ts && bun run scripts/public-api.ts",
|
|
30
|
+
"build": "rm -rf dist && tsc -p tsconfig.build.json",
|
|
31
|
+
"check:dist": "bun run build && bun run scripts/check-dist.ts",
|
|
32
|
+
"prepack": "bun run build",
|
|
33
|
+
"test": "vitest run",
|
|
34
|
+
"test:unit": "vitest run",
|
|
35
|
+
"typecheck": "tsc --noEmit",
|
|
36
|
+
"lint": "biome lint .",
|
|
37
|
+
"format": "biome format .",
|
|
38
|
+
"check": "biome check ."
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"typescript": "^7.0.2",
|
|
42
|
+
"vitest": "^4.1.11"
|
|
43
|
+
}
|
|
44
|
+
}
|