yummies 7.19.3 → 7.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assert.cjs +1 -1
- package/assert.cjs.map +1 -1
- package/assert.js +1 -1
- package/assert.js.map +1 -1
- package/async.cjs +147 -137
- package/async.cjs.map +1 -1
- package/async.d.ts +98 -131
- package/async.js +147 -137
- package/async.js.map +1 -1
- package/common.cjs +3 -1
- package/common.cjs.map +1 -1
- package/common.d.ts +18 -24
- package/common.js +3 -1
- package/common.js.map +1 -1
- package/complex.cjs +1 -0
- package/complex.cjs.map +1 -1
- package/complex.js +1 -0
- package/complex.js.map +1 -1
- package/cookie.cjs +1 -1
- package/cookie.cjs.map +1 -1
- package/cookie.d.ts +0 -18
- package/cookie.js +1 -1
- package/cookie.js.map +1 -1
- package/css-cx.cjs +78 -0
- package/css-cx.cjs.map +1 -0
- package/css-cx.d.ts +69 -0
- package/css-cx.js +74 -0
- package/css-cx.js.map +1 -0
- package/css.cjs +32 -111
- package/css.cjs.map +1 -1
- package/css.d.ts +32 -42
- package/css.js +30 -107
- package/css.js.map +1 -1
- package/data.cjs +60 -50
- package/data.cjs.map +1 -1
- package/data.d.ts +21 -34
- package/data.js +60 -50
- package/data.js.map +1 -1
- package/date-time.cjs +104 -98
- package/date-time.cjs.map +1 -1
- package/date-time.d.ts +51 -57
- package/date-time.js +104 -97
- package/date-time.js.map +1 -1
- package/device.cjs +14 -19
- package/device.cjs.map +1 -1
- package/device.d.ts +15 -26
- package/device.js +14 -19
- package/device.js.map +1 -1
- package/encodings.cjs +1 -1
- package/encodings.cjs.map +1 -1
- package/encodings.d.ts +0 -17
- package/encodings.js +1 -1
- package/encodings.js.map +1 -1
- package/errors.cjs +1 -18
- package/errors.cjs.map +1 -1
- package/errors.d.ts +0 -17
- package/errors.js +1 -17
- package/errors.js.map +1 -1
- package/file.cjs +3 -17
- package/file.cjs.map +1 -1
- package/file.d.ts +1 -16
- package/file.js +3 -17
- package/file.js.map +1 -1
- package/format.cjs +1 -1
- package/format.cjs.map +1 -1
- package/format.js +1 -1
- package/format.js.map +1 -1
- package/html.cjs +113 -173
- package/html.cjs.map +1 -1
- package/html.d.ts +68 -58
- package/html.js +112 -170
- package/html.js.map +1 -1
- package/id-nanoid.cjs +36 -0
- package/id-nanoid.cjs.map +1 -0
- package/id-nanoid.d.ts +26 -0
- package/id-nanoid.js +32 -0
- package/id-nanoid.js.map +1 -0
- package/id.cjs +10 -45
- package/id.cjs.map +1 -1
- package/id.d.ts +27 -36
- package/id.js +6 -40
- package/id.js.map +1 -1
- package/imports.cjs +3 -18
- package/imports.cjs.map +1 -1
- package/imports.d.ts +1 -16
- package/imports.js +3 -17
- package/imports.js.map +1 -1
- package/math.cjs +16 -12
- package/math.cjs.map +1 -1
- package/math.d.ts +9 -24
- package/math.js +16 -12
- package/math.js.map +1 -1
- package/media.cjs +88 -89
- package/media.cjs.map +1 -1
- package/media.d.ts +72 -80
- package/media.js +88 -88
- package/media.js.map +1 -1
- package/mobx.cjs +0 -1
- package/mobx.cjs.map +1 -1
- package/mobx.js.map +1 -1
- package/ms.cjs +3 -17
- package/ms.cjs.map +1 -1
- package/ms.d.ts +1 -16
- package/ms.js +3 -17
- package/ms.js.map +1 -1
- package/number.cjs +1 -17
- package/number.cjs.map +1 -1
- package/number.d.ts +0 -16
- package/number.js +1 -17
- package/number.js.map +1 -1
- package/package.json +6 -6
- package/parser.cjs +1 -1
- package/parser.cjs.map +1 -1
- package/parser.js +1 -1
- package/parser.js.map +1 -1
- package/price.cjs +1 -1
- package/price.cjs.map +1 -1
- package/price.d.ts +0 -16
- package/price.js +1 -1
- package/price.js.map +1 -1
- package/random.cjs +37 -39
- package/random.cjs.map +1 -1
- package/random.d.ts +31 -40
- package/random.js +37 -39
- package/random.js.map +1 -1
- package/react.cjs +0 -1
- package/react.cjs.map +1 -1
- package/react.js.map +1 -1
- package/sanitize-html.cjs +82 -0
- package/sanitize-html.cjs.map +1 -0
- package/sanitize-html.d.ts +28 -0
- package/sanitize-html.js +79 -0
- package/sanitize-html.js.map +1 -0
- package/sound.cjs +1 -17
- package/sound.cjs.map +1 -1
- package/sound.d.ts +0 -16
- package/sound.js +1 -17
- package/sound.js.map +1 -1
- package/storage.cjs +7 -5
- package/storage.cjs.map +1 -1
- package/storage.d.ts +3 -17
- package/storage.js +7 -5
- package/storage.js.map +1 -1
- package/text.cjs +3 -17
- package/text.cjs.map +1 -1
- package/text.d.ts +1 -16
- package/text.js +3 -17
- package/text.js.map +1 -1
- package/type-guard.cjs +38 -1
- package/type-guard.cjs.map +1 -1
- package/type-guard.d.ts +38 -0
- package/type-guard.js +38 -1
- package/type-guard.js.map +1 -1
- package/types.d.ts +10 -1
- package/types.global.d.ts +9 -0
- package/vibrate.cjs +1 -17
- package/vibrate.cjs.map +1 -1
- package/vibrate.d.ts +0 -16
- package/vibrate.js +1 -17
- package/vibrate.js.map +1 -1
- /package/{chunk-pbuEa-1d.js → chunk-D7D4PA-g.js} +0 -0
- /package/{chunk-CZWwpsFl.cjs → chunk-DakpK96I.cjs} +0 -0
package/assert.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_chunk = require("./chunk-
|
|
2
|
+
const require_chunk = require("./chunk-DakpK96I.cjs");
|
|
3
3
|
let yummies_type_guard = require("yummies/type-guard");
|
|
4
4
|
let yummies_common = require("yummies/common");
|
|
5
5
|
//#region src/assert/_exports.ts
|
package/assert.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assert.cjs","names":[],"sources":["../src/assert/_exports.ts"],"sourcesContent":["/**\n * ---header-docs-section---\n * # yummies/assert\n *\n * ## Description\n *\n * Runtime **assertions** for invariants, narrowing, and exhaustiveness. Helpers throw\n * {@link AssertionError} with an optional message (`string` or {@link MaybeFn}) so failing fast stays\n * explicit without a heavy assertion library. Use `assert.ok`, `assert.string`, `assert.defined`,\n * `assert.fail`, and the rest on the namespace export from the package entry.\n *\n * ## Usage\n *\n * ```ts\n * import { assert } from \"yummies/assert\";\n *\n * assert.ok(user.id, \"user id is required\");\n * assert.defined(maybeName);\n * assert.string(raw);\n * ```\n */\n\nimport { callFunction } from 'yummies/common';\nimport { typeGuard } from 'yummies/type-guard';\nimport type { AnyObject, Maybe, MaybeFn } from 'yummies/types';\n\n/**\n * Error thrown by assertion helpers in this module.\n */\nexport class AssertionError extends Error {\n override name = 'AssertionError';\n}\n\nfunction resolveAssertMessage(\n message: MaybeFn<string> | undefined,\n fallback: string,\n): string {\n if (message === undefined) {\n return fallback;\n }\n return callFunction(message);\n}\n\n/**\n * Throws when `condition` is falsy; narrows the type when it is truthy.\n *\n * @param condition Value treated as a boolean guard.\n * @param message Optional message or lazy message factory.\n *\n * @example\n * ```ts\n * assert.ok(user.id, \"user id is required\");\n * ```\n */\nexport function ok(\n condition: unknown,\n message?: MaybeFn<string>,\n): asserts condition {\n if (typeGuard.isFalsy(condition)) {\n throw new AssertionError(resolveAssertMessage(message, 'Assertion failed'));\n }\n}\n\n/**\n * Same as {@link ok}; common alias for internal invariants (e.g. after optional checks).\n */\nexport const invariant: typeof ok = ok;\n\n/**\n * Throws when the value is `null` or `undefined`; otherwise narrows away nullish.\n *\n * @param value Possibly nullish value.\n * @param message Optional message or lazy message factory.\n *\n * @example\n * ```ts\n * assert.defined(maybeName, \"name must be present\");\n * ```\n */\nexport function defined<T>(\n value: Maybe<T>,\n message?: MaybeFn<string>,\n): asserts value is NonNullable<T> {\n if (!typeGuard.isDefined(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected a defined value'),\n );\n }\n}\n\n/**\n * Throws when the value is `null`; allows `undefined` unless combined with other checks.\n *\n * @param value Value that may be `null`.\n * @param message Optional message or lazy message factory.\n */\nexport function notNull<T>(\n value: T | null,\n message?: MaybeFn<string>,\n): asserts value is T {\n if (typeGuard.isNull(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected a non-null value'),\n );\n }\n}\n\n/**\n * Throws when the value is `undefined`.\n *\n * @param value Value that may be `undefined`.\n * @param message Optional message or lazy message factory.\n */\nexport function notUndefined<T>(\n value: T | undefined,\n message?: MaybeFn<string>,\n): asserts value is T {\n if (typeGuard.isUndefined(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected a defined value'),\n );\n }\n}\n\n/**\n * Throws when `value` is not a string (primitive or `String` object); uses `typeGuard.isString`.\n *\n * @param value Value to narrow.\n * @param message Optional message or lazy message factory.\n */\nexport function string(\n value: unknown,\n message?: MaybeFn<string>,\n): asserts value is string {\n if (!typeGuard.isString(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected a string'),\n );\n }\n}\n\n/**\n * Throws when `value` is not a object (primitive or `AnyObject` object); uses `typeGuard.isObject`.\n *\n * @param value Value to narrow.\n * @param message Optional message or lazy message factory.\n */\nexport function object<T extends AnyObject = AnyObject>(\n value: unknown,\n message?: MaybeFn<string>,\n): asserts value is T {\n if (!typeGuard.isObject(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected an object'),\n );\n }\n}\n\n/**\n * Throws when `value` is not a object (primitive or `AnyObject` object); uses `typeGuard.isArray`.\n *\n * @param value Value to narrow.\n * @param message Optional message or lazy message factory.\n */\nexport function array<T extends any[] = any[]>(\n value: unknown,\n message?: MaybeFn<string>,\n): asserts value is T {\n if (!typeGuard.isArray(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected an array'),\n );\n }\n}\n\n/**\n * Throws when `value` is not a finite non-NaN number; uses `typeGuard.isNumber`.\n *\n * @param value Value to narrow.\n * @param message Optional message or lazy message factory.\n */\nexport function number(\n value: unknown,\n message?: MaybeFn<string>,\n): asserts value is number {\n if (!typeGuard.isNumber(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected a finite number'),\n );\n }\n}\n\n/**\n * Throws when `value` is not a boolean; uses `typeGuard.isBoolean`.\n *\n * @param value Value to narrow.\n * @param message Optional message or lazy message factory.\n */\nexport function boolean(\n value: unknown,\n message?: MaybeFn<string>,\n): asserts value is boolean {\n if (!typeGuard.isBoolean(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected a boolean'),\n );\n }\n}\n\n/**\n * Throws when `value` is not a symbol; uses `typeGuard.isSymbol`.\n *\n * @param value Value to narrow.\n * @param message Optional message or lazy message factory.\n */\nexport function symbol(\n value: unknown,\n message?: MaybeFn<string>,\n): asserts value is symbol {\n if (!typeGuard.isSymbol(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected a symbol'),\n );\n }\n}\n\n/**\n * Always throws; use for branches that must be impossible or as a typed “abort”.\n *\n * @param message Optional message or lazy message factory.\n *\n * @example\n * ```ts\n * function parse(kind: \"a\" | \"b\") {\n * if (kind === \"a\") return 1;\n * if (kind === \"b\") return 2;\n * assert.fail(\"unreachable\");\n * }\n * ```\n */\nexport function fail(message?: MaybeFn<string>): never {\n throw new AssertionError(resolveAssertMessage(message, 'Unreachable'));\n}\n\n/**\n * Exhaustiveness helper: call with a `never` value when all union cases are handled.\n *\n * @param value Should be `never` when the type checker is satisfied.\n * @param message Optional message (this path always throws, so a lazy factory is unnecessary).\n */\nexport function unreachable(value: never, message?: string): never {\n throw new AssertionError(\n resolveAssertMessage(message, `Unexpected value: ${String(value)}`),\n );\n}\n\n/**\n * Alias for {@link unreachable} (common name in switch exhaustiveness snippets).\n */\nexport { unreachable as never };\n\n/**\n * Throws when `value` is not an instance of `ctor`.\n *\n * @param value Value to check.\n * @param ctor Constructor used with `instanceof`.\n * @param message Optional message or lazy message factory.\n *\n * @example\n * ```ts\n * assert.instanceOf(el, HTMLElement, \"expected a DOM element\");\n * ```\n */\nexport function instanceOf<T>(\n value: unknown,\n ctor: abstract new (...args: never[]) => T,\n message?: MaybeFn<string>,\n): asserts value is T {\n if (!(value instanceof ctor)) {\n throw new AssertionError(\n resolveAssertMessage(message, `Expected instance of ${ctor.name}`),\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,IAAa,iBAAb,cAAoC,MAAM;CACxC,OAAgB
|
|
1
|
+
{"version":3,"file":"assert.cjs","names":[],"sources":["../src/assert/_exports.ts"],"sourcesContent":["/**\n * ---header-docs-section---\n * # yummies/assert\n *\n * ## Description\n *\n * Runtime **assertions** for invariants, narrowing, and exhaustiveness. Helpers throw\n * {@link AssertionError} with an optional message (`string` or {@link MaybeFn}) so failing fast stays\n * explicit without a heavy assertion library. Use `assert.ok`, `assert.string`, `assert.defined`,\n * `assert.fail`, and the rest on the namespace export from the package entry.\n *\n * ## Usage\n *\n * ```ts\n * import { assert } from \"yummies/assert\";\n *\n * assert.ok(user.id, \"user id is required\");\n * assert.defined(maybeName);\n * assert.string(raw);\n * ```\n */\n\nimport { callFunction } from 'yummies/common';\nimport { typeGuard } from 'yummies/type-guard';\nimport type { AnyObject, Maybe, MaybeFn } from 'yummies/types';\n\n/**\n * Error thrown by assertion helpers in this module.\n */\nexport class AssertionError extends Error {\n override name = 'AssertionError';\n}\n\nfunction resolveAssertMessage(\n message: MaybeFn<string> | undefined,\n fallback: string,\n): string {\n if (message === undefined) {\n return fallback;\n }\n return callFunction(message);\n}\n\n/**\n * Throws when `condition` is falsy; narrows the type when it is truthy.\n *\n * @param condition Value treated as a boolean guard.\n * @param message Optional message or lazy message factory.\n *\n * @example\n * ```ts\n * assert.ok(user.id, \"user id is required\");\n * ```\n */\nexport function ok(\n condition: unknown,\n message?: MaybeFn<string>,\n): asserts condition {\n if (typeGuard.isFalsy(condition)) {\n throw new AssertionError(resolveAssertMessage(message, 'Assertion failed'));\n }\n}\n\n/**\n * Same as {@link ok}; common alias for internal invariants (e.g. after optional checks).\n */\nexport const invariant: typeof ok = ok;\n\n/**\n * Throws when the value is `null` or `undefined`; otherwise narrows away nullish.\n *\n * @param value Possibly nullish value.\n * @param message Optional message or lazy message factory.\n *\n * @example\n * ```ts\n * assert.defined(maybeName, \"name must be present\");\n * ```\n */\nexport function defined<T>(\n value: Maybe<T>,\n message?: MaybeFn<string>,\n): asserts value is NonNullable<T> {\n if (!typeGuard.isDefined(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected a defined value'),\n );\n }\n}\n\n/**\n * Throws when the value is `null`; allows `undefined` unless combined with other checks.\n *\n * @param value Value that may be `null`.\n * @param message Optional message or lazy message factory.\n */\nexport function notNull<T>(\n value: T | null,\n message?: MaybeFn<string>,\n): asserts value is T {\n if (typeGuard.isNull(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected a non-null value'),\n );\n }\n}\n\n/**\n * Throws when the value is `undefined`.\n *\n * @param value Value that may be `undefined`.\n * @param message Optional message or lazy message factory.\n */\nexport function notUndefined<T>(\n value: T | undefined,\n message?: MaybeFn<string>,\n): asserts value is T {\n if (typeGuard.isUndefined(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected a defined value'),\n );\n }\n}\n\n/**\n * Throws when `value` is not a string (primitive or `String` object); uses `typeGuard.isString`.\n *\n * @param value Value to narrow.\n * @param message Optional message or lazy message factory.\n */\nexport function string(\n value: unknown,\n message?: MaybeFn<string>,\n): asserts value is string {\n if (!typeGuard.isString(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected a string'),\n );\n }\n}\n\n/**\n * Throws when `value` is not a object (primitive or `AnyObject` object); uses `typeGuard.isObject`.\n *\n * @param value Value to narrow.\n * @param message Optional message or lazy message factory.\n */\nexport function object<T extends AnyObject = AnyObject>(\n value: unknown,\n message?: MaybeFn<string>,\n): asserts value is T {\n if (!typeGuard.isObject(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected an object'),\n );\n }\n}\n\n/**\n * Throws when `value` is not a object (primitive or `AnyObject` object); uses `typeGuard.isArray`.\n *\n * @param value Value to narrow.\n * @param message Optional message or lazy message factory.\n */\nexport function array<T extends any[] = any[]>(\n value: unknown,\n message?: MaybeFn<string>,\n): asserts value is T {\n if (!typeGuard.isArray(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected an array'),\n );\n }\n}\n\n/**\n * Throws when `value` is not a finite non-NaN number; uses `typeGuard.isNumber`.\n *\n * @param value Value to narrow.\n * @param message Optional message or lazy message factory.\n */\nexport function number(\n value: unknown,\n message?: MaybeFn<string>,\n): asserts value is number {\n if (!typeGuard.isNumber(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected a finite number'),\n );\n }\n}\n\n/**\n * Throws when `value` is not a boolean; uses `typeGuard.isBoolean`.\n *\n * @param value Value to narrow.\n * @param message Optional message or lazy message factory.\n */\nexport function boolean(\n value: unknown,\n message?: MaybeFn<string>,\n): asserts value is boolean {\n if (!typeGuard.isBoolean(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected a boolean'),\n );\n }\n}\n\n/**\n * Throws when `value` is not a symbol; uses `typeGuard.isSymbol`.\n *\n * @param value Value to narrow.\n * @param message Optional message or lazy message factory.\n */\nexport function symbol(\n value: unknown,\n message?: MaybeFn<string>,\n): asserts value is symbol {\n if (!typeGuard.isSymbol(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected a symbol'),\n );\n }\n}\n\n/**\n * Always throws; use for branches that must be impossible or as a typed “abort”.\n *\n * @param message Optional message or lazy message factory.\n *\n * @example\n * ```ts\n * function parse(kind: \"a\" | \"b\") {\n * if (kind === \"a\") return 1;\n * if (kind === \"b\") return 2;\n * assert.fail(\"unreachable\");\n * }\n * ```\n */\nexport function fail(message?: MaybeFn<string>): never {\n throw new AssertionError(resolveAssertMessage(message, 'Unreachable'));\n}\n\n/**\n * Exhaustiveness helper: call with a `never` value when all union cases are handled.\n *\n * @param value Should be `never` when the type checker is satisfied.\n * @param message Optional message (this path always throws, so a lazy factory is unnecessary).\n */\nexport function unreachable(value: never, message?: string): never {\n throw new AssertionError(\n resolveAssertMessage(message, `Unexpected value: ${String(value)}`),\n );\n}\n\n/**\n * Alias for {@link unreachable} (common name in switch exhaustiveness snippets).\n */\nexport { unreachable as never };\n\n/**\n * Throws when `value` is not an instance of `ctor`.\n *\n * @param value Value to check.\n * @param ctor Constructor used with `instanceof`.\n * @param message Optional message or lazy message factory.\n *\n * @example\n * ```ts\n * assert.instanceOf(el, HTMLElement, \"expected a DOM element\");\n * ```\n */\nexport function instanceOf<T>(\n value: unknown,\n ctor: abstract new (...args: never[]) => T,\n message?: MaybeFn<string>,\n): asserts value is T {\n if (!(value instanceof ctor)) {\n throw new AssertionError(\n resolveAssertMessage(message, `Expected instance of ${ctor.name}`),\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,IAAa,iBAAb,cAAoC,MAAM;CACxC,OAAgB;AAClB;AAEA,SAAS,qBACP,SACA,UACQ;CACR,IAAI,YAAY,KAAA,GACd,OAAO;CAET,QAAA,GAAA,eAAA,cAAoB,OAAO;AAC7B;;;;;;;;;;;;AAaA,SAAgB,GACd,WACA,SACmB;CACnB,IAAI,mBAAA,UAAU,QAAQ,SAAS,GAC7B,MAAM,IAAI,eAAe,qBAAqB,SAAS,kBAAkB,CAAC;AAE9E;;;;AAKA,IAAa,YAAuB;;;;;;;;;;;;AAapC,SAAgB,QACd,OACA,SACiC;CACjC,IAAI,CAAC,mBAAA,UAAU,UAAU,KAAK,GAC5B,MAAM,IAAI,eACR,qBAAqB,SAAS,0BAA0B,CAC1D;AAEJ;;;;;;;AAQA,SAAgB,QACd,OACA,SACoB;CACpB,IAAI,mBAAA,UAAU,OAAO,KAAK,GACxB,MAAM,IAAI,eACR,qBAAqB,SAAS,2BAA2B,CAC3D;AAEJ;;;;;;;AAQA,SAAgB,aACd,OACA,SACoB;CACpB,IAAI,mBAAA,UAAU,YAAY,KAAK,GAC7B,MAAM,IAAI,eACR,qBAAqB,SAAS,0BAA0B,CAC1D;AAEJ;;;;;;;AAQA,SAAgB,OACd,OACA,SACyB;CACzB,IAAI,CAAC,mBAAA,UAAU,SAAS,KAAK,GAC3B,MAAM,IAAI,eACR,qBAAqB,SAAS,mBAAmB,CACnD;AAEJ;;;;;;;AAQA,SAAgB,OACd,OACA,SACoB;CACpB,IAAI,CAAC,mBAAA,UAAU,SAAS,KAAK,GAC3B,MAAM,IAAI,eACR,qBAAqB,SAAS,oBAAoB,CACpD;AAEJ;;;;;;;AAQA,SAAgB,MACd,OACA,SACoB;CACpB,IAAI,CAAC,mBAAA,UAAU,QAAQ,KAAK,GAC1B,MAAM,IAAI,eACR,qBAAqB,SAAS,mBAAmB,CACnD;AAEJ;;;;;;;AAQA,SAAgB,OACd,OACA,SACyB;CACzB,IAAI,CAAC,mBAAA,UAAU,SAAS,KAAK,GAC3B,MAAM,IAAI,eACR,qBAAqB,SAAS,0BAA0B,CAC1D;AAEJ;;;;;;;AAQA,SAAgB,QACd,OACA,SAC0B;CAC1B,IAAI,CAAC,mBAAA,UAAU,UAAU,KAAK,GAC5B,MAAM,IAAI,eACR,qBAAqB,SAAS,oBAAoB,CACpD;AAEJ;;;;;;;AAQA,SAAgB,OACd,OACA,SACyB;CACzB,IAAI,CAAC,mBAAA,UAAU,SAAS,KAAK,GAC3B,MAAM,IAAI,eACR,qBAAqB,SAAS,mBAAmB,CACnD;AAEJ;;;;;;;;;;;;;;;AAgBA,SAAgB,KAAK,SAAkC;CACrD,MAAM,IAAI,eAAe,qBAAqB,SAAS,aAAa,CAAC;AACvE;;;;;;;AAQA,SAAgB,YAAY,OAAc,SAAyB;CACjE,MAAM,IAAI,eACR,qBAAqB,SAAS,qBAAqB,OAAO,KAAK,GAAG,CACpE;AACF;;;;;;;;;;;;;AAmBA,SAAgB,WACd,OACA,MACA,SACoB;CACpB,IAAI,EAAE,iBAAiB,OACrB,MAAM,IAAI,eACR,qBAAqB,SAAS,wBAAwB,KAAK,MAAM,CACnE;AAEJ"}
|
package/assert.js
CHANGED
package/assert.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assert.js","names":[],"sources":["../src/assert/_exports.ts"],"sourcesContent":["/**\n * ---header-docs-section---\n * # yummies/assert\n *\n * ## Description\n *\n * Runtime **assertions** for invariants, narrowing, and exhaustiveness. Helpers throw\n * {@link AssertionError} with an optional message (`string` or {@link MaybeFn}) so failing fast stays\n * explicit without a heavy assertion library. Use `assert.ok`, `assert.string`, `assert.defined`,\n * `assert.fail`, and the rest on the namespace export from the package entry.\n *\n * ## Usage\n *\n * ```ts\n * import { assert } from \"yummies/assert\";\n *\n * assert.ok(user.id, \"user id is required\");\n * assert.defined(maybeName);\n * assert.string(raw);\n * ```\n */\n\nimport { callFunction } from 'yummies/common';\nimport { typeGuard } from 'yummies/type-guard';\nimport type { AnyObject, Maybe, MaybeFn } from 'yummies/types';\n\n/**\n * Error thrown by assertion helpers in this module.\n */\nexport class AssertionError extends Error {\n override name = 'AssertionError';\n}\n\nfunction resolveAssertMessage(\n message: MaybeFn<string> | undefined,\n fallback: string,\n): string {\n if (message === undefined) {\n return fallback;\n }\n return callFunction(message);\n}\n\n/**\n * Throws when `condition` is falsy; narrows the type when it is truthy.\n *\n * @param condition Value treated as a boolean guard.\n * @param message Optional message or lazy message factory.\n *\n * @example\n * ```ts\n * assert.ok(user.id, \"user id is required\");\n * ```\n */\nexport function ok(\n condition: unknown,\n message?: MaybeFn<string>,\n): asserts condition {\n if (typeGuard.isFalsy(condition)) {\n throw new AssertionError(resolveAssertMessage(message, 'Assertion failed'));\n }\n}\n\n/**\n * Same as {@link ok}; common alias for internal invariants (e.g. after optional checks).\n */\nexport const invariant: typeof ok = ok;\n\n/**\n * Throws when the value is `null` or `undefined`; otherwise narrows away nullish.\n *\n * @param value Possibly nullish value.\n * @param message Optional message or lazy message factory.\n *\n * @example\n * ```ts\n * assert.defined(maybeName, \"name must be present\");\n * ```\n */\nexport function defined<T>(\n value: Maybe<T>,\n message?: MaybeFn<string>,\n): asserts value is NonNullable<T> {\n if (!typeGuard.isDefined(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected a defined value'),\n );\n }\n}\n\n/**\n * Throws when the value is `null`; allows `undefined` unless combined with other checks.\n *\n * @param value Value that may be `null`.\n * @param message Optional message or lazy message factory.\n */\nexport function notNull<T>(\n value: T | null,\n message?: MaybeFn<string>,\n): asserts value is T {\n if (typeGuard.isNull(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected a non-null value'),\n );\n }\n}\n\n/**\n * Throws when the value is `undefined`.\n *\n * @param value Value that may be `undefined`.\n * @param message Optional message or lazy message factory.\n */\nexport function notUndefined<T>(\n value: T | undefined,\n message?: MaybeFn<string>,\n): asserts value is T {\n if (typeGuard.isUndefined(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected a defined value'),\n );\n }\n}\n\n/**\n * Throws when `value` is not a string (primitive or `String` object); uses `typeGuard.isString`.\n *\n * @param value Value to narrow.\n * @param message Optional message or lazy message factory.\n */\nexport function string(\n value: unknown,\n message?: MaybeFn<string>,\n): asserts value is string {\n if (!typeGuard.isString(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected a string'),\n );\n }\n}\n\n/**\n * Throws when `value` is not a object (primitive or `AnyObject` object); uses `typeGuard.isObject`.\n *\n * @param value Value to narrow.\n * @param message Optional message or lazy message factory.\n */\nexport function object<T extends AnyObject = AnyObject>(\n value: unknown,\n message?: MaybeFn<string>,\n): asserts value is T {\n if (!typeGuard.isObject(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected an object'),\n );\n }\n}\n\n/**\n * Throws when `value` is not a object (primitive or `AnyObject` object); uses `typeGuard.isArray`.\n *\n * @param value Value to narrow.\n * @param message Optional message or lazy message factory.\n */\nexport function array<T extends any[] = any[]>(\n value: unknown,\n message?: MaybeFn<string>,\n): asserts value is T {\n if (!typeGuard.isArray(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected an array'),\n );\n }\n}\n\n/**\n * Throws when `value` is not a finite non-NaN number; uses `typeGuard.isNumber`.\n *\n * @param value Value to narrow.\n * @param message Optional message or lazy message factory.\n */\nexport function number(\n value: unknown,\n message?: MaybeFn<string>,\n): asserts value is number {\n if (!typeGuard.isNumber(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected a finite number'),\n );\n }\n}\n\n/**\n * Throws when `value` is not a boolean; uses `typeGuard.isBoolean`.\n *\n * @param value Value to narrow.\n * @param message Optional message or lazy message factory.\n */\nexport function boolean(\n value: unknown,\n message?: MaybeFn<string>,\n): asserts value is boolean {\n if (!typeGuard.isBoolean(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected a boolean'),\n );\n }\n}\n\n/**\n * Throws when `value` is not a symbol; uses `typeGuard.isSymbol`.\n *\n * @param value Value to narrow.\n * @param message Optional message or lazy message factory.\n */\nexport function symbol(\n value: unknown,\n message?: MaybeFn<string>,\n): asserts value is symbol {\n if (!typeGuard.isSymbol(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected a symbol'),\n );\n }\n}\n\n/**\n * Always throws; use for branches that must be impossible or as a typed “abort”.\n *\n * @param message Optional message or lazy message factory.\n *\n * @example\n * ```ts\n * function parse(kind: \"a\" | \"b\") {\n * if (kind === \"a\") return 1;\n * if (kind === \"b\") return 2;\n * assert.fail(\"unreachable\");\n * }\n * ```\n */\nexport function fail(message?: MaybeFn<string>): never {\n throw new AssertionError(resolveAssertMessage(message, 'Unreachable'));\n}\n\n/**\n * Exhaustiveness helper: call with a `never` value when all union cases are handled.\n *\n * @param value Should be `never` when the type checker is satisfied.\n * @param message Optional message (this path always throws, so a lazy factory is unnecessary).\n */\nexport function unreachable(value: never, message?: string): never {\n throw new AssertionError(\n resolveAssertMessage(message, `Unexpected value: ${String(value)}`),\n );\n}\n\n/**\n * Alias for {@link unreachable} (common name in switch exhaustiveness snippets).\n */\nexport { unreachable as never };\n\n/**\n * Throws when `value` is not an instance of `ctor`.\n *\n * @param value Value to check.\n * @param ctor Constructor used with `instanceof`.\n * @param message Optional message or lazy message factory.\n *\n * @example\n * ```ts\n * assert.instanceOf(el, HTMLElement, \"expected a DOM element\");\n * ```\n */\nexport function instanceOf<T>(\n value: unknown,\n ctor: abstract new (...args: never[]) => T,\n message?: MaybeFn<string>,\n): asserts value is T {\n if (!(value instanceof ctor)) {\n throw new AssertionError(\n resolveAssertMessage(message, `Expected instance of ${ctor.name}`),\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,IAAa,iBAAb,cAAoC,MAAM;CACxC,OAAgB
|
|
1
|
+
{"version":3,"file":"assert.js","names":[],"sources":["../src/assert/_exports.ts"],"sourcesContent":["/**\n * ---header-docs-section---\n * # yummies/assert\n *\n * ## Description\n *\n * Runtime **assertions** for invariants, narrowing, and exhaustiveness. Helpers throw\n * {@link AssertionError} with an optional message (`string` or {@link MaybeFn}) so failing fast stays\n * explicit without a heavy assertion library. Use `assert.ok`, `assert.string`, `assert.defined`,\n * `assert.fail`, and the rest on the namespace export from the package entry.\n *\n * ## Usage\n *\n * ```ts\n * import { assert } from \"yummies/assert\";\n *\n * assert.ok(user.id, \"user id is required\");\n * assert.defined(maybeName);\n * assert.string(raw);\n * ```\n */\n\nimport { callFunction } from 'yummies/common';\nimport { typeGuard } from 'yummies/type-guard';\nimport type { AnyObject, Maybe, MaybeFn } from 'yummies/types';\n\n/**\n * Error thrown by assertion helpers in this module.\n */\nexport class AssertionError extends Error {\n override name = 'AssertionError';\n}\n\nfunction resolveAssertMessage(\n message: MaybeFn<string> | undefined,\n fallback: string,\n): string {\n if (message === undefined) {\n return fallback;\n }\n return callFunction(message);\n}\n\n/**\n * Throws when `condition` is falsy; narrows the type when it is truthy.\n *\n * @param condition Value treated as a boolean guard.\n * @param message Optional message or lazy message factory.\n *\n * @example\n * ```ts\n * assert.ok(user.id, \"user id is required\");\n * ```\n */\nexport function ok(\n condition: unknown,\n message?: MaybeFn<string>,\n): asserts condition {\n if (typeGuard.isFalsy(condition)) {\n throw new AssertionError(resolveAssertMessage(message, 'Assertion failed'));\n }\n}\n\n/**\n * Same as {@link ok}; common alias for internal invariants (e.g. after optional checks).\n */\nexport const invariant: typeof ok = ok;\n\n/**\n * Throws when the value is `null` or `undefined`; otherwise narrows away nullish.\n *\n * @param value Possibly nullish value.\n * @param message Optional message or lazy message factory.\n *\n * @example\n * ```ts\n * assert.defined(maybeName, \"name must be present\");\n * ```\n */\nexport function defined<T>(\n value: Maybe<T>,\n message?: MaybeFn<string>,\n): asserts value is NonNullable<T> {\n if (!typeGuard.isDefined(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected a defined value'),\n );\n }\n}\n\n/**\n * Throws when the value is `null`; allows `undefined` unless combined with other checks.\n *\n * @param value Value that may be `null`.\n * @param message Optional message or lazy message factory.\n */\nexport function notNull<T>(\n value: T | null,\n message?: MaybeFn<string>,\n): asserts value is T {\n if (typeGuard.isNull(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected a non-null value'),\n );\n }\n}\n\n/**\n * Throws when the value is `undefined`.\n *\n * @param value Value that may be `undefined`.\n * @param message Optional message or lazy message factory.\n */\nexport function notUndefined<T>(\n value: T | undefined,\n message?: MaybeFn<string>,\n): asserts value is T {\n if (typeGuard.isUndefined(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected a defined value'),\n );\n }\n}\n\n/**\n * Throws when `value` is not a string (primitive or `String` object); uses `typeGuard.isString`.\n *\n * @param value Value to narrow.\n * @param message Optional message or lazy message factory.\n */\nexport function string(\n value: unknown,\n message?: MaybeFn<string>,\n): asserts value is string {\n if (!typeGuard.isString(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected a string'),\n );\n }\n}\n\n/**\n * Throws when `value` is not a object (primitive or `AnyObject` object); uses `typeGuard.isObject`.\n *\n * @param value Value to narrow.\n * @param message Optional message or lazy message factory.\n */\nexport function object<T extends AnyObject = AnyObject>(\n value: unknown,\n message?: MaybeFn<string>,\n): asserts value is T {\n if (!typeGuard.isObject(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected an object'),\n );\n }\n}\n\n/**\n * Throws when `value` is not a object (primitive or `AnyObject` object); uses `typeGuard.isArray`.\n *\n * @param value Value to narrow.\n * @param message Optional message or lazy message factory.\n */\nexport function array<T extends any[] = any[]>(\n value: unknown,\n message?: MaybeFn<string>,\n): asserts value is T {\n if (!typeGuard.isArray(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected an array'),\n );\n }\n}\n\n/**\n * Throws when `value` is not a finite non-NaN number; uses `typeGuard.isNumber`.\n *\n * @param value Value to narrow.\n * @param message Optional message or lazy message factory.\n */\nexport function number(\n value: unknown,\n message?: MaybeFn<string>,\n): asserts value is number {\n if (!typeGuard.isNumber(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected a finite number'),\n );\n }\n}\n\n/**\n * Throws when `value` is not a boolean; uses `typeGuard.isBoolean`.\n *\n * @param value Value to narrow.\n * @param message Optional message or lazy message factory.\n */\nexport function boolean(\n value: unknown,\n message?: MaybeFn<string>,\n): asserts value is boolean {\n if (!typeGuard.isBoolean(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected a boolean'),\n );\n }\n}\n\n/**\n * Throws when `value` is not a symbol; uses `typeGuard.isSymbol`.\n *\n * @param value Value to narrow.\n * @param message Optional message or lazy message factory.\n */\nexport function symbol(\n value: unknown,\n message?: MaybeFn<string>,\n): asserts value is symbol {\n if (!typeGuard.isSymbol(value)) {\n throw new AssertionError(\n resolveAssertMessage(message, 'Expected a symbol'),\n );\n }\n}\n\n/**\n * Always throws; use for branches that must be impossible or as a typed “abort”.\n *\n * @param message Optional message or lazy message factory.\n *\n * @example\n * ```ts\n * function parse(kind: \"a\" | \"b\") {\n * if (kind === \"a\") return 1;\n * if (kind === \"b\") return 2;\n * assert.fail(\"unreachable\");\n * }\n * ```\n */\nexport function fail(message?: MaybeFn<string>): never {\n throw new AssertionError(resolveAssertMessage(message, 'Unreachable'));\n}\n\n/**\n * Exhaustiveness helper: call with a `never` value when all union cases are handled.\n *\n * @param value Should be `never` when the type checker is satisfied.\n * @param message Optional message (this path always throws, so a lazy factory is unnecessary).\n */\nexport function unreachable(value: never, message?: string): never {\n throw new AssertionError(\n resolveAssertMessage(message, `Unexpected value: ${String(value)}`),\n );\n}\n\n/**\n * Alias for {@link unreachable} (common name in switch exhaustiveness snippets).\n */\nexport { unreachable as never };\n\n/**\n * Throws when `value` is not an instance of `ctor`.\n *\n * @param value Value to check.\n * @param ctor Constructor used with `instanceof`.\n * @param message Optional message or lazy message factory.\n *\n * @example\n * ```ts\n * assert.instanceOf(el, HTMLElement, \"expected a DOM element\");\n * ```\n */\nexport function instanceOf<T>(\n value: unknown,\n ctor: abstract new (...args: never[]) => T,\n message?: MaybeFn<string>,\n): asserts value is T {\n if (!(value instanceof ctor)) {\n throw new AssertionError(\n resolveAssertMessage(message, `Expected instance of ${ctor.name}`),\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,IAAa,iBAAb,cAAoC,MAAM;CACxC,OAAgB;AAClB;AAEA,SAAS,qBACP,SACA,UACQ;CACR,IAAI,YAAY,KAAA,GACd,OAAO;CAET,OAAO,aAAa,OAAO;AAC7B;;;;;;;;;;;;AAaA,SAAgB,GACd,WACA,SACmB;CACnB,IAAI,UAAU,QAAQ,SAAS,GAC7B,MAAM,IAAI,eAAe,qBAAqB,SAAS,kBAAkB,CAAC;AAE9E;;;;AAKA,IAAa,YAAuB;;;;;;;;;;;;AAapC,SAAgB,QACd,OACA,SACiC;CACjC,IAAI,CAAC,UAAU,UAAU,KAAK,GAC5B,MAAM,IAAI,eACR,qBAAqB,SAAS,0BAA0B,CAC1D;AAEJ;;;;;;;AAQA,SAAgB,QACd,OACA,SACoB;CACpB,IAAI,UAAU,OAAO,KAAK,GACxB,MAAM,IAAI,eACR,qBAAqB,SAAS,2BAA2B,CAC3D;AAEJ;;;;;;;AAQA,SAAgB,aACd,OACA,SACoB;CACpB,IAAI,UAAU,YAAY,KAAK,GAC7B,MAAM,IAAI,eACR,qBAAqB,SAAS,0BAA0B,CAC1D;AAEJ;;;;;;;AAQA,SAAgB,OACd,OACA,SACyB;CACzB,IAAI,CAAC,UAAU,SAAS,KAAK,GAC3B,MAAM,IAAI,eACR,qBAAqB,SAAS,mBAAmB,CACnD;AAEJ;;;;;;;AAQA,SAAgB,OACd,OACA,SACoB;CACpB,IAAI,CAAC,UAAU,SAAS,KAAK,GAC3B,MAAM,IAAI,eACR,qBAAqB,SAAS,oBAAoB,CACpD;AAEJ;;;;;;;AAQA,SAAgB,MACd,OACA,SACoB;CACpB,IAAI,CAAC,UAAU,QAAQ,KAAK,GAC1B,MAAM,IAAI,eACR,qBAAqB,SAAS,mBAAmB,CACnD;AAEJ;;;;;;;AAQA,SAAgB,OACd,OACA,SACyB;CACzB,IAAI,CAAC,UAAU,SAAS,KAAK,GAC3B,MAAM,IAAI,eACR,qBAAqB,SAAS,0BAA0B,CAC1D;AAEJ;;;;;;;AAQA,SAAgB,QACd,OACA,SAC0B;CAC1B,IAAI,CAAC,UAAU,UAAU,KAAK,GAC5B,MAAM,IAAI,eACR,qBAAqB,SAAS,oBAAoB,CACpD;AAEJ;;;;;;;AAQA,SAAgB,OACd,OACA,SACyB;CACzB,IAAI,CAAC,UAAU,SAAS,KAAK,GAC3B,MAAM,IAAI,eACR,qBAAqB,SAAS,mBAAmB,CACnD;AAEJ;;;;;;;;;;;;;;;AAgBA,SAAgB,KAAK,SAAkC;CACrD,MAAM,IAAI,eAAe,qBAAqB,SAAS,aAAa,CAAC;AACvE;;;;;;;AAQA,SAAgB,YAAY,OAAc,SAAyB;CACjE,MAAM,IAAI,eACR,qBAAqB,SAAS,qBAAqB,OAAO,KAAK,GAAG,CACpE;AACF;;;;;;;;;;;;;AAmBA,SAAgB,WACd,OACA,MACA,SACoB;CACpB,IAAI,EAAE,iBAAiB,OACrB,MAAM,IAAI,eACR,qBAAqB,SAAS,wBAAwB,KAAK,MAAM,CACnE;AAEJ"}
|
package/async.cjs
CHANGED
|
@@ -1,56 +1,93 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
//#region src/async.ts
|
|
2
|
+
//#region src/async/async-template.ts
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Tagged template that builds an async iterable of string chunks (like a streaming template engine).
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* Static template parts are yielded as-is. Each interpolated “piece” can be a primitive, a nested array of pieces,
|
|
7
|
+
* a `Promise` of a piece (including a resolved primitive), an async iterable of primitives, or a
|
|
8
|
+
* **zero-arg function** whose result is processed the same way (see {@link AsyncTemplatePiece} / `MaybeFn`).
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* Interpolation handling matches `processTemplatePiece`: `null`, `undefined`, and `false` add nothing; any other value
|
|
11
|
+
* becomes text via `String(...)`; functions are called once with no arguments before further processing. Collect chunks
|
|
12
|
+
* with `for await...of` or utilities like `Array.fromAsync` where available.
|
|
13
|
+
*
|
|
14
|
+
* @param strings - Cooked template segments from the tag (`strings[0]`, `strings[1]`, …).
|
|
15
|
+
* @param pieces - Values between segments (`pieces[i]` sits between `strings[i]` and `strings[i + 1]`).
|
|
16
|
+
* @returns An async generator yielding string fragments in document order.
|
|
13
17
|
*
|
|
14
18
|
* @example
|
|
15
|
-
*
|
|
19
|
+
* Plain values and promises:
|
|
16
20
|
* ```ts
|
|
17
|
-
*
|
|
18
|
-
*
|
|
21
|
+
* const gen = asyncTemplate`Hello, ${'world'}! Status: ${Promise.resolve(200)}`;
|
|
22
|
+
* let out = '';
|
|
23
|
+
* for await (const chunk of gen) out += chunk;
|
|
24
|
+
* // out === 'Hello, world! Status: 200'
|
|
19
25
|
* ```
|
|
20
26
|
*
|
|
21
27
|
* @example
|
|
22
|
-
*
|
|
28
|
+
* Falsy pieces are omitted (`null`, `undefined`, `false`); arrays flatten recursively:
|
|
23
29
|
* ```ts
|
|
24
|
-
* const
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
30
|
+
* const gen = asyncTemplate`${null}${false}A${['B', ['C']]}`;
|
|
31
|
+
* const out = await Array.fromAsync(gen).then((parts) => parts.join(''));
|
|
32
|
+
* // out === 'ABC'
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* Stream from an async iterable (e.g. chunked upstream text):
|
|
37
|
+
* ```ts
|
|
38
|
+
* async function* lines() {
|
|
39
|
+
* yield 'line1\n';
|
|
40
|
+
* yield 'line2\n';
|
|
29
41
|
* }
|
|
30
|
-
*
|
|
42
|
+
* const gen = asyncTemplate`Header\n${lines()}Footer`;
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* Lazy piece via a thunk (invoked as `piece()`):
|
|
47
|
+
* ```ts
|
|
48
|
+
* let n = 0;
|
|
49
|
+
* const gen = asyncTemplate`count=${() => ++n}`;
|
|
50
|
+
* // first consumption yields "count=1", etc.
|
|
31
51
|
* ```
|
|
32
52
|
*/
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}, time);
|
|
43
|
-
signal.addEventListener("abort", abortListener, { once: true });
|
|
44
|
-
} else setTimeout(resolve, time);
|
|
45
|
-
});
|
|
53
|
+
async function* asyncTemplate(strings, ...pieces) {
|
|
54
|
+
for (let i = 0; i < strings.length; i++) {
|
|
55
|
+
yield strings[i];
|
|
56
|
+
if (i < pieces.length) {
|
|
57
|
+
const piece = pieces[i];
|
|
58
|
+
yield* processTemplatePiece(piece);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
46
62
|
/**
|
|
47
|
-
*
|
|
63
|
+
* Resolves a template piece into yielded string chunks.
|
|
48
64
|
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
65
|
+
* Skips output when `value === null || value === undefined || value === false`.
|
|
66
|
+
* Otherwise awaits promises, flattens arrays, streams async iterables, invokes **functions** with no arguments and
|
|
67
|
+
* recurses on the return value, and uses `String(value)` for primitives.
|
|
52
68
|
*/
|
|
53
|
-
|
|
69
|
+
async function* processTemplatePiece(piece) {
|
|
70
|
+
if (piece === null || piece === void 0 || piece === false) return;
|
|
71
|
+
if (piece instanceof Promise) {
|
|
72
|
+
yield* processTemplatePiece(await piece);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (Array.isArray(piece)) {
|
|
76
|
+
for (const item of piece) yield* processTemplatePiece(item);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (typeof piece === "object" && piece !== null && typeof piece[Symbol.asyncIterator] === "function") {
|
|
80
|
+
for await (const item of piece) yield* processTemplatePiece(item);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (typeof piece === "function") {
|
|
84
|
+
yield* processTemplatePiece(piece());
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
yield String(piece);
|
|
88
|
+
}
|
|
89
|
+
//#endregion
|
|
90
|
+
//#region src/async/endless-raf.ts
|
|
54
91
|
/**
|
|
55
92
|
* Runs a loop driven by `requestAnimationFrame`: on each frame, `quitFunction` is called first.
|
|
56
93
|
* If it returns a truthy value, the loop stops and no further frames are scheduled.
|
|
@@ -93,44 +130,8 @@ var endlessRAF = (quitFunction, asMicrotask) => {
|
|
|
93
130
|
if (asMicrotask) queueMicrotask(raf);
|
|
94
131
|
else raf();
|
|
95
132
|
};
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
* and `callback` is never run. If the callback runs normally, the abort listener is removed.
|
|
99
|
-
*
|
|
100
|
-
* Does nothing special if `signal` is omitted — behaves like a plain timeout.
|
|
101
|
-
*
|
|
102
|
-
* @param callback - Function to run once after `delayInMs` (same as `setTimeout` callback).
|
|
103
|
-
* @param delayInMs - Milliseconds to wait. Passed through to `setTimeout` (browser/Node semantics apply).
|
|
104
|
-
* @param signal - When aborted, clears the pending timeout so `callback` is not invoked.
|
|
105
|
-
*
|
|
106
|
-
* @example
|
|
107
|
-
* ```ts
|
|
108
|
-
* const controller = new AbortController();
|
|
109
|
-
* setAbortableTimeout(() => console.log('done'), 500, controller.signal);
|
|
110
|
-
* // later: controller.abort(); // timeout cancelled, log never runs
|
|
111
|
-
* ```
|
|
112
|
-
*
|
|
113
|
-
* @example
|
|
114
|
-
* Zero-delay scheduling that can still be cancelled before the macrotask runs:
|
|
115
|
-
* ```ts
|
|
116
|
-
* const ac = new AbortController();
|
|
117
|
-
* setAbortableTimeout(() => startIntro(), 0, ac.signal);
|
|
118
|
-
* // e.g. on teardown: ac.abort();
|
|
119
|
-
* ```
|
|
120
|
-
*/
|
|
121
|
-
function setAbortableTimeout(callback, delayInMs, signal) {
|
|
122
|
-
let internalTimer = null;
|
|
123
|
-
const handleAbort = () => {
|
|
124
|
-
if (internalTimer == null) return;
|
|
125
|
-
clearTimeout(internalTimer);
|
|
126
|
-
internalTimer = null;
|
|
127
|
-
};
|
|
128
|
-
signal?.addEventListener("abort", handleAbort, { once: true });
|
|
129
|
-
internalTimer = setTimeout(() => {
|
|
130
|
-
signal?.removeEventListener("abort", handleAbort);
|
|
131
|
-
callback();
|
|
132
|
-
}, delayInMs);
|
|
133
|
-
}
|
|
133
|
+
//#endregion
|
|
134
|
+
//#region src/async/set-abortable-interval.ts
|
|
134
135
|
/**
|
|
135
136
|
* Like `setInterval`, but when `signal` aborts, the interval is cleared with `clearInterval`
|
|
136
137
|
* and `callback` stops being called. If `signal` is omitted, behaves like a normal interval
|
|
@@ -164,92 +165,101 @@ function setAbortableInterval(callback, delayInMs, signal) {
|
|
|
164
165
|
signal?.addEventListener("abort", handleAbort, { once: true });
|
|
165
166
|
timer = setInterval(callback, delayInMs);
|
|
166
167
|
}
|
|
168
|
+
//#endregion
|
|
169
|
+
//#region src/async/set-abortable-timeout.ts
|
|
167
170
|
/**
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
* Static template parts are yielded as-is. Each interpolated “piece” can be a primitive, a nested array of pieces,
|
|
171
|
-
* a `Promise` of a piece (including a resolved primitive), an async iterable of primitives, or a
|
|
172
|
-
* **zero-arg function** whose result is processed the same way (see {@link AsyncTemplatePiece} / `MaybeFn`).
|
|
171
|
+
* Like `setTimeout`, but if `signal` aborts before the delay fires, the timer is cleared
|
|
172
|
+
* and `callback` is never run. If the callback runs normally, the abort listener is removed.
|
|
173
173
|
*
|
|
174
|
-
*
|
|
175
|
-
* becomes text via `String(...)`; functions are called once with no arguments before further processing. Collect chunks
|
|
176
|
-
* with `for await...of` or utilities like `Array.fromAsync` where available.
|
|
174
|
+
* Does nothing special if `signal` is omitted — behaves like a plain timeout.
|
|
177
175
|
*
|
|
178
|
-
* @param
|
|
179
|
-
* @param
|
|
180
|
-
* @
|
|
176
|
+
* @param callback - Function to run once after `delayInMs` (same as `setTimeout` callback).
|
|
177
|
+
* @param delayInMs - Milliseconds to wait. Passed through to `setTimeout` (browser/Node semantics apply).
|
|
178
|
+
* @param signal - When aborted, clears the pending timeout so `callback` is not invoked.
|
|
181
179
|
*
|
|
182
180
|
* @example
|
|
183
|
-
* Plain values and promises:
|
|
184
181
|
* ```ts
|
|
185
|
-
* const
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
* // out === 'Hello, world! Status: 200'
|
|
182
|
+
* const controller = new AbortController();
|
|
183
|
+
* setAbortableTimeout(() => console.log('done'), 500, controller.signal);
|
|
184
|
+
* // later: controller.abort(); // timeout cancelled, log never runs
|
|
189
185
|
* ```
|
|
190
186
|
*
|
|
191
187
|
* @example
|
|
192
|
-
*
|
|
188
|
+
* Zero-delay scheduling that can still be cancelled before the macrotask runs:
|
|
193
189
|
* ```ts
|
|
194
|
-
* const
|
|
195
|
-
*
|
|
196
|
-
* //
|
|
190
|
+
* const ac = new AbortController();
|
|
191
|
+
* setAbortableTimeout(() => startIntro(), 0, ac.signal);
|
|
192
|
+
* // e.g. on teardown: ac.abort();
|
|
197
193
|
* ```
|
|
194
|
+
*/
|
|
195
|
+
function setAbortableTimeout(callback, delayInMs, signal) {
|
|
196
|
+
let internalTimer = null;
|
|
197
|
+
const handleAbort = () => {
|
|
198
|
+
if (internalTimer == null) return;
|
|
199
|
+
clearTimeout(internalTimer);
|
|
200
|
+
internalTimer = null;
|
|
201
|
+
};
|
|
202
|
+
signal?.addEventListener("abort", handleAbort, { once: true });
|
|
203
|
+
internalTimer = setTimeout(() => {
|
|
204
|
+
signal?.removeEventListener("abort", handleAbort);
|
|
205
|
+
callback();
|
|
206
|
+
}, delayInMs);
|
|
207
|
+
}
|
|
208
|
+
//#endregion
|
|
209
|
+
//#region src/async/sleep.ts
|
|
210
|
+
/**
|
|
211
|
+
* Returns a promise that resolves after `time` milliseconds.
|
|
212
|
+
*
|
|
213
|
+
* When `signal` is passed and becomes aborted before the delay elapses, the promise
|
|
214
|
+
* rejects with `signal.reason` (same as native `fetch` / `AbortController` usage).
|
|
215
|
+
* The timeout is cleared on abort so no resolve happens after cancellation.
|
|
216
|
+
*
|
|
217
|
+
* @param time - Delay in milliseconds. Defaults to `0` (next macrotask tick, same idea as `setTimeout(0)`).
|
|
218
|
+
* @param signal - Optional `AbortSignal` to cancel the wait early.
|
|
219
|
+
* @returns A promise that resolves with `void` when the delay completes, or rejects if aborted.
|
|
198
220
|
*
|
|
199
221
|
* @example
|
|
200
|
-
*
|
|
222
|
+
* Basic pause in an async function:
|
|
201
223
|
* ```ts
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
* yield 'line2\n';
|
|
205
|
-
* }
|
|
206
|
-
* const gen = asyncTemplate`Header\n${lines()}Footer`;
|
|
224
|
+
* await sleep(250);
|
|
225
|
+
* console.log('after 250ms');
|
|
207
226
|
* ```
|
|
208
227
|
*
|
|
209
228
|
* @example
|
|
210
|
-
*
|
|
229
|
+
* Cancellable delay tied to component unmount or user action:
|
|
211
230
|
* ```ts
|
|
212
|
-
*
|
|
213
|
-
*
|
|
214
|
-
*
|
|
231
|
+
* const ac = new AbortController();
|
|
232
|
+
* try {
|
|
233
|
+
* await sleep(5000, ac.signal);
|
|
234
|
+
* } catch (e) {
|
|
235
|
+
* // aborted — e is signal.reason
|
|
236
|
+
* }
|
|
237
|
+
* ac.abort('user cancelled');
|
|
215
238
|
* ```
|
|
216
239
|
*/
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
240
|
+
var sleep = (time = 0, signal) => new Promise((resolve, reject) => {
|
|
241
|
+
if (signal) {
|
|
242
|
+
const abortListener = () => {
|
|
243
|
+
clearTimeout(timerId);
|
|
244
|
+
reject(signal?.reason);
|
|
245
|
+
};
|
|
246
|
+
const timerId = setTimeout(() => {
|
|
247
|
+
signal.removeEventListener("abort", abortListener);
|
|
248
|
+
resolve();
|
|
249
|
+
}, time);
|
|
250
|
+
signal.addEventListener("abort", abortListener, { once: true });
|
|
251
|
+
} else setTimeout(resolve, time);
|
|
252
|
+
});
|
|
253
|
+
//#endregion
|
|
254
|
+
//#region src/async/wait-async.ts
|
|
226
255
|
/**
|
|
227
|
-
*
|
|
256
|
+
* Creates a promise that resolves after the specified number of milliseconds.
|
|
228
257
|
*
|
|
229
|
-
*
|
|
230
|
-
*
|
|
231
|
-
*
|
|
258
|
+
* @deprecated Use `sleep` instead.
|
|
259
|
+
* @param ms Delay in milliseconds.
|
|
260
|
+
* @returns Promise
|
|
232
261
|
*/
|
|
233
|
-
|
|
234
|
-
if (piece === null || piece === void 0 || piece === false) return;
|
|
235
|
-
if (piece instanceof Promise) {
|
|
236
|
-
yield* processTemplatePiece(await piece);
|
|
237
|
-
return;
|
|
238
|
-
}
|
|
239
|
-
if (Array.isArray(piece)) {
|
|
240
|
-
for (const item of piece) yield* processTemplatePiece(item);
|
|
241
|
-
return;
|
|
242
|
-
}
|
|
243
|
-
if (typeof piece === "object" && piece !== null && typeof piece[Symbol.asyncIterator] === "function") {
|
|
244
|
-
for await (const item of piece) yield* processTemplatePiece(item);
|
|
245
|
-
return;
|
|
246
|
-
}
|
|
247
|
-
if (typeof piece === "function") {
|
|
248
|
-
yield* processTemplatePiece(piece());
|
|
249
|
-
return;
|
|
250
|
-
}
|
|
251
|
-
yield String(piece);
|
|
252
|
-
}
|
|
262
|
+
var waitAsync = (ms = 1e3) => sleep(ms);
|
|
253
263
|
//#endregion
|
|
254
264
|
exports.asyncTemplate = asyncTemplate;
|
|
255
265
|
exports.endlessRAF = endlessRAF;
|
package/async.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"async.cjs","names":[],"sources":["../src/async.ts"],"sourcesContent":["/**\n * ---header-docs-section---\n * # yummies/async\n *\n * ## Description\n *\n * Helpers for asynchronous control flow: delays, cancellable waits, scheduling on the next frame,\n * and small utilities around `requestAnimationFrame` and `queueMicrotask`. They complement native\n * `Promise`/`AbortSignal` patterns and keep timing logic easy to test and tree-shake per call site.\n * Import only what you need from `yummies/async` so bundlers can drop unused helpers.\n *\n * ## Usage\n *\n * ```ts\n * import { sleep } from \"yummies/async\";\n * ```\n */\n\nimport type { MaybeFn, MaybePromise, Primitive } from './types.js';\n\n/**\n * Returns a promise that resolves after `time` milliseconds.\n *\n * When `signal` is passed and becomes aborted before the delay elapses, the promise\n * rejects with `signal.reason` (same as native `fetch` / `AbortController` usage).\n * The timeout is cleared on abort so no resolve happens after cancellation.\n *\n * @param time - Delay in milliseconds. Defaults to `0` (next macrotask tick, same idea as `setTimeout(0)`).\n * @param signal - Optional `AbortSignal` to cancel the wait early.\n * @returns A promise that resolves with `void` when the delay completes, or rejects if aborted.\n *\n * @example\n * Basic pause in an async function:\n * ```ts\n * await sleep(250);\n * console.log('after 250ms');\n * ```\n *\n * @example\n * Cancellable delay tied to component unmount or user action:\n * ```ts\n * const ac = new AbortController();\n * try {\n * await sleep(5000, ac.signal);\n * } catch (e) {\n * // aborted — e is signal.reason\n * }\n * ac.abort('user cancelled');\n * ```\n */\nexport const sleep = (time: number = 0, signal?: AbortSignal) =>\n new Promise<void>((resolve, reject) => {\n if (signal) {\n const abortListener = () => {\n clearTimeout(timerId);\n reject(signal?.reason);\n };\n const timerId = setTimeout(() => {\n signal.removeEventListener('abort', abortListener);\n resolve();\n }, time);\n signal.addEventListener('abort', abortListener, { once: true });\n } else {\n setTimeout(resolve, time);\n }\n });\n\n/**\n * Creates a promise that resolves after the specified number of milliseconds.\n *\n * @deprecated Use `sleep` instead.\n * @param ms Delay in milliseconds.\n * @returns Promise\n */\nexport const waitAsync = async (ms = 1000) =>\n new Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * Runs a loop driven by `requestAnimationFrame`: on each frame, `quitFunction` is called first.\n * If it returns a truthy value, the loop stops and no further frames are scheduled.\n * If it returns falsy or nothing, the next frame is scheduled recursively.\n *\n * Use this for per-frame work (animations, layout reads after paint) without managing\n * `cancelAnimationFrame` manually — returning `true` from `quitFunction` is the exit condition.\n *\n * When `asMicrotask` is `true`, scheduling the next RAF is deferred with `queueMicrotask`\n * so other microtasks can run before the frame is requested (useful when you need to\n * batch DOM updates or let reactive frameworks flush first).\n *\n * @param quitFunction - Invoked each animation frame. Return `true` to stop the loop.\n * @param asMicrotask - If `true`, wrap the `requestAnimationFrame` call in `queueMicrotask`.\n *\n * @example\n * Stop after 60 frames (~1s at 60Hz):\n * ```ts\n * let frames = 0;\n * endlessRAF(() => {\n * frames++;\n * updateSomething(frames);\n * return frames >= 60;\n * });\n * ```\n *\n * @example\n * Run until an element is removed or a flag is set:\n * ```ts\n * let running = true;\n * endlessRAF(() => {\n * if (!running || !document.body.contains(el)) return true;\n * draw(el);\n * }, true);\n * ```\n */\nexport const endlessRAF = (\n quitFunction: () => boolean | void,\n asMicrotask?: boolean,\n) => {\n if (quitFunction()) return;\n\n const raf = () =>\n requestAnimationFrame(() => endlessRAF(quitFunction, asMicrotask));\n\n if (asMicrotask) {\n queueMicrotask(raf);\n } else {\n raf();\n }\n};\n\n/**\n * Like `setTimeout`, but if `signal` aborts before the delay fires, the timer is cleared\n * and `callback` is never run. If the callback runs normally, the abort listener is removed.\n *\n * Does nothing special if `signal` is omitted — behaves like a plain timeout.\n *\n * @param callback - Function to run once after `delayInMs` (same as `setTimeout` callback).\n * @param delayInMs - Milliseconds to wait. Passed through to `setTimeout` (browser/Node semantics apply).\n * @param signal - When aborted, clears the pending timeout so `callback` is not invoked.\n *\n * @example\n * ```ts\n * const controller = new AbortController();\n * setAbortableTimeout(() => console.log('done'), 500, controller.signal);\n * // later: controller.abort(); // timeout cancelled, log never runs\n * ```\n *\n * @example\n * Zero-delay scheduling that can still be cancelled before the macrotask runs:\n * ```ts\n * const ac = new AbortController();\n * setAbortableTimeout(() => startIntro(), 0, ac.signal);\n * // e.g. on teardown: ac.abort();\n * ```\n */\nexport function setAbortableTimeout(\n callback: VoidFunction,\n delayInMs?: number,\n signal?: AbortSignal,\n) {\n let internalTimer: number | null = null;\n\n const handleAbort = () => {\n if (internalTimer == null) {\n return;\n }\n clearTimeout(internalTimer);\n internalTimer = null;\n };\n\n signal?.addEventListener('abort', handleAbort, { once: true });\n\n internalTimer = setTimeout(() => {\n signal?.removeEventListener('abort', handleAbort);\n callback();\n }, delayInMs);\n}\n\n/**\n * Like `setInterval`, but when `signal` aborts, the interval is cleared with `clearInterval`\n * and `callback` stops being called. If `signal` is omitted, behaves like a normal interval\n * (you must clear it yourself).\n *\n * @param callback - Invoked every `delayInMs` milliseconds until aborted or cleared.\n * @param delayInMs - Interval period in milliseconds (same as `setInterval`).\n * @param signal - Aborting stops the interval and removes the abort listener path from keeping work alive.\n *\n * @example\n * ```ts\n * const controller = new AbortController();\n * setAbortableInterval(() => console.log('tick'), 1000, controller.signal);\n * // stop: controller.abort();\n * ```\n *\n * @example\n * ```ts\n * const ac = new AbortController();\n * setAbortableInterval(syncStatus, 30_000, ac.signal);\n * window.addEventListener('beforeunload', () => ac.abort());\n * ```\n */\nexport function setAbortableInterval(\n callback: VoidFunction,\n delayInMs?: number,\n signal?: AbortSignal,\n) {\n let timer: number | null = null;\n\n const handleAbort = () => {\n if (timer == null) {\n return;\n }\n clearInterval(timer);\n timer = null;\n };\n\n signal?.addEventListener('abort', handleAbort, { once: true });\n\n timer = setInterval(callback, delayInMs);\n}\n\n/**\n * A single interpolated segment in {@link asyncTemplate}.\n *\n * - **Primitives** use `String(value)` for output, except that values matching\n * `value === null || value === undefined || value === false` yield no text (early return in `processTemplatePiece`).\n * Other falsy values such as `0` or `''` are still stringified.\n * - **Arrays** are flattened recursively in order.\n * - **Promises** are awaited; the resolved value is processed the same way.\n * - **Async iterables of primitives** are streamed in order; each yielded value uses the same rules\n * as a standalone primitive (`String(...)`, with `null` / `undefined` / `false` omitted).\n * - **Functions** (thunks): if the piece is a function, it is invoked with **no arguments** (`piece()`), and the return\n * value is processed recursively—so you can defer work or return any other {@link AsyncTemplatePiece} shape\n * (see {@link MaybeFn}). At runtime a thunk may also return a `Promise` of a piece; that is covered by\n * {@link MaybePromise} on each template interpolation.\n */\nexport type AsyncTemplatePiece = MaybeFn<\n | Primitive\n | void\n | AsyncIterable<Primitive>\n | Promise<Primitive>\n | AsyncTemplatePiece[]\n>;\n\n/**\n * Tagged template that builds an async iterable of string chunks (like a streaming template engine).\n *\n * Static template parts are yielded as-is. Each interpolated “piece” can be a primitive, a nested array of pieces,\n * a `Promise` of a piece (including a resolved primitive), an async iterable of primitives, or a\n * **zero-arg function** whose result is processed the same way (see {@link AsyncTemplatePiece} / `MaybeFn`).\n *\n * Interpolation handling matches `processTemplatePiece`: `null`, `undefined`, and `false` add nothing; any other value\n * becomes text via `String(...)`; functions are called once with no arguments before further processing. Collect chunks\n * with `for await...of` or utilities like `Array.fromAsync` where available.\n *\n * @param strings - Cooked template segments from the tag (`strings[0]`, `strings[1]`, …).\n * @param pieces - Values between segments (`pieces[i]` sits between `strings[i]` and `strings[i + 1]`).\n * @returns An async generator yielding string fragments in document order.\n *\n * @example\n * Plain values and promises:\n * ```ts\n * const gen = asyncTemplate`Hello, ${'world'}! Status: ${Promise.resolve(200)}`;\n * let out = '';\n * for await (const chunk of gen) out += chunk;\n * // out === 'Hello, world! Status: 200'\n * ```\n *\n * @example\n * Falsy pieces are omitted (`null`, `undefined`, `false`); arrays flatten recursively:\n * ```ts\n * const gen = asyncTemplate`${null}${false}A${['B', ['C']]}`;\n * const out = await Array.fromAsync(gen).then((parts) => parts.join(''));\n * // out === 'ABC'\n * ```\n *\n * @example\n * Stream from an async iterable (e.g. chunked upstream text):\n * ```ts\n * async function* lines() {\n * yield 'line1\\n';\n * yield 'line2\\n';\n * }\n * const gen = asyncTemplate`Header\\n${lines()}Footer`;\n * ```\n *\n * @example\n * Lazy piece via a thunk (invoked as `piece()`):\n * ```ts\n * let n = 0;\n * const gen = asyncTemplate`count=${() => ++n}`;\n * // first consumption yields \"count=1\", etc.\n * ```\n */\nexport async function* asyncTemplate(\n strings: TemplateStringsArray,\n ...pieces: MaybePromise<AsyncTemplatePiece>[]\n) {\n for (let i = 0; i < strings.length; i++) {\n yield strings[i];\n\n if (i < pieces.length) {\n const piece = pieces[i];\n yield* processTemplatePiece(piece);\n }\n }\n}\n\n/**\n * Resolves a template piece into yielded string chunks.\n *\n * Skips output when `value === null || value === undefined || value === false`.\n * Otherwise awaits promises, flattens arrays, streams async iterables, invokes **functions** with no arguments and\n * recurses on the return value, and uses `String(value)` for primitives.\n */\nasync function* processTemplatePiece(\n piece: MaybePromise<AsyncTemplatePiece>,\n): AsyncGenerator<string, void, unknown> {\n if (piece === null || piece === undefined || piece === false) {\n return;\n }\n\n if (piece instanceof Promise) {\n const resolved = await piece;\n yield* processTemplatePiece(resolved);\n return;\n }\n\n if (Array.isArray(piece)) {\n for (const item of piece) {\n yield* processTemplatePiece(item);\n }\n return;\n }\n\n if (\n typeof piece === 'object' &&\n piece !== null &&\n typeof (piece as AsyncIterable<unknown>)[Symbol.asyncIterator] ===\n 'function'\n ) {\n for await (const item of piece as AsyncIterable<AsyncTemplatePiece>) {\n yield* processTemplatePiece(item);\n }\n return;\n }\n\n if (typeof piece === 'function') {\n yield* processTemplatePiece(piece());\n return;\n }\n\n yield String(piece);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDA,IAAa,SAAS,OAAe,GAAG,WACtC,IAAI,SAAe,SAAS,WAAW;AACrC,KAAI,QAAQ;EACV,MAAM,sBAAsB;AAC1B,gBAAa,QAAQ;AACrB,UAAO,QAAQ,OAAO;;EAExB,MAAM,UAAU,iBAAiB;AAC/B,UAAO,oBAAoB,SAAS,cAAc;AAClD,YAAS;KACR,KAAK;AACR,SAAO,iBAAiB,SAAS,eAAe,EAAE,MAAM,MAAM,CAAC;OAE/D,YAAW,SAAS,KAAK;EAE3B;;;;;;;;AASJ,IAAa,YAAY,OAAO,KAAK,QACnC,IAAI,SAAS,YAAY,WAAW,SAAS,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCnD,IAAa,cACX,cACA,gBACG;AACH,KAAI,cAAc,CAAE;CAEpB,MAAM,YACJ,4BAA4B,WAAW,cAAc,YAAY,CAAC;AAEpE,KAAI,YACF,gBAAe,IAAI;KAEnB,MAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BT,SAAgB,oBACd,UACA,WACA,QACA;CACA,IAAI,gBAA+B;CAEnC,MAAM,oBAAoB;AACxB,MAAI,iBAAiB,KACnB;AAEF,eAAa,cAAc;AAC3B,kBAAgB;;AAGlB,SAAQ,iBAAiB,SAAS,aAAa,EAAE,MAAM,MAAM,CAAC;AAE9D,iBAAgB,iBAAiB;AAC/B,UAAQ,oBAAoB,SAAS,YAAY;AACjD,YAAU;IACT,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;AA0Bf,SAAgB,qBACd,UACA,WACA,QACA;CACA,IAAI,QAAuB;CAE3B,MAAM,oBAAoB;AACxB,MAAI,SAAS,KACX;AAEF,gBAAc,MAAM;AACpB,UAAQ;;AAGV,SAAQ,iBAAiB,SAAS,aAAa,EAAE,MAAM,MAAM,CAAC;AAE9D,SAAQ,YAAY,UAAU,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4E1C,gBAAuB,cACrB,SACA,GAAG,QACH;AACA,MAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,QAAM,QAAQ;AAEd,MAAI,IAAI,OAAO,QAAQ;GACrB,MAAM,QAAQ,OAAO;AACrB,UAAO,qBAAqB,MAAM;;;;;;;;;;;AAYxC,gBAAgB,qBACd,OACuC;AACvC,KAAI,UAAU,QAAQ,UAAU,KAAA,KAAa,UAAU,MACrD;AAGF,KAAI,iBAAiB,SAAS;AAE5B,SAAO,qBADU,MAAM,MACc;AACrC;;AAGF,KAAI,MAAM,QAAQ,MAAM,EAAE;AACxB,OAAK,MAAM,QAAQ,MACjB,QAAO,qBAAqB,KAAK;AAEnC;;AAGF,KACE,OAAO,UAAU,YACjB,UAAU,QACV,OAAQ,MAAiC,OAAO,mBAC9C,YACF;AACA,aAAW,MAAM,QAAQ,MACvB,QAAO,qBAAqB,KAAK;AAEnC;;AAGF,KAAI,OAAO,UAAU,YAAY;AAC/B,SAAO,qBAAqB,OAAO,CAAC;AACpC;;AAGF,OAAM,OAAO,MAAM"}
|
|
1
|
+
{"version":3,"file":"async.cjs","names":[],"sources":["../src/async/async-template.ts","../src/async/endless-raf.ts","../src/async/set-abortable-interval.ts","../src/async/set-abortable-timeout.ts","../src/async/sleep.ts","../src/async/wait-async.ts"],"sourcesContent":["import type { MaybePromise } from 'yummies/types';\n\nimport type { AsyncTemplatePiece } from './async-template-piece.js';\n\n/**\n * Tagged template that builds an async iterable of string chunks (like a streaming template engine).\n *\n * Static template parts are yielded as-is. Each interpolated “piece” can be a primitive, a nested array of pieces,\n * a `Promise` of a piece (including a resolved primitive), an async iterable of primitives, or a\n * **zero-arg function** whose result is processed the same way (see {@link AsyncTemplatePiece} / `MaybeFn`).\n *\n * Interpolation handling matches `processTemplatePiece`: `null`, `undefined`, and `false` add nothing; any other value\n * becomes text via `String(...)`; functions are called once with no arguments before further processing. Collect chunks\n * with `for await...of` or utilities like `Array.fromAsync` where available.\n *\n * @param strings - Cooked template segments from the tag (`strings[0]`, `strings[1]`, …).\n * @param pieces - Values between segments (`pieces[i]` sits between `strings[i]` and `strings[i + 1]`).\n * @returns An async generator yielding string fragments in document order.\n *\n * @example\n * Plain values and promises:\n * ```ts\n * const gen = asyncTemplate`Hello, ${'world'}! Status: ${Promise.resolve(200)}`;\n * let out = '';\n * for await (const chunk of gen) out += chunk;\n * // out === 'Hello, world! Status: 200'\n * ```\n *\n * @example\n * Falsy pieces are omitted (`null`, `undefined`, `false`); arrays flatten recursively:\n * ```ts\n * const gen = asyncTemplate`${null}${false}A${['B', ['C']]}`;\n * const out = await Array.fromAsync(gen).then((parts) => parts.join(''));\n * // out === 'ABC'\n * ```\n *\n * @example\n * Stream from an async iterable (e.g. chunked upstream text):\n * ```ts\n * async function* lines() {\n * yield 'line1\\n';\n * yield 'line2\\n';\n * }\n * const gen = asyncTemplate`Header\\n${lines()}Footer`;\n * ```\n *\n * @example\n * Lazy piece via a thunk (invoked as `piece()`):\n * ```ts\n * let n = 0;\n * const gen = asyncTemplate`count=${() => ++n}`;\n * // first consumption yields \"count=1\", etc.\n * ```\n */\nexport async function* asyncTemplate(\n strings: TemplateStringsArray,\n ...pieces: MaybePromise<AsyncTemplatePiece>[]\n) {\n for (let i = 0; i < strings.length; i++) {\n yield strings[i];\n\n if (i < pieces.length) {\n const piece = pieces[i];\n yield* processTemplatePiece(piece);\n }\n }\n}\n\n/**\n * Resolves a template piece into yielded string chunks.\n *\n * Skips output when `value === null || value === undefined || value === false`.\n * Otherwise awaits promises, flattens arrays, streams async iterables, invokes **functions** with no arguments and\n * recurses on the return value, and uses `String(value)` for primitives.\n */\nasync function* processTemplatePiece(\n piece: MaybePromise<AsyncTemplatePiece>,\n): AsyncGenerator<string, void, unknown> {\n if (piece === null || piece === undefined || piece === false) {\n return;\n }\n\n if (piece instanceof Promise) {\n const resolved = await piece;\n yield* processTemplatePiece(resolved);\n return;\n }\n\n if (Array.isArray(piece)) {\n for (const item of piece) {\n yield* processTemplatePiece(item);\n }\n return;\n }\n\n if (\n typeof piece === 'object' &&\n piece !== null &&\n typeof (piece as AsyncIterable<unknown>)[Symbol.asyncIterator] ===\n 'function'\n ) {\n for await (const item of piece as AsyncIterable<AsyncTemplatePiece>) {\n yield* processTemplatePiece(item);\n }\n return;\n }\n\n if (typeof piece === 'function') {\n yield* processTemplatePiece(piece());\n return;\n }\n\n yield String(piece);\n}\n","/**\n * Runs a loop driven by `requestAnimationFrame`: on each frame, `quitFunction` is called first.\n * If it returns a truthy value, the loop stops and no further frames are scheduled.\n * If it returns falsy or nothing, the next frame is scheduled recursively.\n *\n * Use this for per-frame work (animations, layout reads after paint) without managing\n * `cancelAnimationFrame` manually — returning `true` from `quitFunction` is the exit condition.\n *\n * When `asMicrotask` is `true`, scheduling the next RAF is deferred with `queueMicrotask`\n * so other microtasks can run before the frame is requested (useful when you need to\n * batch DOM updates or let reactive frameworks flush first).\n *\n * @param quitFunction - Invoked each animation frame. Return `true` to stop the loop.\n * @param asMicrotask - If `true`, wrap the `requestAnimationFrame` call in `queueMicrotask`.\n *\n * @example\n * Stop after 60 frames (~1s at 60Hz):\n * ```ts\n * let frames = 0;\n * endlessRAF(() => {\n * frames++;\n * updateSomething(frames);\n * return frames >= 60;\n * });\n * ```\n *\n * @example\n * Run until an element is removed or a flag is set:\n * ```ts\n * let running = true;\n * endlessRAF(() => {\n * if (!running || !document.body.contains(el)) return true;\n * draw(el);\n * }, true);\n * ```\n */\nexport const endlessRAF = (\n quitFunction: () => boolean | void,\n asMicrotask?: boolean,\n) => {\n if (quitFunction()) return;\n\n const raf = () =>\n requestAnimationFrame(() => endlessRAF(quitFunction, asMicrotask));\n\n if (asMicrotask) {\n queueMicrotask(raf);\n } else {\n raf();\n }\n};\n","/**\n * Like `setInterval`, but when `signal` aborts, the interval is cleared with `clearInterval`\n * and `callback` stops being called. If `signal` is omitted, behaves like a normal interval\n * (you must clear it yourself).\n *\n * @param callback - Invoked every `delayInMs` milliseconds until aborted or cleared.\n * @param delayInMs - Interval period in milliseconds (same as `setInterval`).\n * @param signal - Aborting stops the interval and removes the abort listener path from keeping work alive.\n *\n * @example\n * ```ts\n * const controller = new AbortController();\n * setAbortableInterval(() => console.log('tick'), 1000, controller.signal);\n * // stop: controller.abort();\n * ```\n *\n * @example\n * ```ts\n * const ac = new AbortController();\n * setAbortableInterval(syncStatus, 30_000, ac.signal);\n * window.addEventListener('beforeunload', () => ac.abort());\n * ```\n */\nexport function setAbortableInterval(\n callback: VoidFunction,\n delayInMs?: number,\n signal?: AbortSignal,\n) {\n let timer: number | null = null;\n\n const handleAbort = () => {\n if (timer == null) {\n return;\n }\n clearInterval(timer);\n timer = null;\n };\n\n signal?.addEventListener('abort', handleAbort, { once: true });\n\n timer = setInterval(callback, delayInMs);\n}\n","/**\n * Like `setTimeout`, but if `signal` aborts before the delay fires, the timer is cleared\n * and `callback` is never run. If the callback runs normally, the abort listener is removed.\n *\n * Does nothing special if `signal` is omitted — behaves like a plain timeout.\n *\n * @param callback - Function to run once after `delayInMs` (same as `setTimeout` callback).\n * @param delayInMs - Milliseconds to wait. Passed through to `setTimeout` (browser/Node semantics apply).\n * @param signal - When aborted, clears the pending timeout so `callback` is not invoked.\n *\n * @example\n * ```ts\n * const controller = new AbortController();\n * setAbortableTimeout(() => console.log('done'), 500, controller.signal);\n * // later: controller.abort(); // timeout cancelled, log never runs\n * ```\n *\n * @example\n * Zero-delay scheduling that can still be cancelled before the macrotask runs:\n * ```ts\n * const ac = new AbortController();\n * setAbortableTimeout(() => startIntro(), 0, ac.signal);\n * // e.g. on teardown: ac.abort();\n * ```\n */\nexport function setAbortableTimeout(\n callback: VoidFunction,\n delayInMs?: number,\n signal?: AbortSignal,\n) {\n let internalTimer: number | null = null;\n\n const handleAbort = () => {\n if (internalTimer == null) {\n return;\n }\n clearTimeout(internalTimer);\n internalTimer = null;\n };\n\n signal?.addEventListener('abort', handleAbort, { once: true });\n\n internalTimer = setTimeout(() => {\n signal?.removeEventListener('abort', handleAbort);\n callback();\n }, delayInMs);\n}\n","/**\n * Returns a promise that resolves after `time` milliseconds.\n *\n * When `signal` is passed and becomes aborted before the delay elapses, the promise\n * rejects with `signal.reason` (same as native `fetch` / `AbortController` usage).\n * The timeout is cleared on abort so no resolve happens after cancellation.\n *\n * @param time - Delay in milliseconds. Defaults to `0` (next macrotask tick, same idea as `setTimeout(0)`).\n * @param signal - Optional `AbortSignal` to cancel the wait early.\n * @returns A promise that resolves with `void` when the delay completes, or rejects if aborted.\n *\n * @example\n * Basic pause in an async function:\n * ```ts\n * await sleep(250);\n * console.log('after 250ms');\n * ```\n *\n * @example\n * Cancellable delay tied to component unmount or user action:\n * ```ts\n * const ac = new AbortController();\n * try {\n * await sleep(5000, ac.signal);\n * } catch (e) {\n * // aborted — e is signal.reason\n * }\n * ac.abort('user cancelled');\n * ```\n */\nexport const sleep = (time: number = 0, signal?: AbortSignal) =>\n new Promise<void>((resolve, reject) => {\n if (signal) {\n const abortListener = () => {\n clearTimeout(timerId);\n reject(signal?.reason);\n };\n const timerId = setTimeout(() => {\n signal.removeEventListener('abort', abortListener);\n resolve();\n }, time);\n signal.addEventListener('abort', abortListener, { once: true });\n } else {\n setTimeout(resolve, time);\n }\n });\n","import { sleep } from './sleep.js';\n\n/**\n * Creates a promise that resolves after the specified number of milliseconds.\n *\n * @deprecated Use `sleep` instead.\n * @param ms Delay in milliseconds.\n * @returns Promise\n */\nexport const waitAsync = (ms = 1000) => sleep(ms);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsDA,gBAAuB,cACrB,SACA,GAAG,QACH;CACA,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;EACvC,MAAM,QAAQ;EAEd,IAAI,IAAI,OAAO,QAAQ;GACrB,MAAM,QAAQ,OAAO;GACrB,OAAO,qBAAqB,KAAK;EACnC;CACF;AACF;;;;;;;;AASA,gBAAgB,qBACd,OACuC;CACvC,IAAI,UAAU,QAAQ,UAAU,KAAA,KAAa,UAAU,OACrD;CAGF,IAAI,iBAAiB,SAAS;EAE5B,OAAO,qBAAqB,MADL,KACa;EACpC;CACF;CAEA,IAAI,MAAM,QAAQ,KAAK,GAAG;EACxB,KAAK,MAAM,QAAQ,OACjB,OAAO,qBAAqB,IAAI;EAElC;CACF;CAEA,IACE,OAAO,UAAU,YACjB,UAAU,QACV,OAAQ,MAAiC,OAAO,mBAC9C,YACF;EACA,WAAW,MAAM,QAAQ,OACvB,OAAO,qBAAqB,IAAI;EAElC;CACF;CAEA,IAAI,OAAO,UAAU,YAAY;EAC/B,OAAO,qBAAqB,MAAM,CAAC;EACnC;CACF;CAEA,MAAM,OAAO,KAAK;AACpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC7EA,IAAa,cACX,cACA,gBACG;CACH,IAAI,aAAa,GAAG;CAEpB,MAAM,YACJ,4BAA4B,WAAW,cAAc,WAAW,CAAC;CAEnE,IAAI,aACF,eAAe,GAAG;MAElB,IAAI;AAER;;;;;;;;;;;;;;;;;;;;;;;;;;AC3BA,SAAgB,qBACd,UACA,WACA,QACA;CACA,IAAI,QAAuB;CAE3B,MAAM,oBAAoB;EACxB,IAAI,SAAS,MACX;EAEF,cAAc,KAAK;EACnB,QAAQ;CACV;CAEA,QAAQ,iBAAiB,SAAS,aAAa,EAAE,MAAM,KAAK,CAAC;CAE7D,QAAQ,YAAY,UAAU,SAAS;AACzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;AChBA,SAAgB,oBACd,UACA,WACA,QACA;CACA,IAAI,gBAA+B;CAEnC,MAAM,oBAAoB;EACxB,IAAI,iBAAiB,MACnB;EAEF,aAAa,aAAa;EAC1B,gBAAgB;CAClB;CAEA,QAAQ,iBAAiB,SAAS,aAAa,EAAE,MAAM,KAAK,CAAC;CAE7D,gBAAgB,iBAAiB;EAC/B,QAAQ,oBAAoB,SAAS,WAAW;EAChD,SAAS;CACX,GAAG,SAAS;AACd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AChBA,IAAa,SAAS,OAAe,GAAG,WACtC,IAAI,SAAe,SAAS,WAAW;CACrC,IAAI,QAAQ;EACV,MAAM,sBAAsB;GAC1B,aAAa,OAAO;GACpB,OAAO,QAAQ,MAAM;EACvB;EACA,MAAM,UAAU,iBAAiB;GAC/B,OAAO,oBAAoB,SAAS,aAAa;GACjD,QAAQ;EACV,GAAG,IAAI;EACP,OAAO,iBAAiB,SAAS,eAAe,EAAE,MAAM,KAAK,CAAC;CAChE,OACE,WAAW,SAAS,IAAI;AAE5B,CAAC;;;;;;;;;;ACpCH,IAAa,aAAa,KAAK,QAAS,MAAM,EAAE"}
|