@stacksjs/defaults 0.75.445 → 0.75.450
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/ai/skills/stacks-arrays/SKILL.md +9 -1
- package/ai/skills/stacks-auth/SKILL.md +26 -0
- package/ai/skills/stacks-cache/SKILL.md +12 -2
- package/ai/skills/stacks-datetime/SKILL.md +8 -0
- package/ai/skills/stacks-native/CATALOG.md +24 -22
- package/ai/skills/stacks-objects/SKILL.md +16 -13
- package/ai/skills/stacks-pagination/SKILL.md +8 -1
- package/ai/skills/stacks-socials/SKILL.md +14 -0
- package/ai/skills/stacks-storage/SKILL.md +8 -0
- package/ai/skills/stacks-strings/SKILL.md +2 -0
- package/ai/skills/stacks-utils/SKILL.md +24 -5
- package/ai/skills/stacks-validation/SKILL.md +39 -22
- package/ide/vscode/package.json +1 -1
- package/package.json +4 -4
- package/resources/components/Dashboard/UI/Avatar.stx +31 -21
|
@@ -269,9 +269,11 @@ These standalone functions are also available through the root `arr` namespace:
|
|
|
269
269
|
- `groupBy`, `keyBy`, `countBy` use selector functions and return typed records.
|
|
270
270
|
Repeated keyBy keys overwrite earlier entries; groupBy accumulates them.
|
|
271
271
|
- `sortBy(array, ...selectors)` copies before sorting, supports multiple keys,
|
|
272
|
-
and accepts `{ by, order: 'desc' }` selectors.
|
|
272
|
+
and accepts `{ by, order: 'desc' }` selectors. Each selector runs once per element;
|
|
273
|
+
cached keys preserve stable ties.
|
|
273
274
|
- `sumBy`, `meanBy`, `minBy`, `maxBy` aggregate selected values. `meanBy` returns
|
|
274
275
|
undefined on an empty input; extrema return the selected element, not its value.
|
|
276
|
+
Extrema retain infinite endpoints and ignore NaN candidates; ties keep the first.
|
|
275
277
|
- `zip`, `zipWith` stop at the shorter input; `unzip` splits pairs.
|
|
276
278
|
- `difference` keeps first-input duplicates that are not excluded;
|
|
277
279
|
`intersection` and `union` deduplicate by Set identity.
|
|
@@ -280,6 +282,12 @@ These standalone functions are also available through the root `arr` namespace:
|
|
|
280
282
|
- `splitAt` supports negative indexes; `splitWhen` starts the second half at
|
|
281
283
|
the first match; `times` requires a non-negative integer count.
|
|
282
284
|
|
|
285
|
+
`take`, `takeLast`, `drop` and `dropLast` truncate fractional counts toward zero,
|
|
286
|
+
clamp negatives/NaN to zero and treat Infinity as the entire array. Population
|
|
287
|
+
variance, standard deviation, covariance and z-scores use scaled centered arithmetic
|
|
288
|
+
for finite inputs. Standard deviation stays finite when only its square is outside
|
|
289
|
+
the number range; unrepresentable final results keep IEEE number behavior.
|
|
290
|
+
|
|
283
291
|
Read `core/arrays/src/transform.ts` and `tests/transform.test.ts` for precise
|
|
284
292
|
empty-input and selector behavior. These pure helpers are preferable to a new
|
|
285
293
|
utility dependency for common native transformations.
|
|
@@ -737,13 +737,39 @@ not authenticate them. OAuth resource endpoints must explicitly use
|
|
|
737
737
|
required scopes. Ordinary refresh also refuses delegated refresh credentials;
|
|
738
738
|
use the OAuth token endpoint and the registered client's protocol authentication.
|
|
739
739
|
|
|
740
|
+
### Userinfo and pairwise subjects
|
|
741
|
+
|
|
742
|
+
The provider has no id_token. A relying party that signs people in with this
|
|
743
|
+
provider reads `oauthUserInfoResponse(request, { scopes, resource, audience,
|
|
744
|
+
workspaceId, isSubjectEligible, pairwiseSecret, claims })`: the same delegated
|
|
745
|
+
token checks as any protected resource, then `{ ...claims, sub }`. `sub` comes
|
|
746
|
+
from `pairwiseOAuthSubject(secret, clientId, subject)`, an HMAC that differs per
|
|
747
|
+
client so two relying parties cannot join records on it; keep its secret apart
|
|
748
|
+
from rotating app keys. `claims({ sub, subject, clientId, scopes })` releases
|
|
749
|
+
only what the granted scopes cover, and null answers 401. The socials
|
|
750
|
+
`StacksIssuerProvider` is the matching client.
|
|
751
|
+
|
|
740
752
|
## Token-only recovery endpoints
|
|
741
753
|
|
|
742
754
|
For high-entropy reset credentials, `mintPasswordResetToken()` returns `{ token, digest }`.
|
|
743
755
|
Store the digest in `password_resets.token`, never the plaintext.
|
|
756
|
+
Prefer `issuePasswordResetToken(email, { throttleMs?, expiresAt?, eligible? })` when
|
|
757
|
+
issuing for an existing account. It locks that account before checking its current
|
|
758
|
+
email, the synchronous application eligibility predicate and the saved throttle.
|
|
759
|
+
It considers all supported legacy email-case variants when throttling, and retires
|
|
760
|
+
them together when replacing the credential. `throttleMs: 0` disables throttling.
|
|
761
|
+
It atomically replaces the digest and returns `{ issued: true, token, userId, email }`
|
|
762
|
+
or `{ issued: false }`. The latter deliberately combines unknown, ineligible and
|
|
763
|
+
throttled accounts; recovery endpoints must keep their public response generic.
|
|
764
|
+
Only send the returned credential after issuance commits.
|
|
765
|
+
Treat its value as opaque. It is bound to the issuing account, so reassigning an
|
|
766
|
+
email address cannot let an old recovery reset the address's new account.
|
|
744
767
|
`consumePasswordResetToken(token, async claim => { ... })` locks the owner and token,
|
|
745
768
|
checks the stored expiry and consumes it in the same transaction as callback writes.
|
|
746
769
|
`claim` is `{ userId, email, hasExplicitExpiry }`; result is `{ consumed: false }` or
|
|
747
770
|
`{ consumed: true, value }`. Failures roll back the credential and account changes.
|
|
748
771
|
Use database work only in the callback, and send notifications after commit.
|
|
772
|
+
The credential is consumed before the callback, so it composes with
|
|
773
|
+
`revokeAccountCredentials(claim.userId)`. That sweep also removes any pending
|
|
774
|
+
password-reset links; changing a password must retire recovery credentials too.
|
|
749
775
|
The existing `passwordResets(email)` flow supports email-addressed bcrypt tokens.
|
|
@@ -27,8 +27,9 @@ const products = await cache.mget<{ name: string }>(['product:42', 'product:43']
|
|
|
27
27
|
shipped) on every driver, memory included, so a value set with no TTL
|
|
28
28
|
expires after an hour. The `memory` export is a separate in-process
|
|
29
29
|
instance with no default expiry.
|
|
30
|
-
- `setForever` stores without expiry; `getTtl` reads
|
|
31
|
-
`ttl(key, seconds)` updates it.
|
|
30
|
+
- `setForever` stores without expiry; `getTtl` reads the absolute expiry in epoch
|
|
31
|
+
milliseconds (zero for forever); `ttl(key, seconds)` updates it.
|
|
32
|
+
Missing or expired values are undefined.
|
|
32
33
|
- `mset([{ key, value, ttl? }])` writes entries. `del(keyOrKeys)` and
|
|
33
34
|
`deleteMany(keys)` return counts; `remove(key)` returns void.
|
|
34
35
|
- `has/missing/take`, `keys(pattern?)`, `getStats`,
|
|
@@ -61,6 +62,15 @@ deploys, pointing `path` at a file the deploy preserves (the app's own SQLite
|
|
|
61
62
|
database works; the table is the driver's alone). `createCache(driver,
|
|
62
63
|
options?)` selects one of memory, redis, singlestore or sqlite.
|
|
63
64
|
|
|
65
|
+
SQLite TTLs, including `stdTTL`, must be finite non-negative seconds with
|
|
66
|
+
representable expiry timestamps. Zero alone means forever; fractions work.
|
|
67
|
+
Invalid TTLs throw RangeError before publication; invalid `mset` entries roll
|
|
68
|
+
back the batch. `getTtl` evicts expired entries instead of reporting stale
|
|
69
|
+
metadata. `mget` preserves special keys such as `__proto__` as own properties.
|
|
70
|
+
SQLite key globs are case-sensitive, with only `*` a wildcard; `?`, brackets,
|
|
71
|
+
percent, underscore and backslash are literal. An empty pattern matches an
|
|
72
|
+
empty key, while an omitted pattern lists all live keys in the prefix.
|
|
73
|
+
|
|
64
74
|
The `cache` export is the driver `config/cache.ts` selects, with its `prefix`
|
|
65
75
|
and `ttl` applied on every driver (memory also takes `maxKeys`, `useClones`
|
|
66
76
|
and `drivers.memory`), resolved on first use and once the app's config has
|
|
@@ -258,6 +258,11 @@ offset; the named IANA zone converts it into an instant. `isoInZone` retains
|
|
|
258
258
|
that zone's offset in serialized output rather than merely displaying a date.
|
|
259
259
|
`addCalendarMonths` clones and clamps the day; ordinary `DateTime.addMonths`
|
|
260
260
|
preserves native Date overflow instead. Do not interchange those contracts.
|
|
261
|
+
Calendar-month clamping keeps literal early years in local and UTC mode and throws
|
|
262
|
+
RangeError for an out-of-range result. A zero-month shift preserves the exact instant.
|
|
263
|
+
Named-zone conversion rejects impossible calendar and clock fields before applying
|
|
264
|
+
DST disambiguation. Era-aware offsets support year zero and BCE instants; `isoInZone`
|
|
265
|
+
retains seconds for expanded ISO years.
|
|
261
266
|
|
|
262
267
|
`zonedTimeToUtc` resolves DST edges the same way in every zone (RFC 5545 and
|
|
263
268
|
Temporal's `'compatible'` rule):
|
|
@@ -309,6 +314,7 @@ minutesUntil('2026-10-25', '09:00', 'Europe/Berlin', new Date('2026-10-24T22:00:
|
|
|
309
314
|
- `minutesUntil` keeps the seconds of `now` as a fraction; round where you
|
|
310
315
|
display or compare. Negative once the moment has passed.
|
|
311
316
|
- `addDays` refuses a result past 9999-12-31.
|
|
317
|
+
- `todayIn` returns canonical dates from 0000 through 9999 and rejects BCE or expanded-year dates.
|
|
312
318
|
|
|
313
319
|
### Reading `DATE` columns: `parseSqlDate` (`@stacksjs/database`)
|
|
314
320
|
|
|
@@ -363,6 +369,8 @@ clockMinutes, addClockMinutes and timeWindowsCover. Recurrence validation
|
|
|
363
369
|
rejects invalid weekday entries; expansion refuses excessive ranges and
|
|
364
370
|
midnight-crossing durations instead of silently truncating them. Adjacent
|
|
365
371
|
windows can cover one continuous slot. ScheduleInputError carries status 422.
|
|
372
|
+
Every supplied availability window is validated before checking coverage, even
|
|
373
|
+
when an earlier valid window already covers the slot.
|
|
366
374
|
|
|
367
375
|
localDateRange(from, to, ...zones) converts inclusive calendar days to an
|
|
368
376
|
exclusive-end UTC instant range in a selected valid zone, including DST days.
|
|
@@ -16,14 +16,14 @@ Browser runtime bindings are documented separately in `stacks-auto-imports`.
|
|
|
16
16
|
| `@stacksjs/alias` | [`stacks-alias`](../stacks-alias/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/alias/src/index.ts) | 3 |
|
|
17
17
|
| `@stacksjs/analytics` | [`stacks-analytics`](../stacks-analytics/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/analytics/src/index.ts) | 6 |
|
|
18
18
|
| `@stacksjs/api` | [`stacks-api`](../stacks-api/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/api/src/index.ts) | 12 |
|
|
19
|
-
| `@stacksjs/arrays` | [`stacks-arrays`](../stacks-arrays/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/arrays/src/index.ts) |
|
|
19
|
+
| `@stacksjs/arrays` | [`stacks-arrays`](../stacks-arrays/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/arrays/src/index.ts) | 12 |
|
|
20
20
|
| `@stacksjs/audio` | [`stacks-audio`](../stacks-audio/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/audio/src/index.ts) | 3 |
|
|
21
|
-
| `@stacksjs/auth` | [`stacks-auth`](../stacks-auth/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/index.ts) |
|
|
21
|
+
| `@stacksjs/auth` | [`stacks-auth`](../stacks-auth/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/index.ts) | 127 |
|
|
22
22
|
| `@stacksjs/browser` | [`stacks-browser`](../stacks-browser/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/browser/src/index.ts) | 8 |
|
|
23
23
|
| `@stacksjs/browser-extension` | [`stacks-browser-extension`](../stacks-browser-extension/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/browser-extension/src/index.ts) | 9 |
|
|
24
24
|
| `@stacksjs/buddy` | [`stacks-buddy`](../stacks-buddy/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/buddy/src/index.ts) | 179 |
|
|
25
25
|
| `@stacksjs/build` | [`stacks-build`](../stacks-build/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/build/src/index.ts) | 6 |
|
|
26
|
-
| `@stacksjs/cache` | [`stacks-cache`](../stacks-cache/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/cache/src/index.ts) |
|
|
26
|
+
| `@stacksjs/cache` | [`stacks-cache`](../stacks-cache/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/cache/src/index.ts) | 24 |
|
|
27
27
|
| `@stacksjs/calendar-api` | [`stacks-calendar`](../stacks-calendar/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/calendar-api/src/index.ts) | 5 |
|
|
28
28
|
| `@stacksjs/charts` | [`stacks-charts`](../stacks-charts/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/charts/src/index.ts) | 3 |
|
|
29
29
|
| `@stacksjs/chat` | [`stacks-chat`](../stacks-chat/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/chat/src/index.ts) | 6 |
|
|
@@ -36,7 +36,7 @@ Browser runtime bindings are documented separately in `stacks-auto-imports`.
|
|
|
36
36
|
| `@stacksjs/config` | [`stacks-config`](../stacks-config/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/config/src/index.ts) | 16 |
|
|
37
37
|
| `@stacksjs/cron` | [`stacks-cron`](../stacks-cron/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/cron/src/index.ts) | 6 |
|
|
38
38
|
| `@stacksjs/database` | [`stacks-database`](../stacks-database/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/index.ts) | 138 |
|
|
39
|
-
| `@stacksjs/datetime` | [`stacks-datetime`](../stacks-datetime/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/datetime/src/index.ts) |
|
|
39
|
+
| `@stacksjs/datetime` | [`stacks-datetime`](../stacks-datetime/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/datetime/src/index.ts) | 22 |
|
|
40
40
|
| `@stacksjs/defaults` | [`stacks-build`](../stacks-build/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/defaults/package.json) | 2 |
|
|
41
41
|
| `@stacksjs/deploy` | [`stacks-deploy`](../stacks-deploy/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/deploy/package.json) | 1 |
|
|
42
42
|
| `@stacksjs/desktop-build` | [`stacks-desktop`](../stacks-desktop/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/desktop/src/index.ts) | 15 |
|
|
@@ -64,9 +64,9 @@ Browser runtime bindings are documented separately in `stacks-auto-imports`.
|
|
|
64
64
|
| `@stacksjs/model-meta` | [`stacks-models`](../stacks-models/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/model-meta/src/index.ts) | 1 |
|
|
65
65
|
| `@stacksjs/newsletter` | [`stacks-newsletter`](../stacks-newsletter/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/newsletter/src/index.ts) | 7 |
|
|
66
66
|
| `@stacksjs/notifications` | [`stacks-notifications`](../stacks-notifications/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/notifications/src/index.ts) | 18 |
|
|
67
|
-
| `@stacksjs/objects` | [`stacks-objects`](../stacks-objects/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/objects/src/index.ts) |
|
|
67
|
+
| `@stacksjs/objects` | [`stacks-objects`](../stacks-objects/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/objects/src/index.ts) | 8 |
|
|
68
68
|
| `@stacksjs/orm` | [`stacks-orm`](../stacks-orm/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/index.ts) | 76 |
|
|
69
|
-
| `@stacksjs/pagination` | [`stacks-pagination`](../stacks-pagination/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/pagination/src/index.ts) |
|
|
69
|
+
| `@stacksjs/pagination` | [`stacks-pagination`](../stacks-pagination/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/pagination/src/index.ts) | 1 |
|
|
70
70
|
| `@stacksjs/path` | [`stacks-path`](../stacks-path/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/path/src/index.ts) | 13 |
|
|
71
71
|
| `@stacksjs/payments` | [`stacks-payments`](../stacks-payments/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/payments/src/index.ts) | 39 |
|
|
72
72
|
| `@stacksjs/push` | [`stacks-push`](../stacks-push/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/push/src/index.ts) | 8 |
|
|
@@ -85,16 +85,16 @@ Browser runtime bindings are documented separately in `stacks-auto-imports`.
|
|
|
85
85
|
| `@stacksjs/skills` | [`stacks-skills`](../stacks-skills/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/skills/src/index.ts) | 1 |
|
|
86
86
|
| `@stacksjs/slug` | [`stacks-slug`](../stacks-slug/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/slug/src/index.ts) | 5 |
|
|
87
87
|
| `@stacksjs/sms` | [`stacks-sms`](../stacks-sms/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/sms/src/index.ts) | 6 |
|
|
88
|
-
| `@stacksjs/socials` | [`stacks-socials`](../stacks-socials/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/socials/src/index.ts) |
|
|
89
|
-
| `@stacksjs/storage` | [`stacks-storage`](../stacks-storage/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/index.ts) |
|
|
90
|
-
| `@stacksjs/strings` | [`stacks-strings`](../stacks-strings/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/strings/src/index.ts) |
|
|
88
|
+
| `@stacksjs/socials` | [`stacks-socials`](../stacks-socials/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/socials/src/index.ts) | 18 |
|
|
89
|
+
| `@stacksjs/storage` | [`stacks-storage`](../stacks-storage/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/index.ts) | 48 |
|
|
90
|
+
| `@stacksjs/strings` | [`stacks-strings`](../stacks-strings/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/strings/src/index.ts) | 11 |
|
|
91
91
|
| `@stacksjs/testing` | [`stacks-testing`](../stacks-testing/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/testing/src/index.ts) | 24 |
|
|
92
92
|
| `@stacksjs/tinker` | [`stacks-repl`](../stacks-repl/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/tinker/src/index.ts) | 1 |
|
|
93
93
|
| `@stacksjs/tunnel` | [`stacks-tunnel`](../stacks-tunnel/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/tunnel/src/index.ts) | 1 |
|
|
94
94
|
| `@stacksjs/types` | [`stacks-types`](../stacks-types/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/types/src/index.ts) | 2 |
|
|
95
95
|
| `@stacksjs/ui` | [`stacks-ui`](../stacks-ui/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ui/src/index.ts) | 6 |
|
|
96
|
-
| `@stacksjs/utils` | [`stacks-utils`](../stacks-utils/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/index.ts) |
|
|
97
|
-
| `@stacksjs/validation` | [`stacks-validation`](../stacks-validation/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/validation/src/index.ts) |
|
|
96
|
+
| `@stacksjs/utils` | [`stacks-utils`](../stacks-utils/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/index.ts) | 22 |
|
|
97
|
+
| `@stacksjs/validation` | [`stacks-validation`](../stacks-validation/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/validation/src/index.ts) | 25 |
|
|
98
98
|
| `@stacksjs/video` | [`stacks-video`](../stacks-video/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/video/src/index.ts) | 3 |
|
|
99
99
|
| `@stacksjs/whois` | [`stacks-whois`](../stacks-whois/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/whois/src/index.ts) | 5 |
|
|
100
100
|
|
|
@@ -169,7 +169,7 @@ Declared runtime exports: `arr`.
|
|
|
169
169
|
|
|
170
170
|
Local source modules: [src/arr.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/arrays/src/arr.ts), [src/macro.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/arrays/src/macro.ts).
|
|
171
171
|
|
|
172
|
-
Evidence directory: [
|
|
172
|
+
Evidence directory: [12 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/arrays/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
|
|
173
173
|
|
|
174
174
|
### @stacksjs/audio
|
|
175
175
|
|
|
@@ -187,9 +187,9 @@ Guidance: [`stacks-auth`](../stacks-auth/SKILL.md). Source: [storage/framework/c
|
|
|
187
187
|
|
|
188
188
|
Declared runtime exports: `DEFAULT_ROLE_PACKS`, `createBqbRbacStore`, `generateTOTP`, `generateTOTPSecret`, `requestImpersonation`, `seedDefaultRoles`, `totpKeyUri`, `verifyTOTP`.
|
|
189
189
|
|
|
190
|
-
Local source modules: [src/authentication.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/authentication.ts), [src/authenticator.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/authenticator.ts), [src/authorizable.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/authorizable.ts), [src/browser-session.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/browser-session.ts), [src/client.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/client.ts), [src/cookie-auth.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/cookie-auth.ts), [src/credential-user.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/credential-user.ts), [src/email-verification.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/email-verification.ts), [src/gate.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/gate.ts), [src/impersonation-auth.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/impersonation-auth.ts), [src/impersonation-store.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/impersonation-store.ts), [src/impersonation.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/impersonation.ts), [src/magic-link.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/magic-link.ts), [src/middleware.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/middleware.ts), [src/oauth-authorization-codes.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-authorization-codes.ts), [src/oauth-authorization-endpoint.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-authorization-endpoint.ts), [src/oauth-authorization-requests.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-authorization-requests.ts), [src/oauth-authorization-response.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-authorization-response.ts), [src/oauth-authorization.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-authorization.ts), [src/oauth-browser-session.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-browser-session.ts), [src/oauth-client-registration.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-client-registration.ts), [src/oauth-consent.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-consent.ts), [src/oauth-delegated-access.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-delegated-access.ts), [src/oauth-dynamic-registration.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-dynamic-registration.ts), [src/oauth-grants.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-grants.ts), [src/oauth-introspection.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-introspection.ts), [src/oauth-metadata.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-metadata.ts), [src/oauth-pkce.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-pkce.ts), [src/oauth-protected-resource.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-protected-resource.ts), [src/oauth-provider.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-provider.ts), [src/oauth-pruning.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-pruning.ts), [src/oauth-revocation.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-revocation.ts), [src/oauth-server.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-server.ts), [src/oauth-token-endpoint.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-token-endpoint.ts), [src/oauth-token-exchange.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-token-exchange.ts), [src/oauth-token-request.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-token-request.ts), [src/oauth-token-response.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-token-response.ts), [src/page-gate.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/page-gate.ts), [src/passkey.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/passkey.ts), [src/passkeys.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/passkeys.ts), [src/password/reset-token.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/password/reset-token.ts), [src/password/reset.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/password/reset.ts), [src/permissions.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/permissions.ts), [src/policy.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/policy.ts), [src/rate-limiter.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/rate-limiter.ts), [src/rbac-seed.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/rbac-seed.ts), [src/rbac-store-bqb.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/rbac-store-bqb.ts), [src/rbac.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/rbac.ts), [src/referrals.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/referrals.ts), [src/register.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/register.ts), [src/request-token.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/request-token.ts), [src/session-auth.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/session-auth.ts), [src/session-handoff.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/session-handoff.ts), [src/socials.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/socials.ts), [src/team.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/team.ts), [src/tokens.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/tokens.ts), [src/two-factor.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/two-factor.ts), [src/user.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/user.ts).
|
|
190
|
+
Local source modules: [src/authentication.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/authentication.ts), [src/authenticator.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/authenticator.ts), [src/authorizable.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/authorizable.ts), [src/browser-session.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/browser-session.ts), [src/client.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/client.ts), [src/cookie-auth.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/cookie-auth.ts), [src/credential-user.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/credential-user.ts), [src/email-verification.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/email-verification.ts), [src/gate.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/gate.ts), [src/impersonation-auth.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/impersonation-auth.ts), [src/impersonation-store.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/impersonation-store.ts), [src/impersonation.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/impersonation.ts), [src/magic-link.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/magic-link.ts), [src/middleware.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/middleware.ts), [src/oauth-authorization-codes.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-authorization-codes.ts), [src/oauth-authorization-endpoint.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-authorization-endpoint.ts), [src/oauth-authorization-requests.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-authorization-requests.ts), [src/oauth-authorization-response.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-authorization-response.ts), [src/oauth-authorization.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-authorization.ts), [src/oauth-browser-session.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-browser-session.ts), [src/oauth-client-registration.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-client-registration.ts), [src/oauth-consent.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-consent.ts), [src/oauth-delegated-access.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-delegated-access.ts), [src/oauth-dynamic-registration.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-dynamic-registration.ts), [src/oauth-grants.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-grants.ts), [src/oauth-introspection.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-introspection.ts), [src/oauth-metadata.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-metadata.ts), [src/oauth-pkce.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-pkce.ts), [src/oauth-protected-resource.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-protected-resource.ts), [src/oauth-provider.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-provider.ts), [src/oauth-pruning.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-pruning.ts), [src/oauth-revocation.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-revocation.ts), [src/oauth-server.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-server.ts), [src/oauth-token-endpoint.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-token-endpoint.ts), [src/oauth-token-exchange.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-token-exchange.ts), [src/oauth-token-request.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-token-request.ts), [src/oauth-token-response.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-token-response.ts), [src/oauth-userinfo.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/oauth-userinfo.ts), [src/page-gate.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/page-gate.ts), [src/passkey.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/passkey.ts), [src/passkeys.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/passkeys.ts), [src/password/reset-token.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/password/reset-token.ts), [src/password/reset.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/password/reset.ts), [src/permissions.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/permissions.ts), [src/policy.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/policy.ts), [src/rate-limiter.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/rate-limiter.ts), [src/rbac-seed.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/rbac-seed.ts), [src/rbac-store-bqb.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/rbac-store-bqb.ts), [src/rbac.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/rbac.ts), [src/referrals.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/referrals.ts), [src/register.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/register.ts), [src/request-token.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/request-token.ts), [src/session-auth.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/session-auth.ts), [src/session-handoff.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/session-handoff.ts), [src/socials.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/socials.ts), [src/team.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/team.ts), [src/tokens.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/tokens.ts), [src/two-factor.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/two-factor.ts), [src/user.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/user.ts).
|
|
191
191
|
|
|
192
|
-
Evidence directory: [
|
|
192
|
+
Evidence directory: [127 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
|
|
193
193
|
|
|
194
194
|
### @stacksjs/browser
|
|
195
195
|
|
|
@@ -239,7 +239,7 @@ Read the entrypoint and package export map for re-exported or type-only surfaces
|
|
|
239
239
|
|
|
240
240
|
Local source modules: [src/drivers/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/cache/src/drivers/index.ts), [src/key.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/cache/src/key.ts).
|
|
241
241
|
|
|
242
|
-
Evidence directory: [
|
|
242
|
+
Evidence directory: [24 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/cache/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
|
|
243
243
|
|
|
244
244
|
### @stacksjs/calendar-api
|
|
245
245
|
|
|
@@ -367,7 +367,7 @@ Declared runtime exports: `DateTime`, `addCalendarMonths`, `addDays`, `dateForma
|
|
|
367
367
|
|
|
368
368
|
Local source modules: [src/calendar.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/datetime/src/calendar.ts), [src/format.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/datetime/src/format.ts), [src/local.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/datetime/src/local.ts), [src/now.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/datetime/src/now.ts), [src/parse.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/datetime/src/parse.ts), [src/schedule.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/datetime/src/schedule.ts), [src/zone.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/datetime/src/zone.ts).
|
|
369
369
|
|
|
370
|
-
Evidence directory: [
|
|
370
|
+
Evidence directory: [22 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/datetime/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
|
|
371
371
|
|
|
372
372
|
### @stacksjs/defaults
|
|
373
373
|
|
|
@@ -631,7 +631,7 @@ Declared runtime exports: `clearUndefined`, `deepMerge`, `hasOwnProperty`, `isKe
|
|
|
631
631
|
|
|
632
632
|
Local source modules: [src/transform.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/objects/src/transform.ts).
|
|
633
633
|
|
|
634
|
-
Evidence directory: [
|
|
634
|
+
Evidence directory: [8 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/objects/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
|
|
635
635
|
|
|
636
636
|
### @stacksjs/orm
|
|
637
637
|
|
|
@@ -649,6 +649,8 @@ Guidance: [`stacks-pagination`](../stacks-pagination/SKILL.md). Source: [storage
|
|
|
649
649
|
|
|
650
650
|
Declared runtime exports: `isCursorPaginator`, `isPaginator`, `isSimplePaginator`, `toCursorPaginator`, `toPaginator`, `toSimplePaginator`.
|
|
651
651
|
|
|
652
|
+
Evidence directory: [1 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/pagination/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
|
|
653
|
+
|
|
652
654
|
### @stacksjs/path
|
|
653
655
|
|
|
654
656
|
Guidance: [`stacks-path`](../stacks-path/SKILL.md). Source: [storage/framework/core/path/src/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/path/src/index.ts).
|
|
@@ -831,7 +833,7 @@ Read the entrypoint and package export map for re-exported or type-only surfaces
|
|
|
831
833
|
|
|
832
834
|
Local source modules: [src/abstract.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/socials/src/abstract.ts), [src/authorize.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/socials/src/authorize.ts), [src/drivers/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/socials/src/drivers/index.ts), [src/exceptions.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/socials/src/exceptions.ts), [src/flows.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/socials/src/flows.ts), [src/handoff.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/socials/src/handoff.ts), [src/identities.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/socials/src/identities.ts), [src/meta-graph.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/socials/src/meta-graph.ts), [src/publish.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/socials/src/publish.ts), [src/registry.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/socials/src/registry.ts), [src/token.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/socials/src/token.ts), [src/types.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/socials/src/types.ts).
|
|
833
835
|
|
|
834
|
-
Evidence directory: [
|
|
836
|
+
Evidence directory: [18 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/socials/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
|
|
835
837
|
|
|
836
838
|
### @stacksjs/storage
|
|
837
839
|
|
|
@@ -841,7 +843,7 @@ Declared runtime exports: `PathSanitizeError`, `Storage`, `StorageManager`, `Upl
|
|
|
841
843
|
|
|
842
844
|
Local source modules: [src/adapters/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/adapters/index.ts), [src/bounded-text-file.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/bounded-text-file.ts), [src/completed-artifact-directory.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/completed-artifact-directory.ts), [src/copy.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/copy.ts), [src/delete.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/delete.ts), [src/drivers/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/drivers/index.ts), [src/facade.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/facade.ts), [src/file-info.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/file-info.ts), [src/files.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/files.ts), [src/folders.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/folders.ts), [src/fs.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/fs.ts), [src/glob.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/glob.ts), [src/hash.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/hash.ts), [src/helpers.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/helpers.ts), [src/mime-verify.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/mime-verify.ts), [src/path-sanitize.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/path-sanitize.ts), [src/provision.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/provision.ts), [src/s3-presigned-post.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/s3-presigned-post.ts), [src/signed-url.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/signed-url.ts), [src/static-serve.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/static-serve.ts), [src/storage.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/storage.ts), [src/temporary-workspaces.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/temporary-workspaces.ts), [src/types.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/types.ts), [src/types/filesystem.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/types/filesystem.ts), [src/uploaded-file.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/uploaded-file.ts), [src/zip.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/zip.ts).
|
|
843
845
|
|
|
844
|
-
Evidence directory: [
|
|
846
|
+
Evidence directory: [48 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
|
|
845
847
|
|
|
846
848
|
### @stacksjs/strings
|
|
847
849
|
|
|
@@ -851,7 +853,7 @@ Declared runtime exports: `string`.
|
|
|
851
853
|
|
|
852
854
|
Local source modules: [src/string.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/strings/src/string.ts).
|
|
853
855
|
|
|
854
|
-
Evidence directory: [
|
|
856
|
+
Evidence directory: [11 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/strings/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
|
|
855
857
|
|
|
856
858
|
### @stacksjs/testing
|
|
857
859
|
|
|
@@ -909,7 +911,7 @@ Declared runtime exports: `browserUtils`, `clamp`, `notNullish`, `retry`, `useOn
|
|
|
909
911
|
|
|
910
912
|
Local source modules: [src/bytes.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/bytes.ts), [src/clean.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/clean.ts), [src/colors.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/colors.ts), [src/config.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/config.ts), [src/debounce.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/debounce.ts), [src/detect.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/detect.ts), [src/equal.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/equal.ts), [src/errors.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/errors.ts), [src/export-size.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/export-size.ts), [src/find.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/find.ts), [src/git.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/git.ts), [src/hash.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/hash.ts), [src/helpers.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/helpers.ts), [src/macroable.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/macroable.ts), [src/markdown.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/markdown.ts), [src/merge.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/merge.ts), [src/observer.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/observer.ts), [src/pipe.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/pipe.ts), [src/pipeline.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/pipeline.ts), [src/safe-json.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/safe-json.ts), [src/size.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/size.ts), [src/versions.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/src/versions.ts).
|
|
911
913
|
|
|
912
|
-
Evidence directory: [
|
|
914
|
+
Evidence directory: [22 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/utils/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
|
|
913
915
|
|
|
914
916
|
### @stacksjs/validation
|
|
915
917
|
|
|
@@ -919,7 +921,7 @@ Declared runtime exports: `applyConditionals`, `isArray`, `isBoolean`, `isFuncti
|
|
|
919
921
|
|
|
920
922
|
Local source modules: [src/input.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/validation/src/input.ts), [src/messages.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/validation/src/messages.ts), [src/reporter.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/validation/src/reporter.ts), [src/schema.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/validation/src/schema.ts), [src/validator.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/validation/src/validator.ts).
|
|
921
923
|
|
|
922
|
-
Evidence directory: [
|
|
924
|
+
Evidence directory: [25 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/validation/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
|
|
923
925
|
|
|
924
926
|
### @stacksjs/video
|
|
925
927
|
|
|
@@ -81,16 +81,10 @@ const result = deepMerge(target, source)
|
|
|
81
81
|
const merged = deepMerge(defaults, userConfig, overrides)
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
-
The `DeepMerge<T, S>` type
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
? DeepMerge<F[K], S[K]>
|
|
89
|
-
: K extends keyof S ? S[K]
|
|
90
|
-
: K extends keyof F ? F[K]
|
|
91
|
-
: never
|
|
92
|
-
}>
|
|
93
|
-
```
|
|
84
|
+
The `DeepMerge<T, S>` type from `@stacksjs/types` preserves primitive, array and
|
|
85
|
+
built-in instance values while merging record keys recursively. A replaced Date
|
|
86
|
+
target no longer exposes Date methods. The authoritative type is in
|
|
87
|
+
`core/types/src/utils.ts`; verify consumers against built declarations.
|
|
94
88
|
|
|
95
89
|
### objectPick -- Pick Properties by Key
|
|
96
90
|
```typescript
|
|
@@ -153,7 +147,7 @@ if (isKeyOf(config, key)) {
|
|
|
153
147
|
|
|
154
148
|
### objectKeys -- Strictly Typed Object.keys
|
|
155
149
|
```typescript
|
|
156
|
-
function objectKeys<T extends object>(obj: T): Array
|
|
150
|
+
function objectKeys<T extends object>(obj: T): Array<ObjectStringKey<T>>
|
|
157
151
|
```
|
|
158
152
|
|
|
159
153
|
Returns `Object.keys(obj)` with a stricter return type than the built-in `Object.keys()` (which returns `string[]`).
|
|
@@ -166,10 +160,13 @@ const keys = objectKeys(user)
|
|
|
166
160
|
|
|
167
161
|
### objectEntries -- Strictly Typed Object.entries
|
|
168
162
|
```typescript
|
|
169
|
-
function objectEntries<T extends object>(obj: T): Array<
|
|
163
|
+
function objectEntries<T extends object>(obj: T): Array<ObjectStringEntry<T>>
|
|
170
164
|
```
|
|
171
165
|
|
|
172
166
|
Returns `Object.entries(obj)` with a stricter return type than the built-in `Object.entries()` (which returns `[string, any][]`).
|
|
167
|
+
`ObjectStringKey<T>` stringifies numeric keys and excludes symbols;
|
|
168
|
+
`ObjectStringEntry<T>` pairs those keys with the visited values. Both functions
|
|
169
|
+
declare their return types explicitly so built declarations preserve the arrays.
|
|
173
170
|
|
|
174
171
|
```typescript
|
|
175
172
|
const user = { name: 'John', age: 30 }
|
|
@@ -197,9 +194,14 @@ The root also exports `omit`, `pickBy`, `omitBy`, `mapValues`, `mapKeys`,
|
|
|
197
194
|
`invert`, `isEmptyObject`, `getPath` and `setPath` from `transform.ts`.
|
|
198
195
|
Use a path array such as `['items', 0, 'name']`, not an assumed dot-string
|
|
199
196
|
parser. `getPath(source, path, fallback?)` reads a nested value;
|
|
197
|
+
`getPath` returns `unknown` even with a fallback; narrow a present value before use.
|
|
198
|
+
`mapValues` preserves optional properties and omits symbol keys in its result type,
|
|
199
|
+
matching its enumerable string-key traversal. The pure `@stacksjs/objects/transform`
|
|
200
|
+
entry ships both JavaScript and declarations.
|
|
200
201
|
`setPath(source, path, value)` performs a persistent update by copying containers
|
|
201
202
|
along the path and sharing unaffected siblings. Treat paths as application-owned
|
|
202
|
-
inputs; this helper is not a path authorization boundary.
|
|
203
|
+
inputs; this helper is not a path authorization boundary. Array `length` updates
|
|
204
|
+
use native length semantics on the copy and reject invalid lengths. Choose `objectPick` for key-based selection and
|
|
203
205
|
`pickBy` for predicate selection. Read transform signatures for callback
|
|
204
206
|
argument order; `objectMap`'s `(key, value)` is not a universal convention.
|
|
205
207
|
Retained evidence: `core/objects/tests/transform.test.ts`.
|
|
@@ -212,6 +214,7 @@ Retained evidence: `core/objects/tests/transform.test.ts`.
|
|
|
212
214
|
- `deepMerge` does NOT deeply merge arrays -- arrays from source replace arrays in target entirely.
|
|
213
215
|
- `deepMerge` merges only plain objects key by key: a Date, Map, Set or class instance from a source is assigned as
|
|
214
216
|
is, and a string, array or number in the target is replaced by a source's object.
|
|
217
|
+
A non-plain nested target also gives way to a plain source record.
|
|
215
218
|
- `deepMerge` uses `isObject()` from `@stacksjs/validation` combined with `!Array.isArray()` to determine mergeability.
|
|
216
219
|
- A `"__proto__"` key is data, never a prototype. `JSON.parse` and the router's request input keep one as an own key:
|
|
217
220
|
`deepMerge` skips it and merges only into the target's own properties, and the transform helpers keep it as an own
|
|
@@ -25,7 +25,14 @@ native parser. Do not treat a cursor as a trusted SQL fragment.
|
|
|
25
25
|
|
|
26
26
|
toPaginator, toSimplePaginator and toCursorPaginator adapt source results.
|
|
27
27
|
isPaginator/isSimplePaginator/isCursorPaginator identify the canonical shapes;
|
|
28
|
-
they
|
|
28
|
+
they require every mandatory metadata field, safe positive page integers,
|
|
29
|
+
non-negative integer totals and correctly typed optional links. They do not
|
|
30
|
+
authenticate a source or validate rows. Empty out-of-range pages remain valid.
|
|
31
|
+
|
|
32
|
+
BigInt cursors serialize as exact decimal strings. Composite cursors encode
|
|
33
|
+
BigInts as decimal string entries inside a JSON array. Keep those tokens intact
|
|
34
|
+
through query parameters; the ORM parser restores tuples and SQL bindings
|
|
35
|
+
accept decimal strings without a lossy Number conversion.
|
|
29
36
|
|
|
30
37
|
## HTTP and UI
|
|
31
38
|
|
|
@@ -34,6 +34,20 @@ instance redirect. X always uses PKCE; its verifier lives in the base class
|
|
|
34
34
|
(getPkceVerifier/withCodeVerifier), so a callback on a fresh instance can
|
|
35
35
|
restore it. Registry descriptors say `pkce` (X) and `nonce` (Apple).
|
|
36
36
|
|
|
37
|
+
## Signing in with another Stacks application
|
|
38
|
+
|
|
39
|
+
`StacksIssuerProvider({ issuer, clientId, clientSecret, redirectUrl, scopes,
|
|
40
|
+
resource, userInfoUrl })` signs people in with another Stacks app that runs
|
|
41
|
+
`oauthProvider`: Authorization Code with S256 PKCE (always on, so carry
|
|
42
|
+
`getPkceVerifier()` in the flow and restore it with `withCodeVerifier()`) and
|
|
43
|
+
client_secret_basic. Send `resource` whenever the issuer binds scopes to one.
|
|
44
|
+
`getTokens(code)` keeps the refresh token that `getAccessToken` drops;
|
|
45
|
+
`refreshTokens(rt)` rotates it, `revokeToken(rt)` unlinks (RFC 7009) and
|
|
46
|
+
`getClaims(token)` / `getUserByToken(token)` read the issuer's
|
|
47
|
+
`oauthUserInfoResponse` endpoint, keyed by its pairwise `sub`. Only a boolean
|
|
48
|
+
`email_verified` counts as verified. It is constructed directly, not through the
|
|
49
|
+
registry.
|
|
50
|
+
|
|
37
51
|
## Flow state (login CSRF)
|
|
38
52
|
|
|
39
53
|
A callback that exchanges any `code` signs the victim into the attacker's
|
|
@@ -291,6 +291,14 @@ const local = createLocalStorage({ root: './storage' })
|
|
|
291
291
|
- MIME type detection is extension-based (supports txt, html, css, js, json, xml, pdf, zip, jpg, jpeg, png, gif, svg, mp4, mp3, wav)
|
|
292
292
|
- `list()` returns an async iterable; supports `deep: true` for recursive listing
|
|
293
293
|
|
|
294
|
+
### Memory adapter stream lifecycle
|
|
295
|
+
|
|
296
|
+
A move to the same normalized path is a no-op for an existing file, preserving
|
|
297
|
+
bytes, visibility and modification time. A missing source still throws.
|
|
298
|
+
`putStream` aborts pending reads promptly, cancels the reader and never publishes
|
|
299
|
+
partial contents. Stream writes release reader locks on success, failure and
|
|
300
|
+
abort. Existing destination contents survive a failed or aborted upload.
|
|
301
|
+
|
|
294
302
|
### S3 Adapter (`S3StorageAdapter`)
|
|
295
303
|
|
|
296
304
|
```typescript
|
|
@@ -429,6 +429,8 @@ interface PluralizeOptions { count?, inclusive? }
|
|
|
429
429
|
- `helpers.ts` exports `toString()` (Object.prototype.toString, not ordinary
|
|
430
430
|
string coercion) and `mask(value, character, index, length?)`. Mask supports
|
|
431
431
|
a negative starting index and uses the first character of its mask string.
|
|
432
|
+
Index and explicit length must be safe integers, otherwise it throws RangeError.
|
|
433
|
+
Negative integer lengths mask nothing. Coordinates count Unicode code points.
|
|
432
434
|
|
|
433
435
|
## CSV exports
|
|
434
436
|
|
|
@@ -45,7 +45,7 @@ export { clamp, notNullish, retry, useOnline } from '@stacksjs/browser'
|
|
|
45
45
|
|
|
46
46
|
## Deep Merge (`merge.ts`)
|
|
47
47
|
|
|
48
|
-
Replacement for `defu`.
|
|
48
|
+
Replacement for `defu`. Only own enumerable string keys are read. Arrays concatenate; plain records recursively merge. Non-plain nested values (including URL, ArrayBuffer, Blob and class instances) retain identity. A plain record replaces a non-plain target rather than copying its indices or prototype fields. A `"__proto__"` key is skipped, as defu skips it, so a parsed request body cannot set the result's prototype.
|
|
49
49
|
|
|
50
50
|
```typescript
|
|
51
51
|
import { merge, mergeDefaults, createMerger, defu } from '@stacksjs/utils'
|
|
@@ -79,6 +79,13 @@ throttledFn.cancel() // cancel pending invocation
|
|
|
79
79
|
await delay(1000) // sleep for 1 second (returns Promise<void>)
|
|
80
80
|
```
|
|
81
81
|
|
|
82
|
+
Calls and debounce `flush()` return `ReturnType<T> | undefined`: before any
|
|
83
|
+
invocation there is no result; suppressed calls return the last result,
|
|
84
|
+
including a Promise for async callbacks. Both preserve the callback receiver.
|
|
85
|
+
Pending arguments are consumed before invoking, so reentrant calls survive.
|
|
86
|
+
`cancel()` clears pending work; throttle cancellation also resets its interval.
|
|
87
|
+
Manual debounce `flush()` invokes pending work even with `trailing: false`.
|
|
88
|
+
|
|
82
89
|
Note: unlike some implementations, this debounce does NOT support `maxWait`. The throttle uses `Date.now()` for timing, not setTimeout stacking.
|
|
83
90
|
|
|
84
91
|
## Color Output (`colors.ts`)
|
|
@@ -156,6 +163,10 @@ readableSize(1024) // alias for formatBytes
|
|
|
156
163
|
|
|
157
164
|
Units: B, KB, MB, GB, TB, PB, EB, ZB, YB (decimal) or B, KiB, MiB, GiB, TiB, PiB, EiB, ZiB, YiB (binary).
|
|
158
165
|
|
|
166
|
+
`parseBytes` accepts a complete decimal with an optional known decimal or
|
|
167
|
+
binary unit (case-insensitive). It rejects partial numbers, unknown units,
|
|
168
|
+
trailing text and non-finite output. Fractions and negative values are allowed.
|
|
169
|
+
|
|
159
170
|
## Export Size Calculation (`size.ts`)
|
|
160
171
|
|
|
161
172
|
```typescript
|
|
@@ -433,19 +444,27 @@ Glob belongs to `@stacksjs/storage`; it is not re-exported from the utils root.
|
|
|
433
444
|
|
|
434
445
|
## Safe serialization and typed composition
|
|
435
446
|
|
|
436
|
-
`safeJsonParse(text, fallback?)
|
|
437
|
-
|
|
438
|
-
|
|
447
|
+
`safeJsonParse(text, fallback?)` and `safeJsonParseResult` make parse failure
|
|
448
|
+
behavior explicit. A parse generic result type is a caller annotation, not
|
|
449
|
+
validation of untrusted JSON.
|
|
439
450
|
Validate decoded objects at the request boundary before treating them as a
|
|
440
451
|
model, config, or provider payload.
|
|
441
452
|
|
|
453
|
+
`safeJsonStringify` returns `string | undefined`, matching JSON for unsupported
|
|
454
|
+
roots (undefined, functions and symbols). Shared non-cyclic objects serialize
|
|
455
|
+
at every occurrence; only ancestor cycles become `[Circular]`. BigInts become
|
|
456
|
+
decimal strings. User getters and `toJSON` methods can still throw.
|
|
457
|
+
|
|
442
458
|
`pipe(value, ...steps)` applies ordinary typed unary functions left to right.
|
|
443
459
|
`piped(...steps)` returns the composed function and `tap(effect)` returns a
|
|
444
460
|
pass-through step. These differ from middleware-style `Pipeline`, whose pipes
|
|
445
461
|
receive a next function. Choose the simple function seam for data transforms.
|
|
446
462
|
|
|
447
463
|
`isDeepEqual` now compares Date, RegExp, Map, Set, typed arrays and ArrayBuffers
|
|
448
|
-
by value and tracks circular pairs.
|
|
464
|
+
by value and tracks active circular pairs. Cycle topology/sharing need not
|
|
465
|
+
match when fields are structurally equal. Objects require matching own
|
|
466
|
+
enumerable string keys. Arrays distinguish a hole from an own undefined slot;
|
|
467
|
+
two corresponding holes compare equal. Host objects and Errors remain identity
|
|
449
468
|
comparisons. Read retained equal tests for a non-plain object rather than
|
|
450
469
|
assuming every object with similar printable fields is equal.
|
|
451
470
|
|
|
@@ -274,14 +274,17 @@ const result = await validateField('User', { name: 'John', email: 'john@example.
|
|
|
274
274
|
```
|
|
275
275
|
|
|
276
276
|
Behavior:
|
|
277
|
-
1. Finds
|
|
277
|
+
1. Finds exact model filenames or qualified paths recursively, preferring app overrides
|
|
278
278
|
2. Extracts validation rules from model attributes
|
|
279
|
-
3.
|
|
280
|
-
4.
|
|
281
|
-
5. Validates
|
|
279
|
+
3. Accepts attribute and snake-case column names, preferring the attribute spelling when both are supplied
|
|
280
|
+
4. Applies custom messages to reported failures without executing predicates again or replacing the shared provider
|
|
281
|
+
5. Validates through the context-aware object schema
|
|
282
282
|
6. Throws `HttpError(422)` with error JSON on validation failure
|
|
283
283
|
7. Throws `HttpError(404)` if model not found
|
|
284
|
-
8.
|
|
284
|
+
8. An optional default excuses absence, never a supplied invalid value
|
|
285
|
+
|
|
286
|
+
Ambiguous bare model names require a qualified path. Declared fields and conditional
|
|
287
|
+
siblings use own properties; inherited values never count as submitted input.
|
|
285
288
|
|
|
286
289
|
### `customValidate(attributes, params)`
|
|
287
290
|
|
|
@@ -314,13 +317,17 @@ isObjectNotEmpty(undefined) // false
|
|
|
314
317
|
|
|
315
318
|
## Error Reporter (`reporter.ts`)
|
|
316
319
|
|
|
317
|
-
|
|
320
|
+
Validation operations start an async-local latest-error scope before their first await.
|
|
321
|
+
Successful operations clear prior failures; `getErrors()` returns an independent snapshot.
|
|
322
|
+
Standalone adapters that report directly create a scope with `withValidationContext()`:
|
|
318
323
|
|
|
319
324
|
```typescript
|
|
320
|
-
import { reportError, getErrors } from '@stacksjs/validation'
|
|
325
|
+
import { reportError, getErrors, withValidationContext } from '@stacksjs/validation'
|
|
321
326
|
|
|
322
|
-
|
|
323
|
-
|
|
327
|
+
withValidationContext(() => {
|
|
328
|
+
reportError([{ message: 'Invalid', value: '', field: 'email' }])
|
|
329
|
+
const errors = getErrors() // this scope's latest MessageObject[]
|
|
330
|
+
})
|
|
324
331
|
```
|
|
325
332
|
|
|
326
333
|
Interface: `{ message: string, value: string, field: string }`
|
|
@@ -388,7 +395,7 @@ type ValidationString = ValidationRule
|
|
|
388
395
|
- Numeric classification functions (`isEvenOrOdd`, etc.) return string defaults for non-numbers rather than throwing
|
|
389
396
|
- Schema validators map to database column types -- `schema.integer()` creates an integer column, `schema.string()` creates a varchar, etc.
|
|
390
397
|
- `validateField` converts attribute names to snake_case using `snakeCase()` from `@stacksjs/strings`
|
|
391
|
-
- `validateField`
|
|
398
|
+
- `validateField` validates supplied values even when their attributes declare defaults
|
|
392
399
|
- Validation error messages are customizable per-rule in model definitions via the `message` object
|
|
393
400
|
- The schema export is Stacks' proxy over the underlying validation instance, with typed object/array/enum inference, file validation and conditionals; it is not the same object as the upstream v export
|
|
394
401
|
- Custom validators can be added with `schema.custom<T>(fn, message)` for types not covered by built-in validators
|
|
@@ -397,16 +404,23 @@ type ValidationString = ValidationRule
|
|
|
397
404
|
|
|
398
405
|
## Request, conditional and file validation
|
|
399
406
|
|
|
400
|
-
The root validate(requestOrRecord, rules) is async, returns the validated payload
|
|
407
|
+
The root validate(requestOrRecord, rules, options?) is async, returns the validated payload
|
|
401
408
|
and throws HttpError(422) with normalized field errors on failure. Rules are
|
|
402
|
-
validators or { rule, message? }
|
|
403
|
-
|
|
404
|
-
|
|
409
|
+
validators or { rule, message? }. Plain records are application data, including URL,
|
|
410
|
+
query and params fields. Native Request bodies and enhanced request.all() are read
|
|
411
|
+
directly; jsonBody/formBody adapters remain supported. URL/query/params-only adapters
|
|
412
|
+
select { source: 'request' }; { source: 'data' } forces data interpretation.
|
|
413
|
+
Returned values contain declared supplied fields, recursively through object shapes
|
|
414
|
+
and array.each() elements. Opaque validators retain their accepted values. Use the
|
|
415
|
+
returned cleaned payload at the boundary, including action getValidated()/safe().
|
|
405
416
|
|
|
406
417
|
Schema declarations can use the narrow `@stacksjs/validation/runtime` entry.
|
|
407
418
|
The schema proxy adds typed object/array/enum inference and conditional rules:
|
|
408
419
|
when(sibling, literalOrPredicate, refine) applies cross-field refinements through
|
|
409
|
-
objectWithContext
|
|
420
|
+
objectWithContext, action validations, model writes and validateModelInput.
|
|
421
|
+
Model contexts recognize attribute/column aliases. Creates include declared defaults;
|
|
422
|
+
partial updates validate supplied fields and siblings without loading stored values.
|
|
423
|
+
Refinements preserve reusable schemas. sometimes has the underlying optional/empty-value semantics.
|
|
410
424
|
Read object-with-context.ts before treating presence-only rules as stricter than
|
|
411
425
|
they are. Inferred object shapes are native, not a hand-written request interface.
|
|
412
426
|
|
|
@@ -417,19 +431,17 @@ An upload is a class instance (the router's `UploadedFile`); a plain object, whi
|
|
|
417
431
|
is what a JSON body gives for the same field name, is refused.
|
|
418
432
|
|
|
419
433
|
registerRule/getCustomRule, unique(table,column,exceptId?), exists(table,column)
|
|
420
|
-
and validateFieldAsync support application async validation.
|
|
421
|
-
|
|
422
|
-
validation, not authorization or a replacement for database constraints. Validate
|
|
434
|
+
and validateFieldAsync support application async validation. These helpers propagate query failures
|
|
435
|
+
instead of approving unchecked values. Keep operational failures separate from invalid input. Validate
|
|
423
436
|
uniqueness at the durable write boundary and handle a uniqueness violation there.
|
|
424
437
|
|
|
425
|
-
|
|
426
|
-
request-local concurrent state. Read errors on the returned/raised validation
|
|
427
|
-
result instead. Local is.ts helpers and legacy rules/type declarations are not
|
|
438
|
+
Local is.ts helpers and legacy rules/type declarations are not
|
|
428
439
|
automatically all public exports from the root.
|
|
429
440
|
|
|
430
441
|
Source: `storage/framework/core/validation/src/index.ts`, runtime.ts,
|
|
431
442
|
schema.ts, request-validator.ts, conditional.ts, file-validator.ts and validator.ts.
|
|
432
|
-
Tests: conditional.test.ts,
|
|
443
|
+
Tests: conditional.test.ts, conditional-boundaries.test.ts, input-contracts.test.ts,
|
|
444
|
+
boundary-e2e.test.ts, file-validator.test.ts, async-rules.test.ts,
|
|
433
445
|
runtime-entry.test.ts and type-inference.test-d.ts under core/validation/tests.
|
|
434
446
|
|
|
435
447
|
## Custom action input
|
|
@@ -456,6 +468,11 @@ null, and absent boolean input returns undefined. Boolean input accepts JSON
|
|
|
456
468
|
booleans and the explicit form values `true`, `false`, `1`, `0` and their strings,
|
|
457
469
|
and a checkbox's `on` and `off`.
|
|
458
470
|
|
|
471
|
+
Numeric bounds reject NaN and inverted intervals; -Infinity and Infinity explicitly
|
|
472
|
+
mean an unbounded lower/upper endpoint. Text maxLength requires a nonnegative safe
|
|
473
|
+
integer. Invalid configuration throws RangeError even for absent optional input.
|
|
474
|
+
Unsafe whole numbers are rejected whether or not integer-only input was requested.
|
|
475
|
+
|
|
459
476
|
`validateModelInput` checks only supplied fields using `getDefinition()` rules.
|
|
460
477
|
The action still selects writable fields, requires creation fields and validates
|
|
461
478
|
relationships. Use the transaction callback executor for all atomic persistence.
|
package/ide/vscode/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"publisher": "Stacks",
|
|
3
3
|
"name": "vscode-stacks",
|
|
4
4
|
"displayName": "Stacks",
|
|
5
|
-
"version": "0.75.
|
|
5
|
+
"version": "0.75.450",
|
|
6
6
|
"description": "Stacks, built into VS Code: stx templates, pickier linting and formatting, encrypted env files, the dev server preview and every buddy command. No other extensions required.",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"funding": "https://github.com/sponsors/chrisbbreuer",
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@stacksjs/defaults",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"sideEffects": false,
|
|
5
|
-
"version": "0.75.
|
|
5
|
+
"version": "0.75.450",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "git+https://github.com/stacksjs/stacks.git",
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@iconify-json/f7": "^1.2.2",
|
|
47
47
|
"@iconify-json/hugeicons": "^1.2.35",
|
|
48
|
-
"@stacksjs/mobile": "0.75.
|
|
49
|
-
"@stacksjs/sanitizer": "0.2.
|
|
50
|
-
"@stacksjs/stx": "0.2.
|
|
48
|
+
"@stacksjs/mobile": "0.75.450",
|
|
49
|
+
"@stacksjs/sanitizer": "0.2.792",
|
|
50
|
+
"@stacksjs/stx": "0.2.792",
|
|
51
51
|
"@xterm/addon-fit": "^0.11.0",
|
|
52
52
|
"@xterm/xterm": "^6.0.0",
|
|
53
53
|
"ts-qr-codes": "^0.1.8"
|
|
@@ -3,12 +3,13 @@ interface AvatarProps {
|
|
|
3
3
|
src?: string
|
|
4
4
|
alt?: string
|
|
5
5
|
name?: string
|
|
6
|
+
initials?: string
|
|
6
7
|
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'
|
|
7
8
|
rounded?: 'sm' | 'md' | 'lg' | 'full'
|
|
8
9
|
status?: 'online' | 'offline' | 'away' | 'busy'
|
|
9
10
|
}
|
|
10
11
|
|
|
11
|
-
const { src = '', alt = '', name = '', size = 'md', rounded = 'full', status = '' } = defineProps<AvatarProps>()
|
|
12
|
+
const { src = '', alt = '', name = '', initials: suppliedInitials = '', size = 'md', rounded = 'full', status = '' } = defineProps<AvatarProps>()
|
|
12
13
|
|
|
13
14
|
const sizeClasses = {
|
|
14
15
|
xs: 'h-5 w-5 text-[10px]',
|
|
@@ -50,10 +51,10 @@ function getInitials(fullName: string) {
|
|
|
50
51
|
return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase()
|
|
51
52
|
}
|
|
52
53
|
|
|
53
|
-
const initials = getInitials(name)
|
|
54
|
+
const initials = suppliedInitials || getInitials(name)
|
|
54
55
|
|
|
55
56
|
// Background colors for initials (consistent based on name)
|
|
56
|
-
const bgColors = [
|
|
57
|
+
export const bgColors = [
|
|
57
58
|
'bg-red-500/15 text-red-600 dark:bg-red-400/20 dark:text-red-400',
|
|
58
59
|
'bg-orange-500/15 text-orange-600 dark:bg-orange-400/20 dark:text-orange-400',
|
|
59
60
|
'bg-yellow-500/15 text-yellow-600 dark:bg-yellow-400/20 dark:text-yellow-400',
|
|
@@ -66,33 +67,42 @@ const bgColors = [
|
|
|
66
67
|
'bg-pink-500/15 text-pink-600 dark:bg-pink-400/20 dark:text-pink-400'
|
|
67
68
|
]
|
|
68
69
|
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
defineClientPayload({ bgColors })
|
|
71
|
+
</script>
|
|
72
|
+
<script client>
|
|
73
|
+
const avatarSrc = useReactiveProp('src', {{ src }})
|
|
74
|
+
const avatarAlt = useReactiveProp('alt', {{ alt }})
|
|
75
|
+
const avatarName = useReactiveProp('name', {{ name }})
|
|
76
|
+
const avatarInitials = useReactiveProp('initials', {{ suppliedInitials }})
|
|
77
|
+
const avatarDescription = derived(() => avatarAlt() || avatarName() || 'Avatar')
|
|
78
|
+
const avatarFallback = derived(() => {
|
|
79
|
+
if (avatarInitials()) return avatarInitials()
|
|
80
|
+
const parts = String(avatarName() || '').trim().split(/\s+/).filter(Boolean)
|
|
81
|
+
if (!parts.length) return ''
|
|
82
|
+
return (parts.length === 1 ? parts[0].slice(0, 2) : parts[0][0] + parts[parts.length - 1][0]).toUpperCase()
|
|
83
|
+
})
|
|
84
|
+
const avatarColor = derived(() => {
|
|
85
|
+
const name = String(avatarName() || '')
|
|
86
|
+
if (!name) return 'bg-black/[0.06] text-neutral-500 dark:bg-white/10 dark:text-neutral-400'
|
|
71
87
|
let hash = 0
|
|
72
|
-
for (let i = 0; i <
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const bgColor = name ? bgColors[getBgColorIndex(name)] : 'bg-black/[0.06] text-neutral-500 dark:bg-white/10 dark:text-neutral-400'
|
|
88
|
+
for (let i = 0; i < name.length; i++) hash = name.charCodeAt(i) + ((hash << 5) - hash)
|
|
89
|
+
const colors = bgColors
|
|
90
|
+
return colors[Math.abs(hash) % colors.length]
|
|
91
|
+
})
|
|
79
92
|
</script>
|
|
80
93
|
<div class="inline-flex relative flex-shrink-0">
|
|
81
|
-
@if(src)
|
|
82
94
|
<img
|
|
95
|
+
:if="avatarSrc"
|
|
83
96
|
src="{{ src }}"
|
|
97
|
+
:src="avatarSrc"
|
|
84
98
|
alt="{{ alt || name || 'Avatar' }}"
|
|
99
|
+
:alt="avatarDescription"
|
|
85
100
|
class="object-cover {{ sizeClasses[size] }} {{ radiusClasses[rounded] }}"
|
|
86
101
|
>
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
<span>{{ initials }}</span>
|
|
91
|
-
@else
|
|
92
|
-
<span aria-hidden="true" class="h-1/2 w-1/2 text-neutral-400 i-hugeicons-user"></span>
|
|
93
|
-
@endif
|
|
102
|
+
<div :if="!avatarSrc" :class="avatarColor" class="inline-flex items-center justify-center font-medium {{ sizeClasses[size] }} {{ radiusClasses[rounded] }}">
|
|
103
|
+
<span :if="avatarFallback" :text="avatarFallback">{{ initials }}</span>
|
|
104
|
+
<span :if="!avatarFallback" aria-hidden="true" class="h-1/2 w-1/2 text-neutral-400 i-hugeicons-user"></span>
|
|
94
105
|
</div>
|
|
95
|
-
@endif
|
|
96
106
|
|
|
97
107
|
@if(status)
|
|
98
108
|
<span class="absolute bottom-0 right-0 rounded-full ring-2 ring-white dark:ring-neutral-900 {{ statusColors[status] }} {{ statusSizes[size] }}"></span>
|