@manyducks.co/dolla 2.0.0-alpha.30 → 2.0.0-alpha.32

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/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/modules/http.ts","../src/modules/i18n.ts","../src/modules/router.utils.ts","../src/modules/router.ts","../src/views/default-crash-view.ts","../src/core/batch.ts","../src/core/dolla.ts","../src/index.ts"],"sourcesContent":["import { isObject } from \"../typeChecking.js\";\nimport type { Dolla, Logger } from \"../core/dolla.js\";\n\n/**\n * A simple HTTP client with middleware support. Middleware applies to all requests made through this store,\n * so it's the perfect way to handle things like auth headers and permission checks for API calls.\n */\nexport class HTTP {\n #middleware: HTTPMiddleware[] = [];\n #fetch = getDefaultFetch();\n #dolla: Dolla;\n #logger: Logger;\n\n constructor(dolla: Dolla) {\n this.#dolla = dolla;\n this.#logger = dolla.createLogger(\"Dolla.http\");\n }\n\n /**\n * Adds a new middleware that will apply to subsequent requests.\n * Returns a function to remove this middleware.\n *\n * @param middleware - A middleware function that will intercept requests.\n */\n use(fn: HTTPMiddleware) {\n this.#middleware.push(fn);\n\n // Call returned function to remove this middleware for subsequent requests.\n return () => {\n this.#middleware.splice(this.#middleware.indexOf(fn), 1);\n };\n }\n\n async get<ResBody = unknown>(uri: string, options?: RequestOptions<never>) {\n return this.#request<ResBody, never>(\"get\", uri, options);\n }\n\n async put<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"put\", uri, options);\n }\n\n async patch<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"patch\", uri, options);\n }\n\n async post<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"post\", uri, options);\n }\n\n async delete<ResBody = unknown>(uri: string, options?: RequestOptions<never>) {\n return this.#request<ResBody, never>(\"delete\", uri, options);\n }\n\n async head<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"head\", uri, options);\n }\n\n async options<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"options\", uri, options);\n }\n\n async trace<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"trace\", uri, options);\n }\n\n async #request<ResBody, ReqBody>(method: string, uri: string, options?: RequestOptions<any>) {\n const runner = new Runner<ResBody, ReqBody>({\n ...options,\n method,\n uri,\n middleware: this.#middleware,\n fetch: this.#fetch,\n logger: this.#logger,\n });\n return runner.fetch();\n }\n}\n\nfunction getDefaultFetch(): typeof window.fetch {\n if (typeof window !== \"undefined\" && window.fetch) {\n return window.fetch.bind(window);\n }\n\n if (typeof global !== \"undefined\" && global.fetch) {\n return global.fetch.bind(global);\n }\n\n throw new Error(\"Running in neither browser nor node. Please run this app in one of the supported environments.\");\n}\n\n/*====================*\\\n|| Request ||\n\\*====================*/\n\nexport type HTTPMiddleware = (\n request: HTTPRequest<unknown>,\n next: () => Promise<HTTPResponse<unknown>>,\n) => void | Promise<void>;\n\nexport interface RequestOptions<ReqBody> {\n /**\n * Body to send with the request.\n */\n body?: ReqBody;\n\n /**\n * Headers to send with the request.\n */\n headers?: Record<string, any> | Headers;\n\n /**\n * Query params to interpolate into the URL.\n */\n query?: Record<string, any> | URLSearchParams;\n}\n\nexport interface HTTPRequest<Body> {\n method: string;\n url: URL;\n headers: Headers;\n body: Body;\n}\n\nexport interface HTTPResponse<Body> {\n method: string;\n url: URL;\n headers: Headers;\n status: number;\n statusText: string;\n body: Body;\n}\n\ninterface MakeRequestConfig<ReqBody> extends RequestOptions<ReqBody> {\n method: string;\n uri: string;\n middleware: HTTPMiddleware[];\n fetch: typeof window.fetch;\n logger: Logger;\n}\n\nexport class HTTPResponseError extends Error {\n response;\n\n constructor(response: HTTPResponse<any>) {\n const { status, statusText, method, url } = response;\n const message = `${status} ${statusText}: Request failed (${method.toUpperCase()} ${url.toString()})`;\n\n super(message);\n\n this.response = response;\n }\n}\n\nclass Request<ReqBody> implements HTTPRequest<ReqBody> {\n method: string;\n url: URL;\n headers = new Headers();\n body!: ReqBody;\n\n get isSameOrigin() {\n return this.url.origin === window.location.origin;\n }\n\n constructor(config: MakeRequestConfig<ReqBody>) {\n this.method = config.method;\n this.body = config.body!;\n if (config.uri.startsWith(\"http\")) {\n this.url = new URL(config.uri);\n } else {\n this.url = new URL(config.uri, window.location.origin);\n }\n\n this._applyHeaders(config.headers);\n this._applyQueryParams(config.query);\n }\n\n private _applyHeaders(headers: any) {\n if (headers == null) return;\n\n if (headers instanceof Map || headers instanceof Headers) {\n headers.forEach((value, key) => {\n this.headers.set(key, value);\n });\n } else if (isObject(headers)) {\n for (const name in headers) {\n const value = headers[name];\n if (value instanceof Date) {\n this.headers.set(name, value.toISOString());\n } else if (value != null) {\n this.headers.set(name, String(value));\n }\n }\n } else {\n throw new TypeError(`Unknown headers type. Got: ${headers}`);\n }\n }\n\n private _applyQueryParams(query: any) {\n if (query == null) return;\n\n if (query instanceof Map || query instanceof URLSearchParams) {\n query.forEach((value, key) => {\n this.url.searchParams.set(key, value);\n });\n } else if (isObject(query)) {\n for (const name in query) {\n const value = query[name];\n if (value instanceof Date) {\n this.url.searchParams.set(name, value.toISOString());\n } else if (value != null) {\n this.url.searchParams.set(name, String(value));\n }\n }\n } else {\n throw new TypeError(`Unknown query params type. Got: ${query}`);\n }\n }\n}\n\nclass Runner<ResBody, ReqBody> {\n private _middleware;\n private _fetch;\n\n private _request: Request<ReqBody>;\n private _response?: HTTPResponse<ResBody>;\n\n constructor(config: MakeRequestConfig<ReqBody>) {\n this._middleware = config.middleware;\n this._fetch = config.fetch;\n\n this._request = new Request(config);\n }\n\n async fetch() {\n if (this._middleware.length > 0) {\n const mount = (index = 0) => {\n const current = this._middleware[index];\n const next = this._middleware[index + 1] ? mount(index + 1) : this._handler.bind(this);\n\n return async () =>\n current(this._request, async () => {\n await next();\n return this._response!;\n });\n };\n\n await mount()();\n } else {\n await this._handler();\n }\n\n if (this._response!.status < 200 || this._response!.status >= 400) {\n throw new HTTPResponseError(this._response!);\n }\n\n return this._response!;\n }\n\n // This is the function that performs the actual request after the final middleware.\n private async _handler() {\n let reqBody: BodyInit;\n\n const req = this._request;\n\n if (!req.headers.has(\"content-type\") && isObject(req.body)) {\n // Auto-detect JSON bodies and encode as a string with correct headers.\n req.headers.set(\"content-type\", \"application/json\");\n reqBody = JSON.stringify(req.body);\n } else {\n reqBody = req.body as BodyInit;\n }\n\n const fetched = await this._fetch(req.url.toString(), {\n method: req.method,\n headers: req.headers,\n body: reqBody,\n });\n\n // Auto-parse response body based on content-type header\n const contentType = fetched.headers.get(\"content-type\");\n\n let body: ResBody;\n\n if (contentType?.includes(\"application/json\")) {\n body = await fetched.json();\n } else if (contentType?.includes(\"application/x-www-form-urlencoded\")) {\n body = (await fetched.formData()) as ResBody;\n } else {\n body = (await fetched.text()) as ResBody;\n }\n\n this._response = {\n method: req.method,\n url: req.url,\n status: fetched.status,\n statusText: fetched.statusText,\n headers: fetched.headers,\n body,\n };\n }\n}\n\n// async function makeRequest<ResBody, ReqBody>(config: MakeRequestConfig<ReqBody>) {\n// const { headers, query, fetch, middleware, logger } = config;\n\n// const request: HTTPRequest<ReqBody> = {\n// method: config.method,\n// uri: config.uri,\n// get sameOrigin() {\n// return !request.uri.startsWith(\"http\");\n// },\n// query: new URLSearchParams(),\n// headers: new Headers(),\n// body: config.body!,\n// };\n\n// // Read headers into request\n// if (headers) {\n// if (headers instanceof Map || headers instanceof Headers) {\n// headers.forEach((value, key) => {\n// request.headers.set(key, value);\n// });\n// } else if (headers != null && typeof headers === \"object\" && !Array.isArray(headers)) {\n// for (const name in headers) {\n// const value = headers[name];\n// if (value instanceof Date) {\n// request.headers.set(name, value.toISOString());\n// } else if (value != null) {\n// request.headers.set(name, String(value));\n// }\n// }\n// } else {\n// throw new TypeError(`Unknown headers type. Got: ${headers}`);\n// }\n// }\n\n// // Read query params into request\n// if (query) {\n// if (query instanceof Map || query instanceof URLSearchParams) {\n// query.forEach((value, key) => {\n// request.query.set(key, value);\n// });\n// } else if (query != null && typeof query === \"object\" && !Array.isArray(query)) {\n// for (const name in query) {\n// const value = query[name];\n// if (value instanceof Date) {\n// request.query.set(name, value.toISOString());\n// } else if (value != null) {\n// request.query.set(name, String(value));\n// }\n// }\n// } else {\n// throw new TypeError(`Unknown query params type. Got: ${query}`);\n// }\n// }\n\n// let response: HTTPResponse<ResBody>;\n\n// // This is the function that performs the actual request after the final middleware.\n// const handler = async () => {\n// const query = request.query.toString();\n// const fullURL = query.length > 0 ? request.uri + \"?\" + query : request.uri;\n\n// let reqBody: BodyInit;\n\n// if (!request.headers.has(\"content-type\") && isObject(request.body)) {\n// // Auto-detect JSON bodies and encode as a string with correct headers.\n// request.headers.set(\"content-type\", \"application/json\");\n// reqBody = JSON.stringify(request.body);\n// } else {\n// reqBody = request.body as BodyInit;\n// }\n\n// const fetched = await fetch(fullURL, {\n// method: request.method,\n// headers: request.headers,\n// body: reqBody,\n// });\n\n// // Auto-parse response body based on content-type header\n// const headers = Object.fromEntries<string>(fetched.headers.entries());\n// const contentType = headers[\"content-type\"];\n\n// let body: ResBody;\n\n// if (contentType?.includes(\"application/json\")) {\n// body = await fetched.json();\n// } else if (contentType?.includes(\"application/x-www-form-urlencoded\")) {\n// body = (await fetched.formData()) as ResBody;\n// } else {\n// body = (await fetched.text()) as ResBody;\n// }\n\n// response = {\n// method: request.method,\n// uri: request.uri,\n// status: fetched.status,\n// statusText: fetched.statusText,\n// headers: headers,\n// body,\n// };\n\n// // logger.info(\"response\", response);\n// };\n\n// if (middleware.length > 0) {\n// const mount = (index = 0) => {\n// const current = middleware[index];\n// const next = middleware[index + 1] ? mount(index + 1) : handler;\n\n// return async () =>\n// current(request, async () => {\n// await next();\n// return response;\n// });\n// };\n\n// await mount()();\n// } else {\n// await handler();\n// }\n\n// if (response!.status < 200 || response!.status >= 400) {\n// throw new HTTPResponseError(response!);\n// }\n\n// return response!;\n// }\n","import type { Dolla, Logger } from \"../core/dolla.js\";\nimport { createState, derive, type MaybeState, type State } from \"../core/state.js\";\nimport { isFunction, isObject, isString, typeOf } from \"../typeChecking.js\";\nimport { deepEqual } from \"../utils.js\";\n\n// ----- Types ----- //\n\n/**\n * A JSON object of translated strings. Values can be string templates or nested objects.\n */\ninterface LocalizedStrings extends Record<string, string | LocalizedStrings> {}\n\nenum SegmentType {\n Static,\n Variable,\n}\ntype StringTemplate = { segments: (StaticSegment | VariableSegment)[] };\n/**\n * A string segment with literal text to be appended without processing.\n */\ntype StaticSegment = {\n type: SegmentType.Static;\n text: string;\n};\n/**\n * A variable passed to the t() function. Needs to be formatted before it is appended.\n */\ntype VariableSegment = {\n type: SegmentType.Variable;\n name: string;\n formats: Format[];\n};\n/**\n * A formatter to be applied to a variable.\n */\ntype Format = {\n name: string;\n options: Record<string, any>;\n};\n\nexport interface TranslationConfig {\n /**\n * Name of the locale this translation is for (BCP 47 locale names recommended).\n */\n locale: string;\n\n /**\n * Path to a JSON file with translated strings for this language.\n */\n path?: string;\n\n /**\n * A callback function that returns a Promise that resolves to the translation object for this language.\n */\n fetch?: () => Promise<LocalizedStrings>;\n}\n\nexport type I18nSetupOptions = {\n /**\n * Default locale to load on startup\n */\n locale?: string | null;\n\n translations: TranslationConfig[];\n};\n\nexport type TOptions = {\n /**\n *\n */\n count?: MaybeState<number>;\n\n /**\n *\n */\n context?: MaybeState<string>;\n\n /**\n * Override formats specified in the template with the ones in the array for each named variable.\n *\n * @example\n * t(\"example_key\", {\n * count: 5,\n * formatOverrides: {\n * count: [ { name: \"datetime\", options: { style: \"currency\", currency: \"JPY\" } } ]\n * }\n * });\n */\n formatOverrides?: MaybeState<Record<string, Record<string, Format[]>>>;\n\n [value: string]: MaybeState<any>;\n};\n\nexport type Formatter = (locale: string, value: unknown, options: Record<string, any>) => string;\n\n// ----- Code ----- //\n\nclass Translation {\n dolla: Dolla;\n config: TranslationConfig;\n\n #isLoaded = false;\n\n #templates = new Map<string, StringTemplate>();\n\n constructor(config: TranslationConfig, dolla: Dolla) {\n this.config = config;\n this.dolla = dolla;\n }\n\n async load(): Promise<void> {\n let strings: LocalizedStrings | undefined;\n\n if (!this.#isLoaded) {\n if (isFunction(this.config.fetch)) {\n strings = await this.config.fetch();\n if (!isObject(strings)) {\n throw new Error(`Fetch function did not return an object of language strings: ${strings}`);\n }\n } else if (isString(this.config.path)) {\n const res = await fetch(this.config.path);\n if (res.ok) {\n const body = await res.json();\n if (isObject(body)) {\n strings = body as LocalizedStrings;\n } else {\n throw new Error(\n `Language path '${this.config.path}' did not return an object of language strings: ${body}`,\n );\n }\n } else {\n throw new Error(`HTTP request failed.`);\n }\n }\n }\n\n if (strings) {\n const entries = this.#compile(strings);\n for (const entry of entries) {\n this.#templates.set(entry[0], entry[1]);\n }\n } else {\n throw new Error(`Language could not be loaded.`);\n }\n }\n\n getTemplate(selector: string): StringTemplate {\n return (\n this.#templates.get(selector) ?? {\n segments: [{ type: SegmentType.Static, text: `[MISSING: ${selector}]` }],\n }\n );\n }\n\n hasTemplate(selector: string): boolean {\n return this.#templates.has(selector);\n }\n\n #compile(strings: { [key: string]: any }, path: string[] = []): [string, StringTemplate][] {\n const entries: [string, StringTemplate][] = [];\n\n for (const key in strings) {\n switch (typeOf(strings[key])) {\n case \"string\":\n entries.push([[...path, key].join(\".\"), this.#parseTemplate(strings[key])]);\n break;\n case \"object\":\n entries.push(...this.#compile(strings[key], [...path, key]));\n break;\n default:\n throw new Error(\n `Expected to find a string or object at ${[...path, key].join(\".\")}. Got: ${typeOf(strings[key])}`,\n );\n }\n }\n\n return entries;\n }\n\n #parseTemplate(template: string): StringTemplate {\n // \"{{itemName}} costs {{amount | number(style: currency, currency: USD)}}.\"\n\n enum Loc {\n /**\n * Outside value braces.\n */\n Static,\n /**\n * Inside value braces; currently parsing the name of the value. e.g. `{{ [name] | number(style: currency, currency: USD) }}`\n */\n ValueName,\n /**\n * Inside value braces; currently parsing the name of a format function. e.g. `{{ name | [number](style: currency, currency: USD) }}`\n */\n FormatName,\n /**\n * Inside value braces; currently parsing the name of a format option. e.g. `{{ name | number([style]: currency, currency: USD) }}`\n */\n FormatOptionName,\n /**\n * Inside value braces; currently parsing the value of a format option. e.g. `{{ name | number(style: [currency], currency: USD ) }}`\n */\n FormatOptionValue,\n /**\n * Inside value braces; just reached the closing bracket of a format option. e.g. `{{ name | number(style: [currency], currency: USD) [] }}`\n */\n FormatOptionEnd,\n }\n\n const parsed: StringTemplate = {\n segments: [],\n };\n\n let buffer = \"\";\n let i = 0;\n let loc: Loc = Loc.Static;\n let segment!: VariableSegment;\n let format!: VariableSegment[\"formats\"][0];\n\n let formatOptionName!: string;\n\n const startSegment = () => {\n segment = {\n type: SegmentType.Variable,\n name: \"\",\n formats: [],\n };\n };\n\n const startFormat = () => {\n format = {\n name: \"\",\n options: {},\n };\n };\n\n while (i < template.length) {\n // Skip spaces (unless we're in static)\n if (loc !== Loc.Static && template[i] === \" \") {\n i++;\n continue;\n }\n\n switch (loc) {\n case Loc.Static:\n if (template[i] === \"{\" && template[i + 1] === \"{\") {\n loc = Loc.ValueName;\n i += 2;\n // close static segment\n if (buffer.length > 0) {\n parsed.segments.push({ type: SegmentType.Static, text: buffer });\n buffer = \"\";\n }\n startSegment();\n } else {\n buffer += template[i];\n i++;\n }\n break;\n case Loc.ValueName:\n if (template[i] === \"|\") {\n loc = Loc.FormatName;\n i += 1;\n // add name to value segment\n segment.name = buffer;\n buffer = \"\";\n startFormat();\n } else if (template[i] === \"}\" && template[i + 1] === \"}\") {\n loc = Loc.Static;\n i += 2;\n // close value segment\n segment.name = buffer;\n buffer = \"\";\n parsed.segments.push(segment);\n } else {\n buffer += template[i];\n i++;\n }\n break;\n case Loc.FormatName:\n if (template[i] === \"(\") {\n loc = Loc.FormatOptionName;\n i += 1;\n // add name to format object\n format.name = buffer;\n buffer = \"\";\n } else if (template[i] === \"}\" && template[i + 1] === \"}\") {\n loc = Loc.Static;\n i += 2;\n // close format and value segment\n segment.formats.push(format);\n parsed.segments.push(segment);\n } else {\n buffer += template[i];\n i++;\n }\n break;\n case Loc.FormatOptionName:\n if (template[i] === \")\") {\n // TODO: error - no value provided for option\n } else if (template[i] === \":\") {\n loc = Loc.FormatOptionValue;\n i += 1;\n // add name to format option object\n formatOptionName = buffer;\n buffer = \"\";\n } else if (template[i] === \"}\" && template[i + 1] === \"}\") {\n // TODO: error - format options parenthesis not closed\n } else {\n buffer += template[i];\n i++;\n }\n break;\n case Loc.FormatOptionValue:\n if (template[i] === \")\") {\n loc = Loc.FormatOptionEnd;\n i += 1;\n // add value to format option object\n // add format option to format object; we're done with this format\n format.options[formatOptionName] = buffer;\n buffer = \"\";\n segment.formats.push(format);\n } else if (template[i] === \",\") {\n loc = Loc.FormatOptionName;\n i += 1;\n // add value to format option object\n // add format option to format object; we're adding another option\n format.options[formatOptionName] = buffer;\n buffer = \"\";\n } else if (template[i] === \"}\" && template[i + 1] === \"}\") {\n // TODO: error - format options parenthesis not closed\n } else {\n buffer += template[i];\n i++;\n }\n break;\n case Loc.FormatOptionEnd:\n if (template[i] === \"|\") {\n loc = Loc.FormatName;\n i += 1;\n startFormat();\n } else if (template[i] === \"}\" && template[i + 1] === \"}\") {\n loc = Loc.Static;\n i += 2;\n // add value segment\n parsed.segments.push(segment);\n } else {\n // TODO: error - no other valid characters\n }\n break;\n }\n }\n\n if (loc === Loc.Static && buffer.length > 0) {\n parsed.segments.push({ type: SegmentType.Static, text: buffer });\n }\n\n return parsed;\n }\n}\n\n/**\n * Dolla's I(nternationalizatio)n module. Manages language translations and locale-based formatting.\n */\nexport class I18n {\n #dolla: Dolla;\n #logger: Logger;\n #translations = new Map<string, Translation>();\n #cache: [key: string, values: Record<string, any> | undefined, output: string][] = [];\n #formats = new Map<string, Formatter>();\n\n #initialLocale = \"auto\";\n\n $locale: State<string | undefined>;\n #setLocale;\n\n constructor(dolla: Dolla) {\n this.#dolla = dolla;\n this.#logger = dolla.createLogger(\"Dolla.i18n\");\n\n const [$locale, setLocale] = createState<string>();\n\n this.$locale = $locale;\n this.#setLocale = setLocale;\n\n this.addFormat(\"number\", (_, value, options) => {\n return this.#formatNumber(Number(value), options);\n });\n this.addFormat(\"datetime\", (_, value, options) => {\n return this.#formatDateTime(value as any, options);\n });\n this.addFormat(\"list\", (_, value, options) => {\n return this.#formatList(value as any, options);\n });\n\n /**\n * Load language before the app mounts.\n */\n dolla.beforeMount(async () => {\n if (this.#translations.size > 0) {\n await this.setLocale(this.#initialLocale);\n }\n });\n }\n\n get locales() {\n return [...this.#translations.keys()];\n }\n\n setup(options: I18nSetupOptions) {\n // Convert languages into Language instances.\n options.translations.forEach((entry) => {\n this.#translations.set(entry.locale, new Translation(entry, this.#dolla));\n });\n\n // Check that initialLanguage is actually registered.\n if (options.locale && options.locale !== \"auto\") {\n const isRegistered = options.translations.some((entry) => entry.locale === options.locale);\n if (!isRegistered) {\n throw new Error(`Initial locale '${options.locale}' is not registered in the locales array.`);\n }\n this.#initialLocale = options.locale;\n }\n\n this.#logger.info(\n `${this.#translations.size} language${this.#translations.size === 1 ? \"\" : \"s\"} supported: '${[...this.#translations.keys()].join(\"', '\")}'`,\n );\n }\n\n async setLocale(name: string) {\n let realName!: string;\n\n if (name === \"auto\") {\n let names = [];\n\n if (typeof navigator !== \"undefined\") {\n const nav = navigator as any;\n\n if (nav.languages?.length > 0) {\n names.push(...nav.languages);\n } else if (nav.language) {\n names.push(nav.language);\n } else if (nav.browserLanguage) {\n names.push(nav.browserLanguage);\n } else if (nav.userLanguage) {\n names.push(nav.userLanguage);\n }\n }\n\n for (const name of names) {\n if (this.#translations.has(name)) {\n // Found a matching language.\n realName = name;\n }\n }\n } else {\n // Tag is the actual tag to set.\n if (this.#translations.has(name)) {\n realName = name;\n }\n }\n\n if (realName == null) {\n const firstLanguage = this.#translations.keys().next().value;\n if (firstLanguage) {\n realName = firstLanguage;\n }\n }\n\n if (!realName || !this.#translations.has(realName)) {\n throw new Error(`Locale '${name}' has no translation.`);\n }\n\n const translation = this.#translations.get(realName)!;\n\n try {\n await translation.load();\n\n this.#cache = [];\n this.#setLocale(realName);\n\n this.#logger.info(\"set language to \" + realName);\n } catch (error) {\n if (error instanceof Error) {\n this.#logger.crash(error);\n }\n }\n }\n\n /**\n * Returns a State containing the value at `key`.\n \n * @param selector - Key to the translated value.\n * @param options - A map of `{{placeholder}}` names and the values to replace them with.\n * \n * @example\n * const $value = t(\"your.key.here\", { count: 5 });\n */\n t(selector: string, options?: TOptions): State<string> {\n if (this === undefined) {\n throw new Error(\n `The 't' function cannot be destructured. If you need a standalone version you can import it like so: 'import { t } from \"@manyducks.co/dolla\"'`,\n );\n }\n\n // Split keys and values so we can observe values which may be States.\n let optionKeys = [];\n let optionValues = [];\n for (const key in options) {\n optionKeys.push(key);\n optionValues.push(options[key]);\n }\n\n return derive([this.$locale, ...optionValues], (locale, ...currentValues) => {\n if (locale == null) {\n return \"[NO LOCALE SET]\";\n }\n\n // Reassemble options now that State values are unwrapped.\n const options: Record<string, any> = {};\n for (let i = 0; i < currentValues.length; i++) {\n options[optionKeys[i]] = currentValues[i];\n }\n\n return this.#getValue(locale, selector, options);\n });\n }\n\n #getValue(locale: string, selector: string, options: Record<string, any>): string {\n const cached = this.#getCached(selector, options);\n if (cached) return cached;\n\n const translation = this.#translations.get(locale)!;\n\n // Handle count (pluralization) and context. Keys become \"key_context_pluralization\".\n\n if (options.context != null) {\n selector += \"_\" + options.context;\n }\n if (options.count != null) {\n if (options.ordinal) {\n // Try to match the exact number key if there is one (e.g. \"myExampleKey_ordinal_(=2)\" when count is 2).\n const exact = `${selector}_ordinal_(=${options.count})`;\n if (translation.hasTemplate(exact)) {\n selector = exact;\n } else {\n selector += \"_ordinal_\" + new Intl.PluralRules(locale, { type: \"ordinal\" }).select(options.count);\n }\n } else {\n // Try to match the exact number key if there is one (e.g. \"myExampleKey_(=2)\" when count is 2).\n const exact = `${selector}_(=${options.count})`;\n if (translation.hasTemplate(exact)) {\n selector = exact;\n } else {\n selector += \"_\" + new Intl.PluralRules(locale).select(options.count);\n }\n }\n }\n\n const template = translation.getTemplate(selector);\n let output = \"\";\n\n for (const segment of template.segments) {\n if (segment.type === SegmentType.Static) {\n output += segment.text;\n } else if (segment.type === SegmentType.Variable) {\n let value = resolve(options, segment.name);\n\n const formats = options.formatOverrides?.[segment.name] ?? [...segment.formats];\n\n if (segment.name === \"count\" && formats.length === 0) {\n formats.push({ name: \"number\", options: {} });\n }\n\n for (const format of formats) {\n const fn = this.#formats.get(format.name);\n if (fn == null) {\n const error = new Error(\n `Failed to load format '${format.name}' when processing '${selector}', template: ${template}`,\n );\n this.#logger.crash(error);\n throw error;\n }\n value = fn(locale, value, format.options);\n }\n\n output += value;\n }\n }\n\n return output;\n }\n\n /**\n * Add a custom format callback.\n *\n * @example\n * Dolla.i18n.addFormat(\"uppercase\", (locale, value, options) => {\n * return value.toUpperCase();\n * });\n *\n * {\n * \"greeting\": \"Hello, {{name|uppercase}}!\"\n * }\n *\n * t(\"greeting\", {name: \"world\"}); // State<\"Hello, WORLD!\">\n */\n addFormat(name: string, callback: (locale: string, value: unknown, options: Record<string, any>) => string) {\n this.#formats.set(name, callback);\n }\n\n /**\n * Creates an `Intl.Collator` configured for the current locale.\n * NOTE: The Collator remains bound to the locale it was created with, even when the app's locale changes.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Collator/Collator#options\n */\n collator(options?: Intl.CollatorOptions) {\n return new Intl.Collator(this.$locale.get(), options);\n }\n\n /**\n * Returns a State containing the number formatted for the current locale. Uses `Intl.NumberFormat` under the hood.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#options\n */\n number(count: MaybeState<number | bigint>, options?: Intl.NumberFormatOptions): State<string> {\n return derive([this.$locale, count], (_, value) => this.#formatNumber(value, options));\n }\n\n #formatNumber(count: number | bigint, options?: Intl.NumberFormatOptions): string {\n return new Intl.NumberFormat(this.$locale.get(), options).format(count);\n }\n\n /**\n * Returns a State containing the date formatted for the current locale. Uses `Intl.DateTimeFormat` under the hood.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat#options\n *\n * @example\n * const date = new Date();\n * const $formatted = Dolla.i18n.dateTime(date, { dateFormat: \"short\" });\n */\n dateTime(date?: MaybeState<string | number | Date | undefined>, options?: Intl.DateTimeFormatOptions): State<string> {\n return derive([this.$locale, date], (_, value) => this.#formatDateTime(value, options));\n }\n\n #formatDateTime(date?: string | number | Date, options?: Intl.DateTimeFormatOptions): string {\n return new Intl.DateTimeFormat(this.$locale.get(), options).format(isString(date) ? new Date(date) : date);\n }\n\n /**\n * Returns a State containing the date formatted for the current locale. Uses `Intl.DateTimeFormat` under the hood.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat#options\n *\n * @example\n * const list = new Date();\n * const $formatted = Dolla.i18n.list(list, { });\n */\n list(list: MaybeState<Iterable<string>>, options?: Intl.ListFormatOptions): State<string> {\n return derive([this.$locale, list], (_, value) => this.#formatList(value, options));\n }\n\n #formatList(list: Iterable<string>, options?: Intl.ListFormatOptions): string {\n return new Intl.ListFormat(this.$locale.get(), options).format(list);\n }\n\n // relativeTime(): State<string> {\n\n // }\n\n #getCached(key: string, values?: Record<string, any>): string | undefined {\n for (const entry of this.#cache) {\n if (entry[0] === key && deepEqual(entry[1], values)) {\n return entry[2];\n }\n }\n }\n}\n\nfunction resolve(object: any, key: string) {\n const parsed = String(key)\n .split(/[\\.\\[\\]]/)\n .filter((part) => part.trim() !== \"\");\n let value = object;\n\n while (parsed.length > 0) {\n const part = parsed.shift()!;\n\n if (value != null) {\n value = value[part];\n } else {\n value = undefined;\n }\n }\n\n return value;\n}\n","import { assertString, assertArrayOf, isFunction } from \"../typeChecking.js\";\n\nexport type RouteMatch<T = Record<string, any>> = {\n /**\n * The path string that triggered this match.\n */\n path: string;\n\n /**\n * The pattern satisfied by `path`.\n */\n pattern: string;\n\n /**\n * Named params as parsed from `path`.\n */\n params: Record<string, string | number>;\n\n /**\n * Query params as parsed from `path`.\n */\n query: Record<string, string | number | boolean>;\n\n /**\n * Metadata registered to this route.\n */\n meta: T;\n};\n\nexport enum FragTypes {\n Literal = 1,\n Param = 2,\n Wildcard = 3,\n NumericParam = 4,\n}\n\nexport type RouteFragment = {\n name: string;\n type: FragTypes;\n value: string | number | null;\n};\n\nexport type ParsedRoute<T> = {\n pattern: string;\n fragments: RouteFragment[];\n meta: T;\n};\n\nexport type RouteMatchOptions<T> = {\n willMatch?: (route: ParsedRoute<T>) => boolean;\n};\n\n/**\n * Separates a URL path into multiple fragments.\n *\n * @param path - A path string (e.g. `\"/api/users/5\"`)\n * @returns an array of fragments (e.g. `[\"api\", \"users\", \"5\"]`)\n */\nexport function splitPath(path: string): string[] {\n assertString(path, \"Expected `path` to be a string. Got type: %t, value: %v\");\n\n return path\n .split(\"/\")\n .map((f) => f.trim())\n .filter((f) => f !== \"\");\n}\n\n/**\n * Joins multiple URL path fragments into a single string.\n *\n * @param parts - One or more URL fragments (e.g. `[\"api\", \"users\", 5]`)\n * @returns a joined path (e.g. `\"api/users/5\"`)\n */\nexport function joinPath(parts: { toString(): string }[]): string {\n assertArrayOf(\n (part) => isFunction(part?.toString),\n parts,\n \"Expected `parts` to be an array of objects with a .toString() method. Got type: %t, value: %v\",\n );\n\n parts = parts.filter((x) => x).flatMap(String);\n\n let joined = parts.shift()?.toString();\n\n if (joined) {\n for (const part of parts.map((p) => p.toString())) {\n if (part.startsWith(\".\")) {\n // Resolve relative path against joined\n joined = resolvePath(joined, part);\n } else if (joined[joined.length - 1] !== \"/\") {\n if (part[0] !== \"/\") {\n joined += \"/\" + part;\n } else {\n joined += part;\n }\n } else {\n if (part[0] === \"/\") {\n joined += part.slice(1);\n } else {\n joined += part;\n }\n }\n }\n\n // Remove trailing slash (unless path is just '/')\n if (joined && joined !== \"/\" && joined.endsWith(\"/\")) {\n joined = joined.slice(0, joined.length - 1);\n }\n }\n\n return joined ?? \"\";\n}\n\nexport function resolvePath(base: string, part: string | null) {\n assertString(base, \"Expected `base` to be a string. Got type: %t, value: %v\");\n\n if (part == null) {\n part = base;\n base = \"\";\n }\n\n if (part.startsWith(\"/\")) {\n return part;\n }\n\n let resolved = base;\n\n while (true) {\n if (part.startsWith(\"..\")) {\n for (let i = resolved.length; i > 0; --i) {\n if (resolved[i] === \"/\" || i === 0) {\n resolved = resolved.slice(0, i);\n part = part.replace(/^\\.\\.\\/?/, \"\");\n break;\n }\n }\n } else if (part.startsWith(\".\")) {\n part = part.replace(/^\\.\\/?/, \"\");\n } else {\n break;\n }\n }\n\n return joinPath([resolved, part]);\n}\n\nexport function parseQueryParams(query: string): Record<string, string | number | boolean> {\n if (!query) return {};\n\n if (query.startsWith(\"?\")) {\n query = query.slice(1);\n }\n\n const entries = query\n .split(\"&\")\n .filter((x) => x.trim() !== \"\")\n .map((entry) => {\n const [key, value] = entry.split(\"=\").map((x) => x.trim());\n\n if (value.toLowerCase() === \"true\") {\n return [key, true] as const;\n }\n\n if (value.toLowerCase() === \"false\") {\n return [key, false] as const;\n }\n\n // Return value as a number if it parses as one.\n if (!isNaN(Number(value))) {\n return [key, Number(value)] as const;\n }\n\n return [key, value] as const;\n });\n\n return Object.fromEntries(entries);\n}\n\n/**\n * Returns the nearest match, or undefined if the path matches no route.\n *\n * @param url - Path to match against routes.\n * @param options - Options to customize how matching operates.\n */\nexport function matchRoutes<T>(\n routes: ParsedRoute<T>[],\n url: string,\n options: RouteMatchOptions<T> = {},\n): RouteMatch<T> | undefined {\n const [path, query] = url.split(\"?\");\n const parts = splitPath(path);\n\n routes: for (const route of routes) {\n const { fragments } = route;\n const hasWildcard = fragments[fragments.length - 1]?.type === FragTypes.Wildcard;\n\n if (!hasWildcard && fragments.length !== parts.length) {\n continue routes;\n }\n\n if (options.willMatch && !options.willMatch(route)) {\n continue routes;\n }\n\n const matched: RouteFragment[] = [];\n\n fragments: for (let i = 0; i < fragments.length; i++) {\n const part = parts[i];\n const frag = fragments[i];\n\n if (part == null && frag.type !== FragTypes.Wildcard) {\n continue routes;\n }\n\n switch (frag.type) {\n case FragTypes.Literal:\n if (frag.name.toLowerCase() === part.toLowerCase()) {\n matched.push(frag);\n break;\n } else {\n continue routes;\n }\n case FragTypes.Param:\n matched.push({ ...frag, value: part });\n break;\n case FragTypes.Wildcard:\n matched.push({ ...frag, value: parts.slice(i).join(\"/\") });\n break fragments;\n case FragTypes.NumericParam:\n if (!isNaN(Number(part))) {\n matched.push({ ...frag, value: Number(part) });\n break;\n } else {\n continue routes;\n }\n default:\n throw new Error(`Unknown fragment type: ${frag.type}`);\n }\n }\n\n const params: Record<string, string | number> = {};\n\n for (const frag of matched) {\n if (frag.type === FragTypes.Param) {\n params[frag.name] = decodeURIComponent(frag.value as string);\n }\n\n if (frag.type === FragTypes.NumericParam) {\n params[frag.name] = frag.value as number;\n }\n\n if (frag.type === FragTypes.Wildcard) {\n params.wildcard = \"/\" + decodeURIComponent(frag.value as string);\n }\n }\n\n return {\n path: \"/\" + matched.map((f) => f.value).join(\"/\"),\n pattern:\n \"/\" +\n fragments\n .map((f) => {\n if (f.type === FragTypes.Param) {\n return `{${f.name}}`;\n }\n\n if (f.type === FragTypes.NumericParam) {\n return `{#${f.name}}`;\n }\n\n return f.name;\n })\n .join(\"/\"),\n params,\n query: parseQueryParams(query),\n meta: route.meta,\n };\n }\n}\n\n/**\n * Sort routes descending by specificity. Guarantees that the most specific route matches first\n * no matter the order in which they were added.\n *\n * Routes without named params and routes with more fragments are weighted more heavily.\n */\nexport function sortRoutes<T>(routes: ParsedRoute<T>[]): ParsedRoute<T>[] {\n const withoutParams = [];\n const withNumericParams = [];\n const withParams = [];\n const wildcard = [];\n\n for (const route of routes) {\n const { fragments } = route;\n\n if (fragments.some((f) => f.type === FragTypes.Wildcard)) {\n wildcard.push(route);\n } else if (fragments.some((f) => f.type === FragTypes.NumericParam)) {\n withNumericParams.push(route);\n } else if (fragments.some((f) => f.type === FragTypes.Param)) {\n withParams.push(route);\n } else {\n withoutParams.push(route);\n }\n }\n\n const bySizeDesc = (a: ParsedRoute<T>, b: ParsedRoute<T>) => {\n if (a.fragments.length > b.fragments.length) {\n return -1;\n } else {\n return 1;\n }\n };\n\n withoutParams.sort(bySizeDesc);\n withNumericParams.sort(bySizeDesc);\n withParams.sort(bySizeDesc);\n wildcard.sort(bySizeDesc);\n\n return [...withoutParams, ...withNumericParams, ...withParams, ...wildcard];\n}\n\n/**\n * Converts a route pattern into a set of matchable fragments.\n *\n * @param route - A route string (e.g. \"/api/users/{id}\")\n */\nexport function patternToFragments(pattern: string): RouteFragment[] {\n const parts = splitPath(pattern);\n const fragments = [];\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n\n if (part === \"*\") {\n if (i !== parts.length - 1) {\n throw new Error(`Wildcard must be at the end of a pattern. Received: ${pattern}`);\n }\n fragments.push({\n type: FragTypes.Wildcard,\n name: \"*\",\n value: null,\n });\n } else if (part.at(0) === \"{\" && part.at(-1) === \"}\") {\n fragments.push({\n type: part[1] === \"#\" ? FragTypes.NumericParam : FragTypes.Param,\n name: part[1] === \"#\" ? part.slice(2, -1) : part.slice(1, -1),\n value: null,\n });\n } else {\n fragments.push({\n type: FragTypes.Literal,\n name: part,\n value: part,\n });\n }\n }\n\n return fragments;\n}\n","import type { Dolla, Logger } from \"../core/dolla.js\";\nimport type { ViewElement, ViewFunction } from \"../core/nodes/view.js\";\nimport { createState, derive, type StopFunction } from \"../core/state.js\";\nimport { assert, isFunction, isObject, isString } from \"../typeChecking.js\";\nimport type { Stringable } from \"../types.js\";\nimport { shallowEqual } from \"../utils.js\";\nimport { Passthrough } from \"../views/passthrough.js\";\nimport {\n joinPath,\n matchRoutes,\n patternToFragments,\n resolvePath,\n sortRoutes,\n splitPath,\n type ParsedRoute,\n type RouteMatch,\n} from \"./router.utils.js\";\n\n// ----- Types ----- //\n\nexport interface RouteMatchContext {\n /**\n * Redirects the user to a different route instead of matching the current one.\n */\n redirect(path: string): void;\n}\n\nexport interface Route {\n /**\n * The path or path fragment to match.\n */\n path: string;\n\n /**\n * Path to redirect to when this route is matched, or a callback function that returns such path.\n */\n redirect?: string | ((ctx: RouteRedirectContext) => string) | ((ctx: RouteRedirectContext) => Promise<string>);\n\n /**\n * View to display when this route is matched.\n */\n view?: ViewFunction<any>;\n\n /**\n * Subroutes.\n */\n routes?: Route[];\n\n /**\n * Called after the match is identified but before it is acted on. Use this to set state, load data, etc.\n */\n beforeMatch?: (ctx: RouteMatchContext) => void | Promise<void>;\n}\n\nexport interface RouteMeta {\n redirect?: string | ((ctx: RouteRedirectContext) => string) | ((ctx: RouteRedirectContext) => Promise<string>);\n pattern?: string;\n layers?: RouteLayer[];\n beforeMatch?: (ctx: RouteMatchContext) => void | Promise<void>;\n}\n\nexport interface RouteConfig {\n pattern: string;\n meta: RouteMeta;\n}\n\nexport interface RouteLayer {\n id: number;\n view: ViewFunction<{}>;\n}\n\n/**\n * An active route layer whose markup has been initialized into a view.\n */\ninterface ActiveLayer {\n id: number;\n view: ViewElement;\n}\n\n/**\n * Object passed to redirect callbacks. Contains information useful for determining how to redirect.\n */\nexport interface RouteRedirectContext {\n /**\n * The path as it appears in the URL bar.\n */\n path: string;\n\n /**\n * The pattern that this path was matched with.\n */\n pattern: string;\n\n /**\n * Named route params parsed from `path`.\n */\n params: Record<string, string | number | undefined>;\n\n /**\n * Query params parsed from `path`.\n */\n query: Record<string, string | number | boolean | undefined>;\n}\n\n/**\n * A log for a single step in the route resolution process.\n */\ninterface JourneyStep {\n kind: \"match\" | \"redirect\" | \"miss\";\n message: string;\n}\n\nexport interface NavigateOptions {\n /**\n * Replace the current item in the history stack instead of adding a new one.\n * The back button will send the user to the page they visited before this. Defaults to false.\n */\n replace?: boolean;\n\n /**\n * Preserve existing query params (if any) when navigating. Defaults to false.\n */\n preserveQuery?: boolean;\n}\n\nexport interface RouterOptions {\n routes: Route[];\n\n /**\n * When true, the router will construct routes like \"https://www.example.com/#/sub/route\" which work without any backend intervention.\n */\n hash?: boolean;\n}\n\n// ----- Code ----- //\n\nexport class Router {\n #dolla: Dolla;\n #logger: Logger;\n\n #layerId = 0;\n #activeLayers: ActiveLayer[] = [];\n #routes: ParsedRoute<RouteMeta>[] = [];\n\n /**\n * Use hash routing when true. Configured in router options.\n */\n #hash = false;\n\n // Callbacks that need to be called on unmount.\n #cleanupCallbacks: StopFunction[] = [];\n\n /**\n * The current match object.\n */\n #$match;\n #setMatch;\n\n /**\n * The currently matched route pattern, if any.\n */\n $pattern;\n /**\n * The current URL path.\n */\n $path;\n /**\n * The current named path params.\n */\n $params;\n /**\n * The current query params. Changes to this object will be reflected in the URL.\n */\n $query;\n\n constructor(dolla: Dolla) {\n this.#dolla = dolla;\n this.#logger = dolla.createLogger(\"Dolla.router\");\n\n [this.#$match, this.#setMatch] = createState<RouteMatch>();\n\n this.$pattern = derive([this.#$match], (m) => m?.pattern);\n this.$path = derive([this.#$match], (m) => m?.path ?? window.location.pathname);\n this.$params = derive([this.#$match], (m) => m?.params ?? {}, { equals: shallowEqual });\n this.$query = derive([this.#$match], (m) => m?.query ?? {}, { equals: shallowEqual });\n\n dolla.beforeMount(async () => {\n // Listen for popstate events and update route accordingly.\n const onPopState = () => {\n this.#updateRoute();\n };\n window.addEventListener(\"popstate\", onPopState);\n this.#cleanupCallbacks.push(() => window.removeEventListener(\"popstate\", onPopState));\n\n const rootElement = dolla.getRootElement()!;\n\n // Listen for clicks on <a> tags within the app.\n this.#cleanupCallbacks.push(\n catchLinks(rootElement, (anchor) => {\n let href = anchor.getAttribute(\"href\")!;\n this.#logger.info(\"intercepted click on <a> tag\", anchor);\n\n if (!/^https?:\\/\\/|^\\//.test(href)) {\n href = joinPath([window.location.pathname, href]);\n }\n\n this.#push(href);\n }),\n );\n this.#logger.info(\"will intercept clicks on <a> tags within root element\", rootElement);\n\n // Setup initial route content.\n await this.#updateRoute();\n });\n\n dolla.onUnmount(() => {\n for (const callback of this.#cleanupCallbacks) {\n callback();\n }\n this.#cleanupCallbacks = [];\n });\n }\n\n async setup(options: RouterOptions) {\n assert(options != null, \"Options object must not be null. Got: %t\");\n assert(\n !this.#dolla.isMounted,\n \"Dolla is already mounted. Dolla.router.setup() must be called before Dolla.mount().\",\n );\n\n if (options.hash) {\n this.#hash = true;\n }\n\n // Add routes.\n this.#routes = sortRoutes(\n options.routes\n .flatMap((route) => this.#prepareRoute(route))\n .map((route) => ({\n pattern: route.pattern,\n meta: route.meta,\n fragments: patternToFragments(route.pattern),\n })),\n );\n assertValidRedirects(this.#routes);\n }\n\n /**\n * Navigate backward. Pass a number of steps to hit the back button that many times.\n */\n back(steps = 1) {\n window.history.go(-steps);\n }\n\n /**\n * Navigate forward. Pass a number of steps to hit the forward button that many times.\n */\n forward(steps = 1) {\n window.history.go(steps);\n }\n\n /**\n * Navigates to another route.\n *\n * @example\n * Dolla.router.go(\"/login\"); // navigate to `/login`\n * Dolla.router.go[\"/users\", 215], { replace: true }); // replace current history entry with `/users/215`\n */\n go(path: Stringable | Stringable[], options: NavigateOptions = {}) {\n if (this.#dolla == null) {\n throw new Error(`Routa methods won't work until you register it: Dolla.use(Routa, { /* ...options */ })`);\n }\n\n let joined: string;\n\n if (Array.isArray(path)) {\n joined = joinPath(path);\n } else {\n joined = path.toString();\n }\n\n joined = resolvePath(window.location.pathname, joined);\n\n if (options.preserveQuery) {\n joined += window.location.search;\n }\n\n if (options.replace) {\n this.#replace(joined);\n } else {\n this.#push(joined);\n }\n }\n\n #push(href: string, state?: any) {\n this.#logger.info(\"(push)\", href);\n\n window.history.pushState(state, \"\", this.#hash ? \"/#\" + href : href);\n this.#updateRoute(href);\n }\n\n #replace(href: string, state?: any) {\n this.#logger.info(\"(replace)\", href);\n\n window.history.replaceState(state, \"\", this.#hash ? \"/#\" + href : href);\n this.#updateRoute(href);\n }\n\n #getCurrentURL(): URL {\n if (this.#hash) {\n return new URL(window.location.hash.slice(1), window.location.origin);\n } else {\n return new URL(window.location.pathname, window.location.origin);\n }\n }\n\n /**\n * Run when the location changes. Diffs and mounts new routes and updates\n * the $path, $route, $params and $query states accordingly.\n */\n async #updateRoute(href?: string) {\n const logger = this.#logger;\n const url = href ? new URL(href, window.location.origin) : this.#getCurrentURL();\n\n const { match, journey } = await this.#resolveRoute(url);\n\n for (const step of journey) {\n switch (step.kind) {\n case \"match\":\n logger.info(`📍 ${step.message}`);\n break;\n case \"redirect\":\n logger.info(`↩️ ${step.message}`);\n break;\n case \"miss\":\n logger.info(`💀 ${step.message}`);\n break;\n default:\n break;\n }\n }\n\n if (match) {\n const currentPattern = this.$pattern.get();\n\n this.#setMatch(match);\n\n if (match.pattern !== currentPattern) {\n this.#mountRoute(match);\n }\n } else {\n logger.crash(new NoRouteError(`Failed to match route '${url.pathname}'`));\n }\n\n return { match, journey };\n }\n\n /**\n * Takes a URL and finds a match, following redirects.\n */\n async #resolveRoute(\n url: URL,\n journey: JourneyStep[] = [],\n ): Promise<{\n match: RouteMatch<RouteMeta> | null;\n journey: JourneyStep[];\n }> {\n const match = matchRoutes(this.#routes, url.pathname);\n\n if (!match) {\n return {\n match: null,\n journey: [...journey, { kind: \"miss\", message: `no match for '${url.pathname}'` }],\n };\n }\n\n let redirect = match.meta.redirect;\n\n if (match.meta.beforeMatch) {\n await match.meta.beforeMatch({\n // TODO: Allow setting context variables from here? Would apply to the context of the matched view.\n redirect: (path) => {\n redirect = path;\n },\n });\n }\n\n if (redirect != null) {\n let path: string;\n\n if (isString(redirect)) {\n path = replaceParams(redirect, match.params);\n } else if (isFunction(redirect)) {\n const redirectContext: RouteRedirectContext = {\n path: match.path,\n pattern: match.pattern,\n params: match.params,\n query: match.query,\n };\n path = await redirect(redirectContext);\n if (!isString(path)) {\n throw new Error(`Redirect function must return a path to redirect to.`);\n }\n if (!path.startsWith(\"/\")) {\n // Not absolute. Resolve against matched path.\n path = resolvePath(match.path, path);\n }\n } else {\n throw new TypeError(`Redirect must either be a path string or a function.`);\n }\n\n return this.#resolveRoute(new URL(path, window.location.origin), [\n ...journey,\n { kind: \"redirect\", message: `redirecting '${match.path}' -> '${path}'` },\n ]);\n } else {\n return { match, journey: [...journey, { kind: \"match\", message: `matched route '${match.path}'` }] };\n }\n }\n\n /**\n * Takes a matched route and mounts it.\n */\n #mountRoute(match: RouteMatch<RouteMeta>) {\n const layers = match.meta.layers!;\n\n // Diff and update route layers.\n for (let i = 0; i < layers.length; i++) {\n const matchedLayer = layers[i];\n const activeLayer = this.#activeLayers[i];\n\n if (activeLayer?.id !== matchedLayer.id) {\n // Discard all previously active layers starting at this depth.\n this.#activeLayers = this.#activeLayers.slice(0, i);\n activeLayer?.view.unmount();\n\n const parentLayer = this.#activeLayers.at(-1);\n const parent = parentLayer?.view ?? this.#dolla!.getRootView()!;\n\n const view = parent.setChildView(matchedLayer.view);\n this.#activeLayers.push({ id: matchedLayer.id, view });\n }\n }\n }\n\n /**\n * Parses a route definition object into a set of matchable routes.\n *\n * @param route - Route config object.\n * @param layers - Array of parent layers. Passed when this function calls itself on nested routes.\n */\n #prepareRoute(route: Route, parents: Route[] = [], layers: RouteLayer[] = []) {\n if (!isObject(route) || !isString(route.path)) {\n throw new TypeError(`Route configs must be objects with a 'path' string property. Got: ${route}`);\n }\n\n if (route.redirect && route.routes) {\n throw new Error(`Route cannot have both a 'redirect' and nested 'routes'.`);\n } else if (route.redirect && route.view) {\n throw new Error(`Route cannot have both a 'redirect' and a 'view'.`);\n } else if (!route.view && !route.routes && !route.redirect) {\n throw new Error(`Route must have a 'view', a 'redirect', or a set of nested 'routes'.`);\n }\n\n let parts: string[] = [];\n\n for (const parent of parents) {\n parts.push(...splitPath(parent.path));\n }\n\n parts.push(...splitPath(route.path));\n\n // Remove trailing wildcard for joining with nested routes.\n if (parts[parts.length - 1] === \"*\") {\n parts.pop();\n }\n\n const routes: RouteConfig[] = [];\n\n if (route.redirect) {\n let redirect = route.redirect;\n\n if (isString(redirect)) {\n redirect = resolvePath(joinPath(parts), redirect);\n\n if (!redirect.startsWith(\"/\")) {\n redirect = \"/\" + redirect;\n }\n }\n\n routes.push({\n pattern: \"/\" + joinPath([...parts, ...splitPath(route.path)]),\n meta: {\n redirect,\n },\n });\n\n return routes;\n }\n\n let view: ViewFunction<any> = Passthrough;\n\n if (isFunction(route.view)) {\n view = route.view;\n } else if (route.view) {\n throw new TypeError(`Route '${route.path}' expected a view function or undefined. Got: ${route.view}`);\n }\n\n const layer: RouteLayer = { id: this.#layerId++, view };\n\n // Parse nested routes if they exist.\n if (route.routes) {\n for (const subroute of route.routes) {\n routes.push(...this.#prepareRoute(subroute, [...parents, route], [...layers, layer]));\n }\n } else {\n routes.push({\n pattern: parent ? joinPath([...parents.map((p) => p.path), route.path]) : route.path,\n meta: {\n pattern: route.path,\n layers: [...layers, layer],\n beforeMatch: route.beforeMatch,\n },\n });\n }\n\n return routes;\n }\n}\n\nconst safeExternalLink = /(noopener|noreferrer) (noopener|noreferrer)/;\nconst protocolLink = /^[\\w-_]+:/;\n\n/**\n * Intercepts links within the root node.\n *\n * This is adapted from https://github.com/choojs/nanohref/blob/master/index.js\n *\n * @param root - Element under which to intercept link clicks\n * @param callback - Function to call when a click event is intercepted\n * @param _window - (optional) Override for global window object\n */\nexport function catchLinks(root: HTMLElement, callback: (anchor: HTMLAnchorElement) => void, _window = window) {\n function traverse(node: HTMLElement | null): HTMLAnchorElement | null {\n if (!node || node === root) {\n return null;\n }\n\n if (node.localName !== \"a\" || (node as any).href === undefined) {\n return traverse(node.parentNode as HTMLElement | null);\n }\n\n return node as HTMLAnchorElement;\n }\n\n function handler(e: MouseEvent) {\n if ((e.button && e.button !== 0) || e.ctrlKey || e.metaKey || e.altKey || e.shiftKey || e.defaultPrevented) {\n return;\n }\n\n const anchor = traverse(e.target as HTMLElement);\n\n if (!anchor) {\n return;\n }\n\n if (\n _window.location.protocol !== anchor.protocol ||\n _window.location.hostname !== anchor.hostname ||\n _window.location.port !== anchor.port ||\n anchor.hasAttribute(\"data-router-ignore\") ||\n anchor.hasAttribute(\"download\") ||\n (anchor.getAttribute(\"target\") === \"_blank\" && safeExternalLink.test(anchor.getAttribute(\"rel\")!)) ||\n protocolLink.test(anchor.getAttribute(\"href\")!)\n ) {\n return;\n }\n\n e.preventDefault();\n callback(anchor);\n }\n\n root.addEventListener(\"click\", handler);\n\n return function cancel() {\n root.removeEventListener(\"click\", handler);\n };\n}\n\n/**\n * Replace route pattern param placeholders with real matched values.\n */\nfunction replaceParams(path: string, params: Record<string, string | number>) {\n for (const key in params) {\n const value = params[key].toString();\n path = path.replace(`{${key}}`, value).replace(`{#${key}}`, value);\n }\n\n return path;\n}\n\nfunction assertValidRedirects(routes: ParsedRoute<RouteMeta>[]) {\n // Test redirects to make sure all possible redirect targets actually exist.\n for (const route of routes) {\n if (route.meta.redirect) {\n let redirectPath: string;\n\n if (isFunction(route.meta.redirect)) {\n // throw new Error(`Redirect functions are not yet supported.`);\n // Just allow, though it could fail later. Best not to call the function and cause potential side effects.\n } else if (isString(route.meta.redirect)) {\n redirectPath = route.meta.redirect;\n\n const match = matchRoutes(routes, redirectPath, {\n willMatch(r) {\n return r !== route;\n },\n });\n\n if (!match) {\n throw new Error(`Found a redirect to an undefined URL. From '${route.pattern}' to '${route.meta.redirect}'`);\n }\n } else {\n throw new TypeError(`Expected a string or redirect function. Got: ${route.meta.redirect}`);\n }\n }\n }\n}\n\nclass NoRouteError extends Error {}\n","import { cond, html } from \"../core/markup.js\";\n\n/**\n * Props passed to the crash view when a crash occurs.\n */\nexport type CrashViewProps = {\n /**\n * JavaScript Error object.\n */\n error: Error;\n\n /**\n * A string to identify the logger that reported this error.\n */\n loggerName: string;\n\n /**\n * Unique identifier to pinpoint the specific view that reported the crash.\n */\n uid?: string;\n};\n\nexport function DefaultCrashView(props: CrashViewProps) {\n return html`\n <div\n style=${{\n backgroundColor: \"#880000\",\n color: \"#fff\",\n padding: \"2rem\",\n position: \"fixed\",\n inset: 0,\n fontSize: \"20px\",\n }}\n >\n <h1 style=${{ marginBottom: \"0.5rem\" }}>The app has crashed</h1>\n <p style=${{ marginBottom: \"0.25rem\" }}>\n <span style=${{ fontFamily: \"monospace\" }}>${props.loggerName}</span>\n ${cond(props.uid, html`<span style=${{ fontFamily: \"monospace\", opacity: 0.5 }}> [uid: ${props.uid}]</span>`)}\n ${\" \"}says:\n </p>\n <blockquote\n style=${{\n backgroundColor: \"#991111\",\n padding: \"0.25em\",\n borderRadius: \"6px\",\n fontFamily: \"monospace\",\n marginBottom: \"1rem\",\n }}\n >\n <span\n style=${{\n display: \"inline-block\",\n backgroundColor: \"red\",\n padding: \"0.1em 0.4em\",\n marginRight: \"0.5em\",\n borderRadius: \"4px\",\n fontSize: \"0.9em\",\n fontWeight: \"bold\",\n }}\n >\n ${props.error.name}\n </span>\n ${props.error.message}\n </blockquote>\n\n <p>Please see the browser console for details.</p>\n </div>\n `;\n}\n","import type { Dolla, Logger } from \"./dolla.js\";\n\n/**\n * Batches DOM updates; reads before writes.\n */\nexport class Batch {\n #dolla: Dolla;\n #logger: Logger;\n\n // Keys ensure only the most recent callback queued with a certain key\n // will be called, keeping DOM operations to a minimum.\n #keyedWrites = new Map<string, () => void>();\n\n // All unkeyed writes are run on every batch.\n #unkeyedWrites: (() => void)[] = [];\n\n // All read callbacks are run before updates on every batch.\n #reads: (() => void)[] = [];\n\n #batchInProgress = false;\n\n // When true, batches that would exceed 16ms will be split and deferred to a rAF.\n // This may not be desirable, because while it does prevent hitching it sometimes leaves\n // the state partially rendered for a brief second and certain elements can be seen to update after the fact.\n // But the tradeoff here is snappier navigation with possibly slightly out of date DOM updates on heavy pages.\n #deferIfOvertime = true;\n #deferrals = 0;\n\n #msFormat = new Intl.NumberFormat(\"en-US\", {\n maximumFractionDigits: 2,\n minimumFractionDigits: 0,\n style: \"unit\",\n unit: \"millisecond\",\n unitDisplay: \"short\",\n });\n\n constructor(dolla: Dolla) {\n this.#dolla = dolla;\n this.#logger = dolla.createLogger(\"Dolla.batch\");\n }\n\n /**\n * Queues a callback that runs before the next batch of writes.\n */\n read(callback: () => void) {\n this.#reads.push(callback);\n this.#queueBatch();\n }\n\n /**\n * Queues a callback to run in the next render batch.\n * Always put DOM mutations in a write callback when possible to help Dolla batch them efficiently.\n */\n write(callback: () => void, key?: string) {\n if (key) {\n this.#keyedWrites.set(key, callback);\n } else {\n this.#unkeyedWrites.push(callback);\n }\n this.#queueBatch();\n }\n\n #queueBatch() {\n if (!this.#batchInProgress) {\n this.#batchInProgress = true;\n const isDevEnv = this.#dolla.getEnv() === \"development\";\n queueMicrotask(() => {\n this.#runBatch(isDevEnv);\n });\n }\n }\n\n #runBatch(isDevEnv = false) {\n const start = performance.now();\n let elapsed = 0;\n\n const total = this.#reads.length + this.#keyedWrites.size + this.#unkeyedWrites.length;\n let completed = 0;\n\n /**\n * Runs after each operation. If true, the batch has been deferred and processing should stop. If false, processing of the current batch should continue.\n */\n const checkpoint = () => {\n completed++;\n elapsed = performance.now() - start;\n if (this.#deferIfOvertime && elapsed > 12 && completed < total) {\n this.#deferrals++;\n if (isDevEnv) {\n this.#logger.warn(\n `⚠️ Deferring batch to next frame. Performed ${completed} of ${total} batched operation${completed === 1 ? \"\" : \"s\"} in ${this.#msFormat.format(elapsed)} (deferral ${this.#deferrals}).`,\n );\n }\n requestAnimationFrame(() => {\n this.#runBatch(isDevEnv);\n });\n return true;\n }\n return false;\n };\n\n const keyedWrites = [...this.#keyedWrites.entries()];\n\n let key: string | undefined;\n let op: (() => void) | undefined;\n\n // Run reads.\n while ((op = this.#reads.shift())) {\n op();\n if (checkpoint()) return;\n }\n\n // Run keyed writes first.\n for ([key, op] of keyedWrites) {\n op();\n this.#keyedWrites.delete(key);\n if (checkpoint()) return;\n }\n\n // Run unkeyed writes second.\n while ((op = this.#unkeyedWrites.shift())) {\n op();\n if (checkpoint()) return;\n }\n\n if (isDevEnv) {\n this.#logger[elapsed > 16 ? \"warn\" : \"info\"](\n `${elapsed > 16 ? \"⚠️ (>=16ms) \" : \"\"}Executed ${completed} operation${completed === 1 ? \"\" : \"s\"} in ${this.#msFormat.format(elapsed)}${this.#deferrals > 0 ? ` (after ${this.#deferrals} deferral${this.#deferrals === 1 ? \"\" : \"s\"})` : \"\"}.`,\n );\n }\n this.#deferrals = 0;\n // Trigger again to catch updates queued while this batch was running.\n if (this.#reads.length || this.#keyedWrites.size || this.#unkeyedWrites.length) {\n queueMicrotask(() => {\n this.#runBatch(isDevEnv);\n });\n } else {\n this.#batchInProgress = false;\n }\n }\n}\n","import { Emitter } from \"@manyducks.co/emitter\";\nimport { HTTP } from \"../modules/http.js\";\nimport { I18n } from \"../modules/i18n.js\";\nimport { Router } from \"../modules/router.js\";\nimport { assertInstanceOf, isString } from \"../typeChecking.js\";\nimport { colorFromString, createMatcher, noOp } from \"../utils.js\";\nimport { DefaultCrashView, type CrashViewProps } from \"../views/default-crash-view.js\";\nimport { Passthrough } from \"../views/passthrough.js\";\nimport { Batch } from \"./batch.js\";\nimport { ContextEvent, type WildcardListenerMap, type ElementContext, type StorableContext } from \"./context.js\";\nimport { constructMarkup, createMarkup, groupElements, type Markup, type MarkupElement } from \"./markup.js\";\nimport { View, type ViewElement, type ViewFunction } from \"./nodes/view.js\";\nimport { createRef, isRef } from \"./ref.js\";\nimport { createState, createWatcher, derive, isState, toState, toValue } from \"./state.js\";\nimport { Stats } from \"./stats.js\";\nimport { isStore, isStoreFactory, StoreError, type Store, type StoreFactory } from \"./store.js\";\n\n// Affects which log messages will print and how much debugging info is included in the DOM.\nexport type Environment = \"development\" | \"production\";\n\n/**\n * Log type toggles. Each message category can be turned on or off or enabled only in a specific environment.\n */\nexport type Loggles = {\n info: boolean | Environment;\n log: boolean | Environment;\n warn: boolean | Environment;\n error: boolean | Environment;\n};\n\nexport interface Logger {\n info(...args: any[]): void;\n log(...args: any[]): void;\n warn(...args: any[]): void;\n error(...args: any[]): void;\n crash(error: Error): void;\n\n setName(name: string): Logger;\n}\n\nexport interface LoggerErrorContext {\n error: Error;\n loggerName: string;\n uid?: string;\n}\n\nexport type LoggerOptions = {\n /**\n * Console object to use for logging (mostly for testing). Uses window.console by default.\n */\n console?: any;\n\n /**\n * Unique ID to print with logs. Makes it easier to track down messages from specific view instances.\n */\n uid?: string;\n};\n\nexport class Dolla implements StorableContext {\n readonly batch: Batch;\n\n // Remove `private` when there are public methods to call.\n private readonly stats: Stats;\n\n readonly http: HTTP;\n readonly i18n: I18n;\n readonly router: Router;\n\n #isMounted = false;\n #env: Environment = \"production\";\n #rootElement?: HTMLElement;\n #rootView?: ViewElement;\n #crashView: ViewFunction<CrashViewProps> = DefaultCrashView;\n\n #watcher = createWatcher();\n\n #beforeMountCallbacks: Array<() => void | Promise<void>> = [];\n #onMountCallbacks: Array<() => void> = [];\n #beforeUnmountCallbacks: Array<() => void | Promise<void>> = [];\n #onUnmountCallbacks: Array<() => void> = [];\n\n #rootElementContext: ElementContext = {\n root: this,\n data: {},\n emitter: new Emitter(),\n stores: new Map(),\n viewName: \"Dolla\",\n };\n\n #loggles: Loggles = {\n info: \"development\",\n log: \"development\",\n warn: \"development\",\n error: true,\n };\n #match = createMatcher(\"*,-Dolla.*\");\n\n #wildcardListeners: WildcardListenerMap = new Map();\n\n // Registration functions for modules.\n // All modules will be registered before mount.\n #modules: (() => Promise<any>)[] = [];\n\n constructor() {\n this.batch = new Batch(this);\n this.stats = new Stats(this);\n this.http = new HTTP(this);\n this.i18n = new I18n(this);\n this.router = new Router(this);\n }\n\n watch = this.#watcher.watch;\n\n createState = createState;\n toState = toState;\n toValue = toValue;\n isState = isState;\n derive = derive;\n createWatcher = createWatcher;\n\n createRef = createRef;\n isRef = isRef;\n\n /**\n * True when the app is connected to a DOM node and displayed to the user.\n */\n get isMounted() {\n return this.#isMounted;\n }\n\n /**\n * Get the current environment that this app is running in.\n * Environment affects which log messages will print and how much debugging info is included in the DOM.\n */\n getEnv() {\n return this.#env;\n }\n\n /**\n * Sets the environment that this app is running in.\n * Environment affects which log messages will print and how much debugging info is included in the DOM.\n */\n setEnv(value: Environment) {\n this.#env = value;\n }\n\n /**\n * Sets the view that will be shown when the `crash` method is called on any logger.\n * When a crash is reported the app will be unmounted and replaced with this crash page.\n */\n setCrashView(view: ViewFunction<CrashViewProps>) {\n this.#crashView = view;\n }\n\n /**\n * Returns the HTMLElement Dolla is mounted to. This will return undefined until Dolla.mount() is called.\n */\n getRootElement() {\n return this.#rootElement;\n }\n\n /**\n * Returns the top level view Dolla is rendering inside the root element. This will return undefined until Dolla.mount() is called.\n */\n getRootView() {\n return this.#rootView;\n }\n\n /**\n * Sets a context variable and returns its value. Context variables are accessible on the app and in child views.\n */\n set<T>(key: string | symbol, value: T): T {\n this.#rootElementContext.data[key] = value;\n return value;\n }\n\n /**\n * Gets the value of a context variable. Returns null if the variable is not set.\n */\n get<T>(key: string | symbol): T | null {\n return (this.#rootElementContext.data[key] as T) ?? null;\n }\n\n /**\n * Returns an object of all context variables stored at the app level.\n */\n // getAll(): Record<string | symbol, unknown> {\n // return { ...this.#rootElementContext.data };\n // }\n\n /**\n * Adds a listener to be called when `eventName` is emitted.\n */\n on<T = unknown>(eventName: string, listener: (event: ContextEvent<T>) => void): void {\n if (eventName === \"*\") {\n const wrappedListener = (_eventName: any, event: ContextEvent<T>) => {\n listener(event);\n };\n this.#rootElementContext.emitter.on(eventName, wrappedListener);\n this.#wildcardListeners.set(listener, wrappedListener);\n } else {\n this.#rootElementContext.emitter.on(eventName, listener);\n }\n }\n\n /**\n * Removes a listener from the list to be called when `eventName` is emitted.\n */\n off<T = unknown>(eventName: string, listener: (event: ContextEvent<T>) => void): void {\n if (eventName === \"*\") {\n const wrappedListener = this.#wildcardListeners.get(listener);\n if (wrappedListener) {\n this.#rootElementContext.emitter.off(eventName, wrappedListener);\n this.#wildcardListeners.delete(listener);\n }\n } else {\n this.#rootElementContext.emitter.off(eventName, listener);\n }\n }\n\n /**\n * Adds a listener to be called when `eventName` is emitted. The listener is immediately removed after being called once.\n */\n once<T = unknown>(eventName: string, listener: (event: ContextEvent<T>) => void): void {\n if (eventName === \"*\") {\n const wrappedListener = (_eventName: any, event: ContextEvent<T>) => {\n this.#wildcardListeners.delete(listener);\n listener(event);\n };\n this.#rootElementContext.emitter.once(eventName, wrappedListener);\n this.#wildcardListeners.set(listener, wrappedListener);\n } else {\n this.#rootElementContext.emitter.once(eventName, listener);\n }\n }\n\n /**\n * Emits a new event to all listeners.\n */\n emit<T = unknown>(eventName: string, detail: T): boolean {\n return this.#rootElementContext.emitter.emit(eventName, new ContextEvent(eventName, detail));\n }\n\n /**\n * Attaches a new store to this context.\n */\n attachStore(store: Store<any, any>): void {\n const attached = store.attach(this.#rootElementContext);\n if (!attached) {\n let name = store.name ? `'${store.name}'` : \"this store\";\n console.warn(`An instance of ${name} was already attached to this context.`);\n }\n }\n\n /**\n * Gets the nearest instance of a store. Throws an error if the store isn't provided higher in the tree.\n */\n useStore<Value>(factory: StoreFactory<any, Value>): Value {\n if (isStoreFactory(factory)) {\n const key = (factory as any).key as string; // The key assigned inside of createStore.\n const store = this.#rootElementContext.stores.get(key);\n if (store == null) {\n throw new StoreError(`Store not found on this context.`);\n } else {\n return store.value;\n }\n } else if (isStore(factory)) {\n throw new StoreError(\n `Received a Store instance. Please pass the Store factory function to useStore without calling it.`,\n );\n } else {\n throw new StoreError(`Invalid store.`);\n }\n }\n\n async mount(selector: string, view?: ViewFunction<any>): Promise<void>;\n async mount(element: HTMLElement, view?: ViewFunction<any>): Promise<void>;\n\n async mount(target: string | HTMLElement, view?: ViewFunction<any>) {\n if (this.#isMounted) {\n throw new Error(`Dolla is already mounted.`);\n }\n\n if (isString(target)) {\n const match = document.querySelector<HTMLElement>(target);\n assertInstanceOf(HTMLElement, match, `Selector '${target}' did not match any element.`);\n this.#rootElement = match!;\n } else {\n assertInstanceOf(HTMLElement, target, \"Expected an HTML element or a selector string. Got type: %t, value: %v\");\n this.#rootElement = target;\n }\n\n // First, initialize the root view. The router store needs this to connect the initial route.\n const rootViewMarkup = createMarkup(view ?? Passthrough);\n this.#rootView = this.constructView(rootViewMarkup.type as ViewFunction<any>, rootViewMarkup.props);\n\n // Register modules\n // TODO: Handle errors\n await Promise.all(this.#modules.map((register) => register()));\n\n // Run beforeMount\n // TODO: Handle errors\n await Promise.all(this.#beforeMountCallbacks.map((callback) => callback()));\n\n this.#rootView.mount(this.#rootElement);\n this.#isMounted = true;\n\n // Run onMount for stores.\n for (const store of this.#rootElementContext.stores.values()) {\n store.handleMount();\n }\n\n // Run onMount\n // TODO: Handle errors\n for (const callback of this.#onMountCallbacks) {\n callback();\n }\n }\n\n async unmount() {\n if (!this.#isMounted) return;\n\n // Run beforeUnmount\n await Promise.all(this.#beforeUnmountCallbacks.map((callback) => callback()));\n\n this.#rootView?.unmount(false);\n\n this.#watcher.stopAll();\n\n this.#isMounted = false;\n\n // Run onUnmount\n for (const callback of this.#onUnmountCallbacks) {\n callback();\n }\n }\n\n /**\n * Registers a `callback` to run after `Dolla.mount` is called, before the app is mounted. If `callback` returns a Promise,\n * it will be awaited before mounting finishes. Use this to perform initial setup before the app is displayed to the user.\n */\n beforeMount(callback: () => void | Promise<void>) {\n this.#beforeMountCallbacks.push(callback);\n }\n\n /**\n * Registers a `callback` to run after the app is mounted.\n */\n onMount(callback: () => void) {\n this.#onMountCallbacks.push(callback);\n }\n\n /**\n * Registers a `callback` to run after `Dolla.unmount` is called, before the app is unmounted. If `callback` returns a Promise,\n * it will be awaited before unmounting finishes. Use this to perform cleanup.\n */\n beforeUnmount(callback: () => void | Promise<void>) {\n this.#beforeUnmountCallbacks.push(callback);\n }\n\n /**\n * Registers a `callback` to run after the app is unmounted.\n */\n onUnmount(callback: () => void) {\n this.#onUnmountCallbacks.push(callback);\n }\n\n /**\n * Update log type toggles. Values that are not passed will remain unchanged.\n */\n setLoggles(options: Partial<Loggles>) {\n for (const key in options) {\n const value = options[key as keyof Loggles];\n if (value) {\n this.#loggles[key as keyof Loggles] = value;\n }\n }\n }\n\n setLogFilter(filter: string | RegExp) {\n this.#match = createMatcher(filter);\n }\n\n createLogger(name: string, options?: LoggerOptions): Logger {\n const _console = options?.console ?? getDefaultConsole();\n\n const self = this;\n\n return {\n setName(newName: string) {\n name = newName;\n return this;\n },\n\n get info() {\n if (\n self.#loggles.info === false ||\n (isString(self.#loggles.info) && self.#loggles.info !== self.getEnv()) ||\n !self.#match(name)\n ) {\n return noOp;\n } else {\n let label = `%c${name}`;\n if (options?.uid) {\n label += ` %c[uid: %c${options.uid}%c]`;\n } else {\n label += `%c%c%c`;\n }\n return _console.info.bind(\n _console,\n label,\n `color:${colorFromString(label)};font-weight:bold`,\n `color:#777`,\n `color:#aaa`,\n `color:#777`,\n );\n }\n },\n\n get log() {\n if (\n self.#loggles.log === false ||\n (isString(self.#loggles.log) && self.#loggles.log !== self.getEnv()) ||\n !self.#match(name)\n ) {\n return noOp;\n } else {\n let label = `%c${name}`;\n if (options?.uid) {\n label += ` %c[uid: %c${options.uid}%c]`;\n } else {\n label += `%c%c%c`;\n }\n return _console.log.bind(\n _console,\n label,\n `color:${colorFromString(label)};font-weight:bold`,\n `color:#777`,\n `color:#aaa`,\n `color:#777`,\n );\n }\n },\n\n get warn() {\n if (\n self.#loggles.warn === false ||\n (isString(self.#loggles.warn) && self.#loggles.warn !== self.getEnv()) ||\n !self.#match(name)\n ) {\n return noOp;\n } else {\n let label = `%c${name}`;\n if (options?.uid) {\n label += ` %c[uid: %c${options.uid}%c]`;\n } else {\n label += `%c%c%c`;\n }\n return _console.warn.bind(\n _console,\n label,\n `color:${colorFromString(label)};font-weight:bold`,\n `color:#777`,\n `color:#aaa`,\n `color:#777`,\n );\n }\n },\n\n get error() {\n if (\n self.#loggles.error === false ||\n (isString(self.#loggles.error) && self.#loggles.error !== self.getEnv()) ||\n !self.#match(name)\n ) {\n return noOp;\n } else {\n let label = `%c${name}`;\n if (options?.uid) {\n label += ` %c[uid: %c${options.uid}%c]`;\n } else {\n label += `%c%c%c`;\n }\n return _console.error.bind(\n _console,\n label,\n `color:${colorFromString(label)};font-weight:bold`,\n `color:#777`,\n `color:#aaa`,\n `color:#777`,\n );\n }\n },\n\n crash(error: Error) {\n if (self.isMounted) {\n // Unmount the app.\n self.unmount();\n\n // Mount the crash page\n const crashPage = self.constructView(self.#crashView, {\n error,\n loggerName: name,\n uid: options?.uid,\n });\n crashPage.mount(self.#rootElement!);\n }\n\n throw error;\n },\n };\n }\n\n /**\n *\n */\n constructView<P>(view: ViewFunction<P>, props: P, children: Markup[] = []): ViewElement {\n return new View(this.#rootElementContext, view, props, children);\n }\n\n /**\n *\n */\n constructMarkup(markup: Markup | Markup[]): MarkupElement {\n return groupElements(constructMarkup(this.#rootElementContext, markup));\n }\n}\n\nexport function getDefaultConsole() {\n if (typeof window !== \"undefined\" && window.console) {\n return window.console;\n }\n if (typeof global !== \"undefined\" && global.console) {\n return global.console;\n }\n}\n","// States\nexport { createState, derive, isState, toState, toValue } from \"./core/state.js\";\nexport type { MaybeState, Setter, State, StopFunction } from \"./core/state.js\";\n\n// Ref\nexport { createRef, isRef, type Ref } from \"./core/ref.js\";\n\n// Store\nexport { createStore, type Store, type StoreFunction, type StoreFactory } from \"./core/store.js\";\n\n// Equality checks (useful for states)\nexport { deepEqual, shallowEqual, strictEqual } from \"./utils.js\";\n\n// Markup\nexport { cond, createMarkup, html, portal, repeat } from \"./core/markup.js\";\nexport type { Markup, MarkupElement } from \"./core/markup.js\";\n\n// View\nexport { createView } from \"./core/nodes/view.js\";\n\nimport { Dolla } from \"./core/dolla.js\";\nconst dolla = new Dolla();\n\nexport default dolla;\n\n// Language: standalone `t` function\nexport const t = dolla.i18n.t.bind(dolla.i18n);\n\nexport function setDevDebug(value: boolean) {\n if (typeof window !== \"undefined\") {\n (window as any).DOLLA_DEV_DEBUG = value;\n }\n}\n\nexport function getDevDebug(): boolean {\n if (typeof window !== \"undefined\") {\n return (window as any).DOLLA_DEV_DEBUG === true;\n }\n return false;\n}\n\n// Other types\nexport type { Dolla, Environment, Logger, LoggerErrorContext, LoggerOptions, Loggles } from \"./core/dolla.js\";\nexport type { ViewContext, ViewElement, ViewFunction } from \"./core/nodes/view.js\";\nexport type { HTTPRequest, HTTPResponse } from \"./modules/http.js\";\nexport type { InputType, Renderable } from \"./types.js\";\nexport type { CrashViewProps } from \"./views/default-crash-view.js\";\n\nimport type { IntrinsicElements as Elements } from \"./types\";\n\ndeclare global {\n namespace JSX {\n interface IntrinsicElements extends Elements {\n // Catch all for custom elements\n [tag: string]: any;\n }\n }\n}\n"],"names":["HTTP","dolla","__privateAdd","_HTTP_instances","_middleware","_fetch","getDefaultFetch","_dolla","_logger","__privateSet","fn","__privateGet","uri","options","__privateMethod","request_fn","method","Runner","HTTPResponseError","response","status","statusText","url","message","__publicField","Request","config","headers","value","key","isObject","name","query","mount","index","current","next","reqBody","req","fetched","contentType","body","Translation","_Translation_instances","_isLoaded","_templates","strings","isFunction","isString","res","entries","compile_fn","entry","selector","path","typeOf","parseTemplate_fn","template","Loc","Loc2","parsed","buffer","i","loc","segment","format","formatOptionName","startSegment","startFormat","I18n","_I18n_instances","_translations","_cache","_formats","_initialLocale","_setLocale","$locale","setLocale","createState","_","formatNumber_fn","formatDateTime_fn","formatList_fn","realName","names","nav","_a","firstLanguage","translation","error","optionKeys","optionValues","derive","locale","currentValues","getValue_fn","callback","count","date","list","cached","getCached_fn","exact","output","resolve","formats","values","deepEqual","object","part","splitPath","assertString","f","joinPath","parts","assertArrayOf","x","joined","p","resolvePath","base","resolved","parseQueryParams","matchRoutes","routes","route","fragments","matched","frag","params","sortRoutes","withoutParams","withNumericParams","withParams","wildcard","bySizeDesc","b","patternToFragments","pattern","Router","_Router_instances","_layerId","_activeLayers","_routes","_hash","_cleanupCallbacks","_$match","_setMatch","__privateWrapper","m","shallowEqual","onPopState","updateRoute_fn","rootElement","catchLinks","anchor","href","push_fn","assert","prepareRoute_fn","assertValidRedirects","steps","replace_fn","state","getCurrentURL_fn","logger","match","journey","resolveRoute_fn","step","currentPattern","mountRoute_fn","NoRouteError","redirect","replaceParams","redirectContext","layers","matchedLayer","activeLayer","parentLayer","view","parents","parent","Passthrough","layer","subroute","safeExternalLink","protocolLink","root","_window","traverse","node","handler","e","redirectPath","r","DefaultCrashView","props","html","cond","Batch","_Batch_instances","_keyedWrites","_unkeyedWrites","_reads","_batchInProgress","_deferIfOvertime","_deferrals","_msFormat","queueBatch_fn","isDevEnv","runBatch_fn","start","elapsed","total","completed","checkpoint","keyedWrites","op","Dolla","_isMounted","_env","_rootElement","_rootView","_crashView","_watcher","createWatcher","_beforeMountCallbacks","_onMountCallbacks","_beforeUnmountCallbacks","_onUnmountCallbacks","_rootElementContext","Emitter","_loggles","_match","createMatcher","_wildcardListeners","_modules","toState","toValue","isState","createRef","isRef","Stats","eventName","listener","wrappedListener","_eventName","event","detail","ContextEvent","store","factory","isStoreFactory","StoreError","isStore","target","assertInstanceOf","rootViewMarkup","createMarkup","register","filter","_console","getDefaultConsole","self","newName","noOp","label","colorFromString","children","View","markup","groupElements","constructMarkup","t","setDevDebug","getDevDebug"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/modules/router.utils.ts","../src/modules/router.ts","../src/modules/http.ts","../src/modules/i18n.ts","../src/views/default-crash-view.ts","../src/core/batch.ts","../src/core/dolla.ts","../src/index.ts"],"sourcesContent":["import { assertString, assertArrayOf, isFunction } from \"../typeChecking.js\";\n\nexport type RouteMatch<T = Record<string, any>> = {\n /**\n * The path string that triggered this match.\n */\n path: string;\n\n /**\n * The pattern satisfied by `path`.\n */\n pattern: string;\n\n /**\n * Named params as parsed from `path`.\n */\n params: Record<string, string | number>;\n\n /**\n * Query params as parsed from `path`.\n */\n query: Record<string, string | number | boolean>;\n\n /**\n * Metadata registered to this route.\n */\n meta: T;\n};\n\nexport enum FragTypes {\n Literal = 1,\n Param = 2,\n Wildcard = 3,\n NumericParam = 4,\n}\n\nexport type RouteFragment = {\n name: string;\n type: FragTypes;\n value: string | number | null;\n};\n\nexport type ParsedRoute<T> = {\n pattern: string;\n fragments: RouteFragment[];\n meta: T;\n};\n\nexport type RouteMatchOptions<T> = {\n willMatch?: (route: ParsedRoute<T>) => boolean;\n};\n\n/**\n * Separates a URL path into multiple fragments.\n *\n * @param path - A path string (e.g. `\"/api/users/5\"`)\n * @returns an array of fragments (e.g. `[\"api\", \"users\", \"5\"]`)\n */\nexport function splitPath(path: string): string[] {\n assertString(path, \"Expected `path` to be a string. Got type: %t, value: %v\");\n\n return path\n .split(\"/\")\n .map((f) => f.trim())\n .filter((f) => f !== \"\");\n}\n\n/**\n * Joins multiple URL path fragments into a single string.\n *\n * @param parts - One or more URL fragments (e.g. `[\"api\", \"users\", 5]`)\n * @returns a joined path (e.g. `\"api/users/5\"`)\n */\nexport function joinPath(parts: { toString(): string }[]): string {\n assertArrayOf(\n (part) => isFunction(part?.toString),\n parts,\n \"Expected `parts` to be an array of objects with a .toString() method. Got type: %t, value: %v\",\n );\n\n parts = parts.filter((x) => x).flatMap(String);\n\n let joined = parts.shift()?.toString();\n\n if (joined) {\n for (const part of parts.map((p) => p.toString())) {\n if (part.startsWith(\".\")) {\n // Resolve relative path against joined\n joined = resolvePath(joined, part);\n } else if (joined[joined.length - 1] !== \"/\") {\n if (part[0] !== \"/\") {\n joined += \"/\" + part;\n } else {\n joined += part;\n }\n } else {\n if (part[0] === \"/\") {\n joined += part.slice(1);\n } else {\n joined += part;\n }\n }\n }\n\n // Remove trailing slash (unless path is just '/')\n if (joined && joined !== \"/\" && joined.endsWith(\"/\")) {\n joined = joined.slice(0, joined.length - 1);\n }\n }\n\n return joined ?? \"\";\n}\n\nexport function resolvePath(base: string, part: string | null) {\n assertString(base, \"Expected `base` to be a string. Got type: %t, value: %v\");\n\n if (part == null) {\n part = base;\n base = \"\";\n }\n\n if (part.startsWith(\"/\")) {\n return part;\n }\n\n let resolved = base;\n\n while (true) {\n if (part.startsWith(\"..\")) {\n for (let i = resolved.length; i > 0; --i) {\n if (resolved[i] === \"/\" || i === 0) {\n resolved = resolved.slice(0, i);\n part = part.replace(/^\\.\\.\\/?/, \"\");\n break;\n }\n }\n } else if (part.startsWith(\".\")) {\n part = part.replace(/^\\.\\/?/, \"\");\n } else {\n break;\n }\n }\n\n return joinPath([resolved, part]);\n}\n\nexport function parseQueryParams(query: string): Record<string, string | number | boolean> {\n if (!query) return {};\n\n if (query.startsWith(\"?\")) {\n query = query.slice(1);\n }\n\n const entries = query\n .split(\"&\")\n .filter((x) => x.trim() !== \"\")\n .map((entry) => {\n const [key, value] = entry.split(\"=\").map((x) => x.trim());\n\n if (value.toLowerCase() === \"true\") {\n return [key, true] as const;\n }\n\n if (value.toLowerCase() === \"false\") {\n return [key, false] as const;\n }\n\n // Return value as a number if it parses as one.\n if (!isNaN(Number(value))) {\n return [key, Number(value)] as const;\n }\n\n return [key, value] as const;\n });\n\n return Object.fromEntries(entries);\n}\n\n/**\n * Returns the nearest match, or undefined if the path matches no route.\n *\n * @param url - Path to match against routes.\n * @param options - Options to customize how matching operates.\n */\nexport function matchRoutes<T>(\n routes: ParsedRoute<T>[],\n url: string,\n options: RouteMatchOptions<T> = {},\n): RouteMatch<T> | undefined {\n const [path, query] = url.split(\"?\");\n const parts = splitPath(path);\n\n routes: for (const route of routes) {\n const { fragments } = route;\n const hasWildcard = fragments[fragments.length - 1]?.type === FragTypes.Wildcard;\n\n if (!hasWildcard && fragments.length !== parts.length) {\n continue routes;\n }\n\n if (options.willMatch && !options.willMatch(route)) {\n continue routes;\n }\n\n const matched: RouteFragment[] = [];\n\n fragments: for (let i = 0; i < fragments.length; i++) {\n const part = parts[i];\n const frag = fragments[i];\n\n if (part == null && frag.type !== FragTypes.Wildcard) {\n continue routes;\n }\n\n switch (frag.type) {\n case FragTypes.Literal:\n if (frag.name.toLowerCase() === part.toLowerCase()) {\n matched.push(frag);\n break;\n } else {\n continue routes;\n }\n case FragTypes.Param:\n matched.push({ ...frag, value: part });\n break;\n case FragTypes.Wildcard:\n matched.push({ ...frag, value: parts.slice(i).join(\"/\") });\n break fragments;\n case FragTypes.NumericParam:\n if (!isNaN(Number(part))) {\n matched.push({ ...frag, value: Number(part) });\n break;\n } else {\n continue routes;\n }\n default:\n throw new Error(`Unknown fragment type: ${frag.type}`);\n }\n }\n\n const params: Record<string, string | number> = {};\n\n for (const frag of matched) {\n if (frag.type === FragTypes.Param) {\n params[frag.name] = decodeURIComponent(frag.value as string);\n }\n\n if (frag.type === FragTypes.NumericParam) {\n params[frag.name] = frag.value as number;\n }\n\n if (frag.type === FragTypes.Wildcard) {\n params.wildcard = \"/\" + decodeURIComponent(frag.value as string);\n }\n }\n\n return {\n path: \"/\" + matched.map((f) => f.value).join(\"/\"),\n pattern:\n \"/\" +\n fragments\n .map((f) => {\n if (f.type === FragTypes.Param) {\n return `{${f.name}}`;\n }\n\n if (f.type === FragTypes.NumericParam) {\n return `{#${f.name}}`;\n }\n\n return f.name;\n })\n .join(\"/\"),\n params,\n query: parseQueryParams(query),\n meta: route.meta,\n };\n }\n}\n\n/**\n * Sort routes descending by specificity. Guarantees that the most specific route matches first\n * no matter the order in which they were added.\n *\n * Routes without named params and routes with more fragments are weighted more heavily.\n */\nexport function sortRoutes<T>(routes: ParsedRoute<T>[]): ParsedRoute<T>[] {\n const withoutParams = [];\n const withNumericParams = [];\n const withParams = [];\n const wildcard = [];\n\n for (const route of routes) {\n const { fragments } = route;\n\n if (fragments.some((f) => f.type === FragTypes.Wildcard)) {\n wildcard.push(route);\n } else if (fragments.some((f) => f.type === FragTypes.NumericParam)) {\n withNumericParams.push(route);\n } else if (fragments.some((f) => f.type === FragTypes.Param)) {\n withParams.push(route);\n } else {\n withoutParams.push(route);\n }\n }\n\n const bySizeDesc = (a: ParsedRoute<T>, b: ParsedRoute<T>) => {\n if (a.fragments.length > b.fragments.length) {\n return -1;\n } else {\n return 1;\n }\n };\n\n withoutParams.sort(bySizeDesc);\n withNumericParams.sort(bySizeDesc);\n withParams.sort(bySizeDesc);\n wildcard.sort(bySizeDesc);\n\n return [...withoutParams, ...withNumericParams, ...withParams, ...wildcard];\n}\n\n/**\n * Converts a route pattern into a set of matchable fragments.\n *\n * @param route - A route string (e.g. \"/api/users/{id}\")\n */\nexport function patternToFragments(pattern: string): RouteFragment[] {\n const parts = splitPath(pattern);\n const fragments = [];\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n\n if (part === \"*\") {\n if (i !== parts.length - 1) {\n throw new Error(`Wildcard must be at the end of a pattern. Received: ${pattern}`);\n }\n fragments.push({\n type: FragTypes.Wildcard,\n name: \"*\",\n value: null,\n });\n } else if (part.at(0) === \"{\" && part.at(-1) === \"}\") {\n fragments.push({\n type: part[1] === \"#\" ? FragTypes.NumericParam : FragTypes.Param,\n name: part[1] === \"#\" ? part.slice(2, -1) : part.slice(1, -1),\n value: null,\n });\n } else {\n fragments.push({\n type: FragTypes.Literal,\n name: part,\n value: part,\n });\n }\n }\n\n return fragments;\n}\n","import type { Dolla, Logger } from \"../core/dolla.js\";\nimport { type ViewElement, type ViewFunction } from \"../core/nodes/view.js\";\nimport { createState, derive, type StopFunction } from \"../core/state.js\";\nimport { IS_ROUTER } from \"../core/symbols.js\";\nimport { assertObject, isFunction, isObject, isString } from \"../typeChecking.js\";\nimport type { Stringable } from \"../types.js\";\nimport { shallowEqual } from \"../utils.js\";\nimport { Passthrough } from \"../views/passthrough.js\";\nimport {\n joinPath,\n matchRoutes,\n patternToFragments,\n resolvePath,\n sortRoutes,\n splitPath,\n type ParsedRoute,\n type RouteMatch,\n} from \"./router.utils.js\";\n\n// ----- Types ----- //\n\nexport interface RouteMatchContext {\n /**\n * Redirects the user to a different route instead of matching the current one.\n */\n redirect(path: string): void;\n}\n\nexport interface Route {\n /**\n * The path or path fragment to match.\n */\n path: string;\n\n /**\n * Path to redirect to when this route is matched, or a callback function that returns such path.\n */\n redirect?: string | ((ctx: RouteRedirectContext) => string) | ((ctx: RouteRedirectContext) => Promise<string>);\n\n /**\n * View to display when this route is matched.\n */\n view?: ViewFunction<any>;\n\n /**\n * Subroutes.\n */\n routes?: Route[];\n\n /**\n * Called after the match is identified but before it is acted on. Use this to set state, load data, etc.\n */\n beforeMatch?: (ctx: RouteMatchContext) => void | Promise<void>;\n}\n\nexport interface RouteMeta {\n redirect?: string | ((ctx: RouteRedirectContext) => string) | ((ctx: RouteRedirectContext) => Promise<string>);\n pattern?: string;\n layers?: RouteLayer[];\n beforeMatch?: (ctx: RouteMatchContext) => void | Promise<void>;\n}\n\nexport interface RouteConfig {\n pattern: string;\n meta: RouteMeta;\n}\n\nexport interface RouteLayer {\n id: number;\n view: ViewFunction<{}>;\n}\n\n/**\n * An active route layer whose markup has been initialized into a view.\n */\ninterface ActiveLayer {\n id: number;\n view: ViewElement;\n}\n\n/**\n * Object passed to redirect callbacks. Contains information useful for determining how to redirect.\n */\nexport interface RouteRedirectContext {\n /**\n * The path as it appears in the URL bar.\n */\n path: string;\n\n /**\n * The pattern that this path was matched with.\n */\n pattern: string;\n\n /**\n * Named route params parsed from `path`.\n */\n params: Record<string, string | number | undefined>;\n\n /**\n * Query params parsed from `path`.\n */\n query: Record<string, string | number | boolean | undefined>;\n}\n\n/**\n * A log for a single step in the route resolution process.\n */\ninterface JourneyStep {\n kind: \"match\" | \"redirect\" | \"miss\";\n message: string;\n}\n\nexport interface NavigateOptions {\n /**\n * Replace the current item in the history stack instead of adding a new one.\n * The back button will send the user to the page they visited before this. Defaults to false.\n */\n replace?: boolean;\n\n /**\n * Preserve existing query params (if any) when navigating. Defaults to false.\n */\n preserveQuery?: boolean;\n}\n\nexport interface RouterOptions {\n routes: Route[];\n\n /**\n * When true, the router will construct routes like \"https://www.example.com/#/sub/route\" which work without any backend intervention.\n */\n hash?: boolean;\n}\n\n// ----- Code ----- //\n\nexport function createRouter(options: RouterOptions): Router {\n return new Router(options);\n}\n\nconst ROUTER_MOUNT = Symbol.for(\"DollaRouterMountMethod\");\nconst ROUTER_UNMOUNT = Symbol.for(\"DollaRouterUnmountMethod\");\n\nexport function _isRouter(value: any): value is Router {\n return value?.[IS_ROUTER] === true;\n}\n\nexport async function _mountRouter(router: Router, dolla: Dolla) {\n return router[ROUTER_MOUNT](dolla);\n}\n\nexport async function _unmountRouter(router: Router) {\n return router[ROUTER_UNMOUNT]();\n}\n\nexport class Router {\n [IS_ROUTER] = true;\n\n #dolla?: Dolla;\n #logger?: Logger;\n\n #layerId = 0;\n #activeLayers: ActiveLayer[] = [];\n #routes: ParsedRoute<RouteMeta>[] = [];\n\n #isMounted = false;\n\n /**\n * Use hash routing when true. Configured in router options.\n */\n #hash = false;\n\n // Callbacks that need to be called on unmount.\n #cleanupCallbacks: StopFunction[] = [];\n\n /**\n * The current match object.\n */\n #$match;\n #setMatch;\n\n /**\n * The currently matched route pattern, if any.\n */\n $pattern;\n /**\n * The current URL path.\n */\n $path;\n /**\n * The current named path params.\n */\n $params;\n /**\n * The current query params. Changes to this object will be reflected in the URL.\n */\n $query;\n\n constructor(options: RouterOptions) {\n assertObject(options, \"Options must be an object. Got: %t\");\n\n [this.#$match, this.#setMatch] = createState<RouteMatch>();\n\n this.$pattern = derive([this.#$match], (m) => m?.pattern);\n this.$path = derive([this.#$match], (m) => m?.path ?? window.location.pathname);\n this.$params = derive([this.#$match], (m) => m?.params ?? {}, { equals: shallowEqual });\n this.$query = derive([this.#$match], (m) => m?.query ?? {}, { equals: shallowEqual });\n\n if (options.hash) {\n this.#hash = true;\n }\n\n // Add routes.\n this.#routes = sortRoutes(\n options.routes\n .flatMap((route) => this.#prepareRoute(route))\n .map((route) => ({\n pattern: route.pattern,\n meta: route.meta,\n fragments: patternToFragments(route.pattern),\n })),\n );\n assertValidRedirects(this.#routes);\n }\n\n async [ROUTER_MOUNT](dolla: Dolla) {\n this.#dolla = dolla;\n this.#logger = dolla.createLogger(\"Dolla.router\");\n\n // Listen for popstate events and update route accordingly.\n const onPopState = () => {\n this.#updateRoute();\n };\n window.addEventListener(\"popstate\", onPopState);\n this.#cleanupCallbacks.push(() => window.removeEventListener(\"popstate\", onPopState));\n\n const rootElement = dolla.getRootElement()!;\n\n // Listen for clicks on <a> tags within the app.\n this.#cleanupCallbacks.push(\n catchLinks(rootElement, (anchor) => {\n let href = anchor.getAttribute(\"href\")!;\n this.#logger!.info(\"intercepted click on <a> tag\", anchor);\n\n if (!/^https?:\\/\\/|^\\//.test(href)) {\n href = joinPath([window.location.pathname, href]);\n }\n\n this.#push(href);\n }),\n );\n this.#logger.info(\"will intercept clicks on <a> tags within root element\", rootElement);\n\n this.#isMounted = true;\n\n // Setup initial route content.\n await this.#updateRoute();\n }\n\n async [ROUTER_UNMOUNT]() {\n for (const callback of this.#cleanupCallbacks) {\n callback();\n }\n this.#cleanupCallbacks = [];\n }\n\n /**\n * Navigate backward. Pass a number of steps to hit the back button that many times.\n */\n back(steps = 1) {\n window.history.go(-steps);\n }\n\n /**\n * Navigate forward. Pass a number of steps to hit the forward button that many times.\n */\n forward(steps = 1) {\n window.history.go(steps);\n }\n\n /**\n * Navigates to another route.\n *\n * @example\n * router.go(\"/login\"); // navigate to `/login`\n * router.go[\"/users\", 215], { replace: true }); // replace current history entry with `/users/215`\n */\n go(path: Stringable | Stringable[], options: NavigateOptions = {}) {\n if (this.#dolla == null) {\n throw new Error(`Routa methods won't work until you register it: Dolla.use(Routa, { /* ...options */ })`);\n }\n\n let joined: string;\n\n if (Array.isArray(path)) {\n joined = joinPath(path);\n } else {\n joined = path.toString();\n }\n\n joined = resolvePath(window.location.pathname, joined);\n\n if (options.preserveQuery) {\n joined += window.location.search;\n }\n\n if (options.replace) {\n this.#replace(joined);\n } else {\n this.#push(joined);\n }\n }\n\n #push(href: string, state?: any) {\n this.#logger?.info(\"(push)\", href);\n\n window.history.pushState(state, \"\", this.#hash ? \"/#\" + href : href);\n this.#updateRoute(href);\n }\n\n #replace(href: string, state?: any) {\n this.#logger?.info(\"(replace)\", href);\n\n window.history.replaceState(state, \"\", this.#hash ? \"/#\" + href : href);\n this.#updateRoute(href);\n }\n\n #getCurrentURL(): URL {\n if (this.#hash) {\n return new URL(window.location.hash.slice(1), window.location.origin);\n } else {\n return new URL(window.location.pathname, window.location.origin);\n }\n }\n\n /**\n * Run when the location changes. Diffs and mounts new routes and updates\n * the $path, $route, $params and $query states accordingly.\n */\n async #updateRoute(href?: string) {\n const logger = this.#logger;\n const rootView = this.#dolla?.getRootView();\n const url = href ? new URL(href, window.location.origin) : this.#getCurrentURL();\n\n const { match, journey } = await this.#resolveRoute(url);\n\n for (const step of journey) {\n switch (step.kind) {\n case \"match\":\n logger?.info(`📍 ${step.message}`);\n break;\n case \"redirect\":\n logger?.info(`↩️ ${step.message}`);\n break;\n case \"miss\":\n logger?.info(`💀 ${step.message}`);\n break;\n default:\n break;\n }\n }\n\n if (match) {\n const currentPattern = this.$pattern.get();\n\n this.#setMatch(match);\n\n if (rootView && match.pattern !== currentPattern) {\n this.#mountRoute(rootView, match);\n }\n } else {\n // Only crash if routing has been configured.\n if (this.#isMounted) {\n logger!.crash(new NoRouteError(`Failed to match route '${url.pathname}'`));\n }\n }\n\n return { match, journey };\n }\n\n /**\n * Takes a URL and finds a match, following redirects.\n */\n async #resolveRoute(\n url: URL,\n journey: JourneyStep[] = [],\n ): Promise<{\n match: RouteMatch<RouteMeta> | null;\n journey: JourneyStep[];\n }> {\n const match = matchRoutes(this.#routes, url.pathname);\n\n if (!match) {\n return {\n match: null,\n journey: [...journey, { kind: \"miss\", message: `no match for '${url.pathname}'` }],\n };\n }\n\n let redirect = match.meta.redirect;\n\n if (match.meta.beforeMatch) {\n await match.meta.beforeMatch({\n // TODO: Allow setting context variables from here? Would apply to the context of the matched view.\n redirect: (path) => {\n redirect = path;\n },\n });\n }\n\n if (redirect != null) {\n let path: string;\n\n if (isString(redirect)) {\n path = replaceParams(redirect, match.params);\n } else if (isFunction(redirect)) {\n const redirectContext: RouteRedirectContext = {\n path: match.path,\n pattern: match.pattern,\n params: match.params,\n query: match.query,\n };\n path = await redirect(redirectContext);\n if (!isString(path)) {\n throw new Error(`Redirect function must return a path to redirect to.`);\n }\n if (!path.startsWith(\"/\")) {\n // Not absolute. Resolve against matched path.\n path = resolvePath(match.path, path);\n }\n } else {\n throw new TypeError(`Redirect must either be a path string or a function.`);\n }\n\n return this.#resolveRoute(new URL(path, window.location.origin), [\n ...journey,\n { kind: \"redirect\", message: `redirecting '${match.path}' -> '${path}'` },\n ]);\n } else {\n return { match, journey: [...journey, { kind: \"match\", message: `matched route '${match.path}'` }] };\n }\n }\n\n /**\n * Takes a matched route and mounts it.\n */\n #mountRoute(rootView: ViewElement, match: RouteMatch<RouteMeta>) {\n const layers = match.meta.layers!;\n\n // Diff and update route layers.\n for (let i = 0; i < layers.length; i++) {\n const matchedLayer = layers[i];\n const activeLayer = this.#activeLayers[i];\n\n if (activeLayer?.id !== matchedLayer.id) {\n // Discard all previously active layers starting at this depth.\n this.#activeLayers = this.#activeLayers.slice(0, i);\n activeLayer?.view.unmount();\n\n const parentLayer = this.#activeLayers.at(-1);\n const parent = parentLayer?.view ?? rootView;\n\n const view = parent.setChildView(matchedLayer.view);\n this.#activeLayers.push({ id: matchedLayer.id, view });\n }\n }\n }\n\n /**\n * Parses a route definition object into a set of matchable routes.\n *\n * @param route - Route config object.\n * @param layers - Array of parent layers. Passed when this function calls itself on nested routes.\n */\n #prepareRoute(route: Route, parents: Route[] = [], layers: RouteLayer[] = []) {\n if (!isObject(route) || !isString(route.path)) {\n throw new TypeError(`Route configs must be objects with a 'path' string property. Got: ${route}`);\n }\n\n if (route.redirect && route.routes) {\n throw new Error(`Route cannot have both a 'redirect' and nested 'routes'.`);\n } else if (route.redirect && route.view) {\n throw new Error(`Route cannot have both a 'redirect' and a 'view'.`);\n } else if (!route.view && !route.routes && !route.redirect) {\n throw new Error(`Route must have a 'view', a 'redirect', or a set of nested 'routes'.`);\n }\n\n let parts: string[] = [];\n\n for (const parent of parents) {\n parts.push(...splitPath(parent.path));\n }\n\n parts.push(...splitPath(route.path));\n\n // Remove trailing wildcard for joining with nested routes.\n if (parts[parts.length - 1] === \"*\") {\n parts.pop();\n }\n\n const routes: RouteConfig[] = [];\n\n if (route.redirect) {\n let redirect = route.redirect;\n\n if (isString(redirect)) {\n redirect = resolvePath(joinPath(parts), redirect);\n\n if (!redirect.startsWith(\"/\")) {\n redirect = \"/\" + redirect;\n }\n }\n\n routes.push({\n pattern: \"/\" + joinPath([...parts, ...splitPath(route.path)]),\n meta: {\n redirect,\n },\n });\n\n return routes;\n }\n\n let view: ViewFunction<any> = Passthrough;\n\n if (isFunction(route.view)) {\n view = route.view;\n } else if (route.view) {\n throw new TypeError(`Route '${route.path}' expected a view function or undefined. Got: ${route.view}`);\n }\n\n const layer: RouteLayer = { id: this.#layerId++, view };\n\n // Parse nested routes if they exist.\n if (route.routes) {\n for (const subroute of route.routes) {\n routes.push(...this.#prepareRoute(subroute, [...parents, route], [...layers, layer]));\n }\n } else {\n routes.push({\n pattern: parent ? joinPath([...parents.map((p) => p.path), route.path]) : route.path,\n meta: {\n pattern: route.path,\n layers: [...layers, layer],\n beforeMatch: route.beforeMatch,\n },\n });\n }\n\n return routes;\n }\n}\n\nconst safeExternalLink = /(noopener|noreferrer) (noopener|noreferrer)/;\nconst protocolLink = /^[\\w-_]+:/;\n\n/**\n * Intercepts links within the root node.\n *\n * This is adapted from https://github.com/choojs/nanohref/blob/master/index.js\n *\n * @param root - Element under which to intercept link clicks\n * @param callback - Function to call when a click event is intercepted\n * @param _window - (optional) Override for global window object\n */\nexport function catchLinks(root: Element, callback: (anchor: HTMLAnchorElement) => void, _window = window) {\n function traverse(node: HTMLElement | null): HTMLAnchorElement | null {\n if (!node || node === root) {\n return null;\n }\n\n if (node.localName !== \"a\" || (node as any).href === undefined) {\n return traverse(node.parentNode as HTMLElement | null);\n }\n\n return node as HTMLAnchorElement;\n }\n\n function handler(e: MouseEvent) {\n if ((e.button && e.button !== 0) || e.ctrlKey || e.metaKey || e.altKey || e.shiftKey || e.defaultPrevented) {\n return;\n }\n\n const anchor = traverse(e.target as HTMLElement);\n\n if (!anchor) {\n return;\n }\n\n if (\n _window.location.protocol !== anchor.protocol ||\n _window.location.hostname !== anchor.hostname ||\n _window.location.port !== anchor.port ||\n anchor.hasAttribute(\"data-router-ignore\") ||\n anchor.hasAttribute(\"download\") ||\n (anchor.getAttribute(\"target\") === \"_blank\" && safeExternalLink.test(anchor.getAttribute(\"rel\")!)) ||\n protocolLink.test(anchor.getAttribute(\"href\")!)\n ) {\n return;\n }\n\n e.preventDefault();\n callback(anchor);\n }\n\n root.addEventListener(\"click\", handler as any);\n\n return function cancel() {\n root.removeEventListener(\"click\", handler as any);\n };\n}\n\n/**\n * Replace route pattern param placeholders with real matched values.\n */\nfunction replaceParams(path: string, params: Record<string, string | number>) {\n for (const key in params) {\n const value = params[key].toString();\n path = path.replace(`{${key}}`, value).replace(`{#${key}}`, value);\n }\n\n return path;\n}\n\nfunction assertValidRedirects(routes: ParsedRoute<RouteMeta>[]) {\n // Test redirects to make sure all possible redirect targets actually exist.\n for (const route of routes) {\n if (route.meta.redirect) {\n let redirectPath: string;\n\n if (isFunction(route.meta.redirect)) {\n // throw new Error(`Redirect functions are not yet supported.`);\n // Just allow, though it could fail later. Best not to call the function and cause potential side effects.\n } else if (isString(route.meta.redirect)) {\n redirectPath = route.meta.redirect;\n\n const match = matchRoutes(routes, redirectPath, {\n willMatch(r) {\n return r !== route;\n },\n });\n\n if (!match) {\n throw new Error(`Found a redirect to an undefined URL. From '${route.pattern}' to '${route.meta.redirect}'`);\n }\n } else {\n throw new TypeError(`Expected a string or redirect function. Got: ${route.meta.redirect}`);\n }\n }\n }\n}\n\nclass NoRouteError extends Error {}\n","import { isObject } from \"../typeChecking.js\";\nimport type { Dolla, Logger } from \"../core/dolla.js\";\n\n/**\n * A simple HTTP client with middleware support. Middleware applies to all requests made through this store,\n * so it's the perfect way to handle things like auth headers and permission checks for API calls.\n */\nexport class HTTP {\n #middleware: HTTPMiddleware[] = [];\n #fetch = getDefaultFetch();\n #dolla: Dolla;\n #logger: Logger;\n\n constructor(dolla: Dolla) {\n this.#dolla = dolla;\n this.#logger = dolla.createLogger(\"Dolla.http\");\n }\n\n /**\n * Adds a new middleware that will apply to subsequent requests.\n * Returns a function to remove this middleware.\n *\n * @param middleware - A middleware function that will intercept requests.\n */\n use(fn: HTTPMiddleware) {\n this.#middleware.push(fn);\n\n // Call returned function to remove this middleware for subsequent requests.\n return () => {\n this.#middleware.splice(this.#middleware.indexOf(fn), 1);\n };\n }\n\n async get<ResBody = unknown>(uri: string, options?: RequestOptions<never>) {\n return this.#request<ResBody, never>(\"get\", uri, options);\n }\n\n async put<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"put\", uri, options);\n }\n\n async patch<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"patch\", uri, options);\n }\n\n async post<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"post\", uri, options);\n }\n\n async delete<ResBody = unknown>(uri: string, options?: RequestOptions<never>) {\n return this.#request<ResBody, never>(\"delete\", uri, options);\n }\n\n async head<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"head\", uri, options);\n }\n\n async options<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"options\", uri, options);\n }\n\n async trace<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"trace\", uri, options);\n }\n\n async #request<ResBody, ReqBody>(method: string, uri: string, options?: RequestOptions<any>) {\n const runner = new Runner<ResBody, ReqBody>({\n ...options,\n method,\n uri,\n middleware: this.#middleware,\n fetch: this.#fetch,\n logger: this.#logger,\n });\n return runner.fetch();\n }\n}\n\nfunction getDefaultFetch(): typeof window.fetch {\n if (typeof window !== \"undefined\" && window.fetch) {\n return window.fetch.bind(window);\n }\n\n if (typeof global !== \"undefined\" && global.fetch) {\n return global.fetch.bind(global);\n }\n\n throw new Error(\"Running in neither browser nor node. Please run this app in one of the supported environments.\");\n}\n\n/*====================*\\\n|| Request ||\n\\*====================*/\n\nexport type HTTPMiddleware = (\n request: HTTPRequest<unknown>,\n next: () => Promise<HTTPResponse<unknown>>,\n) => void | Promise<void>;\n\nexport interface RequestOptions<ReqBody> {\n /**\n * Body to send with the request.\n */\n body?: ReqBody;\n\n /**\n * Headers to send with the request.\n */\n headers?: Record<string, any> | Headers;\n\n /**\n * Query params to interpolate into the URL.\n */\n query?: Record<string, any> | URLSearchParams;\n}\n\nexport interface HTTPRequest<Body> {\n method: string;\n url: URL;\n headers: Headers;\n body: Body;\n}\n\nexport interface HTTPResponse<Body> {\n method: string;\n url: URL;\n headers: Headers;\n status: number;\n statusText: string;\n body: Body;\n}\n\ninterface MakeRequestConfig<ReqBody> extends RequestOptions<ReqBody> {\n method: string;\n uri: string;\n middleware: HTTPMiddleware[];\n fetch: typeof window.fetch;\n logger: Logger;\n}\n\nexport class HTTPResponseError extends Error {\n response;\n\n constructor(response: HTTPResponse<any>) {\n const { status, statusText, method, url } = response;\n const message = `${status} ${statusText}: Request failed (${method.toUpperCase()} ${url.toString()})`;\n\n super(message);\n\n this.response = response;\n }\n}\n\nclass Request<ReqBody> implements HTTPRequest<ReqBody> {\n method: string;\n url: URL;\n headers = new Headers();\n body!: ReqBody;\n\n get isSameOrigin() {\n return this.url.origin === window.location.origin;\n }\n\n constructor(config: MakeRequestConfig<ReqBody>) {\n this.method = config.method;\n this.body = config.body!;\n if (config.uri.startsWith(\"http\")) {\n this.url = new URL(config.uri);\n } else {\n this.url = new URL(config.uri, window.location.origin);\n }\n\n this._applyHeaders(config.headers);\n this._applyQueryParams(config.query);\n }\n\n private _applyHeaders(headers: any) {\n if (headers == null) return;\n\n if (headers instanceof Map || headers instanceof Headers) {\n headers.forEach((value, key) => {\n this.headers.set(key, value);\n });\n } else if (isObject(headers)) {\n for (const name in headers) {\n const value = headers[name];\n if (value instanceof Date) {\n this.headers.set(name, value.toISOString());\n } else if (value != null) {\n this.headers.set(name, String(value));\n }\n }\n } else {\n throw new TypeError(`Unknown headers type. Got: ${headers}`);\n }\n }\n\n private _applyQueryParams(query: any) {\n if (query == null) return;\n\n if (query instanceof Map || query instanceof URLSearchParams) {\n query.forEach((value, key) => {\n this.url.searchParams.set(key, value);\n });\n } else if (isObject(query)) {\n for (const name in query) {\n const value = query[name];\n if (value instanceof Date) {\n this.url.searchParams.set(name, value.toISOString());\n } else if (value != null) {\n this.url.searchParams.set(name, String(value));\n }\n }\n } else {\n throw new TypeError(`Unknown query params type. Got: ${query}`);\n }\n }\n}\n\nclass Runner<ResBody, ReqBody> {\n private _middleware;\n private _fetch;\n\n private _request: Request<ReqBody>;\n private _response?: HTTPResponse<ResBody>;\n\n constructor(config: MakeRequestConfig<ReqBody>) {\n this._middleware = config.middleware;\n this._fetch = config.fetch;\n\n this._request = new Request(config);\n }\n\n async fetch() {\n if (this._middleware.length > 0) {\n const mount = (index = 0) => {\n const current = this._middleware[index];\n const next = this._middleware[index + 1] ? mount(index + 1) : this._handler.bind(this);\n\n return async () =>\n current(this._request, async () => {\n await next();\n return this._response!;\n });\n };\n\n await mount()();\n } else {\n await this._handler();\n }\n\n if (this._response!.status < 200 || this._response!.status >= 400) {\n throw new HTTPResponseError(this._response!);\n }\n\n return this._response!;\n }\n\n // This is the function that performs the actual request after the final middleware.\n private async _handler() {\n let reqBody: BodyInit;\n\n const req = this._request;\n\n if (!req.headers.has(\"content-type\") && isObject(req.body)) {\n // Auto-detect JSON bodies and encode as a string with correct headers.\n req.headers.set(\"content-type\", \"application/json\");\n reqBody = JSON.stringify(req.body);\n } else {\n reqBody = req.body as BodyInit;\n }\n\n const fetched = await this._fetch(req.url.toString(), {\n method: req.method,\n headers: req.headers,\n body: reqBody,\n });\n\n // Auto-parse response body based on content-type header\n const contentType = fetched.headers.get(\"content-type\");\n\n let body: ResBody;\n\n if (contentType?.includes(\"application/json\")) {\n body = await fetched.json();\n } else if (contentType?.includes(\"application/x-www-form-urlencoded\")) {\n body = (await fetched.formData()) as ResBody;\n } else {\n body = (await fetched.text()) as ResBody;\n }\n\n this._response = {\n method: req.method,\n url: req.url,\n status: fetched.status,\n statusText: fetched.statusText,\n headers: fetched.headers,\n body,\n };\n }\n}\n\n// async function makeRequest<ResBody, ReqBody>(config: MakeRequestConfig<ReqBody>) {\n// const { headers, query, fetch, middleware, logger } = config;\n\n// const request: HTTPRequest<ReqBody> = {\n// method: config.method,\n// uri: config.uri,\n// get sameOrigin() {\n// return !request.uri.startsWith(\"http\");\n// },\n// query: new URLSearchParams(),\n// headers: new Headers(),\n// body: config.body!,\n// };\n\n// // Read headers into request\n// if (headers) {\n// if (headers instanceof Map || headers instanceof Headers) {\n// headers.forEach((value, key) => {\n// request.headers.set(key, value);\n// });\n// } else if (headers != null && typeof headers === \"object\" && !Array.isArray(headers)) {\n// for (const name in headers) {\n// const value = headers[name];\n// if (value instanceof Date) {\n// request.headers.set(name, value.toISOString());\n// } else if (value != null) {\n// request.headers.set(name, String(value));\n// }\n// }\n// } else {\n// throw new TypeError(`Unknown headers type. Got: ${headers}`);\n// }\n// }\n\n// // Read query params into request\n// if (query) {\n// if (query instanceof Map || query instanceof URLSearchParams) {\n// query.forEach((value, key) => {\n// request.query.set(key, value);\n// });\n// } else if (query != null && typeof query === \"object\" && !Array.isArray(query)) {\n// for (const name in query) {\n// const value = query[name];\n// if (value instanceof Date) {\n// request.query.set(name, value.toISOString());\n// } else if (value != null) {\n// request.query.set(name, String(value));\n// }\n// }\n// } else {\n// throw new TypeError(`Unknown query params type. Got: ${query}`);\n// }\n// }\n\n// let response: HTTPResponse<ResBody>;\n\n// // This is the function that performs the actual request after the final middleware.\n// const handler = async () => {\n// const query = request.query.toString();\n// const fullURL = query.length > 0 ? request.uri + \"?\" + query : request.uri;\n\n// let reqBody: BodyInit;\n\n// if (!request.headers.has(\"content-type\") && isObject(request.body)) {\n// // Auto-detect JSON bodies and encode as a string with correct headers.\n// request.headers.set(\"content-type\", \"application/json\");\n// reqBody = JSON.stringify(request.body);\n// } else {\n// reqBody = request.body as BodyInit;\n// }\n\n// const fetched = await fetch(fullURL, {\n// method: request.method,\n// headers: request.headers,\n// body: reqBody,\n// });\n\n// // Auto-parse response body based on content-type header\n// const headers = Object.fromEntries<string>(fetched.headers.entries());\n// const contentType = headers[\"content-type\"];\n\n// let body: ResBody;\n\n// if (contentType?.includes(\"application/json\")) {\n// body = await fetched.json();\n// } else if (contentType?.includes(\"application/x-www-form-urlencoded\")) {\n// body = (await fetched.formData()) as ResBody;\n// } else {\n// body = (await fetched.text()) as ResBody;\n// }\n\n// response = {\n// method: request.method,\n// uri: request.uri,\n// status: fetched.status,\n// statusText: fetched.statusText,\n// headers: headers,\n// body,\n// };\n\n// // logger.info(\"response\", response);\n// };\n\n// if (middleware.length > 0) {\n// const mount = (index = 0) => {\n// const current = middleware[index];\n// const next = middleware[index + 1] ? mount(index + 1) : handler;\n\n// return async () =>\n// current(request, async () => {\n// await next();\n// return response;\n// });\n// };\n\n// await mount()();\n// } else {\n// await handler();\n// }\n\n// if (response!.status < 200 || response!.status >= 400) {\n// throw new HTTPResponseError(response!);\n// }\n\n// return response!;\n// }\n","import type { Dolla, Logger } from \"../core/dolla.js\";\nimport { createState, derive, type MaybeState, type State } from \"../core/state.js\";\nimport { isFunction, isObject, isString, typeOf } from \"../typeChecking.js\";\nimport { deepEqual } from \"../utils.js\";\n\n// ----- Types ----- //\n\n/**\n * A JSON object of translated strings. Values can be string templates or nested objects.\n */\ninterface LocalizedStrings extends Record<string, string | LocalizedStrings> {}\n\nenum SegmentType {\n Static,\n Variable,\n}\ntype StringTemplate = { segments: (StaticSegment | VariableSegment)[] };\n/**\n * A string segment with literal text to be appended without processing.\n */\ntype StaticSegment = {\n type: SegmentType.Static;\n text: string;\n};\n/**\n * A variable passed to the t() function. Needs to be formatted before it is appended.\n */\ntype VariableSegment = {\n type: SegmentType.Variable;\n name: string;\n formats: Format[];\n};\n/**\n * A formatter to be applied to a variable.\n */\ntype Format = {\n name: string;\n options: Record<string, any>;\n};\n\nexport interface TranslationConfig {\n /**\n * Name of the locale this translation is for (BCP 47 locale names recommended).\n */\n locale: string;\n\n /**\n * Path to a JSON file with translated strings for this language.\n */\n path?: string;\n\n /**\n * A callback function that returns a Promise that resolves to the translation object for this language.\n */\n fetch?: () => Promise<LocalizedStrings>;\n}\n\nexport type I18nSetupOptions = {\n /**\n * Default locale to load on startup\n */\n locale?: string | null;\n\n translations: TranslationConfig[];\n};\n\nexport type TOptions = {\n /**\n *\n */\n count?: MaybeState<number>;\n\n /**\n *\n */\n context?: MaybeState<string>;\n\n /**\n * Override formats specified in the template with the ones in the array for each named variable.\n *\n * @example\n * t(\"example_key\", {\n * count: 5,\n * formatOverrides: {\n * count: [ { name: \"datetime\", options: { style: \"currency\", currency: \"JPY\" } } ]\n * }\n * });\n */\n formatOverrides?: MaybeState<Record<string, Record<string, Format[]>>>;\n\n [value: string]: MaybeState<any>;\n};\n\nexport type Formatter = (locale: string, value: unknown, options: Record<string, any>) => string;\n\n// ----- Code ----- //\n\nclass Translation {\n dolla: Dolla;\n config: TranslationConfig;\n\n #isLoaded = false;\n\n #templates = new Map<string, StringTemplate>();\n\n constructor(config: TranslationConfig, dolla: Dolla) {\n this.config = config;\n this.dolla = dolla;\n }\n\n async load(): Promise<void> {\n let strings: LocalizedStrings | undefined;\n\n if (!this.#isLoaded) {\n if (isFunction(this.config.fetch)) {\n strings = await this.config.fetch();\n if (!isObject(strings)) {\n throw new Error(`Fetch function did not return an object of language strings: ${strings}`);\n }\n } else if (isString(this.config.path)) {\n const res = await fetch(this.config.path);\n if (res.ok) {\n const body = await res.json();\n if (isObject(body)) {\n strings = body as LocalizedStrings;\n } else {\n throw new Error(\n `Language path '${this.config.path}' did not return an object of language strings: ${body}`,\n );\n }\n } else {\n throw new Error(`HTTP request failed.`);\n }\n }\n }\n\n if (strings) {\n const entries = this.#compile(strings);\n for (const entry of entries) {\n this.#templates.set(entry[0], entry[1]);\n }\n } else {\n throw new Error(`Language could not be loaded.`);\n }\n }\n\n getTemplate(selector: string): StringTemplate {\n return (\n this.#templates.get(selector) ?? {\n segments: [{ type: SegmentType.Static, text: `[MISSING: ${selector}]` }],\n }\n );\n }\n\n hasTemplate(selector: string): boolean {\n return this.#templates.has(selector);\n }\n\n #compile(strings: { [key: string]: any }, path: string[] = []): [string, StringTemplate][] {\n const entries: [string, StringTemplate][] = [];\n\n for (const key in strings) {\n switch (typeOf(strings[key])) {\n case \"string\":\n entries.push([[...path, key].join(\".\"), this.#parseTemplate(strings[key])]);\n break;\n case \"object\":\n entries.push(...this.#compile(strings[key], [...path, key]));\n break;\n default:\n throw new Error(\n `Expected to find a string or object at ${[...path, key].join(\".\")}. Got: ${typeOf(strings[key])}`,\n );\n }\n }\n\n return entries;\n }\n\n #parseTemplate(template: string): StringTemplate {\n // \"{{itemName}} costs {{amount | number(style: currency, currency: USD)}}.\"\n\n enum Loc {\n /**\n * Outside value braces.\n */\n Static,\n /**\n * Inside value braces; currently parsing the name of the value. e.g. `{{ [name] | number(style: currency, currency: USD) }}`\n */\n ValueName,\n /**\n * Inside value braces; currently parsing the name of a format function. e.g. `{{ name | [number](style: currency, currency: USD) }}`\n */\n FormatName,\n /**\n * Inside value braces; currently parsing the name of a format option. e.g. `{{ name | number([style]: currency, currency: USD) }}`\n */\n FormatOptionName,\n /**\n * Inside value braces; currently parsing the value of a format option. e.g. `{{ name | number(style: [currency], currency: USD ) }}`\n */\n FormatOptionValue,\n /**\n * Inside value braces; just reached the closing bracket of a format option. e.g. `{{ name | number(style: [currency], currency: USD) [] }}`\n */\n FormatOptionEnd,\n }\n\n const parsed: StringTemplate = {\n segments: [],\n };\n\n let buffer = \"\";\n let i = 0;\n let loc: Loc = Loc.Static;\n let segment!: VariableSegment;\n let format!: VariableSegment[\"formats\"][0];\n\n let formatOptionName!: string;\n\n const startSegment = () => {\n segment = {\n type: SegmentType.Variable,\n name: \"\",\n formats: [],\n };\n };\n\n const startFormat = () => {\n format = {\n name: \"\",\n options: {},\n };\n };\n\n while (i < template.length) {\n // Skip spaces (unless we're in static)\n if (loc !== Loc.Static && template[i] === \" \") {\n i++;\n continue;\n }\n\n switch (loc) {\n case Loc.Static:\n if (template[i] === \"{\" && template[i + 1] === \"{\") {\n loc = Loc.ValueName;\n i += 2;\n // close static segment\n if (buffer.length > 0) {\n parsed.segments.push({ type: SegmentType.Static, text: buffer });\n buffer = \"\";\n }\n startSegment();\n } else {\n buffer += template[i];\n i++;\n }\n break;\n case Loc.ValueName:\n if (template[i] === \"|\") {\n loc = Loc.FormatName;\n i += 1;\n // add name to value segment\n segment.name = buffer;\n buffer = \"\";\n startFormat();\n } else if (template[i] === \"}\" && template[i + 1] === \"}\") {\n loc = Loc.Static;\n i += 2;\n // close value segment\n segment.name = buffer;\n buffer = \"\";\n parsed.segments.push(segment);\n } else {\n buffer += template[i];\n i++;\n }\n break;\n case Loc.FormatName:\n if (template[i] === \"(\") {\n loc = Loc.FormatOptionName;\n i += 1;\n // add name to format object\n format.name = buffer;\n buffer = \"\";\n } else if (template[i] === \"}\" && template[i + 1] === \"}\") {\n loc = Loc.Static;\n i += 2;\n // close format and value segment\n segment.formats.push(format);\n parsed.segments.push(segment);\n } else {\n buffer += template[i];\n i++;\n }\n break;\n case Loc.FormatOptionName:\n if (template[i] === \")\") {\n // TODO: error - no value provided for option\n } else if (template[i] === \":\") {\n loc = Loc.FormatOptionValue;\n i += 1;\n // add name to format option object\n formatOptionName = buffer;\n buffer = \"\";\n } else if (template[i] === \"}\" && template[i + 1] === \"}\") {\n // TODO: error - format options parenthesis not closed\n } else {\n buffer += template[i];\n i++;\n }\n break;\n case Loc.FormatOptionValue:\n if (template[i] === \")\") {\n loc = Loc.FormatOptionEnd;\n i += 1;\n // add value to format option object\n // add format option to format object; we're done with this format\n format.options[formatOptionName] = buffer;\n buffer = \"\";\n segment.formats.push(format);\n } else if (template[i] === \",\") {\n loc = Loc.FormatOptionName;\n i += 1;\n // add value to format option object\n // add format option to format object; we're adding another option\n format.options[formatOptionName] = buffer;\n buffer = \"\";\n } else if (template[i] === \"}\" && template[i + 1] === \"}\") {\n // TODO: error - format options parenthesis not closed\n } else {\n buffer += template[i];\n i++;\n }\n break;\n case Loc.FormatOptionEnd:\n if (template[i] === \"|\") {\n loc = Loc.FormatName;\n i += 1;\n startFormat();\n } else if (template[i] === \"}\" && template[i + 1] === \"}\") {\n loc = Loc.Static;\n i += 2;\n // add value segment\n parsed.segments.push(segment);\n } else {\n // TODO: error - no other valid characters\n }\n break;\n }\n }\n\n if (loc === Loc.Static && buffer.length > 0) {\n parsed.segments.push({ type: SegmentType.Static, text: buffer });\n }\n\n return parsed;\n }\n}\n\n/**\n * Dolla's I(nternationalizatio)n module. Manages language translations and locale-based formatting.\n */\nexport class I18n {\n #dolla: Dolla;\n #logger: Logger;\n #translations = new Map<string, Translation>();\n #cache: [key: string, values: Record<string, any> | undefined, output: string][] = [];\n #formats = new Map<string, Formatter>();\n\n #initialLocale = \"auto\";\n\n $locale: State<string | undefined>;\n #setLocale;\n\n constructor(dolla: Dolla) {\n this.#dolla = dolla;\n this.#logger = dolla.createLogger(\"Dolla.i18n\");\n\n const [$locale, setLocale] = createState<string>();\n\n this.$locale = $locale;\n this.#setLocale = setLocale;\n\n this.addFormat(\"number\", (_, value, options) => {\n return this.#formatNumber(Number(value), options);\n });\n this.addFormat(\"datetime\", (_, value, options) => {\n return this.#formatDateTime(value as any, options);\n });\n this.addFormat(\"list\", (_, value, options) => {\n return this.#formatList(value as any, options);\n });\n\n /**\n * Load language before the app mounts.\n */\n dolla.beforeMount(async () => {\n if (this.#translations.size > 0) {\n await this.setLocale(this.#initialLocale);\n }\n });\n }\n\n get locales() {\n return [...this.#translations.keys()];\n }\n\n setup(options: I18nSetupOptions) {\n // Convert languages into Language instances.\n options.translations.forEach((entry) => {\n this.#translations.set(entry.locale, new Translation(entry, this.#dolla));\n });\n\n // Check that initialLanguage is actually registered.\n if (options.locale && options.locale !== \"auto\") {\n const isRegistered = options.translations.some((entry) => entry.locale === options.locale);\n if (!isRegistered) {\n throw new Error(`Initial locale '${options.locale}' is not registered in the locales array.`);\n }\n this.#initialLocale = options.locale;\n }\n\n this.#logger.info(\n `${this.#translations.size} language${this.#translations.size === 1 ? \"\" : \"s\"} supported: '${[...this.#translations.keys()].join(\"', '\")}'`,\n );\n }\n\n async setLocale(name: string) {\n let realName!: string;\n\n if (name === \"auto\") {\n let names = [];\n\n if (typeof navigator !== \"undefined\") {\n const nav = navigator as any;\n\n if (nav.languages?.length > 0) {\n names.push(...nav.languages);\n } else if (nav.language) {\n names.push(nav.language);\n } else if (nav.browserLanguage) {\n names.push(nav.browserLanguage);\n } else if (nav.userLanguage) {\n names.push(nav.userLanguage);\n }\n }\n\n for (const name of names) {\n if (this.#translations.has(name)) {\n // Found a matching language.\n realName = name;\n }\n }\n } else {\n // Tag is the actual tag to set.\n if (this.#translations.has(name)) {\n realName = name;\n }\n }\n\n if (realName == null) {\n const firstLanguage = this.#translations.keys().next().value;\n if (firstLanguage) {\n realName = firstLanguage;\n }\n }\n\n if (!realName || !this.#translations.has(realName)) {\n throw new Error(`Locale '${name}' has no translation.`);\n }\n\n const translation = this.#translations.get(realName)!;\n\n try {\n await translation.load();\n\n this.#cache = [];\n this.#setLocale(realName);\n\n this.#logger.info(\"set language to \" + realName);\n } catch (error) {\n if (error instanceof Error) {\n this.#logger.crash(error);\n }\n }\n }\n\n /**\n * Returns a State containing the value at `key`.\n \n * @param selector - Key to the translated value.\n * @param options - A map of `{{placeholder}}` names and the values to replace them with.\n * \n * @example\n * const $value = t(\"your.key.here\", { count: 5 });\n */\n t(selector: string, options?: TOptions): State<string> {\n if (this === undefined) {\n throw new Error(\n `The 't' function cannot be destructured. If you need a standalone version you can import it like so: 'import { t } from \"@manyducks.co/dolla\"'`,\n );\n }\n\n // Split keys and values so we can observe values which may be States.\n let optionKeys = [];\n let optionValues = [];\n for (const key in options) {\n optionKeys.push(key);\n optionValues.push(options[key]);\n }\n\n return derive([this.$locale, ...optionValues], (locale, ...currentValues) => {\n if (locale == null) {\n return \"[NO LOCALE SET]\";\n }\n\n // Reassemble options now that State values are unwrapped.\n const options: Record<string, any> = {};\n for (let i = 0; i < currentValues.length; i++) {\n options[optionKeys[i]] = currentValues[i];\n }\n\n return this.#getValue(locale, selector, options);\n });\n }\n\n #getValue(locale: string, selector: string, options: Record<string, any>): string {\n const cached = this.#getCached(selector, options);\n if (cached) return cached;\n\n const translation = this.#translations.get(locale)!;\n\n // Handle count (pluralization) and context. Keys become \"key_context_pluralization\".\n\n if (options.context != null) {\n selector += \"_\" + options.context;\n }\n if (options.count != null) {\n if (options.ordinal) {\n // Try to match the exact number key if there is one (e.g. \"myExampleKey_ordinal_(=2)\" when count is 2).\n const exact = `${selector}_ordinal_(=${options.count})`;\n if (translation.hasTemplate(exact)) {\n selector = exact;\n } else {\n selector += \"_ordinal_\" + new Intl.PluralRules(locale, { type: \"ordinal\" }).select(options.count);\n }\n } else {\n // Try to match the exact number key if there is one (e.g. \"myExampleKey_(=2)\" when count is 2).\n const exact = `${selector}_(=${options.count})`;\n if (translation.hasTemplate(exact)) {\n selector = exact;\n } else {\n selector += \"_\" + new Intl.PluralRules(locale).select(options.count);\n }\n }\n }\n\n const template = translation.getTemplate(selector);\n let output = \"\";\n\n for (const segment of template.segments) {\n if (segment.type === SegmentType.Static) {\n output += segment.text;\n } else if (segment.type === SegmentType.Variable) {\n let value = resolve(options, segment.name);\n\n const formats = options.formatOverrides?.[segment.name] ?? [...segment.formats];\n\n if (segment.name === \"count\" && formats.length === 0) {\n formats.push({ name: \"number\", options: {} });\n }\n\n for (const format of formats) {\n const fn = this.#formats.get(format.name);\n if (fn == null) {\n const error = new Error(\n `Failed to load format '${format.name}' when processing '${selector}', template: ${template}`,\n );\n this.#logger.crash(error);\n throw error;\n }\n value = fn(locale, value, format.options);\n }\n\n output += value;\n }\n }\n\n return output;\n }\n\n /**\n * Add a custom format callback.\n *\n * @example\n * Dolla.i18n.addFormat(\"uppercase\", (locale, value, options) => {\n * return value.toUpperCase();\n * });\n *\n * {\n * \"greeting\": \"Hello, {{name|uppercase}}!\"\n * }\n *\n * t(\"greeting\", {name: \"world\"}); // State<\"Hello, WORLD!\">\n */\n addFormat(name: string, callback: (locale: string, value: unknown, options: Record<string, any>) => string) {\n this.#formats.set(name, callback);\n }\n\n /**\n * Creates an `Intl.Collator` configured for the current locale.\n * NOTE: The Collator remains bound to the locale it was created with, even when the app's locale changes.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Collator/Collator#options\n */\n collator(options?: Intl.CollatorOptions) {\n return new Intl.Collator(this.$locale.get(), options);\n }\n\n /**\n * Returns a State containing the number formatted for the current locale. Uses `Intl.NumberFormat` under the hood.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#options\n */\n number(count: MaybeState<number | bigint>, options?: Intl.NumberFormatOptions): State<string> {\n return derive([this.$locale, count], (_, value) => this.#formatNumber(value, options));\n }\n\n #formatNumber(count: number | bigint, options?: Intl.NumberFormatOptions): string {\n return new Intl.NumberFormat(this.$locale.get(), options).format(count);\n }\n\n /**\n * Returns a State containing the date formatted for the current locale. Uses `Intl.DateTimeFormat` under the hood.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat#options\n *\n * @example\n * const date = new Date();\n * const $formatted = Dolla.i18n.dateTime(date, { dateFormat: \"short\" });\n */\n dateTime(date?: MaybeState<string | number | Date | undefined>, options?: Intl.DateTimeFormatOptions): State<string> {\n return derive([this.$locale, date], (_, value) => this.#formatDateTime(value, options));\n }\n\n #formatDateTime(date?: string | number | Date, options?: Intl.DateTimeFormatOptions): string {\n return new Intl.DateTimeFormat(this.$locale.get(), options).format(isString(date) ? new Date(date) : date);\n }\n\n /**\n * Returns a State containing the date formatted for the current locale. Uses `Intl.DateTimeFormat` under the hood.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat#options\n *\n * @example\n * const list = new Date();\n * const $formatted = Dolla.i18n.list(list, { });\n */\n list(list: MaybeState<Iterable<string>>, options?: Intl.ListFormatOptions): State<string> {\n return derive([this.$locale, list], (_, value) => this.#formatList(value, options));\n }\n\n #formatList(list: Iterable<string>, options?: Intl.ListFormatOptions): string {\n return new Intl.ListFormat(this.$locale.get(), options).format(list);\n }\n\n // relativeTime(): State<string> {\n\n // }\n\n #getCached(key: string, values?: Record<string, any>): string | undefined {\n for (const entry of this.#cache) {\n if (entry[0] === key && deepEqual(entry[1], values)) {\n return entry[2];\n }\n }\n }\n}\n\nfunction resolve(object: any, key: string) {\n const parsed = String(key)\n .split(/[\\.\\[\\]]/)\n .filter((part) => part.trim() !== \"\");\n let value = object;\n\n while (parsed.length > 0) {\n const part = parsed.shift()!;\n\n if (value != null) {\n value = value[part];\n } else {\n value = undefined;\n }\n }\n\n return value;\n}\n","import { cond, html } from \"../core/markup.js\";\n\n/**\n * Props passed to the crash view when a crash occurs.\n */\nexport type CrashViewProps = {\n /**\n * JavaScript Error object.\n */\n error: Error;\n\n /**\n * A string to identify the logger that reported this error.\n */\n loggerName: string;\n\n /**\n * Unique identifier to pinpoint the specific view that reported the crash.\n */\n uid?: string;\n};\n\nexport function DefaultCrashView(props: CrashViewProps) {\n return html`\n <div\n style=${{\n backgroundColor: \"#880000\",\n color: \"#fff\",\n padding: \"2rem\",\n position: \"fixed\",\n inset: 0,\n fontSize: \"20px\",\n }}\n >\n <h1 style=${{ marginBottom: \"0.5rem\" }}>The app has crashed</h1>\n <p style=${{ marginBottom: \"0.25rem\" }}>\n <span style=${{ fontFamily: \"monospace\" }}>${props.loggerName}</span>\n ${cond(props.uid, html`<span style=${{ fontFamily: \"monospace\", opacity: 0.5 }}> [uid: ${props.uid}]</span>`)}\n ${\" \"}says:\n </p>\n <blockquote\n style=${{\n backgroundColor: \"#991111\",\n padding: \"0.25em\",\n borderRadius: \"6px\",\n fontFamily: \"monospace\",\n marginBottom: \"1rem\",\n }}\n >\n <span\n style=${{\n display: \"inline-block\",\n backgroundColor: \"red\",\n padding: \"0.1em 0.4em\",\n marginRight: \"0.5em\",\n borderRadius: \"4px\",\n fontSize: \"0.9em\",\n fontWeight: \"bold\",\n }}\n >\n ${props.error.name}\n </span>\n ${props.error.message}\n </blockquote>\n\n <p>Please see the browser console for details.</p>\n </div>\n `;\n}\n","import type { Dolla, Logger } from \"./dolla.js\";\n\n/**\n * Batches DOM updates; reads before writes.\n */\nexport class Batch {\n #dolla: Dolla;\n #logger: Logger;\n\n // Keys ensure only the most recent callback queued with a certain key\n // will be called, keeping DOM operations to a minimum.\n #keyedWrites = new Map<string, () => void>();\n\n // All unkeyed writes are run on every batch.\n #unkeyedWrites: (() => void)[] = [];\n\n // All read callbacks are run before updates on every batch.\n #reads: (() => void)[] = [];\n\n #batchInProgress = false;\n\n // When true, batches that would exceed 16ms will be split and deferred to a rAF.\n // This may not be desirable, because while it does prevent hitching it sometimes leaves\n // the state partially rendered for a brief second and certain elements can be seen to update after the fact.\n // But the tradeoff here is snappier navigation with possibly slightly out of date DOM updates on heavy pages.\n #deferIfOvertime = true;\n #deferrals = 0;\n\n #msFormat = new Intl.NumberFormat(\"en-US\", {\n maximumFractionDigits: 2,\n minimumFractionDigits: 0,\n style: \"unit\",\n unit: \"millisecond\",\n unitDisplay: \"short\",\n });\n\n constructor(dolla: Dolla) {\n this.#dolla = dolla;\n this.#logger = dolla.createLogger(\"Dolla.batch\");\n }\n\n /**\n * Queues a callback that runs before the next batch of writes.\n */\n read(callback: () => void) {\n this.#reads.push(callback);\n this.#queueBatch();\n }\n\n /**\n * Queues a callback to run in the next render batch.\n * Always put DOM mutations in a write callback when possible to help Dolla batch them efficiently.\n */\n write(callback: () => void, key?: string) {\n if (key) {\n this.#keyedWrites.set(key, callback);\n } else {\n this.#unkeyedWrites.push(callback);\n }\n this.#queueBatch();\n }\n\n #queueBatch() {\n if (!this.#batchInProgress) {\n this.#batchInProgress = true;\n const isDevEnv = this.#dolla.getEnv() === \"development\";\n queueMicrotask(() => {\n this.#runBatch(isDevEnv);\n });\n }\n }\n\n #runBatch(isDevEnv = false) {\n const start = performance.now();\n let elapsed = 0;\n\n const total = this.#reads.length + this.#keyedWrites.size + this.#unkeyedWrites.length;\n let completed = 0;\n\n /**\n * Runs after each operation. If true, the batch has been deferred and processing should stop. If false, processing of the current batch should continue.\n */\n const checkpoint = () => {\n completed++;\n elapsed = performance.now() - start;\n if (this.#deferIfOvertime && elapsed > 12 && completed < total) {\n this.#deferrals++;\n if (isDevEnv) {\n this.#logger.warn(\n `⚠️ Deferring batch to next frame. Performed ${completed} of ${total} batched operation${completed === 1 ? \"\" : \"s\"} in ${this.#msFormat.format(elapsed)} (deferral ${this.#deferrals}).`,\n );\n }\n requestAnimationFrame(() => {\n this.#runBatch(isDevEnv);\n });\n return true;\n }\n return false;\n };\n\n const keyedWrites = [...this.#keyedWrites.entries()];\n\n let key: string | undefined;\n let op: (() => void) | undefined;\n\n // Run reads.\n while ((op = this.#reads.shift())) {\n op();\n if (checkpoint()) return;\n }\n\n // Run keyed writes first.\n for ([key, op] of keyedWrites) {\n op();\n this.#keyedWrites.delete(key);\n if (checkpoint()) return;\n }\n\n // Run unkeyed writes second.\n while ((op = this.#unkeyedWrites.shift())) {\n op();\n if (checkpoint()) return;\n }\n\n if (isDevEnv) {\n this.#logger[elapsed > 16 ? \"warn\" : \"info\"](\n `${elapsed > 16 ? \"⚠️ (>=16ms) \" : \"\"}Executed ${completed} operation${completed === 1 ? \"\" : \"s\"} in ${this.#msFormat.format(elapsed)}${this.#deferrals > 0 ? ` (after ${this.#deferrals} deferral${this.#deferrals === 1 ? \"\" : \"s\"})` : \"\"}.`,\n );\n }\n this.#deferrals = 0;\n // Trigger again to catch updates queued while this batch was running.\n if (this.#reads.length || this.#keyedWrites.size || this.#unkeyedWrites.length) {\n queueMicrotask(() => {\n this.#runBatch(isDevEnv);\n });\n } else {\n this.#batchInProgress = false;\n }\n }\n}\n","import { Emitter } from \"@manyducks.co/emitter\";\nimport { HTTP } from \"../modules/http.js\";\nimport { I18n } from \"../modules/i18n.js\";\nimport { _isRouter, _mountRouter, _unmountRouter, type Router } from \"../modules/router.js\";\nimport { assertInstanceOf, isFunction, isString } from \"../typeChecking.js\";\nimport { colorFromString, createMatcher, noOp } from \"../utils.js\";\nimport { DefaultCrashView, type CrashViewProps } from \"../views/default-crash-view.js\";\nimport { Passthrough } from \"../views/passthrough.js\";\nimport { Batch } from \"./batch.js\";\nimport { ContextEvent, type ElementContext, type StorableContext, type WildcardListenerMap } from \"./context.js\";\nimport { constructMarkup, createMarkup, groupElements, type Markup, type MarkupElement } from \"./markup.js\";\nimport { View, type ViewElement, type ViewFunction } from \"./nodes/view.js\";\nimport { createRef, isRef } from \"./ref.js\";\nimport { createState, createWatcher, derive, isState, toState, toValue } from \"./state.js\";\nimport { Stats } from \"./stats.js\";\nimport { Store, StoreError, StoreFunction } from \"./store.js\";\n\n// Affects which log messages will print and how much debugging info is included in the DOM.\nexport type Environment = \"development\" | \"production\";\n\n/**\n * Log type toggles. Each message category can be turned on or off or enabled only in a specific environment.\n */\nexport type Loggles = {\n info: boolean | Environment;\n log: boolean | Environment;\n warn: boolean | Environment;\n error: boolean | Environment;\n};\n\nexport interface Logger {\n info(...args: any[]): void;\n log(...args: any[]): void;\n warn(...args: any[]): void;\n error(...args: any[]): void;\n crash(error: Error): void;\n\n setName(name: string): Logger;\n}\n\nexport interface LoggerErrorContext {\n error: Error;\n loggerName: string;\n uid?: string;\n}\n\nexport type LoggerOptions = {\n /**\n * Console object to use for logging (mostly for testing). Uses window.console by default.\n */\n console?: any;\n\n /**\n * Unique ID to print with logs. Makes it easier to track down messages from specific view instances.\n */\n uid?: string;\n};\n\nexport class Dolla implements StorableContext {\n readonly batch: Batch;\n\n // Remove `private` when there are public methods to call.\n private readonly stats: Stats;\n\n readonly http: HTTP;\n readonly i18n: I18n;\n\n #isMounted = false;\n #env: Environment = \"production\";\n #rootElement?: Element;\n #rootView?: ViewElement;\n #crashView: ViewFunction<CrashViewProps> = DefaultCrashView;\n\n #watcher = createWatcher();\n #router?: Router;\n\n #beforeMountCallbacks: Array<() => void | Promise<void>> = [];\n #onMountCallbacks: Array<() => void> = [];\n #beforeUnmountCallbacks: Array<() => void | Promise<void>> = [];\n #onUnmountCallbacks: Array<() => void> = [];\n\n #rootElementContext: ElementContext = {\n root: this,\n data: {},\n emitter: new Emitter(),\n stores: new Map(),\n viewName: \"Dolla\",\n };\n\n #loggles: Loggles = {\n info: \"development\",\n log: \"development\",\n warn: \"development\",\n error: true,\n };\n #match = createMatcher(\"*,-Dolla.*\");\n\n #wildcardListeners: WildcardListenerMap = new Map();\n\n // Registration functions for modules.\n // All modules will be registered before mount.\n #modules: (() => Promise<any>)[] = [];\n\n constructor() {\n this.batch = new Batch(this);\n this.stats = new Stats(this);\n this.http = new HTTP(this);\n this.i18n = new I18n(this);\n }\n\n watch = this.#watcher.watch;\n\n createState = createState;\n toState = toState;\n toValue = toValue;\n isState = isState;\n derive = derive;\n createWatcher = createWatcher;\n\n createRef = createRef;\n isRef = isRef;\n\n /**\n * True when the app is connected to a DOM node and displayed to the user.\n */\n get isMounted() {\n return this.#isMounted;\n }\n\n /**\n * Get the current environment that this app is running in.\n * Environment affects which log messages will print and how much debugging info is included in the DOM.\n */\n getEnv() {\n return this.#env;\n }\n\n /**\n * Sets the environment that this app is running in.\n * Environment affects which log messages will print and how much debugging info is included in the DOM.\n */\n setEnv(value: Environment) {\n this.#env = value;\n }\n\n /**\n * Sets the view that will be shown when the `crash` method is called on any logger.\n * When a crash is reported the app will be unmounted and replaced with this crash page.\n */\n setCrashView(view: ViewFunction<CrashViewProps>) {\n this.#crashView = view;\n }\n\n /**\n * Returns the HTMLElement Dolla is mounted to. This will return undefined until Dolla.mount() is called.\n */\n getRootElement() {\n return this.#rootElement;\n }\n\n /**\n * Returns the top level view Dolla is rendering inside the root element. This will return undefined until Dolla.mount() is called.\n */\n getRootView() {\n return this.#rootView;\n }\n\n /**\n * Sets a context variable and returns its value. Context variables are accessible on the app and in child views.\n */\n set<T>(key: string | symbol, value: T): T {\n this.#rootElementContext.data[key] = value;\n return value;\n }\n\n /**\n * Gets the value of a context variable. Returns null if the variable is not set.\n */\n get<T>(key: string | symbol): T | null {\n return (this.#rootElementContext.data[key] as T) ?? null;\n }\n\n /**\n * Returns an object of all context variables stored at the app level.\n */\n // getAll(): Record<string | symbol, unknown> {\n // return { ...this.#rootElementContext.data };\n // }\n\n /**\n * Adds a listener to be called when `eventName` is emitted.\n */\n on<T = unknown>(eventName: string, listener: (event: ContextEvent<T>) => void): void {\n if (eventName === \"*\") {\n const wrappedListener = (_eventName: any, event: ContextEvent<T>) => {\n listener(event);\n };\n this.#rootElementContext.emitter.on(eventName, wrappedListener);\n this.#wildcardListeners.set(listener, wrappedListener);\n } else {\n this.#rootElementContext.emitter.on(eventName, listener);\n }\n }\n\n /**\n * Removes a listener from the list to be called when `eventName` is emitted.\n */\n off<T = unknown>(eventName: string, listener: (event: ContextEvent<T>) => void): void {\n if (eventName === \"*\") {\n const wrappedListener = this.#wildcardListeners.get(listener);\n if (wrappedListener) {\n this.#rootElementContext.emitter.off(eventName, wrappedListener);\n this.#wildcardListeners.delete(listener);\n }\n } else {\n this.#rootElementContext.emitter.off(eventName, listener);\n }\n }\n\n /**\n * Adds a listener to be called when `eventName` is emitted. The listener is immediately removed after being called once.\n */\n once<T = unknown>(eventName: string, listener: (event: ContextEvent<T>) => void): void {\n if (eventName === \"*\") {\n const wrappedListener = (_eventName: any, event: ContextEvent<T>) => {\n this.#wildcardListeners.delete(listener);\n listener(event);\n };\n this.#rootElementContext.emitter.once(eventName, wrappedListener);\n this.#wildcardListeners.set(listener, wrappedListener);\n } else {\n this.#rootElementContext.emitter.once(eventName, listener);\n }\n }\n\n /**\n * Emits a new event to all listeners.\n */\n emit<T = unknown>(eventName: string, detail: T): boolean {\n return this.#rootElementContext.emitter.emit(eventName, new ContextEvent(eventName, detail));\n }\n\n /**\n * Attaches a new store to this context.\n */\n attachStore(store: StoreFunction<{}, any>): void;\n\n /**\n * Attaches a new store to this context.\n */\n attachStore(store: StoreFunction<undefined, any>): void;\n\n /**\n * Attaches a new store to this context.\n */\n attachStore<Options>(store: StoreFunction<Options, any>, options: Options): void;\n\n attachStore<Options>(store: StoreFunction<Options, any>, options?: Options): void {\n const instance = new Store(store, options!);\n const attached = instance.attach(this.#rootElementContext);\n if (!attached) {\n let name = store.name ? `'${store.name}'` : \"this store\";\n console.warn(`An instance of ${name} was already attached to this context.`);\n }\n }\n\n /**\n * Gets the nearest instance of a store. Throws an error if the store isn't provided higher in the tree.\n */\n useStore<Value>(store: StoreFunction<any, Value>): Value {\n if (isFunction(store)) {\n const instance = this.#rootElementContext.stores.get(store);\n if (instance == null) {\n throw new StoreError(`Store not found on this context.`);\n } else {\n return instance.value;\n }\n } else {\n throw new StoreError(`Invalid store.`);\n }\n }\n\n async mount(selector: string, router: Router): Promise<void>;\n async mount(selector: string, view: ViewFunction<any>): Promise<void>;\n async mount(element: Element, router: Router): Promise<void>;\n async mount(element: Element, view: ViewFunction<any>): Promise<void>;\n\n async mount(target: string | Element, root: ViewFunction<any> | Router) {\n if (this.#isMounted) {\n throw new Error(`Dolla is already mounted.`);\n }\n\n if (isString(target)) {\n const match = document.querySelector<Element>(target);\n assertInstanceOf(HTMLElement, match, `Selector '${target}' did not match any element.`);\n this.#rootElement = match!;\n } else {\n assertInstanceOf(HTMLElement, target, \"Expected an HTML element or a selector string. Got type: %t, value: %v\");\n this.#rootElement = target;\n }\n\n if (_isRouter(root)) {\n this.#router = root;\n }\n\n const view = _isRouter(root) ? Passthrough : root;\n\n // First, initialize the root view. The router store needs this to connect the initial route.\n const rootViewMarkup = createMarkup(view);\n this.#rootView = this.constructView(rootViewMarkup.type as ViewFunction<any>, rootViewMarkup.props);\n\n // Register modules\n // TODO: Handle errors\n await Promise.all(this.#modules.map((register) => register()));\n\n if (_isRouter(root)) {\n await _mountRouter(root, this);\n }\n\n // Run beforeMount\n // TODO: Handle errors\n await Promise.all(this.#beforeMountCallbacks.map((callback) => callback()));\n\n this.#rootView.mount(this.#rootElement);\n this.#isMounted = true;\n\n // Run onMount for stores.\n for (const store of this.#rootElementContext.stores.values()) {\n store.handleMount();\n }\n\n // Run onMount\n // TODO: Handle errors\n for (const callback of this.#onMountCallbacks) {\n callback();\n }\n }\n\n async unmount() {\n if (!this.#isMounted) return;\n\n // Run beforeUnmount\n await Promise.all(this.#beforeUnmountCallbacks.map((callback) => callback()));\n\n this.#rootView?.unmount(false);\n\n this.#watcher.stopAll();\n\n if (this.#router) {\n await _unmountRouter(this.#router);\n }\n\n this.#isMounted = false;\n\n // Run onUnmount\n for (const callback of this.#onUnmountCallbacks) {\n callback();\n }\n }\n\n /**\n * Registers a `callback` to run after `Dolla.mount` is called, before the app is mounted. If `callback` returns a Promise,\n * it will be awaited before mounting finishes. Use this to perform initial setup before the app is displayed to the user.\n */\n beforeMount(callback: () => void | Promise<void>) {\n this.#beforeMountCallbacks.push(callback);\n }\n\n /**\n * Registers a `callback` to run after the app is mounted.\n */\n onMount(callback: () => void) {\n this.#onMountCallbacks.push(callback);\n }\n\n /**\n * Registers a `callback` to run after `Dolla.unmount` is called, before the app is unmounted. If `callback` returns a Promise,\n * it will be awaited before unmounting finishes. Use this to perform cleanup.\n */\n beforeUnmount(callback: () => void | Promise<void>) {\n this.#beforeUnmountCallbacks.push(callback);\n }\n\n /**\n * Registers a `callback` to run after the app is unmounted.\n */\n onUnmount(callback: () => void) {\n this.#onUnmountCallbacks.push(callback);\n }\n\n /**\n * Update log type toggles. Values that are not passed will remain unchanged.\n */\n setLoggles(options: Partial<Loggles>) {\n for (const key in options) {\n const value = options[key as keyof Loggles];\n if (value) {\n this.#loggles[key as keyof Loggles] = value;\n }\n }\n }\n\n setLogFilter(filter: string | RegExp) {\n this.#match = createMatcher(filter);\n }\n\n createLogger(name: string, options?: LoggerOptions): Logger {\n const _console = options?.console ?? getDefaultConsole();\n\n const self = this;\n\n return {\n setName(newName: string) {\n name = newName;\n return this;\n },\n\n get info() {\n if (\n self.#loggles.info === false ||\n (isString(self.#loggles.info) && self.#loggles.info !== self.getEnv()) ||\n !self.#match(name)\n ) {\n return noOp;\n } else {\n let label = `%c${name}`;\n if (options?.uid) {\n label += ` %c[uid: %c${options.uid}%c]`;\n } else {\n label += `%c%c%c`;\n }\n return _console.info.bind(\n _console,\n label,\n `color:${colorFromString(label)};font-weight:bold`,\n `color:#777`,\n `color:#aaa`,\n `color:#777`,\n );\n }\n },\n\n get log() {\n if (\n self.#loggles.log === false ||\n (isString(self.#loggles.log) && self.#loggles.log !== self.getEnv()) ||\n !self.#match(name)\n ) {\n return noOp;\n } else {\n let label = `%c${name}`;\n if (options?.uid) {\n label += ` %c[uid: %c${options.uid}%c]`;\n } else {\n label += `%c%c%c`;\n }\n return _console.log.bind(\n _console,\n label,\n `color:${colorFromString(label)};font-weight:bold`,\n `color:#777`,\n `color:#aaa`,\n `color:#777`,\n );\n }\n },\n\n get warn() {\n if (\n self.#loggles.warn === false ||\n (isString(self.#loggles.warn) && self.#loggles.warn !== self.getEnv()) ||\n !self.#match(name)\n ) {\n return noOp;\n } else {\n let label = `%c${name}`;\n if (options?.uid) {\n label += ` %c[uid: %c${options.uid}%c]`;\n } else {\n label += `%c%c%c`;\n }\n return _console.warn.bind(\n _console,\n label,\n `color:${colorFromString(label)};font-weight:bold`,\n `color:#777`,\n `color:#aaa`,\n `color:#777`,\n );\n }\n },\n\n get error() {\n if (\n self.#loggles.error === false ||\n (isString(self.#loggles.error) && self.#loggles.error !== self.getEnv()) ||\n !self.#match(name)\n ) {\n return noOp;\n } else {\n let label = `%c${name}`;\n if (options?.uid) {\n label += ` %c[uid: %c${options.uid}%c]`;\n } else {\n label += `%c%c%c`;\n }\n return _console.error.bind(\n _console,\n label,\n `color:${colorFromString(label)};font-weight:bold`,\n `color:#777`,\n `color:#aaa`,\n `color:#777`,\n );\n }\n },\n\n crash(error: Error) {\n if (self.isMounted) {\n // Unmount the app.\n self.unmount();\n\n // Mount the crash page\n const crashPage = self.constructView(self.#crashView, {\n error,\n loggerName: name,\n uid: options?.uid,\n });\n crashPage.mount(self.#rootElement!);\n }\n\n throw error;\n },\n };\n }\n\n /**\n *\n */\n constructView<P>(view: ViewFunction<P>, props: P, children: Markup[] = []): ViewElement {\n return new View(this.#rootElementContext, view, props, children);\n }\n\n /**\n *\n */\n constructMarkup(markup: Markup | Markup[]): MarkupElement {\n return groupElements(constructMarkup(this.#rootElementContext, markup));\n }\n}\n\nexport function getDefaultConsole() {\n if (typeof window !== \"undefined\" && window.console) {\n return window.console;\n }\n if (typeof global !== \"undefined\" && global.console) {\n return global.console;\n }\n}\n","// States\nexport { createState, derive, isState, toState, toValue } from \"./core/state.js\";\nexport type { MaybeState, Setter, State, StopFunction } from \"./core/state.js\";\n\n// Ref\nexport { createRef, isRef, type Ref } from \"./core/ref.js\";\n\n// Store\nexport { type StoreFunction, type StoreContext } from \"./core/store.js\";\n\n// Router\nexport { createRouter, type Router, type RouterOptions } from \"./modules/router.js\";\n\n// Equality checks (useful for states)\nexport { deepEqual, shallowEqual, strictEqual } from \"./utils.js\";\n\n// Markup\nexport { cond, createMarkup, html, portal, repeat } from \"./core/markup.js\";\nexport type { Markup, MarkupElement } from \"./core/markup.js\";\n\nimport { Dolla } from \"./core/dolla.js\";\nconst dolla = new Dolla();\n\nexport default dolla;\n\n// Language: standalone `t` function\nexport const t = dolla.i18n.t.bind(dolla.i18n);\n\nexport function setDevDebug(value: boolean) {\n if (typeof window !== \"undefined\") {\n (window as any).DOLLA_DEV_DEBUG = value;\n }\n}\n\nexport function getDevDebug(): boolean {\n if (typeof window !== \"undefined\") {\n return (window as any).DOLLA_DEV_DEBUG === true;\n }\n return false;\n}\n\n// Other types\nexport type { Dolla, Environment, Logger, LoggerErrorContext, LoggerOptions, Loggles } from \"./core/dolla.js\";\nexport type { ViewContext, ViewElement, ViewFunction } from \"./core/nodes/view.js\";\nexport type { HTTPRequest, HTTPResponse } from \"./modules/http.js\";\nexport type { InputType, Renderable } from \"./types.js\";\nexport type { CrashViewProps } from \"./views/default-crash-view.js\";\n\nimport type { IntrinsicElements as Elements } from \"./types\";\n\ndeclare global {\n namespace JSX {\n interface IntrinsicElements extends Elements {\n // Catch all for custom elements\n [tag: string]: any;\n }\n }\n}\n"],"names":["splitPath","path","assertString","f","joinPath","parts","assertArrayOf","part","isFunction","x","joined","_a","p","resolvePath","base","resolved","i","parseQueryParams","query","entries","entry","key","value","matchRoutes","routes","url","options","route","fragments","matched","frag","params","sortRoutes","withoutParams","withNumericParams","withParams","wildcard","bySizeDesc","b","patternToFragments","pattern","createRouter","Router","ROUTER_MOUNT","ROUTER_UNMOUNT","_isRouter","IS_ROUTER","_mountRouter","router","dolla","_unmountRouter","__privateAdd","_Router_instances","__publicField","_dolla","_logger","_layerId","_activeLayers","_routes","_isMounted","_hash","_cleanupCallbacks","_$match","_setMatch","assertObject","__privateWrapper","createState","derive","__privateGet","m","shallowEqual","__privateSet","__privateMethod","prepareRoute_fn","assertValidRedirects","onPopState","updateRoute_fn","rootElement","catchLinks","anchor","href","push_fn","callback","steps","replace_fn","state","getCurrentURL_fn","logger","rootView","match","journey","resolveRoute_fn","step","currentPattern","mountRoute_fn","NoRouteError","redirect","isString","replaceParams","redirectContext","layers","matchedLayer","activeLayer","parentLayer","view","parents","isObject","parent","Passthrough","layer","subroute","safeExternalLink","protocolLink","root","_window","traverse","node","handler","e","redirectPath","r","HTTP","_HTTP_instances","_middleware","_fetch","getDefaultFetch","fn","uri","request_fn","method","Runner","HTTPResponseError","response","status","statusText","message","Request","config","headers","name","mount","index","current","next","reqBody","req","fetched","contentType","body","Translation","_Translation_instances","_isLoaded","_templates","strings","res","compile_fn","selector","typeOf","parseTemplate_fn","template","Loc","Loc2","parsed","buffer","loc","segment","format","formatOptionName","startSegment","startFormat","I18n","_I18n_instances","_translations","_cache","_formats","_initialLocale","_setLocale","$locale","setLocale","_","formatNumber_fn","formatDateTime_fn","formatList_fn","realName","names","nav","firstLanguage","translation","error","optionKeys","optionValues","locale","currentValues","getValue_fn","count","date","list","cached","getCached_fn","exact","output","resolve","formats","values","deepEqual","object","DefaultCrashView","props","html","cond","Batch","_Batch_instances","_keyedWrites","_unkeyedWrites","_reads","_batchInProgress","_deferIfOvertime","_deferrals","_msFormat","queueBatch_fn","isDevEnv","runBatch_fn","start","elapsed","total","completed","checkpoint","keyedWrites","op","Dolla","_env","_rootElement","_rootView","_crashView","_watcher","createWatcher","_router","_beforeMountCallbacks","_onMountCallbacks","_beforeUnmountCallbacks","_onUnmountCallbacks","_rootElementContext","Emitter","_loggles","_match","createMatcher","_wildcardListeners","_modules","toState","toValue","isState","createRef","isRef","Stats","eventName","listener","wrappedListener","_eventName","event","detail","ContextEvent","store","Store","instance","StoreError","target","assertInstanceOf","rootViewMarkup","createMarkup","register","filter","_console","getDefaultConsole","self","newName","noOp","label","colorFromString","children","View","markup","groupElements","constructMarkup","t","setDevDebug","getDevDebug"],"mappings":"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"}