diff options
Diffstat (limited to 'kittybox-rs/companion-lite')
-rw-r--r-- | kittybox-rs/companion-lite/index.html | 127 | ||||
-rw-r--r-- | kittybox-rs/companion-lite/src/base64.ts | 89 | ||||
-rw-r--r-- | kittybox-rs/companion-lite/src/indieauth.ts | 113 | ||||
-rw-r--r-- | kittybox-rs/companion-lite/src/main.ts | 178 | ||||
-rw-r--r-- | kittybox-rs/companion-lite/src/micropub_api.ts | 125 | ||||
-rw-r--r-- | kittybox-rs/companion-lite/style.css | 47 | ||||
-rw-r--r-- | kittybox-rs/companion-lite/tsconfig.json | 104 |
7 files changed, 0 insertions, 783 deletions
diff --git a/kittybox-rs/companion-lite/index.html b/kittybox-rs/companion-lite/index.html deleted file mode 100644 index fc99c60..0000000 --- a/kittybox-rs/companion-lite/index.html +++ /dev/null @@ -1,127 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <meta charset="utf-8"> - <title>Kittybox-Micropub debug client</title> - <link rel="stylesheet" href="./style.css"> - <script type="module" src="./main.js"></script> - <link rel="jslicense" href="#jslicense"> - </head> - <body> - <noscript> - <h1 class="header">Kittybox Companion (Lite)</h1> - <p>I'm sorry, Kittybox Companion requires JavaScript to work.</p> - - <p>This is a requirement due to multiple interactive features present in Kittybox, such as support for multiple-entry form fields, interactive login sequence and more.</p> - - <p>However, the Micropub standard is extremely flexible, and if you happen to have a token, you can publish articles, notes, likes, follows and more by sending requests directly to the Micropub endpoint.</p> - - <p><a href="https://micropub.spec.indieweb.org/">The Micropub spec is defined here.</a> Good luck!</p> - </noscript> - - <div class="view" id="unauthorized" style="display:none"> - <form action="#" id="indieauth"> - <label for="me">Your website URL:</label> - <input id="me" name="me" type="url"> - <input type="submit"> - </form> - </div> - - <div class="view" id="authorizing" style="display:none"> - <p>Performing the authorization dance...</p> - </div> - - <div class="view" id="authorized" style="display:none"> - <form action="/.kittybox/micropub" method="POST" id="micropub"> - <fieldset> - <legend>Post details:</legend> - <section> - <label for="name">Name (leave blank for an unnamed post):</label> - <input id="name" type="text"> - </section> - <section> - <label for="content">Content:</label> - <textarea id="content" placeholder="Your post's text goes here"></textarea> - </section> - <section> - <label for="category">Categories (separeted by commas):</label> - <input id="category" type="text"> - </section> - <fieldset> - <legend>Channels</legend> - <section> - <input type="radio" id="no_channel" name="channel_select" checked value=""> - <label for="no_channel">Default channel only</label> - </section> - - <section> - <input type="radio" id="select_channels" name="channel_select" value="on"> - <label for="select_channels">Select channels manually</label> - </section> - - <fieldset id="channels" style="display: none"> - <legend>Available channels:</legend> - <template id="channel_selector"> - <section> - <input type="checkbox" name="channel" id="" value=""> - <label for=""></label> - </section> - </template> - <div id="channels_target"></div> - </fieldset> - </fieldset> - </fieldset> - <input type="submit"> - </form> - </div> - - <details id="jslicense"> - <summary>JavaScript licensing information for this software</summary> - <table id="jslicense-labels1"> - <tr> - <td><a href="/.kittybox/micropub/client/main.js">main.js</a></td> - <td><a href="http://www.gnu.org/licenses/agpl-3.0.html">AGPL-3.0</a></td> - <td><a href="https://git.sr.ht/~vikanezrimaya/kittybox/tree/main/item/kittybox-rs/companion-lite/src/main.ts">main.ts (Kittybox source code)</a></td> - </tr> - <tr> - <td><a href="/.kittybox/micropub/client/micropub_api.js">micropub_api.js</a></td> - <td><a href="http://www.gnu.org/licenses/agpl-3.0.html">AGPL-3.0</a></td> - <td><a href="https://git.sr.ht/~vikanezrimaya/kittybox/tree/main/item/kittybox-rs/companion-lite/src/micropub_api.ts">micropub_api.ts (Kittybox source code)</a></td> - </tr> - <tr> - <td><a href="/.kittybox/micropub/client/indieauth.js">indieauth.js</a></td> - <td><a href="http://www.gnu.org/licenses/agpl-3.0.html">AGPL-3.0</a></td> - <td><a href="https://git.sr.ht/~vikanezrimaya/kittybox/tree/main/item/kittybox-rs/companion-lite/src/indieauth.ts">indieauth.ts (Kittybox source code)</a></td> - </tr> - <tr> - <td><a href="/.kittybox/micropub/client/base64.js">base64.js</a></td> - <td><a href="http://creativecommons.org/publicdomain/zero/1.0/legalcode">CC0 (Public Domain)</a></td> - <td><a href="https://git.sr.ht/~vikanezrimaya/kittybox/tree/main/item/kittybox-rs/companion-lite/src/base64.ts">base64.ts</a>, adapted from <a href="https://developer.mozilla.org/en-US/docs/Glossary/Base64#solution_2_%E2%80%93_rewriting_atob_and_btoa_using_typedarrays_and_utf-8">MDN page on Base64</a></td> - </tr> - <tr> - <td><a href="https://esm.sh/microformats-parser@1.4.1?pin=v96">ESM.sh entrypoint for microformats-parser</a></td> - <td><a href="http://www.jclark.com/xml/copying.txt">MIT/Expat</a></td> - <td><a href="https://github.com/ije/esm.sh/blob/main/server/handler.go">esm.sh source code</a> - </tr> - <tr> - <td><a href="https://esm.sh/v96/microformats-parser@1.4.1/es2022/microformats-parser.js">microformats-parser</a></td> - <td><a href="http://www.jclark.com/xml/copying.txt">MIT/Expat</a></td> - <td><a href="https://github.com/microformats/microformats-parser">GitHub repository</a> - </tr> - <tr> - <td><a href="https://esm.sh/v96/parse5@6.0.1/es2022/parse5.js">parse5</a></td> - <td> - <a href="http://www.jclark.com/xml/copying.txt">MIT/Expat</a> - <br> - <a href="http://www.freebsd.org/copyright/freebsd-license.html">BSD-2-Clause</a> - </td> - <td> - <a href="https://github.com/inikulin/parse5">GitHub repository for parse5</a> - <br> - <a href="https://github.com/fb55/entities">GitHub repository for entitites</a>, a parse5 dependency - </td> - </tr> - </table> - </details> - </body> -</html> diff --git a/kittybox-rs/companion-lite/src/base64.ts b/kittybox-rs/companion-lite/src/base64.ts deleted file mode 100644 index 2429894..0000000 --- a/kittybox-rs/companion-lite/src/base64.ts +++ /dev/null @@ -1,89 +0,0 @@ -// Array of bytes to Base64 string decoding -function b64ToUint6(nChr: number) { - return nChr > 64 && nChr < 91 - ? nChr - 65 - : nChr > 96 && nChr < 123 - ? nChr - 71 - : nChr > 47 && nChr < 58 - ? nChr + 4 - : nChr === 43 - ? 62 - : nChr === 47 - ? 63 - : 0; -} - -export function decode(sBase64: string, nBlocksSize?: number) { - const sB64Enc = sBase64.replace(/[^A-Za-z0-9+/]/g, ""); - const nInLen = sB64Enc.length; - const nOutLen = nBlocksSize - ? Math.ceil(((nInLen * 3 + 1) >> 2) / nBlocksSize) * nBlocksSize - : (nInLen * 3 + 1) >> 2; - const taBytes = new Uint8Array(nOutLen); - - let nMod3; - let nMod4; - let nUint24 = 0; - let nOutIdx = 0; - for (let nInIdx = 0; nInIdx < nInLen; nInIdx++) { - nMod4 = nInIdx & 3; - nUint24 |= b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << (6 * (3 - nMod4)); - if (nMod4 === 3 || nInLen - nInIdx === 1) { - nMod3 = 0; - while (nMod3 < 3 && nOutIdx < nOutLen) { - taBytes[nOutIdx] = (nUint24 >>> ((16 >>> nMod3) & 24)) & 255; - nMod3++; - nOutIdx++; - } - nUint24 = 0; - } - } - - return taBytes; -} - -/* Base64 string to array encoding */ -function uint6ToB64(nUint6: number) { - return nUint6 < 26 - ? nUint6 + 65 - : nUint6 < 52 - ? nUint6 + 71 - : nUint6 < 62 - ? nUint6 - 4 - : nUint6 === 62 - ? 43 - : nUint6 === 63 - ? 47 - : 65; -} - -export function encode(aBytes: Uint8Array) { - let nMod3 = 2; - let sB64Enc = ""; - - const nLen = aBytes.length; - let nUint24 = 0; - for (let nIdx = 0; nIdx < nLen; nIdx++) { - nMod3 = nIdx % 3; - if (nIdx > 0 && ((nIdx * 4) / 3) % 76 === 0) { - sB64Enc += "\r\n"; - } - - nUint24 |= aBytes[nIdx] << ((16 >>> nMod3) & 24); - if (nMod3 === 2 || aBytes.length - nIdx === 1) { - sB64Enc += String.fromCodePoint( - uint6ToB64((nUint24 >>> 18) & 63), - uint6ToB64((nUint24 >>> 12) & 63), - uint6ToB64((nUint24 >>> 6) & 63), - uint6ToB64(nUint24 & 63) - ); - nUint24 = 0; - } - } - return ( - sB64Enc.substr(0, sB64Enc.length - 2 + nMod3) + - (nMod3 === 2 ? "" : nMod3 === 1 ? "=" : "==") - ); -} - -export default { encode, decode } diff --git a/kittybox-rs/companion-lite/src/indieauth.ts b/kittybox-rs/companion-lite/src/indieauth.ts deleted file mode 100644 index 40facab..0000000 --- a/kittybox-rs/companion-lite/src/indieauth.ts +++ /dev/null @@ -1,113 +0,0 @@ -// @ts-ignore -import { mf2 } from "https://esm.sh/microformats-parser@1.4.1?pin=v96" -import { MF2 } from "./micropub_api.js" -import base64 from "./base64.js" - /* - const { mf2 }: { - mf2: (html: string, options: { - baseUrl: string, - experimental?: { lang?: boolean, textContent?: boolean } - }) => { - items: MF2[], - rels: {[key: string]: string[]}, - "rel-urls": {[key: string]: { rels: string[], text?: string }} - } - } = - // @ts-ignore - await import("https://esm.sh/microformats-parser@1.4.1?pin=v96"); - */ - -interface IndieauthMetadata { - authorization_endpoint: string, - token_endpoint: string, - issuer: string, - introspection_endpoint?: string, - introspection_endpoint_auth_methods_supported?: ("Bearer")[], - revocation_endpoint?: string, - revocation_endpoint_auth_methods_supported?: ["none"], - scopes_supported?: string[], - response_types_supported: ["code"], - grant_types_supported: ("authorization_code" | "refresh_token")[] - code_challenge_methods_supported: ("S256")[] - authorization_response_iss_parameter_supported: true, - userinfo_endpoint?: string -} - -interface MF2ParsedData { - items: MF2[], - rels: {[key: string]: string[]}, - "rel-urls": {[key: string]: { rels: string[], text?: string }} -} - -export interface IndiewebEndpoints { - authorization_endpoint: URL, - token_endpoint: URL, - userinfo_endpoint: URL | null, - revocation_endpoint: URL | null, - micropub: URL, - -} - -export function create_verifier() { - const array = new Uint8Array(64) - crypto.getRandomValues(array) - - return array.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), '') -} - -export async function create_challenge(verifier: string): Promise<string> { - return await crypto.subtle.digest('SHA-256', Uint8Array.from(verifier, c => c.charCodeAt(0))) - .then((buf) => base64.encode(new Uint8Array(buf))) - .then(s => { - return s - .replaceAll("+", "-") - .replaceAll("/", "_") - .replaceAll(/=$/g, "") - }) -} - -export async function discover_endpoints(me: URL): Promise<IndiewebEndpoints | null> { - const response = await fetch(me); - const data: MF2ParsedData = mf2(await response.text(), { baseUrl: me.toString() }); - let endpoints: Partial<IndiewebEndpoints> = {}; - if ("micropub" in data.rels) { - endpoints.micropub = new URL(data.rels.micropub[0]) - } else { - return null - } - if ("indieauth_metadata" in data.rels) { - const metadata_response = await fetch(data.rels.indieauth_metadata[0], { - headers: { - "Accept": "application/json" - } - }); - - const metadata = await metadata_response.json() as IndieauthMetadata; - endpoints.authorization_endpoint = new URL(metadata.authorization_endpoint) - endpoints.token_endpoint = new URL(metadata.token_endpoint) - if (metadata.userinfo_endpoint != null) { - endpoints.userinfo_endpoint = new URL(metadata.userinfo_endpoint) - } else { - endpoints.userinfo_endpoint = null - } - if (metadata.revocation_endpoint != null) { - endpoints.revocation_endpoint = new URL(metadata.revocation_endpoint) - } else { - endpoints.revocation_endpoint = null - } - - return endpoints as IndiewebEndpoints - } else if ( - "authorization_endpoint" in data.rels - && "token_endpoint" in data.rels - ) { - endpoints.authorization_endpoint = new URL(data.rels.authorization_endpoint[0]) - endpoints.token_endpoint = new URL(data.rels.token_endpoint[0]) - endpoints.userinfo_endpoint = null - endpoints.revocation_endpoint = null - - return endpoints as IndiewebEndpoints - } else { - return null - } -} diff --git a/kittybox-rs/companion-lite/src/main.ts b/kittybox-rs/companion-lite/src/main.ts deleted file mode 100644 index f45cb95..0000000 --- a/kittybox-rs/companion-lite/src/main.ts +++ /dev/null @@ -1,178 +0,0 @@ -import { Micropub, MicropubChannel, MF2 } from "./micropub_api.js"; - -const channel_select_radio = document.getElementById("select_channels") as HTMLInputElement; -channel_select_radio.onclick = async () => { - function populate_channel_list(channels: MicropubChannel[]) { - (document.getElementById("channels") as HTMLElement).style.display = "block"; - const channel_list = document.getElementById("channels_target") as HTMLElement; - channel_list.innerHTML = ""; - channels.forEach((channel) => { - const template = (document.getElementById("channel_selector") as HTMLTemplateElement).content.cloneNode(true) as HTMLElement; - const input = template.querySelector("input") as HTMLInputElement; - const label = template.querySelector("label") as HTMLLabelElement; - input.id = `channel_selector_option_${channel.uid}` - input.value = channel.uid - label.htmlFor = input.id - label.innerHTML = `<a href="${channel.uid}">${channel.name}</a>` - - channel_list.appendChild(template) - }) - } - - if (micropub == null) { - throw new Error("need to authenticate first"); - } - const config = await micropub.config(); - if (config.channels !== undefined) { - populate_channel_list(config.channels) - } -} - -const no_channel_radio = document.getElementById("no_channel") as HTMLInputElement; -no_channel_radio.onclick = () => { - (document.getElementById("channels") as HTMLElement).style.display = "none"; - const channel_list = document.getElementById("channels_target") as HTMLElement - channel_list.innerHTML = ""; -} - -const main_form = document.getElementById("micropub") as HTMLFormElement; -main_form.onsubmit = async (event) => { - function construct_body(form: HTMLFormElement): MF2 { - let content = (form.elements.namedItem("content") as HTMLInputElement).value; - let name: string | undefined = (form.elements.namedItem("name") as HTMLInputElement).value || undefined; - let category: string[] = (form.elements.namedItem("category") as HTMLInputElement).value - .split(",") - .map(val => val.trim()); - - let channel: string[] | undefined = undefined; - let channel_select = (form.elements.namedItem("channel_select") as HTMLInputElement).value; - if (channel_select) { - let channel_selector = form.elements.namedItem("channel"); - if (channel_selector instanceof RadioNodeList) { - channel = (Array.from(channel_selector) as HTMLInputElement[]) - .map(i => i.checked ? i.value : false) - .filter(i => i) as string[]; - } else if (channel_selector instanceof HTMLInputElement) { - channel = [channel_selector.value] - } - } - return { - type: ["h-entry"], - properties: { - content: [content], - name: name ? [name] : undefined, - category: category.length ? category : undefined, - channel: channel ? channel : undefined - } - } - } - - event.preventDefault() - const mf2 = construct_body(main_form); - console.log(JSON.stringify(mf2)); - if (micropub == null) { - throw new Error("need to authenticate first"); - } - try { - const location = await micropub.submit(mf2); - main_form.clear() - - window.open(location, "_blank") - } catch (e) { - console.error(e) - alert(`Error: ${e}`) - return - } - -} - -const indieauth_form = document.getElementById("indieauth") as HTMLFormElement; -indieauth_form.onsubmit = async (event) => { - event.preventDefault() - const form = event.target as HTMLFormElement; - const me = (form.elements.namedItem("me") as HTMLInputElement).value; - if (me != null) { - const { discover_endpoints, create_verifier, create_challenge } = await import("./indieauth.js"); - - const endpoints = await discover_endpoints(new URL(me)); - - if (endpoints != null) { - localStorage.setItem("micropub_endpoint", endpoints.micropub.toString()) - localStorage.setItem("token_endpoint", endpoints.token_endpoint.toString()) - if (endpoints.revocation_endpoint != null) { - localStorage.setItem("revocation_endpoint", endpoints.revocation_endpoint.toString()) - } - } else { - alert("Your website doesn't support Micropub.") - return - } - (document.getElementById("unauthorized") as HTMLElement).style.display = "none"; - (document.getElementById("authorizing") as HTMLElement).style.display = "block"; - const url = endpoints.authorization_endpoint; - let params = new URLSearchParams(); - for (const [key, val] of url.searchParams) { - params.append(key, val) - } - params.set("client_id", window.location.href) - params.set("redirect_uri", window.location.href) - params.set("response_type", "code") - params.set("scope", "profile create media") - params.set("state", "awoo") - const code_verifier = create_verifier() - localStorage.setItem("code_verifier", code_verifier) - params.set("code_challenge", await create_challenge(code_verifier)) - params.set("code_challenge_method", "S256") - - url.search = "?" + params.toString() - - console.log(url) - - window.location.href = url.toString() - } -} - -if (window.location.search != "") { - (document.getElementById("authorizing") as HTMLElement).style.display = "block"; - const params = new URLSearchParams(window.location.search) - if (params.has("code") && params.has("state")) { - const token_endpoint = new URL(localStorage.getItem("token_endpoint")!) - const state = params.get("state") - // XXX check state - - const client_id = new URL(window.location.href); - client_id.search = ""; - const form = new URLSearchParams(); - form.set("grant_type", "authorization_code") - form.set("code", params.get("code")!) - form.set("client_id", client_id.toString()) - form.set("redirect_uri", client_id.toString()) - form.set("code_verifier", localStorage.getItem("code_verifier")!) - - const response = await fetch(token_endpoint, { - method: "POST", - headers: { - "Accept": "application/json", - "Content-Type": "application/x-www-form-urlencoded" - }, - body: form.toString() - }); - - const grant = await response.json(); - - if ("access_token" in grant) { - localStorage.setItem("access_token", grant.access_token); - (document.getElementById("authorizing") as HTMLElement).style.display = "none"; - } - } -} - -let micropub: Micropub | null = null; -const token = localStorage.getItem("access_token") -const endpoint = localStorage.getItem("micropub_endpoint") -if (token == null || endpoint == null) { - (document.getElementById("unauthorized") as HTMLElement).style.display = "block"; -} else { - (document.getElementById("authorized") as HTMLElement).style.display = "block"; - - micropub = new Micropub({ endpoint: new URL(endpoint), token }); -} diff --git a/kittybox-rs/companion-lite/src/micropub_api.ts b/kittybox-rs/companion-lite/src/micropub_api.ts deleted file mode 100644 index fa1c431..0000000 --- a/kittybox-rs/companion-lite/src/micropub_api.ts +++ /dev/null @@ -1,125 +0,0 @@ -export interface MicropubChannel { - readonly uid: string, - readonly name: string -} - -export interface MF2 { - type: string[], - properties: { [key:string]: (string | MF2 | {[key:string]: string})[] | undefined } -} - -export interface MicropubConfig { - readonly channels?: MicropubChannel[], - readonly "media-endpoint"?: string -} - -export interface MicropubErrorMessage { - readonly error: string, - readonly error_description: string | undefined -} - -export class MicropubError extends Error { - readonly status: number | null - readonly response: MicropubErrorMessage | null - - constructor(status: number | null, response: MicropubErrorMessage | null, cause: Error | null = null) { - // Needs to pass both `message` and `options` to install the "cause" property. - if (status == null) { - super("Micropub endpoint didn't respond properly", { cause }); - } else if (response == null) { - super(`Micropub endpoint returned HTTP ${status}`, { cause }); - } else { - super( - `Micropub endpoint returned ${response.error}: ${response.error_description ?? "(no description was provided)"}`, - { cause } - ) - } - - this.status = status; - this.response = response; - } -} - -export class Micropub { - readonly token: string - readonly micropub_endpoint: URL - private config_response: MicropubConfig | null - - constructor({ endpoint, token }: { endpoint: URL, token: string }) { - this.micropub_endpoint = endpoint; - this.token = token; - this.config_response = null; - } - - async config(): Promise<MicropubConfig> { - if (this.config_response != null) { - return this.config_response - } - let url = this.micropub_endpoint; - let params = new URLSearchParams(); - for (const [key, val] of url.searchParams) { - params.append(key, val) - } - params.set("q", "config") - - url.search = "?" + params.toString(); - - const response = await fetch(url, { - headers: { - "Authorization": `Bearer ${this.token}` - } - }); - if (response.ok) { - const config = await response.json() as MicropubConfig; - this.config_response = config - - return config - } else { - throw new MicropubError(response.status, await response.json() as MicropubErrorMessage); - } - } - - async submit(mf2: MF2): Promise<URL> { - const response = await fetch(this.micropub_endpoint, { - method: "POST", - headers: { - "Authorization": `Bearer ${this.token}`, - "Content-Type": "application/json" - }, - body: JSON.stringify(mf2) - }) - - if (response.status != 201 && response.status != 202) { - let err = await response.json() as MicropubErrorMessage; - - throw new MicropubError(response.status, err) - } else { - return new URL(response.headers.get("Location") as string) - } - } - - async upload(file: File): Promise<URL> { - const config = await this.config(); - const media = config["media-endpoint"]; - if (media == null) { - throw new Error("Micropub endpoint doesn't support file uploads") - } - - const form = new FormData(); - form.set("file", file); - - const response = await fetch(media, { - method: "POST", - headers: { - "Authorization": `Bearer ${this.token}`, - }, - body: form - }) - - if (response.ok) { - return new URL(response.headers.get("Location") as string) - } else { - throw new MicropubError(response.status, await response.json()); - } - } -} diff --git a/kittybox-rs/companion-lite/style.css b/kittybox-rs/companion-lite/style.css deleted file mode 100644 index 09ed398..0000000 --- a/kittybox-rs/companion-lite/style.css +++ /dev/null @@ -1,47 +0,0 @@ -* { - box-sizing: border-box; -} - -:root { - font-family: sans-serif; -} - -body { - margin: 0; -} - -body > main { - margin: auto; - max-width: 1024px; -} - -h1.header { - margin-top: 0.75em; - text-align: center; -} - -fieldset + fieldset, -fieldset + input, -section + section, -section + fieldset -{ - margin-top: 0.75em; -} - -input[type="submit"] { - margin-left: auto; - display: block; -} - -form > fieldset > section > label { - width: 100%; - display: block; -} - -form > fieldset > section > input, form > fieldset > section > textarea { - width: 100%; -} - -textarea { - min-height: 10em; -} diff --git a/kittybox-rs/companion-lite/tsconfig.json b/kittybox-rs/companion-lite/tsconfig.json deleted file mode 100644 index 18b94c7..0000000 --- a/kittybox-rs/companion-lite/tsconfig.json +++ /dev/null @@ -1,104 +0,0 @@ -{ - "compilerOptions": { - /* Visit https://aka.ms/tsconfig to read more about this file */ - - /* Projects */ - // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ - // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ - // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ - // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ - // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ - // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ - - /* Language and Environment */ - "target": "es2022", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ - // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ - // "jsx": "preserve", /* Specify what JSX code is generated. */ - // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ - // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ - // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ - // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ - // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ - // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ - // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ - // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ - // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ - - /* Modules */ - "module": "es2022", /* Specify what module code is generated. */ - // "rootDir": "./", /* Specify the root folder within your source files. */ - // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ - // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ - // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ - // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ - // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ - // "types": [], /* Specify type package names to be included without being referenced in a source file. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ - // "resolveJsonModule": true, /* Enable importing .json files. */ - // "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */ - - /* JavaScript Support */ - // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ - // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ - // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ - - /* Emit */ - // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ - // "declarationMap": true, /* Create sourcemaps for d.ts files. */ - // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ - // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ - // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ - "outDir": "./dist", /* Specify an output folder for all emitted files. */ - // "removeComments": true, /* Disable emitting comments. */ - // "noEmit": true, /* Disable emitting files from a compilation. */ - // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ - // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ - // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ - // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ - // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ - // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ - // "newLine": "crlf", /* Set the newline character for emitting files. */ - // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ - // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ - // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ - // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ - // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ - // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ - - /* Interop Constraints */ - // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ - // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ - "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ - // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ - "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ - - /* Type Checking */ - "strict": true, /* Enable all strict type-checking options. */ - // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ - // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ - // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ - // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ - // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ - // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ - // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ - // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ - // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ - // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ - // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ - // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ - // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ - // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ - // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ - // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ - // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ - - /* Completeness */ - // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ - "skipLibCheck": true /* Skip type checking all .d.ts files. */ - }, - "include": ["src/**/*"] -} |