@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.
- package/CONTRIBUTING.md +787 -0
- package/README.md +186 -0
- package/__tests__/README.md +32 -0
- package/__tests__/e2e/all-packages-resolve.e2e.test.ts +40 -0
- package/__tests__/integration/env-and-async.integration.test.ts +12 -0
- package/__tests__/integration/errors-and-uuid.integration.test.ts +14 -0
- package/__tests__/integration/object-and-array.integration.test.ts +15 -0
- package/__tests__/unit/@simpill/_resolver/resolve-packages.unit.test.ts +47 -0
- package/__tests__/unit/@simpill/array.utils/array.utils.unit.test.ts +11 -0
- package/__tests__/unit/@simpill/async.utils/async.utils.unit.test.ts +12 -0
- package/__tests__/unit/@simpill/cache.utils/cache.utils.unit.test.ts +21 -0
- package/__tests__/unit/@simpill/env.utils/env.utils.unit.test.ts +13 -0
- package/__tests__/unit/@simpill/errors.utils/errors.utils.unit.test.ts +13 -0
- package/__tests__/unit/@simpill/object.utils/object.utils.unit.test.ts +11 -0
- package/__tests__/unit/@simpill/patterns.utils/patterns.utils.unit.test.ts +23 -0
- package/__tests__/unit/@simpill/string.utils/string.utils.unit.test.ts +11 -0
- package/__tests__/unit/@simpill/time.utils/time.utils.unit.test.ts +12 -0
- package/__tests__/unit/@simpill/uuid.utils/uuid.utils.unit.test.ts +12 -0
- package/docs/PUBLISHING_AND_PACKAGES.md +258 -0
- package/docs/template/.env.sample +0 -0
- package/docs/template/README.md +0 -0
- package/docs/template/TEMPLATE.md +1040 -0
- package/docs/template/assets/logo-banner.svg +20 -0
- package/docs/template/package.json +14 -0
- package/index.ts +89 -0
- package/package.json +87 -0
- package/scripts/README.md +57 -0
- package/scripts/github/github-set-all-topics.js +120 -0
- package/scripts/github/github-set-repo-topics.sh +33 -0
- package/scripts/github/github-set-repos-public.sh +71 -0
- package/scripts/lib/package-topics.js +57 -0
- package/scripts/lib/publish-order.js +140 -0
- package/scripts/lib/sync-repo-links.js +75 -0
- package/scripts/monorepo/install-hooks.sh +64 -0
- package/scripts/monorepo/monorepo-clean.sh +7 -0
- package/scripts/monorepo/monorepo-sync-deps.js +81 -0
- package/scripts/monorepo/monorepo-verify-deps.js +37 -0
- package/scripts/monorepo/use-local-utils-at-root.js +49 -0
- package/scripts/publish/publish-all.sh +152 -0
- package/scripts/utils/utils-fix-repo-metadata.js +61 -0
- package/scripts/utils/utils-prepare-all.sh +107 -0
- package/scripts/utils/utils-set-npm-keywords.js +132 -0
- package/scripts/utils/utils-update-readme-badges.js +83 -0
- package/scripts/utils/utils-use-local-deps.js +43 -0
- package/scripts/utils/utils-verify-all.sh +45 -0
- package/tsconfig.json +14 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
# Publishing @simpill Packages: GitHub, npm, and Package Layout
|
|
2
|
+
|
|
3
|
+
## Will packages show as `@simpill/<packagename>`?
|
|
4
|
+
|
|
5
|
+
**Yes.** The package name in each `package.json` is already `@simpill/<name>.utils`. How that appears on **npm** and **GitHub** depends on how you set up accounts, not on the repo contents.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## npm: Scope and organization
|
|
10
|
+
|
|
11
|
+
- **Scoped packages** like `@simpill/env.utils` always show on npm as `@simpill/env.utils`; the scope is the part before the first `/`.
|
|
12
|
+
- **Who “owns” the scope** is determined by npm accounts:
|
|
13
|
+
- If your **npm username** is `simpill`, you can publish `@simpill/...` under your user. They will show under your user profile.
|
|
14
|
+
- If you create an **npm organization** named `simpill`, you publish under that org. All packages then show under **https://www.npmjs.com/org/simpill** and you can add other members and teams.
|
|
15
|
+
|
|
16
|
+
**Recommendation:** Create an **npm organization** named `simpill` so all packages live under one place (`/org/simpill`) and you can manage access and members in one place.
|
|
17
|
+
|
|
18
|
+
- Create org: https://www.npmjs.com/org/create (choose name `simpill` if available).
|
|
19
|
+
- Publish with access: `npm publish --access public` (required for scoped packages the first time, or set in each package.json or `.npmrc`).
|
|
20
|
+
|
|
21
|
+
You do **not** need to “claim” anything extra for the scope beyond having the org (or user) named `simpill`.
|
|
22
|
+
|
|
23
|
+
**If you see `404 Scope not found`:** The `@simpill` scope does not exist on npm yet. Create an organization named **simpill** at https://www.npmjs.com/org/create (one-time), then run `npm publish --access public` again from each package directory.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## GitHub: Repo and org
|
|
28
|
+
|
|
29
|
+
- **GitHub** does not use the `@` scope. Repos are `github.com/<owner>/<repo>`.
|
|
30
|
+
- Your **package.json** `repository` / `homepage` / `bugs` URLs should point at the **real** repo where this monorepo lives.
|
|
31
|
+
|
|
32
|
+
Right now many packages use URLs like:
|
|
33
|
+
|
|
34
|
+
- `https://github.com/SkinnnyJay/simpill-utils.git`
|
|
35
|
+
|
|
36
|
+
That implies a repo named `@simpill/adapters.utils` under the user `SkinnnyJay`. In a **monorepo**, you usually have **one repo** and many packages inside it, so the canonical form is:
|
|
37
|
+
|
|
38
|
+
- One repo, e.g. `github.com/<owner>/<repo>` (e.g. `SkinnnyJay/simpill-utils`).
|
|
39
|
+
- In each package, set `repository.url` to that repo and `repository.directory` to the package path, e.g. `utils/@simpill-adapters.utils`.
|
|
40
|
+
|
|
41
|
+
**Recommendation:** If you want a clean “brand” on GitHub:
|
|
42
|
+
|
|
43
|
+
1. Create a **GitHub organization** named `simpill` (if you want `github.com/simpill/...`).
|
|
44
|
+
2. Create a single repo (e.g. `simpill` or `utils`) and put this monorepo there.
|
|
45
|
+
3. In every package `package.json`, set:
|
|
46
|
+
- `repository`: `https://github.com/simpill/<repo>.git` and `"directory": "utils/<name>.utils"`
|
|
47
|
+
- `homepage` and `bugs.url` to the same base URL (and for bugs, `/issues`).
|
|
48
|
+
|
|
49
|
+
Then all packages will show on GitHub under one org/repo; npm will still show them as `@simpill/<packagename>`.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## One big package vs many small ones
|
|
54
|
+
|
|
55
|
+
You said you want to **limit dependencies** and prefer **one logical “product”** implemented as **many small modules**. Your current layout does that:
|
|
56
|
+
|
|
57
|
+
- **One scope:** `@simpill`
|
|
58
|
+
- **Many packages:** `@simpill/env.utils`, `@simpill/adapters.utils`, etc.
|
|
59
|
+
- **Consumers** install only what they use: `npm install @simpill/env.utils @simpill/object.utils` (small dependency set, tree-shakeable).
|
|
60
|
+
- **No single “mega” package** that pulls in everything.
|
|
61
|
+
|
|
62
|
+
So: checking in all current packages and publishing them as-is will give you exactly that: many small `@simpill/<packagename>` packages on npm, with minimal dependency surface per app. You do **not** need to merge them into one large package for that.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Folder layout (per package)
|
|
67
|
+
|
|
68
|
+
Each package under `utils/` follows the same structure. Example for `adapters.utils`:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
utils/
|
|
72
|
+
└── adapters.utils/
|
|
73
|
+
├── package.json # name: "@simpill/adapters.utils"
|
|
74
|
+
├── tsconfig.json
|
|
75
|
+
├── jest.config.js
|
|
76
|
+
├── biome.json
|
|
77
|
+
├── README.md
|
|
78
|
+
├── src/
|
|
79
|
+
│ ├── index.ts # main re-exports
|
|
80
|
+
│ ├── client/ # Edge/browser (no fs)
|
|
81
|
+
│ │ └── index.ts
|
|
82
|
+
│ ├── server/ # Node (full access)
|
|
83
|
+
│ │ └── index.ts
|
|
84
|
+
│ └── shared/ # Runtime-agnostic
|
|
85
|
+
│ └── index.ts
|
|
86
|
+
├── __tests__/ # mirrors src (client/server/shared, unit/integration)
|
|
87
|
+
├── scripts/ # check.sh, install-hooks.sh
|
|
88
|
+
├── dist/ # build output (git-ignored)
|
|
89
|
+
└── coverage/ # test coverage (git-ignored)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Subpath exports in `package.json`:
|
|
93
|
+
|
|
94
|
+
- `@simpill/adapters.utils` → main
|
|
95
|
+
- `@simpill/adapters.utils/client`
|
|
96
|
+
- `@simpill/adapters.utils/server`
|
|
97
|
+
- `@simpill/adapters.utils/shared`
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## How each package looks (quick reference)
|
|
102
|
+
|
|
103
|
+
| npm name | Folder | Description |
|
|
104
|
+
|----------|--------|-------------|
|
|
105
|
+
| `@simpill/adapters.utils` | `utils/@simpill-adapters.utils` | Adapter helpers, logger/cache adapter interfaces |
|
|
106
|
+
| `@simpill/algorithms.utils` | `utils/@simpill-algorithms.utils` | Merge sort, quick sort, binary search, lower/upper bound |
|
|
107
|
+
| `@simpill/annotations.utils` | `utils/@simpill-annotations.utils` | Typed metadata store, annotation helpers |
|
|
108
|
+
| `@simpill/api.utils` | `utils/@simpill-api.utils` | Typed API client, Zod, handler registry, middleware |
|
|
109
|
+
| `@simpill/array.utils` | `utils/@simpill-array.utils` | unique, chunk, compact, groupBy, sortBy, etc. |
|
|
110
|
+
| `@simpill/async.utils` | `utils/@simpill-async.utils` | Retry, timeout, delay, Semaphore |
|
|
111
|
+
| `@simpill/cache.utils` | `utils/@simpill-cache.utils` | LRU, TTL cache, memoize |
|
|
112
|
+
| `@simpill/collections.utils` | `utils/@simpill-collections.utils` | LinkedList, Queue, Stack, LRU/TTL, MultiMap, BiMap |
|
|
113
|
+
| `@simpill/crypto.utils` | `utils/@simpill-crypto.utils` | Hash, randomBytes, timing-safe compare (Node) |
|
|
114
|
+
| `@simpill/data.utils` | `utils/@simpill-data.utils` | validate, prepare, lifecycle, extend, config |
|
|
115
|
+
| `@simpill/env.utils` | `utils/@simpill-env.utils` | Type-safe env vars (Node + Edge) |
|
|
116
|
+
| `@simpill/enum.utils` | `utils/@simpill-enum.utils` | getEnumValue, isValidEnumValue, EnumHelper |
|
|
117
|
+
| `@simpill/errors.utils` | `utils/@simpill-errors.utils` | Typed errors, error codes, serializeError |
|
|
118
|
+
| `@simpill/events.utils` | `utils/@simpill-events.utils` | PubSub, observer, typed event emitter |
|
|
119
|
+
| `@simpill/factories.utils` | `utils/@simpill-factories.utils` | Factory builder, singleton, error factory |
|
|
120
|
+
| `@simpill/file.utils` | `utils/@simpill-file.utils` | readFileUtf8, readFileJson, writeFile, ensureDir (Node) |
|
|
121
|
+
| `@simpill/function.utils` | `utils/@simpill-function.utils` | debounce, throttle, once, pipe, compose |
|
|
122
|
+
| `@simpill/http.utils` | `utils/@simpill-http.utils` | Fetch timeout/retry, typed HTTP client |
|
|
123
|
+
| `@simpill/logger.utils` | `utils/@simpill-logger.utils` | Structured logging, correlation context |
|
|
124
|
+
| `@simpill/middleware.utils` | `utils/@simpill-middleware.utils` | Middleware types, correlation ID middleware |
|
|
125
|
+
| `@simpill/misc.utils` | `utils/@simpill-misc.utils` | Singleton, debounce, throttle, LRU, polling, etc. |
|
|
126
|
+
| `@simpill/nextjs.utils` | `utils/@simpill-nextjs.utils` | Next.js App Router helpers, safe actions, middleware |
|
|
127
|
+
| `@simpill/number.utils` | `utils/@simpill-number.utils` | clamp, roundTo, toInt/Float, isInRange, lerp |
|
|
128
|
+
| `@simpill/object.utils` | `utils/@simpill-object.utils` | pick, omit, merge, get/set, guards |
|
|
129
|
+
| `@simpill/observability.utils` | `utils/@simpill-observability.utils` | Correlation middleware, request context, logger |
|
|
130
|
+
| `@simpill/patterns.utils` | `utils/@simpill-patterns.utils` | Result/Either, strategySelector, pipeAsync |
|
|
131
|
+
| `@simpill/protocols.utils` | `utils/@simpill-protocols.utils` | Shared protocol constants and types |
|
|
132
|
+
| `@simpill/react.utils` | `utils/@simpill-react.utils` | Hooks, safe context, stable callbacks |
|
|
133
|
+
| `@simpill/request-context.utils` | `utils/@simpill-request-context.utils` | AsyncLocalStorage request context |
|
|
134
|
+
| `@simpill/resilience.utils` | `utils/@simpill-resilience.utils` | Circuit breaker, rate limiter, bulkhead |
|
|
135
|
+
| `@simpill/socket.utils` | `utils/@simpill-socket.utils` | Reconnecting WebSocket client |
|
|
136
|
+
| `@simpill/string.utils` | `utils/@simpill-string.utils` | Formatting, casing, trim, slugify |
|
|
137
|
+
| `@simpill/test.utils` | `utils/@simpill-test.utils` | Test patterns, faker, enricher |
|
|
138
|
+
| `@simpill/time.utils` | `utils/@simpill-time.utils` | debounce, throttle, interval manager |
|
|
139
|
+
| `@simpill/token-optimizer.utils` | `utils/@simpill-token-optimizer.utils` | Token cleaning, strategies, telemetry |
|
|
140
|
+
| `@simpill/uuid.utils` | `utils/@simpill-uuid.utils` | UUID generate/validate (v1/v4/v5) |
|
|
141
|
+
| `@simpill/zod.utils` | `utils/@simpill-zod.utils` | Zod helpers, safe-parse, transforms |
|
|
142
|
+
| `@simpill/zustand.utils` | `utils/@simpill-zustand.utils` | Zustand factory, persist, devtools, slices |
|
|
143
|
+
|
|
144
|
+
(If you add or remove packages, update this table and the root README.)
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Pre-publish checklist
|
|
149
|
+
|
|
150
|
+
Use this before publishing any package (or the whole set) to npm and before relying on GitHub links.
|
|
151
|
+
|
|
152
|
+
### npm
|
|
153
|
+
|
|
154
|
+
- [ ] **Scope owner:** Create npm **organization** `simpill` (or confirm npm user `simpill`) so `@simpill/*` is yours.
|
|
155
|
+
- [ ] **Access:** Use `npm publish --access public` for each scoped package (or set `"publishConfig": { "access": "public" }` in package.json).
|
|
156
|
+
- [ ] **Auth:** `npm login` with an account that has publish rights to the `@simpill` scope.
|
|
157
|
+
- [ ] **Version:** Set or bump `version` in each package (e.g. 1.0.0 for first publish).
|
|
158
|
+
- [ ] **Build:** From each package dir: `npm run build` (and ideally `npm run verify`) so `dist/` is up to date; `prepublishOnly` will run build on publish.
|
|
159
|
+
- [ ] **Dependencies:** Packages that depend on other `@simpill/*` packages must use published versions (or `workspace:*` if you use a monorepo tool that supports it) before publishing; no `file:../` in published manifest if those deps are on npm.
|
|
160
|
+
|
|
161
|
+
### GitHub
|
|
162
|
+
|
|
163
|
+
- [ ] **Org/repo:** Create GitHub org `simpill` (optional) and one monorepo (e.g. `simpill` or `simpill-utils`).
|
|
164
|
+
- [ ] **Push:** Ensure this codebase is pushed to that repo (e.g. `main` branch).
|
|
165
|
+
- [ ] **package.json links:** In every package, set:
|
|
166
|
+
- `repository`: `"url": "https://github.com/simpill/<repo>.git"`, `"directory": "utils/<name>.utils"`
|
|
167
|
+
- `homepage`: `"https://github.com/simpill/<repo>/tree/main/utils/<name>.utils#readme"` (or your default branch)
|
|
168
|
+
- `bugs`: `"url": "https://github.com/simpill/<repo>/issues"`
|
|
169
|
+
Replace `<repo>` and default branch if different.
|
|
170
|
+
|
|
171
|
+
### Per-package (repeat for each)
|
|
172
|
+
|
|
173
|
+
- [ ] `name` is `@simpill/<name>.utils`.
|
|
174
|
+
- [ ] `main`, `types`, and `exports` point at `dist/` and match CONTRIBUTING (`.`, `./client`, `./server`, `./shared`).
|
|
175
|
+
- [ ] `files` includes `dist` and `README.md`.
|
|
176
|
+
- [ ] `scripts.prepublishOnly` runs build.
|
|
177
|
+
- [ ] No stray `file:../` in `dependencies` for packages that are published to npm (or convert to workspace protocol / published versions).
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Publish script
|
|
182
|
+
|
|
183
|
+
A script automates **GitHub push** and **npm publish** in the correct dependency order and rewrites `file:../` to `^version` for each package before publishing (then restores `package.json`).
|
|
184
|
+
|
|
185
|
+
### Prerequisites
|
|
186
|
+
|
|
187
|
+
1. **GitHub:** Install [GitHub CLI](https://cli.github.com/) and run `gh auth login` so the repo can be pushed.
|
|
188
|
+
2. **npm:** Log in with an account that can publish to the `@simpill` scope: `npm login`.
|
|
189
|
+
|
|
190
|
+
### Usage
|
|
191
|
+
|
|
192
|
+
From the repo root:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
# Full run: push to GitHub, then publish all packages to npm (with confirmations)
|
|
196
|
+
npm run publish
|
|
197
|
+
# or: ./scripts/publish-all.sh
|
|
198
|
+
|
|
199
|
+
# Dry run: no GitHub push; npm publish --dry-run for each package
|
|
200
|
+
./scripts/publish-all.sh --dry-run
|
|
201
|
+
|
|
202
|
+
# Only npm (skip GitHub push)
|
|
203
|
+
./scripts/publish-all.sh --skip-github
|
|
204
|
+
# or
|
|
205
|
+
./scripts/publish-all.sh --npm-only
|
|
206
|
+
|
|
207
|
+
# Skip confirmation prompts
|
|
208
|
+
./scripts/publish-all.sh --yes
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### What it does
|
|
212
|
+
|
|
213
|
+
1. **GitHub (unless `--skip-github`):** Checks `gh auth status`, then runs `git push`.
|
|
214
|
+
2. **npm:** Checks `npm whoami`, then for each package in **topological order** (dependencies first):
|
|
215
|
+
- Backs up `utils/<name>.utils/package.json`
|
|
216
|
+
- Replaces every `@simpill/*` `file:../` dependency with `^<version>` (from that package’s current version)
|
|
217
|
+
- Runs `npm publish --access public` (or `--dry-run` when using `--dry-run`)
|
|
218
|
+
- Restores `package.json` from backup
|
|
219
|
+
|
|
220
|
+
So you keep `file:../` in the repo for local development; the script only rewrites for the publish step.
|
|
221
|
+
|
|
222
|
+
### Separate packages and synced metadata
|
|
223
|
+
|
|
224
|
+
- **Published separately:** Each package is its own npm package (e.g. `@simpill/async.utils`, `@simpill/errors.utils`). When someone installs one, npm resolves its `@simpill/*` dependencies by version range from the registry.
|
|
225
|
+
- **Version refs between packages:** The publish script rewrites `file:../` to `^<version>` only in the manifest that gets published. So the **version references** between packages are correct: the published `@simpill/async.utils` will list `@simpill/errors.utils: "^1.0.0"` etc., and npm will install the right versions.
|
|
226
|
+
- **Links (repository, homepage, bugs):** The script does **not** change these. Whatever is in each `package.json` is what gets published. So:
|
|
227
|
+
- If you want every package to point at the **same monorepo** (e.g. `github.com/SkinnnyJay/simpill-utils` with `directory: "utils/@simpill-async.utils"`), set `repository`, `homepage`, and `bugs` in each package once—or run the sync script below and commit.
|
|
228
|
+
- After that, every published package on npm will have consistent links to the same repo and directory.
|
|
229
|
+
|
|
230
|
+
To sync repository/homepage/bugs across all packages to one base URL (run once, then commit):
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
# Example: set base to https://github.com/SkinnnyJay/simpill-utils, branch main
|
|
234
|
+
REPO_BASE="https://github.com/SkinnnyJay/simpill-utils" BRANCH="main" node scripts/lib/sync-repo-links.js
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
(See `scripts/lib/sync-repo-links.js` for usage. Omit to leave existing links unchanged.)
|
|
238
|
+
|
|
239
|
+
### Optional: verify before publishing
|
|
240
|
+
|
|
241
|
+
Run the monorepo verify script (if present) before publishing:
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
npm run utils:verify
|
|
245
|
+
# or: ./scripts/utils-verify-all.sh
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
Then run `npm run publish` or `./scripts/publish-all.sh` (or with `--dry-run` first).
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## Summary
|
|
253
|
+
|
|
254
|
+
- **npm:** They will show as `@simpill/<packagename>`. Create an npm **organization** `simpill` (or use user `simpill`) so all packages are under one scope.
|
|
255
|
+
- **GitHub:** Create a **GitHub org** `simpill` and one monorepo if you want clean URLs; then fix every package’s `repository` / `homepage` / `bugs` to that repo and `directory`.
|
|
256
|
+
- **Strategy:** Your current setup (many small packages under one scope) already limits dependencies and gives one “family” of modules; no need to merge into one large package.
|
|
257
|
+
- **Folders:** Each package under `utils/<name>.utils/` is already laid out as in CONTRIBUTING; use the table above as the “how each package looks” reference and the checklist before publishing.
|
|
258
|
+
- **Script:** Use `npm run publish` or `./scripts/publish-all.sh` (with `--dry-run` first) to push to GitHub and publish all packages to npm in dependency order; see [Publish script](#publish-script) above.
|
|
File without changes
|
|
File without changes
|