@simpill/utils 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/CONTRIBUTING.md +787 -0
  2. package/README.md +186 -0
  3. package/__tests__/README.md +32 -0
  4. package/__tests__/e2e/all-packages-resolve.e2e.test.ts +40 -0
  5. package/__tests__/integration/env-and-async.integration.test.ts +12 -0
  6. package/__tests__/integration/errors-and-uuid.integration.test.ts +14 -0
  7. package/__tests__/integration/object-and-array.integration.test.ts +15 -0
  8. package/__tests__/unit/@simpill/_resolver/resolve-packages.unit.test.ts +47 -0
  9. package/__tests__/unit/@simpill/array.utils/array.utils.unit.test.ts +11 -0
  10. package/__tests__/unit/@simpill/async.utils/async.utils.unit.test.ts +12 -0
  11. package/__tests__/unit/@simpill/cache.utils/cache.utils.unit.test.ts +21 -0
  12. package/__tests__/unit/@simpill/env.utils/env.utils.unit.test.ts +13 -0
  13. package/__tests__/unit/@simpill/errors.utils/errors.utils.unit.test.ts +13 -0
  14. package/__tests__/unit/@simpill/object.utils/object.utils.unit.test.ts +11 -0
  15. package/__tests__/unit/@simpill/patterns.utils/patterns.utils.unit.test.ts +23 -0
  16. package/__tests__/unit/@simpill/string.utils/string.utils.unit.test.ts +11 -0
  17. package/__tests__/unit/@simpill/time.utils/time.utils.unit.test.ts +12 -0
  18. package/__tests__/unit/@simpill/uuid.utils/uuid.utils.unit.test.ts +12 -0
  19. package/docs/PUBLISHING_AND_PACKAGES.md +258 -0
  20. package/docs/template/.env.sample +0 -0
  21. package/docs/template/README.md +0 -0
  22. package/docs/template/TEMPLATE.md +1040 -0
  23. package/docs/template/assets/logo-banner.svg +20 -0
  24. package/docs/template/package.json +14 -0
  25. package/index.ts +89 -0
  26. package/package.json +87 -0
  27. package/scripts/README.md +57 -0
  28. package/scripts/github/github-set-all-topics.js +120 -0
  29. package/scripts/github/github-set-repo-topics.sh +33 -0
  30. package/scripts/github/github-set-repos-public.sh +71 -0
  31. package/scripts/lib/package-topics.js +57 -0
  32. package/scripts/lib/publish-order.js +140 -0
  33. package/scripts/lib/sync-repo-links.js +75 -0
  34. package/scripts/monorepo/install-hooks.sh +64 -0
  35. package/scripts/monorepo/monorepo-clean.sh +7 -0
  36. package/scripts/monorepo/monorepo-sync-deps.js +81 -0
  37. package/scripts/monorepo/monorepo-verify-deps.js +37 -0
  38. package/scripts/monorepo/use-local-utils-at-root.js +49 -0
  39. package/scripts/publish/publish-all.sh +152 -0
  40. package/scripts/utils/utils-fix-repo-metadata.js +61 -0
  41. package/scripts/utils/utils-prepare-all.sh +107 -0
  42. package/scripts/utils/utils-set-npm-keywords.js +132 -0
  43. package/scripts/utils/utils-update-readme-badges.js +83 -0
  44. package/scripts/utils/utils-use-local-deps.js +43 -0
  45. package/scripts/utils/utils-verify-all.sh +45 -0
  46. package/tsconfig.json +14 -0
package/README.md ADDED
@@ -0,0 +1,186 @@
1
+ <p align="center">
2
+ <img src="./logo.png" alt="@simpill" width="100%" />
3
+ </p>
4
+
5
+ <p align="center">
6
+ <strong>A collection of lightweight, type-safe TypeScript utility packages for modern JavaScript applications.</strong>
7
+ </p>
8
+
9
+ <p align="center">
10
+ <a href="#philosophy">Philosophy</a> •
11
+ <a href="#repositories">Repositories</a> •
12
+ <a href="#quick-start">Quick Start</a> •
13
+ <a href="#discoverability">Discoverability</a> •
14
+ <a href="#credits-and-inspiration">Credits</a>
15
+ </p>
16
+
17
+ ---
18
+
19
+ ## Philosophy
20
+
21
+ - **Minimal** — Each package does one thing well with minimal dependencies.
22
+ - **Type-safe** — Full TypeScript support with strict mode enabled.
23
+ - **Tested** — 80%+ code coverage required for all packages.
24
+ - **Consistent** — Unified code style, structure, and tooling across all packages.
25
+
26
+ Each package is published under the `@simpill` scope on npm. Source code lives in **separate GitHub repositories**; this repo is the landing page and index.
27
+
28
+ ---
29
+
30
+ ## Repositories
31
+
32
+ Each package has its own repository. Click through for source, README, and contribution instructions.
33
+
34
+ | Package | Description | Status |
35
+ |---------|-------------|--------|
36
+ | [**adapters.utils**](https://github.com/SkinnnyJay/adapters.utils) | Adapter helpers, logger and cache adapter interfaces (Node and Edge). | New |
37
+ | [**algorithms.utils**](https://github.com/SkinnnyJay/algorithms.utils) | Algorithms: stable merge sort, quick sort, binary search, lower/upper bound (Node and Edge). | New |
38
+ | [**annotations.utils**](https://github.com/SkinnnyJay/annotations.utils) | Typed metadata store and annotation helpers for symbols and keys (Node and Edge). | New |
39
+ | [**api.utils**](https://github.com/SkinnnyJay/api.utils) | Typed API client with Zod validation, handler registry, and middleware (Node and Edge). | New |
40
+ | [**array.utils**](https://github.com/SkinnnyJay/array.utils) | Array utilities: unique, chunk, compact, groupBy, sortBy, flattenOnce (Node and Edge). | New |
41
+ | [**async.utils**](https://github.com/SkinnnyJay/async.utils) | Retry failed promises with timeout, delay, and backoff; limit concurrency with Semaphore (Node and Edge). | New |
42
+ | [**cache.utils**](https://github.com/SkinnnyJay/cache.utils) | In-memory LRU and TTL cache with memoize; small and tree-shakeable (Node and Edge). | New |
43
+ | [**collections.utils**](https://github.com/SkinnnyJay/collections.utils) | Type-safe LinkedList, Queue, Stack, LRU/TTL, MultiMap, BiMap—no full collections lib (Node and Edge). | New |
44
+ | [**crypto.utils**](https://github.com/SkinnnyJay/crypto.utils) | Hash, randomBytes, and timing-safe compare for Node.js. | New |
45
+ | [**data.utils**](https://github.com/SkinnnyJay/data.utils) | Data utilities: validate, prepare, lifecycle, extend, config (Node and Edge). | New |
46
+ | [**env.utils**](https://github.com/SkinnnyJay/env.utils) | Lightweight, type-safe environment variable utilities for Node.js and Edge Runtime. | Stable |
47
+ | [**enum.utils**](https://github.com/SkinnnyJay/enum.utils) | Enum helpers: getEnumValue, isValidEnumValue, EnumHelper (Node and Edge). | New |
48
+ | [**errors.utils**](https://github.com/SkinnnyJay/errors.utils) | Typed error classes, error codes, and serializeError for logging and RPC (Node and Edge). | New |
49
+ | [**events.utils**](https://github.com/SkinnnyJay/events.utils) | PubSub, observer, and typed event emitter (Node and Edge). | New |
50
+ | [**factories.utils**](https://github.com/SkinnnyJay/factories.utils) | Typed factory builder, singleton factory, and error factory helpers (Node and Edge). | New |
51
+ | [**file.utils**](https://github.com/SkinnnyJay/file.utils) | Typed file I/O: readFileUtf8, readFileJson, writeFile, ensureDir for Node.js. | New |
52
+ | [**function.utils**](https://github.com/SkinnnyJay/function.utils) | Debounce, throttle, once, pipe, and compose with TypeScript inference (Node and Edge). | New |
53
+ | [**http.utils**](https://github.com/SkinnnyJay/http.utils) | Fetch with timeout, retry, and typed HTTP client—no axios required (Node and Edge). | New |
54
+ | [**ai-image-generated-ai-cli**](https://github.com/simpill/ai-image-generated-ai-cli) | Image AI toolkit: core SDK, CLI (`ai-image-gen`), and prompt discovery web UI (Gemini, OpenAI, xAI). | New |
55
+ | [**logger.utils**](https://github.com/SkinnnyJay/logger.utils) | Lightweight, type-safe structured logging with correlation context for Node.js and Edge Runtime. | In Development |
56
+ | [**middleware.utils**](https://github.com/SkinnnyJay/middleware.utils) | Framework-agnostic middleware types and correlation ID middleware (Node and Edge). | New |
57
+ | [**misc.utils**](https://github.com/SkinnnyJay/misc.utils) | Backend misc: singleton, debounce, throttle, LRU, polling, intervals, enums, once, memoize (Node and Edge). | New |
58
+ | [**nextjs.utils**](https://github.com/SkinnnyJay/nextjs.utils) | Next.js App Router helpers: safe server actions, route handlers, request context, middleware. | New |
59
+ | [**number.utils**](https://github.com/SkinnnyJay/number.utils) | Number utilities: clamp, roundTo, toInt/Float, isInRange, lerp, sum, avg (Node and Edge). | New |
60
+ | [**object.utils**](https://github.com/SkinnnyJay/object.utils) | Type-safe object utilities: pick, omit, merge, get/set by path, guards (Node and Edge). | Stable |
61
+ | [**observability.utils**](https://github.com/SkinnnyJay/observability.utils) | Single integration surface for correlation middleware, request context, and logger (Node). | New |
62
+ | [**patterns.utils**](https://github.com/SkinnnyJay/patterns.utils) | Composable design patterns: Result/Either, strategySelector, pipeAsync (Node and Edge). | New |
63
+ | [**protocols.utils**](https://github.com/SkinnnyJay/protocols.utils) | Shared protocol constants and types for HTTP, correlation, and env parsing (Node and Edge). | New |
64
+ | [**react.utils**](https://github.com/SkinnnyJay/react.utils) | Framework-agnostic React utilities: hooks, safe context, stable callbacks, transitions. | New |
65
+ | [**request-context.utils**](https://github.com/SkinnnyJay/request-context.utils) | AsyncLocalStorage request context (requestId, traceId) for Node.js logging and tracing. | New |
66
+ | [**resilience.utils**](https://github.com/SkinnnyJay/resilience.utils) | Circuit breaker, rate limiter, bulkhead, and jittered backoff for fault-tolerant APIs (Node and Edge). | New |
67
+ | [**socket.utils**](https://github.com/SkinnnyJay/socket.utils) | Reconnecting WebSocket client with optional heartbeat (Node and Edge). | New |
68
+ | [**string.utils**](https://github.com/SkinnnyJay/string.utils) | String utilities: formatting, casing, trim, slugify (Node and Edge). | New |
69
+ | [**test.utils**](https://github.com/SkinnnyJay/test.utils) | Test patterns, faker wrapper, enricher, and test-runner helpers (Node and Edge). | New |
70
+ | [**time.utils**](https://github.com/SkinnnyJay/time.utils) | Time utilities: debounce, throttle, interval manager, managed timeout (Node and Edge). | Stable |
71
+ | [**token-optimizer.utils**](https://github.com/SkinnnyJay/token-optimizer.utils) | Token optimization utilities: cleaning, strategies, telemetry (Node and Edge). | New |
72
+ | [**uuid.utils**](https://github.com/SkinnnyJay/uuid.utils) | Generate and validate UUIDs (v1/v4/v5) with full TypeScript support (Node and Edge). | Stable |
73
+ | [**zod.utils**](https://github.com/SkinnnyJay/zod.utils) | Zod schema helpers: builders, safe-parse, transforms, OpenAPI metadata (Node and Edge). | New |
74
+ | [**zustand.utils**](https://github.com/SkinnnyJay/zustand.utils) | Zustand store helpers: factory, persist, devtools, slices (Node and Edge). | New |
75
+
76
+ ---
77
+
78
+ ## Quick Start
79
+
80
+ Install any package from npm:
81
+
82
+ ```bash
83
+ npm install @simpill/env.utils
84
+ npm install @simpill/logger.utils
85
+ npm install @simpill/cache.utils
86
+ npm install @simpill/async.utils
87
+ npm install @simpill/function.utils
88
+ npm install @simpill/string.utils
89
+ ```
90
+
91
+ Use the **Repositories** table above to open a package’s GitHub repo for docs, API reference, and examples.
92
+
93
+ **Consumption:** Every package is consumable **separately** (npm or `github:SkinnnyJay/<repo>`) and **via @simpill/utils** (run `npm install` at root; all packages land in `node_modules`). Run `npm run verify:deps` to confirm. **No `utils/` folder is required**—package source lives in the GitHub repos above; this repo pulls them in via dependencies. You can remove `utils/` if present.
94
+
95
+ ### Use the main repo in another project
96
+
97
+ The main project references all util packages via GitHub. To pull in the full set of utils from this repo into another project, add the monorepo as a dependency:
98
+
99
+ ```bash
100
+ npm install github:SkinnnyJay/simpill-utils
101
+ ```
102
+
103
+ (or add `"@simpill/utils": "github:SkinnnyJay/simpill-utils"` to your `package.json`). Installing it will fetch each util from its GitHub repo (`github:SkinnnyJay/adapters.utils`, etc.) so you can import any util in your code:
104
+
105
+ ```ts
106
+ import { createAdapter } from "@simpill/adapters.utils";
107
+ import { unique } from "@simpill/array.utils";
108
+ import { getEnvString } from "@simpill/env.utils";
109
+ ```
110
+
111
+ To depend on only one util, install that package from npm or GitHub (e.g. `npm install @simpill/adapters.utils` or `npm install github:SkinnnyJay/adapters.utils`).
112
+
113
+ ### Using @simpill/utils (this repo)
114
+
115
+ Clone and install from the repo root. All @simpill utils are installed from GitHub into `node_modules` and are usable as-is (e.g. `@simpill/env.utils` ships `dist/` in its repo):
116
+
117
+ ```bash
118
+ npm install
119
+ ```
120
+
121
+ Then any script or app at the repo root can require/import them, e.g.:
122
+
123
+ ```js
124
+ const { getEdgeString } = require("@simpill/env.utils/client");
125
+ const { unique } = require("@simpill/array.utils");
126
+ ```
127
+
128
+ To confirm all installed packages are resolvable and load correctly:
129
+
130
+ ```bash
131
+ npm run verify:deps
132
+ npm test
133
+ ```
134
+
135
+ `npm test` imports all 38 @simpill packages and prints NODE_ENV; if any package failed to install (e.g. empty folder), re-run `npm install` or `rm -rf node_modules && npm install`.
136
+
137
+ **Sandbox apps** (e.g. todo-app) live in a separate repo: [simpill-sandbox](https://github.com/simpill/simpill-sandbox). To develop individual util packages, clone their GitHub repos (see [Repositories](#repositories) table).
138
+
139
+ ---
140
+
141
+ ## Discoverability
142
+
143
+ - **GitHub:** Add topics (e.g. `simpill`, `typescript`, `utilities`, `nodejs`, `edge-runtime`) so the org and repos appear in search. See [.github/TOPICS.md](./.github/TOPICS.md) for a full list.
144
+ - **npm:** Every package lists `simpill` and package-specific keywords. Use `npm search simpill` to find all published packages.
145
+
146
+ ---
147
+
148
+ ## Documentation
149
+
150
+ - [CONTRIBUTING.md](./CONTRIBUTING.md) — How to create and maintain packages (and where they live).
151
+
152
+ ---
153
+
154
+ ## Credits and inspiration
155
+
156
+ We build on and are inspired by the following projects and standards.
157
+
158
+ ### Dependencies
159
+
160
+ Packages depend on these core libraries (each link goes to the official repository):
161
+
162
+ | Library | Use in @simpill | Repository |
163
+ |--------|------------------|------------|
164
+ | [Zod](https://github.com/colinhacks/zod) | Schema validation, API types, safe parsing | [colinhacks/zod](https://github.com/colinhacks/zod) |
165
+ | [Zustand](https://github.com/pmndrs/zustand) | Store factory, persist, devtools | [pmndrs/zustand](https://github.com/pmndrs/zustand) |
166
+ | [Next.js](https://github.com/vercel/next.js) | App Router, server actions, middleware | [vercel/next.js](https://github.com/vercel/next.js) |
167
+ | [React](https://github.com/facebook/react) | Hooks, context, transitions | [facebook/react](https://github.com/facebook/react) |
168
+ | [uuid](https://github.com/uuidjs/uuid) | UUID v1/v4/v5 generation and validation | [uuidjs/uuid](https://github.com/uuidjs/uuid) |
169
+ | [Faker](https://github.com/faker-js/faker) | Test data and mocks | [faker-js/faker](https://github.com/faker-js/faker) |
170
+ | [Biome](https://github.com/biomejs/biome) | Linting and formatting (dev) | [biomejs/biome](https://github.com/biomejs/biome) |
171
+ | [Jest](https://github.com/jestjs/jest) | Unit and integration tests (dev) | [jestjs/jest](https://github.com/jestjs/jest) |
172
+ | [TypeScript](https://github.com/microsoft/TypeScript) | Type checking and emit | [microsoft/TypeScript](https://github.com/microsoft/TypeScript) |
173
+
174
+ ### Inspiration and prior art
175
+
176
+ - [Lodash](https://github.com/lodash/lodash) — Array, object, and function utility patterns.
177
+ - [Vercel](https://github.com/vercel) — Next.js, [t3-env](https://github.com/t3-oss/t3-env), and server/edge patterns.
178
+ - [Node.js](https://github.com/nodejs/node) — [AsyncLocalStorage](https://nodejs.org/api/async_context.html#class-asynclocalstorage), `fs`, and runtime separation.
179
+ - [RFC 4122](https://www.rfc-editor.org/rfc/rfc4122) — UUID specification.
180
+ - [TC39](https://github.com/tc39) — ECMAScript and standard library evolution.
181
+
182
+ ---
183
+
184
+ ## License
185
+
186
+ ISC
@@ -0,0 +1,32 @@
1
+ # Monorepo tests
2
+
3
+ Vitest runs unit, integration, and e2e tests for the @simpill monorepo.
4
+
5
+ ## Prerequisites
6
+
7
+ - Run `npm install` at repo root so all `@simpill/*` packages and devDependencies (vitest, vite, typescript, tsx, std-env) are installed.
8
+ - **To run root build, test.ts (smoke), and Vitest against built packages:** root normally installs packages from GitHub (which may not include built `dist/`). To use your local utils instead:
9
+ 1. `npm run utils:prepare` — build all utils packages (install, audit, typecheck, test, build).
10
+ 2. `npm run use:local` — point root at `file:./utils/@simpill-*.utils` and run `npm install`.
11
+ 3. Then `npm run build`, `npm run test:smoke`, and `npm test` use the local built packages.
12
+ - To restore root to GitHub deps: `npm run sync:deps`, then `npm install`.
13
+
14
+ ## Commands
15
+
16
+ From repo root:
17
+
18
+ - `npm test` — run all tests
19
+ - `npm run test:unit` — `__tests__/unit` only
20
+ - `npm run test:integration` — `__tests__/integration` only
21
+ - `npm run test:e2e` — `__tests__/e2e` only
22
+
23
+ ## Layout
24
+
25
+ - **unit** — per-package resolution and behavior: `__tests__/unit/@simpill/<package>/`.
26
+ - **unit/_resolver** — dynamic resolution of packages that do not have a dedicated unit test file.
27
+ - **integration** — cross-package flows (e.g. env + async, errors + uuid, object + array).
28
+ - **e2e** — critical path: core packages resolve and work together (env, uuid, object, array, errors, time).
29
+
30
+ ## Config
31
+
32
+ `vitest.config.ts` at repo root: Node environment, globals, `__tests__/**/*.test.ts`.
@@ -0,0 +1,40 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { getEdgeString } from "@simpill/env.utils/client";
3
+ import * as Env from "@simpill/env.utils";
4
+ import * as Uuid from "@simpill/uuid.utils";
5
+ import * as ObjectUtils from "@simpill/object.utils";
6
+ import * as Async from "@simpill/async.utils";
7
+ import * as ArrayUtils from "@simpill/array.utils";
8
+ import * as Errors from "@simpill/errors.utils";
9
+ import * as Time from "@simpill/time.utils";
10
+
11
+ describe("E2E: all critical packages resolve and work", () => {
12
+ it("env client getEdgeString returns string", () => {
13
+ expect(getEdgeString("NODE_ENV", "development")).toBeDefined();
14
+ });
15
+
16
+ it("all listed packages are non-null", () => {
17
+ const packages: Record<string, unknown> = {
18
+ Env,
19
+ Uuid,
20
+ ObjectUtils,
21
+ Async,
22
+ ArrayUtils,
23
+ Errors,
24
+ Time,
25
+ };
26
+ for (const [name, mod] of Object.entries(packages)) {
27
+ expect(mod, `Package ${name} should resolve`).not.toBeNull();
28
+ expect(mod, `Package ${name} should be object`).toBeDefined();
29
+ }
30
+ });
31
+
32
+ it("cross-package flow: uuid in object pick and array unique", () => {
33
+ const id = Uuid.generateUUID();
34
+ const record = { id, name: "a" };
35
+ const picked = ObjectUtils.pick(record, ["id"]);
36
+ const keys = ArrayUtils.unique(Object.keys(picked));
37
+ expect(keys).toContain("id");
38
+ expect(Uuid.isUUID(picked.id as string)).toBe(true);
39
+ });
40
+ });
@@ -0,0 +1,12 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { getEdgeString } from "@simpill/env.utils/client";
3
+ import { delay } from "@simpill/async.utils";
4
+
5
+ describe("env.utils + async.utils integration", () => {
6
+ it("env value is string and delay completes", async () => {
7
+ const envVal = getEdgeString("NODE_ENV", "test");
8
+ expect(typeof envVal).toBe("string");
9
+ await delay(5);
10
+ expect(envVal).toBeDefined();
11
+ });
12
+ });
@@ -0,0 +1,14 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { serializeError, AppError } from "@simpill/errors.utils";
3
+ import { generateUUID, isUUID } from "@simpill/uuid.utils";
4
+
5
+ describe("errors.utils + uuid.utils integration", () => {
6
+ it("serializeError and generateUUID work together", () => {
7
+ const id = generateUUID();
8
+ expect(isUUID(id)).toBe(true);
9
+ const err = new AppError("test", { code: "E_TEST", meta: { requestId: id } });
10
+ const serialized = serializeError(err);
11
+ expect(serialized).toBeDefined();
12
+ expect(typeof serialized).toBe("object");
13
+ });
14
+ });
@@ -0,0 +1,15 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { pick } from "@simpill/object.utils";
3
+ import { unique, chunk } from "@simpill/array.utils";
4
+
5
+ describe("object.utils + array.utils integration", () => {
6
+ it("pick then unique keys and chunk work together", () => {
7
+ const obj = { a: 1, b: 2, c: 3 };
8
+ const picked = pick(obj, ["a", "c"]);
9
+ const keys = unique(Object.keys(picked));
10
+ expect(keys).toHaveLength(2);
11
+ const chunks = chunk(keys, 1);
12
+ expect(chunks).toHaveLength(2);
13
+ expect(chunks.flat()).toEqual(keys);
14
+ });
15
+ });
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Ensures all monolith @simpill packages resolve (types + runtime).
3
+ * Packages with dedicated unit tests are not re-imported here.
4
+ */
5
+ import { describe, expect, it } from "vitest";
6
+
7
+ const PACKAGES_TO_RESOLVE: Array<{ name: string; loader: () => Promise<Record<string, unknown>> }> = [
8
+ { name: "adapters.utils", loader: () => import("@simpill/adapters.utils") },
9
+ { name: "algorithms.utils", loader: () => import("@simpill/algorithms.utils") },
10
+ { name: "annotations.utils", loader: () => import("@simpill/annotations.utils") },
11
+ { name: "api.utils", loader: () => import("@simpill/api.utils") },
12
+ { name: "collections.utils", loader: () => import("@simpill/collections.utils") },
13
+ { name: "crypto.utils", loader: () => import("@simpill/crypto.utils") },
14
+ { name: "data.utils", loader: () => import("@simpill/data.utils") },
15
+ { name: "enum.utils", loader: () => import("@simpill/enum.utils") },
16
+ { name: "events.utils", loader: () => import("@simpill/events.utils") },
17
+ { name: "factories.utils", loader: () => import("@simpill/factories.utils") },
18
+ { name: "file.utils", loader: () => import("@simpill/file.utils") },
19
+ { name: "function.utils", loader: () => import("@simpill/function.utils") },
20
+ { name: "http.utils", loader: () => import("@simpill/http.utils") },
21
+ { name: "logger.utils", loader: () => import("@simpill/logger.utils") },
22
+ { name: "middleware.utils", loader: () => import("@simpill/middleware.utils") },
23
+ { name: "misc.utils", loader: () => import("@simpill/misc.utils") },
24
+ { name: "nextjs.utils", loader: () => import("@simpill/nextjs.utils") },
25
+ { name: "number.utils", loader: () => import("@simpill/number.utils") },
26
+ { name: "observability.utils", loader: () => import("@simpill/observability.utils") },
27
+ { name: "protocols.utils", loader: () => import("@simpill/protocols.utils") },
28
+ { name: "react.utils", loader: () => import("@simpill/react.utils") },
29
+ { name: "request-context.utils", loader: () => import("@simpill/request-context.utils") },
30
+ { name: "resilience.utils", loader: () => import("@simpill/resilience.utils") },
31
+ { name: "socket.utils", loader: () => import("@simpill/socket.utils") },
32
+ { name: "test.utils", loader: () => import("@simpill/test.utils") },
33
+ { name: "token-optimizer.utils", loader: () => import("@simpill/token-optimizer.utils") },
34
+ { name: "zod.utils", loader: () => import("@simpill/zod.utils") },
35
+ { name: "zustand.utils", loader: () => import("@simpill/zustand.utils") },
36
+ ];
37
+
38
+ describe("@simpill package resolution", () => {
39
+ for (const { name, loader } of PACKAGES_TO_RESOLVE) {
40
+ it(`resolves @simpill/${name}`, async () => {
41
+ const mod = await loader();
42
+ expect(mod).toBeDefined();
43
+ expect(mod).not.toBeNull();
44
+ expect(typeof mod).toBe("object");
45
+ });
46
+ }
47
+ });
@@ -0,0 +1,11 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import * as ArrayUtils from "@simpill/array.utils";
3
+
4
+ describe("@simpill/array.utils", () => {
5
+ it("resolves and unique returns deduped array", () => {
6
+ expect(ArrayUtils).toBeDefined();
7
+ expect(typeof ArrayUtils.unique).toBe("function");
8
+ const out = ArrayUtils.unique([1, 2, 2, 3, 1]);
9
+ expect(out).toEqual([1, 2, 3]);
10
+ });
11
+ });
@@ -0,0 +1,12 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import * as Async from "@simpill/async.utils";
3
+
4
+ describe("@simpill/async.utils", () => {
5
+ it("resolves and delay resolves after ms", async () => {
6
+ expect(Async).toBeDefined();
7
+ expect(typeof Async.delay).toBe("function");
8
+ const start = Date.now();
9
+ await Async.delay(10);
10
+ expect(Date.now() - start).toBeGreaterThanOrEqual(8);
11
+ });
12
+ });
@@ -0,0 +1,21 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import * as Cache from "@simpill/cache.utils";
3
+
4
+ describe("@simpill/cache.utils", () => {
5
+ it("resolves and exports cache utilities", () => {
6
+ expect(Cache).toBeDefined();
7
+ expect(typeof Cache).toBe("object");
8
+ const keys = Object.keys(Cache).filter((k) => (Cache as Record<string, unknown>)[k] != null);
9
+ expect(keys.length).toBeGreaterThan(0);
10
+ });
11
+
12
+ it("exposes a memoize or createMemoize-like function when present", () => {
13
+ const C = Cache as Record<string, unknown>;
14
+ const memoizeFn = C.memoize ?? C.createMemoize;
15
+ if (typeof memoizeFn !== "function") return;
16
+ const double = (n: number) => n * 2;
17
+ const memoized = (memoizeFn as (fn: (n: number) => number) => (n: number) => number)(double);
18
+ expect(memoized(2)).toBe(4);
19
+ expect(memoized(2)).toBe(4);
20
+ });
21
+ });
@@ -0,0 +1,13 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { getEdgeString } from "@simpill/env.utils/client";
3
+ import * as Env from "@simpill/env.utils";
4
+
5
+ describe("@simpill/env.utils", () => {
6
+ it("resolves and exports client getEdgeString", () => {
7
+ expect(Env).toBeDefined();
8
+ expect(typeof Env).toBe("object");
9
+ const value = getEdgeString("NODE_ENV", "development");
10
+ expect(typeof value).toBe("string");
11
+ expect(value.length).toBeGreaterThanOrEqual(0);
12
+ });
13
+ });
@@ -0,0 +1,13 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import * as Errors from "@simpill/errors.utils";
3
+
4
+ describe("@simpill/errors.utils", () => {
5
+ it("resolves and serializeError returns object", () => {
6
+ expect(Errors).toBeDefined();
7
+ expect(typeof Errors.serializeError).toBe("function");
8
+ const out = Errors.serializeError(new Error("test"));
9
+ expect(out).toBeDefined();
10
+ expect(typeof out).toBe("object");
11
+ expect("message" in out || "name" in out).toBe(true);
12
+ });
13
+ });
@@ -0,0 +1,11 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import * as ObjectUtils from "@simpill/object.utils";
3
+
4
+ describe("@simpill/object.utils", () => {
5
+ it("resolves and pick returns subset", () => {
6
+ expect(ObjectUtils).toBeDefined();
7
+ expect(typeof ObjectUtils.pick).toBe("function");
8
+ const out = ObjectUtils.pick({ a: 1, b: 2, c: 3 }, ["a", "c"]);
9
+ expect(out).toEqual({ a: 1, c: 3 });
10
+ });
11
+ });
@@ -0,0 +1,23 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import * as Patterns from "@simpill/patterns.utils";
3
+
4
+ describe("@simpill/patterns.utils", () => {
5
+ it("resolves and exports pattern utilities", () => {
6
+ expect(Patterns).toBeDefined();
7
+ expect(typeof Patterns).toBe("object");
8
+ const keys = Object.keys(Patterns).filter((k) => (Patterns as Record<string, unknown>)[k] != null);
9
+ expect(keys.length).toBeGreaterThan(0);
10
+ });
11
+
12
+ it("pipeAsync composes async steps when present", async () => {
13
+ const P = Patterns as Record<string, unknown>;
14
+ const pipeAsync = P.pipeAsync as (...fns: Array<(n: number) => Promise<number>>) => (x: number) => Promise<number>;
15
+ if (typeof pipeAsync !== "function") return;
16
+ const addOne = async (n: number) => n + 1;
17
+ const double = async (n: number) => n * 2;
18
+ const composed = pipeAsync(addOne, double);
19
+ const result = await composed(1);
20
+ expect(typeof result).toBe("number");
21
+ expect(result).toBe(4);
22
+ });
23
+ });
@@ -0,0 +1,11 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import * as StringUtils from "@simpill/string.utils";
3
+
4
+ describe("@simpill/string.utils", () => {
5
+ it("resolves and exports usable functions", () => {
6
+ expect(StringUtils).toBeDefined();
7
+ expect(typeof StringUtils).toBe("object");
8
+ const keys = Object.keys(StringUtils).filter((k) => typeof (StringUtils as Record<string, unknown>)[k] === "function");
9
+ expect(keys.length).toBeGreaterThan(0);
10
+ });
11
+ });
@@ -0,0 +1,12 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import * as Time from "@simpill/time.utils";
3
+
4
+ describe("@simpill/time.utils", () => {
5
+ it("resolves and getUnixTimeStamp returns number", () => {
6
+ expect(Time).toBeDefined();
7
+ expect(typeof Time.getUnixTimeStamp).toBe("function");
8
+ const ts = Time.getUnixTimeStamp();
9
+ expect(typeof ts).toBe("number");
10
+ expect(ts).toBeGreaterThan(0);
11
+ });
12
+ });
@@ -0,0 +1,12 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import * as Uuid from "@simpill/uuid.utils";
3
+
4
+ describe("@simpill/uuid.utils", () => {
5
+ it("resolves and generateUUID returns valid uuid string", () => {
6
+ expect(Uuid).toBeDefined();
7
+ expect(typeof Uuid.generateUUID).toBe("function");
8
+ const id = Uuid.generateUUID();
9
+ expect(typeof id).toBe("string");
10
+ expect(Uuid.isUUID(id)).toBe(true);
11
+ });
12
+ });