@stacksjs/defaults 0.75.467 → 0.75.473
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-actions/SKILL.md +1 -1
- package/ai/skills/stacks-mobile/SKILL.md +15 -2
- package/ai/skills/stacks-native/CATALOG.md +15 -15
- package/ai/skills/stacks-storage/UPLOADS-AND-DISKS.md +19 -0
- package/app/Actions/Dashboard/Content/FileDestroyAction.ts +3 -4
- package/app/Actions/Dashboard/Content/FileDirectoryStoreAction.ts +3 -4
- package/app/Actions/Dashboard/Content/FileDuplicateAction.ts +3 -4
- package/app/Actions/Dashboard/Content/FileFavoriteAction.ts +3 -4
- package/app/Actions/Dashboard/Content/FileIndexAction.ts +3 -5
- package/app/Actions/Dashboard/Content/FileRenameAction.ts +3 -4
- package/app/Actions/Dashboard/Content/FileReprocessAction.ts +3 -4
- package/app/Actions/Dashboard/Content/FileTagsAction.ts +3 -4
- package/app/Actions/Dashboard/Content/FileUploadAction.ts +3 -4
- package/app/Actions/Dashboard/Content/FileVisibilityAction.ts +3 -4
- package/app/Actions/Dashboard/Content/file-response.test.ts +61 -0
- package/app/Actions/Dashboard/Content/file-response.ts +18 -0
- package/app/Actions/Dashboard/dashboard-response.ts +20 -0
- package/functions/dashboard-badge.test.ts +42 -0
- package/functions/dashboard-badge.ts +104 -0
- package/functions/dashboard-button.test.ts +33 -0
- package/functions/dashboard-button.ts +44 -0
- package/ide/vscode/package.json +1 -1
- package/package.json +4 -4
- package/resources/components/Dashboard/Analytics/AnalyticsHub.stx +10 -1
- package/resources/components/Dashboard/Data/DataRecords.stx +1 -1
- package/resources/components/Dashboard/Email/InboxMessageList.stx +1 -1
- package/resources/components/Dashboard/MobileSidebar.stx +4 -1
- package/resources/components/Dashboard/Models/ModelsOverview.stx +1 -1
- package/resources/components/Dashboard/UI/Badge.stx +21 -44
- package/resources/components/Dashboard/UI/Button.stx +13 -24
- package/resources/components/Dashboard/UI/Card.stx +8 -0
- package/resources/functions/dashboard/sidebar.ts +12 -3
- package/views/dashboard/layouts/default.stx +43 -18
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: stacks-actions
|
|
3
|
-
description: Use when working with Stacks server actions - creating actions in app/Actions/, auto-generated API actions from the useApi model trait, the
|
|
3
|
+
description: Use when working with Stacks server actions - creating actions in app/Actions/, auto-generated API actions from the useApi model trait, the 676 default framework actions (auth, dashboard, commerce, content, deployment, jobs), action request/response handling, or action registration. Covers @stacksjs/actions and storage/framework/defaults/app/Actions/.
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: Bun >= 1.3.0, TypeScript
|
|
6
6
|
allowed-tools: Read Edit Write Bash Grep Glob
|
|
@@ -177,8 +177,10 @@ browser with an explicit return path.
|
|
|
177
177
|
|
|
178
178
|
A named route parameter may need to exclude website paths. Configure
|
|
179
179
|
`nativeScreenConstraints` on both platforms using the exact route key, for
|
|
180
|
-
example `{ '/:username': { username: { pattern: '[a-z]+', exclude: ['terms'],
|
|
181
|
-
|
|
180
|
+
example `{ '/:username': { username: { pattern: '[a-z]+', exclude: ['terms'], normalize: 'lowercase' } } }`.
|
|
181
|
+
Normalization lowercases decoded parameters and excluded values independently
|
|
182
|
+
of device locale; the match returns the normalized parameter. Patterns then
|
|
183
|
+
match the complete value case-sensitively; use syntax shared by JavaScript,
|
|
182
184
|
Foundation and Kotlin. Constraints apply before query items and preserve static
|
|
183
185
|
route priority. The build requires Craft's `nativeRouteConstraints` capability
|
|
184
186
|
and stops if an installed host would ignore the configuration. For application
|
|
@@ -292,6 +294,17 @@ appears; `buddy release:notes <tag> --testflight` does it later, and
|
|
|
292
294
|
`buddy release:notes <tag> --play` prints the 500-character Google Play text.
|
|
293
295
|
The code is `@stacksjs/actions/release-notes`.
|
|
294
296
|
|
|
297
|
+
Set `ios.testFlightGroups` to the names of existing internal groups (for example,
|
|
298
|
+
`['Internal testers']`) to distribute processed builds to those groups.
|
|
299
|
+
`release:ios --wait` confirms `IN_BETA_TESTING` and the configured memberships
|
|
300
|
+
before retiring older builds; upload or `VALID` processing alone is insufficient.
|
|
301
|
+
Without a wait, older builds stay available. Resume a tagged release with
|
|
302
|
+
`buddy release:testflight <tag> --wait [minutes]`, preserving its existing
|
|
303
|
+
localized notes; `--dry-run` validates the
|
|
304
|
+
existing internal groups without assigning or expiring builds. This creates no
|
|
305
|
+
testers, public links or external beta review submissions. `--keep-builds` retains
|
|
306
|
+
that many older processed builds in addition to the newly available release.
|
|
307
|
+
|
|
295
308
|
## Device search index
|
|
296
309
|
|
|
297
310
|
`spotlight` says what of the application's own content a device may index, so
|
|
@@ -11,7 +11,7 @@ Browser runtime bindings are documented separately in `stacks-auto-imports`.
|
|
|
11
11
|
| Package | Task guidance | Source entry | Retained tests |
|
|
12
12
|
|---|---|---|---|
|
|
13
13
|
| `@stacksjs/action-runner` | [`stacks-actions`](../stacks-actions/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/action-runner/src/index.ts) | 1 |
|
|
14
|
-
| `@stacksjs/actions` | [`stacks-actions`](../stacks-actions/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/index.ts) |
|
|
14
|
+
| `@stacksjs/actions` | [`stacks-actions`](../stacks-actions/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/index.ts) | 102 |
|
|
15
15
|
| `@stacksjs/ai` | [`stacks-ai`](../stacks-ai/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/ai/src/index.ts) | 21 |
|
|
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) | 7 |
|
|
@@ -31,11 +31,11 @@ Browser runtime bindings are documented separately in `stacks-auto-imports`.
|
|
|
31
31
|
| `@stacksjs/cloud` | [`stacks-cloud`](../stacks-cloud/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/cloud/src/index.ts) | 10 |
|
|
32
32
|
| `@stacksjs/cms` | [`stacks-cms`](../stacks-cms/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/cms/src/index.ts) | 5 |
|
|
33
33
|
| `@stacksjs/collections` | [`stacks-collections`](../stacks-collections/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/collections/src/index.ts) | 2 |
|
|
34
|
-
| `@stacksjs/commerce` | [`stacks-commerce`](../stacks-commerce/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/commerce/src/index.ts) |
|
|
34
|
+
| `@stacksjs/commerce` | [`stacks-commerce`](../stacks-commerce/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/commerce/src/index.ts) | 15 |
|
|
35
35
|
| `@stacksjs/composables` | [`stacks-composables`](../stacks-composables/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/composables/src/index.ts) | 18 |
|
|
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
|
-
| `@stacksjs/database` | [`stacks-database`](../stacks-database/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/index.ts) |
|
|
38
|
+
| `@stacksjs/database` | [`stacks-database`](../stacks-database/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/index.ts) | 140 |
|
|
39
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 |
|
|
@@ -43,7 +43,7 @@ Browser runtime bindings are documented separately in `stacks-auto-imports`.
|
|
|
43
43
|
| `@stacksjs/development` | [`stacks-development`](../stacks-development/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/development/package.json) | 1 |
|
|
44
44
|
| `@stacksjs/dns` | [`stacks-dns`](../stacks-dns/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/dns/src/index.ts) | 4 |
|
|
45
45
|
| `@stacksjs/docs` | [`stacks-docs`](../stacks-docs/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/docs/src/index.ts) | 2 |
|
|
46
|
-
| `@stacksjs/email` | [`stacks-email`](../stacks-email/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/email/src/index.ts) |
|
|
46
|
+
| `@stacksjs/email` | [`stacks-email`](../stacks-email/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/email/src/index.ts) | 24 |
|
|
47
47
|
| `@stacksjs/enums` | [`stacks-enums`](../stacks-enums/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/enums/src/index.ts) | 3 |
|
|
48
48
|
| `@stacksjs/env` | [`stacks-env`](../stacks-env/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/env/src/index.ts) | 31 |
|
|
49
49
|
| `@stacksjs/error-handling` | [`stacks-error-handling`](../stacks-error-handling/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/error-handling/src/index.ts) | 10 |
|
|
@@ -86,7 +86,7 @@ Browser runtime bindings are documented separately in `stacks-auto-imports`.
|
|
|
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
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) |
|
|
89
|
+
| `@stacksjs/storage` | [`stacks-storage`](../stacks-storage/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/index.ts) | 50 |
|
|
90
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 |
|
|
@@ -115,11 +115,11 @@ Evidence directory: [1 retained tests](https://github.com/stacksjs/stacks/blob/m
|
|
|
115
115
|
|
|
116
116
|
Guidance: [`stacks-actions`](../stacks-actions/SKILL.md). Source: [storage/framework/core/actions/src/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/index.ts).
|
|
117
117
|
|
|
118
|
-
Declared runtime exports: `BlogAdminError`, `DEFAULT_IOS_DEPENDENCIES`, `DEFAULT_STX_LINT_CONFIG`, `IosToolchainError`, `PUBLICATION_CHECK_SCRIPT`, `XCODE_NOTE`, `assertPublicationAllowed`, `blogSlugify`, `craftSupportsWebkit`, `createComponent`, `createDatabase`, `createFactory`, `createFunction`, `createLanguage`, `createMail`, `createMiddleware`, `createMigration`, `createModel`, `createNotification`, `createPage`, `deleteBlogPost`, `describeDanglingRouteActions`, `describeGitHubRelease`, `discoverPackages`, `ensureDiscoveredPackages`, `findDanglingRouteActions`, `formatProject`, `getBlogPost`, `installStack`, `isDryRunActive`, `lintFix`, `lintProject`, `listBlogPosts`, `listStacks`, `loadIosDependencies`, `loadStxLintConfig`, `macosAgentActionFiles`, `macosAgentDevFiles`, `macosAgentDevManifest`, `macosAgentEntry`, `macosAgentRouteFiles`, `makeAction`, `makeCertificate`, `makeCommand`, `makeComponent`, `makeDatabase`, `makeFunction`, `makeJob`, `makeLanguage`, `makeMail`, `makeNotification`, `makePage`, `makePolicy`, `makeQueueTable`, `makeResource`, `makeStack`, `measureDefaultsDrift`, `pantryExecutable`, `pantryInstallArgs`, `parseFields`, `parseGitHubRemote`, `prepareMacosAgent`, `prepareMacosNative`, `publicationChannels`, `publishGitHubRelease`, `resolveStxSource`, `resolveXcodegen`, `runAdd`, `runCommit`, `runMake`, `runStxLint`, `saveBlogPost`, `scaffoldCrud`, `setDryRun`, `summarizeStructureChanges`, `uninstallStack`, `validateReleaseEvidencePlan`, `verifyReleaseEvidence`, `xcodeDeveloperDir`.
|
|
118
|
+
Declared runtime exports: `BlogAdminError`, `DEFAULT_IOS_DEPENDENCIES`, `DEFAULT_STX_LINT_CONFIG`, `IosToolchainError`, `PUBLICATION_CHECK_SCRIPT`, `XCODE_NOTE`, `assertPublicationAllowed`, `blogSlugify`, `craftSupportsWebkit`, `createComponent`, `createDatabase`, `createFactory`, `createFunction`, `createLanguage`, `createMail`, `createMiddleware`, `createMigration`, `createModel`, `createNotification`, `createPage`, `deleteBlogPost`, `describeDanglingRouteActions`, `describeGitHubRelease`, `discoverPackages`, `ensureDiscoveredPackages`, `evaluateReviewOsEvidence`, `findDanglingRouteActions`, `formatProject`, `getBlogPost`, `inspectReviewOsEvidence`, `installStack`, `isDryRunActive`, `lintFix`, `lintProject`, `listBlogPosts`, `listStacks`, `loadIosDependencies`, `loadStxLintConfig`, `macosAgentActionFiles`, `macosAgentDevFiles`, `macosAgentDevManifest`, `macosAgentEntry`, `macosAgentRouteFiles`, `makeAction`, `makeCertificate`, `makeCommand`, `makeComponent`, `makeDatabase`, `makeFunction`, `makeJob`, `makeLanguage`, `makeMail`, `makeNotification`, `makePage`, `makePolicy`, `makeQueueTable`, `makeResource`, `makeStack`, `measureDefaultsDrift`, `pantryExecutable`, `pantryInstallArgs`, `parseFields`, `parseGitHubRemote`, `prepareMacosAgent`, `prepareMacosNative`, `publicationChannels`, `publishGitHubRelease`, `resolveStxSource`, `resolveXcodegen`, `runAdd`, `runCommit`, `runMake`, `runStxLint`, `saveBlogPost`, `scaffoldCrud`, `setDryRun`, `summarizeStructureChanges`, `uninstallStack`, `validateReleaseEvidencePlan`, `verifyReleaseEvidence`, `xcodeDeveloperDir`.
|
|
119
119
|
|
|
120
|
-
Local source modules: [src/action.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/action.ts), [src/add.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/add.ts), [src/blog-admin.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/blog-admin.ts), [src/build/ios-toolchain.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/build/ios-toolchain.ts), [src/build/macos-native.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/build/macos-native.ts), [src/commit.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/commit.ts), [src/dev/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/dev/index.ts), [src/discover-packages.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/discover-packages.ts), [src/generate/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/generate/index.ts), [src/github-release.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/github-release.ts), [src/helpers/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/helpers/index.ts), [src/library/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/library/index.ts), [src/lint/lint.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/lint/lint.ts), [src/lint/stx-gate.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/lint/stx-gate.ts), [src/make-command.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/make-command.ts), [src/make-job.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/make-job.ts), [src/make-policy.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/make-policy.ts), [src/make-resource.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/make-resource.ts), [src/make.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/make.ts), [src/publication-preflight.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/publication-preflight.ts), [src/release-evidence.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/release-evidence.ts), [src/scaffold-crud.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/scaffold-crud.ts), [src/setup/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/setup/index.ts), [src/stacks.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/stacks.ts), [src/stx-source.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/stx-source.ts), [src/upgrade/package-project.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/upgrade/package-project.ts), [src/upgrade/route-actions.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/upgrade/route-actions.ts).
|
|
120
|
+
Local source modules: [src/action.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/action.ts), [src/add.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/add.ts), [src/blog-admin.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/blog-admin.ts), [src/build/ios-toolchain.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/build/ios-toolchain.ts), [src/build/macos-native.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/build/macos-native.ts), [src/commit.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/commit.ts), [src/dev/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/dev/index.ts), [src/discover-packages.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/discover-packages.ts), [src/generate/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/generate/index.ts), [src/github-release.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/github-release.ts), [src/helpers/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/helpers/index.ts), [src/library/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/library/index.ts), [src/lint/lint.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/lint/lint.ts), [src/lint/stx-gate.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/lint/stx-gate.ts), [src/make-command.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/make-command.ts), [src/make-job.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/make-job.ts), [src/make-policy.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/make-policy.ts), [src/make-resource.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/make-resource.ts), [src/make.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/make.ts), [src/publication-preflight.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/publication-preflight.ts), [src/release-evidence.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/release-evidence.ts), [src/reviewos-evidence.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/reviewos-evidence.ts), [src/scaffold-crud.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/scaffold-crud.ts), [src/setup/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/setup/index.ts), [src/stacks.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/stacks.ts), [src/stx-source.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/stx-source.ts), [src/upgrade/package-project.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/upgrade/package-project.ts), [src/upgrade/route-actions.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/src/upgrade/route-actions.ts).
|
|
121
121
|
|
|
122
|
-
Evidence directory: [
|
|
122
|
+
Evidence directory: [102 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/actions/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
|
|
123
123
|
|
|
124
124
|
### @stacksjs/ai
|
|
125
125
|
|
|
@@ -317,7 +317,7 @@ Declared runtime exports: `PriceFormatError`, `auctions`, `breakdownFor`, `carts
|
|
|
317
317
|
|
|
318
318
|
Local source modules: [src/auctions/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/commerce/src/auctions/index.ts), [src/carts/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/commerce/src/carts/index.ts), [src/catalog.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/commerce/src/catalog.ts), [src/coupons/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/commerce/src/coupons/index.ts), [src/customers/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/commerce/src/customers/index.ts), [src/devices/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/commerce/src/devices/index.ts), [src/errors/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/commerce/src/errors/index.ts), [src/gift-cards/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/commerce/src/gift-cards/index.ts), [src/imports/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/commerce/src/imports/index.ts), [src/inventory.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/commerce/src/inventory.ts), [src/money.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/commerce/src/money.ts), [src/orders/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/commerce/src/orders/index.ts), [src/payments/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/commerce/src/payments/index.ts), [src/products/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/commerce/src/products/index.ts), [src/receipt-text.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/commerce/src/receipt-text.ts), [src/receipts/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/commerce/src/receipts/index.ts), [src/register.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/commerce/src/register.ts), [src/releases.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/commerce/src/releases.ts), [src/sales-tax.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/commerce/src/sales-tax.ts), [src/shippings/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/commerce/src/shippings/index.ts), [src/tax-input.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/commerce/src/tax-input.ts), [src/tax/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/commerce/src/tax/index.ts), [src/waitlists/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/commerce/src/waitlists/index.ts), [src/waitlists/restaurant/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/commerce/src/waitlists/restaurant/index.ts).
|
|
319
319
|
|
|
320
|
-
Evidence directory: [
|
|
320
|
+
Evidence directory: [15 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/commerce/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
|
|
321
321
|
|
|
322
322
|
### @stacksjs/composables
|
|
323
323
|
|
|
@@ -357,7 +357,7 @@ Declared runtime exports: `Database`, `EntityQueryBuilder`, `__flushAfterCommitN
|
|
|
357
357
|
|
|
358
358
|
Local source modules: [src/affected-rows.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/affected-rows.ts), [src/auth-tables.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/auth-tables.ts), [src/custom/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/custom/index.ts), [src/database.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/database.ts), [src/datetime-columns.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/datetime-columns.ts), [src/ddl-constraints.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/ddl-constraints.ts), [src/defaults.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/defaults.ts), [src/dialect.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/dialect.ts), [src/driver-config.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/driver-config.ts), [src/drivers/dynamodb.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/drivers/dynamodb.ts), [src/drivers/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/drivers/index.ts), [src/ensure-database.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/ensure-database.ts), [src/erd.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/erd.ts), [src/fk-audit.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/fk-audit.ts), [src/framework-renames.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/framework-renames.ts), [src/framework-route-admission.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/framework-route-admission.ts), [src/hand-written-migrations.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/hand-written-migrations.ts), [src/ignored-migrations.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/ignored-migrations.ts), [src/index-shape.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/index-shape.ts), [src/managed-columns.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/managed-columns.ts), [src/migration-dialect.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/migration-dialect.ts), [src/migration-ledger.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/migration-ledger.ts), [src/migration-names.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/migration-names.ts), [src/migration-path.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/migration-path.ts), [src/migrations.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/migrations.ts), [src/model-sources.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/model-sources.ts), [src/notification-tables.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/notification-tables.ts), [src/package-migrations.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/package-migrations.ts), [src/package-models.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/package-models.ts), [src/query-logger.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/query-logger.ts), [src/rbac-tables.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/rbac-tables.ts), [src/relation-columns.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/relation-columns.ts), [src/replicas.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/replicas.ts), [src/row-lease.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/row-lease.ts), [src/row-lock.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/row-lock.ts), [src/safe-migrations.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/safe-migrations.ts), [src/schema-align.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/schema-align.ts), [src/schema-drift.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/schema-drift.ts), [src/seeder.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/seeder.ts), [src/shadowed-models.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/shadowed-models.ts), [src/sql-helpers.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/sql-helpers.ts), [src/trait-tables.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/trait-tables.ts), [src/transaction-context.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/transaction-context.ts), [src/transaction-options.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/transaction-options.ts), [src/types.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/types.ts), [src/unique-audit.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/unique-audit.ts), [src/utc-defaults.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/utc-defaults.ts), [src/utils.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/utils.ts), [src/uuid-columns.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/uuid-columns.ts), [src/vschema.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/src/vschema.ts).
|
|
359
359
|
|
|
360
|
-
Evidence directory: [
|
|
360
|
+
Evidence directory: [140 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/database/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
|
|
361
361
|
|
|
362
362
|
### @stacksjs/datetime
|
|
363
363
|
|
|
@@ -431,7 +431,7 @@ Declared runtime exports: `discoverMailables`, `inlineCss`, `loadSampleProps`, `
|
|
|
431
431
|
|
|
432
432
|
Local source modules: [src/css-inliner.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/email/src/css-inliner.ts), [src/drivers/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/email/src/drivers/index.ts), [src/email.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/email/src/email.ts), [src/idempotency.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/email/src/idempotency.ts), [src/inbound-parser.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/email/src/inbound-parser.ts), [src/inbox-mailbox.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/email/src/inbox-mailbox.ts), [src/mailable.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/email/src/mailable.ts), [src/mime-preview.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/email/src/mime-preview.ts), [src/preview-ui.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/email/src/preview-ui.ts), [src/preview.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/email/src/preview.ts), [src/sdk/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/email/src/sdk/index.ts), [src/suppression.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/email/src/suppression.ts), [src/template.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/email/src/template.ts), [src/types.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/email/src/types.ts), [src/unsubscribe.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/email/src/unsubscribe.ts), [src/webhook-dedup.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/email/src/webhook-dedup.ts), [src/webhook-events.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/email/src/webhook-events.ts), [src/webhook-handlers.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/email/src/webhook-handlers.ts), [src/webhook-signatures.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/email/src/webhook-signatures.ts).
|
|
433
433
|
|
|
434
|
-
Evidence directory: [
|
|
434
|
+
Evidence directory: [24 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/email/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
|
|
435
435
|
|
|
436
436
|
### @stacksjs/enums
|
|
437
437
|
|
|
@@ -637,7 +637,7 @@ Evidence directory: [10 retained tests](https://github.com/stacksjs/stacks/blob/
|
|
|
637
637
|
|
|
638
638
|
Guidance: [`stacks-orm`](../stacks-orm/SKILL.md). Source: [storage/framework/core/orm/src/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/index.ts).
|
|
639
639
|
|
|
640
|
-
Declared runtime exports: `Activity`, `AnalyticsEvent`, `Auction`, `AuctionItem`, `Author`, `Automation`, `AutomationRun`, `BILLABLE_INSTANCE_METHODS`, `Bid`, `Board`, `BoardColumn`, `Campaign`, `CampaignSend`, `CampaignVariant`, `Card`, `CardAttachment`, `CardComment`, `Cart`, `CartItem`, `Categorizable`, `Category`, `Comment`, `CommunicationSuppression`, `ConsentEvent`, `Coupon`, `Courier`, `CourierPing`, `Customer`, `DeliveryRoute`, `DeliveryStop`, `Deployment`, `DigitalDelivery`, `EmailIdempotency`, `EmailList`, `EmailListSubscriber`, `EmailSuppression`, `EmailWebhookEvent`, `ErrorModel`, `FailedJob`, `FeedbackToken`, `Form`, `FormField`, `FormSubmission`, `GdprRequest`, `GiftCard`, `Job`, `Label`, `LicenseKey`, `Log`, `LoyaltyPoint`, `LoyaltyReward`, `MagicLinkToken`, `MailPreference`, `Manufacturer`, `Menu`, `MenuItem`, `Notification`, `NotificationDelivery`, `Order`, `OrderIdempotency`, `OrderItem`, `Page`, `PageRevision`, `Payment`, `PaymentMethod`, `PaymentProduct`, `PaymentTransaction`, `PaymentWebhookEvent`, `PersonalAccessToken`, `Pledge`, `Post`, `PrintDevice`, `Product`, `ProductUnit`, `ProductVariant`, `QueryLog`, `Receipt`, `Redirect`, `Referral`, `ReferralCode`, `Release`, `Request`, `Review`, `SenderDomain`, `ShippingMethod`, `ShippingRate`, `ShippingZone`, `Site`, `SiteDomain`, `SmsOptOut`, `SocialAccount`, `SocialPost`, `StorageItem`, `StorageItemTask`, `Subscriber`, `SubscriberEmail`, `Subscription`, `SubscriptionNotOwnedError`, `Tag`, `TaxRate`, `Team`, `TeamInvitation`, `TeamMember`, `Transaction`, `UsageEvent`, `User`, `WaitlistProduct`, `WaitlistRestaurant`, `Websocket`, `buildDatabaseSchema`, `collectEncryptedAttributes`, `createAuditMethods`, `createCategorizableMethods`, `createCommentableMethods`, `createLikeableMethods`, `createTaggableMethods`, `customerOwnership`, `decryptValue`, `encryptValue`, `enrichPaginatorUrls`, `filterFillable`, `frameworkModelFeature`, `getWritableFields`, `isBillable`, `isCursorPaginator`, `isEncrypted`, `isPaginator`, `isSimplePaginator`, `isUniqueViolation`, `mapWriteError`, `modelGlobalNames`, `ormReady`, `parentOwnership`, `parseCursor`, `renderDatabaseTypeFile`, `resolveCursorArgs`, `resolvePageArgs`, `selfOwnership`, `setAuditUser`, `siteOwnership`, `teamMembershipOwnership`, `toCursorPaginator`, `toPaginator`, `toSimplePaginator`, `toSnakeCaseKeys`.
|
|
640
|
+
Declared runtime exports: `Activity`, `AnalyticsEvent`, `Auction`, `AuctionItem`, `Author`, `Automation`, `AutomationRun`, `BILLABLE_INSTANCE_METHODS`, `Bid`, `Board`, `BoardColumn`, `Campaign`, `CampaignSend`, `CampaignVariant`, `Card`, `CardAttachment`, `CardComment`, `Cart`, `CartItem`, `Categorizable`, `Category`, `Comment`, `CommunicationSuppression`, `ConsentEvent`, `Coupon`, `Courier`, `CourierPing`, `Customer`, `DeliveryRoute`, `DeliveryStop`, `Deployment`, `DigitalDelivery`, `EmailIdempotency`, `EmailList`, `EmailListSubscriber`, `EmailSuppression`, `EmailWebhookEvent`, `ErrorModel`, `FailedJob`, `FeedbackToken`, `Form`, `FormField`, `FormSubmission`, `GdprRequest`, `GiftCard`, `Job`, `Label`, `LicenseKey`, `Log`, `LoyaltyPoint`, `LoyaltyReward`, `MagicLinkToken`, `MailPreference`, `Manufacturer`, `Menu`, `MenuItem`, `ModelUnavailableError`, `Notification`, `NotificationDelivery`, `Order`, `OrderIdempotency`, `OrderItem`, `Page`, `PageRevision`, `Payment`, `PaymentMethod`, `PaymentProduct`, `PaymentTransaction`, `PaymentWebhookEvent`, `PersonalAccessToken`, `Pledge`, `Post`, `PrintDevice`, `Product`, `ProductUnit`, `ProductVariant`, `QueryLog`, `Receipt`, `Redirect`, `Referral`, `ReferralCode`, `Release`, `Request`, `Review`, `SenderDomain`, `ShippingMethod`, `ShippingRate`, `ShippingZone`, `Site`, `SiteDomain`, `SmsOptOut`, `SocialAccount`, `SocialPost`, `StorageItem`, `StorageItemTask`, `Subscriber`, `SubscriberEmail`, `Subscription`, `SubscriptionNotOwnedError`, `Tag`, `TaxRate`, `Team`, `TeamInvitation`, `TeamMember`, `Transaction`, `UsageEvent`, `User`, `WaitlistProduct`, `WaitlistRestaurant`, `Websocket`, `buildDatabaseSchema`, `collectEncryptedAttributes`, `createAuditMethods`, `createCategorizableMethods`, `createCommentableMethods`, `createLikeableMethods`, `createTaggableMethods`, `customerOwnership`, `decryptValue`, `encryptValue`, `enrichPaginatorUrls`, `filterFillable`, `frameworkModelFeature`, `getWritableFields`, `isBillable`, `isCursorPaginator`, `isEncrypted`, `isPaginator`, `isSimplePaginator`, `isUniqueViolation`, `mapWriteError`, `modelGlobalNames`, `ormReady`, `parentOwnership`, `parseCursor`, `renderDatabaseTypeFile`, `resolveCursorArgs`, `resolvePageArgs`, `selfOwnership`, `setAuditUser`, `siteOwnership`, `teamMembershipOwnership`, `toCursorPaginator`, `toPaginator`, `toSimplePaginator`, `toSnakeCaseKeys`.
|
|
641
641
|
|
|
642
642
|
Local source modules: [src/auto-crud.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/auto-crud.ts), [src/batch-loader.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/batch-loader.ts), [src/db.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/db.ts), [src/define-model.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/define-model.ts), [src/extend-model.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/extend-model.ts), [src/gdpr/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/gdpr/index.ts), [src/generate-database-schema.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/generate-database-schema.ts), [src/locked-row.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/locked-row.ts), [src/messaging.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/messaging.ts), [src/model-types.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/model-types.ts), [src/ownership.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/ownership.ts), [src/paginator-request.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/paginator-request.ts), [src/row-token.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/row-token.ts), [src/subquery.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/subquery.ts), [src/traits/audit.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/traits/audit.ts), [src/traits/billable.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/traits/billable.ts), [src/traits/categorizable.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/traits/categorizable.ts), [src/traits/commentable.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/traits/commentable.ts), [src/traits/likeable.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/traits/likeable.ts), [src/traits/taggable.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/traits/taggable.ts), [src/transaction.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/transaction.ts), [src/types.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/types.ts), [src/utils/encrypted.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/utils/encrypted.ts), [src/utils/prunable.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/orm/src/utils/prunable.ts).
|
|
643
643
|
|
|
@@ -839,11 +839,11 @@ Evidence directory: [18 retained tests](https://github.com/stacksjs/stacks/blob/
|
|
|
839
839
|
|
|
840
840
|
Guidance: [`stacks-storage`](../stacks-storage/SKILL.md). Source: [storage/framework/core/storage/src/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/index.ts).
|
|
841
841
|
|
|
842
|
-
Declared runtime exports: `PathSanitizeError`, `Storage`, `StorageManager`, `UploadedFile`, `azureDisk`, `backblazeDisk`, `clearRevokedSignedStorageTokens`, `configFromEnv`, `createSignedStorageToken`, `detectMimeFromMagicBytes`, `ensureBucket`, `ensureConfiguredBuckets`, `fileInfo`, `fileInfoFromBytes`, `fileKind`, `filebaseDisk`, `gcsDisk`, `hetznerDisk`, `isPreviewable`, `isSignedStorageTokenRevoked`, `localDisk`, `parseDiskPath`, `r2Disk`, `resolveMime`, `revokeSignedStorageToken`, `s3Disk`, `sanitizePresignedDir`, `sanitizePresignedFilename`, `serveFile`, `signS3PresignedPost`, `storage`, `uploadedFile`, `uploadedFiles`, `verifySignedStorageToken`, `verifyUploadedMime`.
|
|
842
|
+
Declared runtime exports: `DirectoryListingChangedError`, `PathSanitizeError`, `Storage`, `StorageManager`, `UploadedFile`, `azureDisk`, `backblazeDisk`, `clearRevokedSignedStorageTokens`, `configFromEnv`, `createSignedStorageToken`, `detectMimeFromMagicBytes`, `ensureBucket`, `ensureConfiguredBuckets`, `fileInfo`, `fileInfoFromBytes`, `fileKind`, `filebaseDisk`, `gcsDisk`, `hetznerDisk`, `isPreviewable`, `isSignedStorageTokenRevoked`, `localDisk`, `parseDiskPath`, `r2Disk`, `resolveMime`, `revokeSignedStorageToken`, `s3Disk`, `sanitizePresignedDir`, `sanitizePresignedFilename`, `serveFile`, `signS3PresignedPost`, `storage`, `uploadedFile`, `uploadedFiles`, `verifySignedStorageToken`, `verifyUploadedMime`.
|
|
843
843
|
|
|
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).
|
|
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/directory-page.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/storage/src/directory-page.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).
|
|
845
845
|
|
|
846
|
-
Evidence directory: [
|
|
846
|
+
Evidence directory: [50 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.
|
|
847
847
|
|
|
848
848
|
### @stacksjs/strings
|
|
849
849
|
|
|
@@ -131,3 +131,22 @@ tenant. Underlying optional methods still need driver support.
|
|
|
131
131
|
|
|
132
132
|
Source: `signed-url.ts`, `static-serve.ts`, `adapters/scoped.ts`; evidence:
|
|
133
133
|
`tests/scoped.test.ts`, `static-serve.test.ts`, `path-sanitize.test.ts`.
|
|
134
|
+
|
|
135
|
+
## Resumable inventories
|
|
136
|
+
|
|
137
|
+
Use a disk's optional `listPage(path, { limit, cursor })` for a durable shallow
|
|
138
|
+
inventory. Each page contains at most 1,000 entries (100 by default) and an
|
|
139
|
+
opaque `nextCursor`. Persist the cursor only in the transaction that enrolls the
|
|
140
|
+
whole page; retrying a page must be idempotent. A null cursor completes the pass.
|
|
141
|
+
Do not emulate this API by materializing `list()` when an adapter lacks it.
|
|
142
|
+
|
|
143
|
+
S3 forwards the provider's continuation token and MaxKeys. Local/Bun disks on
|
|
144
|
+
Darwin or glibc Linux use a bounded 32 KiB native directory block plus its record
|
|
145
|
+
position, preserving that cursor across process restarts without rescanning the
|
|
146
|
+
preceding directory. Local cursors bind to directory identity and modification
|
|
147
|
+
times. `DirectoryListingChangedError` means restart that directory from null;
|
|
148
|
+
previously enrolled records remain valid. Concurrent additions are therefore
|
|
149
|
+
visited during the restarted pass. Symlinks and special files are excluded.
|
|
150
|
+
Permission/provider failures throw and must leave the durable cursor unchanged.
|
|
151
|
+
Windows and unsupported libc hosts fail explicitly rather than claiming a
|
|
152
|
+
bounded inventory through an unbounded fallback.
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { RequestInstance } from '@stacksjs/types'
|
|
2
2
|
import { Action } from '@stacksjs/actions/runtime'
|
|
3
3
|
import { response } from '@stacksjs/router'
|
|
4
|
-
import {
|
|
4
|
+
import { deleteDashboardFile } from './file-manager'
|
|
5
|
+
import { dashboardFileFailure } from './file-response'
|
|
5
6
|
|
|
6
7
|
export default new Action({
|
|
7
8
|
name: 'FileDestroyAction',
|
|
@@ -16,9 +17,7 @@ export default new Action({
|
|
|
16
17
|
return response.json(deleted)
|
|
17
18
|
}
|
|
18
19
|
catch (error) {
|
|
19
|
-
|
|
20
|
-
return response.json({ message: error.message, fields: error.fields }, error.status)
|
|
21
|
-
throw error
|
|
20
|
+
return dashboardFileFailure(error, 'The file could not be deleted.', 'FileDestroyAction')
|
|
22
21
|
}
|
|
23
22
|
},
|
|
24
23
|
})
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { RequestInstance } from '@stacksjs/types'
|
|
2
2
|
import { Action } from '@stacksjs/actions/runtime'
|
|
3
3
|
import { response } from '@stacksjs/router'
|
|
4
|
-
import { createDashboardDirectory
|
|
4
|
+
import { createDashboardDirectory } from './file-manager'
|
|
5
|
+
import { dashboardFileFailure } from './file-response'
|
|
5
6
|
|
|
6
7
|
export default new Action({
|
|
7
8
|
name: 'FileDirectoryStoreAction',
|
|
@@ -17,9 +18,7 @@ export default new Action({
|
|
|
17
18
|
return response.json(directory, 201)
|
|
18
19
|
}
|
|
19
20
|
catch (error) {
|
|
20
|
-
|
|
21
|
-
return response.json({ message: error.message, fields: error.fields }, error.status)
|
|
22
|
-
throw error
|
|
21
|
+
return dashboardFileFailure(error, 'The folder could not be created.', 'FileDirectoryStoreAction')
|
|
23
22
|
}
|
|
24
23
|
},
|
|
25
24
|
})
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { RequestInstance } from '@stacksjs/types'
|
|
2
2
|
import { Action } from '@stacksjs/actions/runtime'
|
|
3
3
|
import { response } from '@stacksjs/router'
|
|
4
|
-
import {
|
|
4
|
+
import { duplicateDashboardFile } from './file-manager'
|
|
5
|
+
import { dashboardFileFailure } from './file-response'
|
|
5
6
|
|
|
6
7
|
export default new Action({
|
|
7
8
|
name: 'FileDuplicateAction',
|
|
@@ -17,9 +18,7 @@ export default new Action({
|
|
|
17
18
|
return response.json(duplicated)
|
|
18
19
|
}
|
|
19
20
|
catch (error) {
|
|
20
|
-
|
|
21
|
-
return response.json({ message: error.message, fields: error.fields }, error.status)
|
|
22
|
-
throw error
|
|
21
|
+
return dashboardFileFailure(error, 'The file could not be duplicated.', 'FileDuplicateAction')
|
|
23
22
|
}
|
|
24
23
|
},
|
|
25
24
|
})
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { RequestInstance } from '@stacksjs/types'
|
|
2
2
|
import { Action } from '@stacksjs/actions/runtime'
|
|
3
3
|
import { response } from '@stacksjs/router'
|
|
4
|
-
import {
|
|
4
|
+
import { setDashboardFileFavorite } from './file-manager'
|
|
5
|
+
import { dashboardFileFailure } from './file-response'
|
|
5
6
|
|
|
6
7
|
export default new Action({
|
|
7
8
|
name: 'FileFavoriteAction',
|
|
@@ -17,9 +18,7 @@ export default new Action({
|
|
|
17
18
|
return response.json(result)
|
|
18
19
|
}
|
|
19
20
|
catch (error) {
|
|
20
|
-
|
|
21
|
-
return response.json({ message: error.message, fields: error.fields }, error.status)
|
|
22
|
-
throw error
|
|
21
|
+
return dashboardFileFailure(error, 'The favorite could not be saved.', 'FileFavoriteAction')
|
|
23
22
|
}
|
|
24
23
|
},
|
|
25
24
|
})
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { RequestInstance } from '@stacksjs/types'
|
|
2
2
|
import { Action } from '@stacksjs/actions/runtime'
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { getDashboardFileSnapshot, normalizeDashboardFileLimit } from './file-manager'
|
|
4
|
+
import { dashboardFileFailure } from './file-response'
|
|
5
5
|
|
|
6
6
|
export default new Action({
|
|
7
7
|
name: 'FileIndexAction',
|
|
@@ -16,9 +16,7 @@ export default new Action({
|
|
|
16
16
|
})
|
|
17
17
|
}
|
|
18
18
|
catch (error) {
|
|
19
|
-
|
|
20
|
-
return response.json({ message: error.message, fields: error.fields }, error.status)
|
|
21
|
-
throw error
|
|
19
|
+
return dashboardFileFailure(error, 'Files could not be loaded.', 'FileIndexAction')
|
|
22
20
|
}
|
|
23
21
|
},
|
|
24
22
|
})
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { RequestInstance } from '@stacksjs/types'
|
|
2
2
|
import { Action } from '@stacksjs/actions/runtime'
|
|
3
3
|
import { response } from '@stacksjs/router'
|
|
4
|
-
import {
|
|
4
|
+
import { renameDashboardFile } from './file-manager'
|
|
5
|
+
import { dashboardFileFailure } from './file-response'
|
|
5
6
|
|
|
6
7
|
export default new Action({
|
|
7
8
|
name: 'FileRenameAction',
|
|
@@ -17,9 +18,7 @@ export default new Action({
|
|
|
17
18
|
return response.json(renamed)
|
|
18
19
|
}
|
|
19
20
|
catch (error) {
|
|
20
|
-
|
|
21
|
-
return response.json({ message: error.message, fields: error.fields }, error.status)
|
|
22
|
-
throw error
|
|
21
|
+
return dashboardFileFailure(error, 'The file could not be renamed.', 'FileRenameAction')
|
|
23
22
|
}
|
|
24
23
|
},
|
|
25
24
|
})
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { RequestInstance } from '@stacksjs/types'
|
|
2
2
|
import { Action } from '@stacksjs/actions/runtime'
|
|
3
3
|
import { response } from '@stacksjs/router'
|
|
4
|
-
import {
|
|
4
|
+
import { reprocessDashboardFile } from './file-manager'
|
|
5
|
+
import { dashboardFileFailure } from './file-response'
|
|
5
6
|
|
|
6
7
|
export default new Action({
|
|
7
8
|
name: 'FileReprocessAction',
|
|
@@ -23,9 +24,7 @@ export default new Action({
|
|
|
23
24
|
return response.json(result)
|
|
24
25
|
}
|
|
25
26
|
catch (error) {
|
|
26
|
-
|
|
27
|
-
return response.json({ message: error.message, fields: error.fields }, error.status)
|
|
28
|
-
throw error
|
|
27
|
+
return dashboardFileFailure(error, 'The file could not be reprocessed.', 'FileReprocessAction')
|
|
29
28
|
}
|
|
30
29
|
},
|
|
31
30
|
})
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { RequestInstance } from '@stacksjs/types'
|
|
2
2
|
import { Action } from '@stacksjs/actions/runtime'
|
|
3
3
|
import { response } from '@stacksjs/router'
|
|
4
|
-
import {
|
|
4
|
+
import { setDashboardFileTags } from './file-manager'
|
|
5
|
+
import { dashboardFileFailure } from './file-response'
|
|
5
6
|
|
|
6
7
|
export default new Action({
|
|
7
8
|
name: 'FileTagsAction',
|
|
@@ -19,9 +20,7 @@ export default new Action({
|
|
|
19
20
|
return response.json(result)
|
|
20
21
|
}
|
|
21
22
|
catch (error) {
|
|
22
|
-
|
|
23
|
-
return response.json({ message: error.message, fields: error.fields }, error.status)
|
|
24
|
-
throw error
|
|
23
|
+
return dashboardFileFailure(error, 'The tags could not be saved.', 'FileTagsAction')
|
|
25
24
|
}
|
|
26
25
|
},
|
|
27
26
|
})
|
|
@@ -2,7 +2,8 @@ import type { RequestInstance } from '@stacksjs/types'
|
|
|
2
2
|
import type { UploadedFileLike } from '@stacksjs/storage'
|
|
3
3
|
import { Action } from '@stacksjs/actions/runtime'
|
|
4
4
|
import { response } from '@stacksjs/router'
|
|
5
|
-
import {
|
|
5
|
+
import { uploadDashboardFiles } from './file-manager'
|
|
6
|
+
import { dashboardFileFailure } from './file-response'
|
|
6
7
|
|
|
7
8
|
const MAX_FILES = 20
|
|
8
9
|
const MAX_FILE_BYTES = 10 * 1024 * 1024
|
|
@@ -34,9 +35,7 @@ export default new Action({
|
|
|
34
35
|
return response.json({ uploaded }, 201)
|
|
35
36
|
}
|
|
36
37
|
catch (error) {
|
|
37
|
-
|
|
38
|
-
return response.json({ message: error.message, fields: error.fields }, error.status)
|
|
39
|
-
throw error
|
|
38
|
+
return dashboardFileFailure(error, 'The upload could not be completed.', 'FileUploadAction')
|
|
40
39
|
}
|
|
41
40
|
},
|
|
42
41
|
})
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { RequestInstance } from '@stacksjs/types'
|
|
2
2
|
import { Action } from '@stacksjs/actions/runtime'
|
|
3
3
|
import { response } from '@stacksjs/router'
|
|
4
|
-
import {
|
|
4
|
+
import { setDashboardFileVisibility } from './file-manager'
|
|
5
|
+
import { dashboardFileFailure } from './file-response'
|
|
5
6
|
|
|
6
7
|
export default new Action({
|
|
7
8
|
name: 'FileVisibilityAction',
|
|
@@ -17,9 +18,7 @@ export default new Action({
|
|
|
17
18
|
return response.json(updated)
|
|
18
19
|
}
|
|
19
20
|
catch (error) {
|
|
20
|
-
|
|
21
|
-
return response.json({ message: error.message, fields: error.fields }, error.status)
|
|
22
|
-
throw error
|
|
21
|
+
return dashboardFileFailure(error, 'The visibility could not be changed.', 'FileVisibilityAction')
|
|
23
22
|
}
|
|
24
23
|
},
|
|
25
24
|
})
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { RequestInstance } from '@stacksjs/types'
|
|
2
|
+
import { afterEach, describe, expect, spyOn, test } from 'bun:test'
|
|
3
|
+
import FileIndexAction from './FileIndexAction'
|
|
4
|
+
import { DashboardFileError } from './file-manager'
|
|
5
|
+
import { dashboardFileFailure } from './file-response'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* File actions answer a failure they did not write with a safe 503
|
|
9
|
+
* (stacksjs/stacks#3174). They rethrew it, and the router put the driver's own
|
|
10
|
+
* message - `relation "storage_items" does not exist` - in the response body
|
|
11
|
+
* in every environment, which the file manager then showed in its banner.
|
|
12
|
+
*/
|
|
13
|
+
const driverMessage = 'relation "storage_items" does not exist'
|
|
14
|
+
|
|
15
|
+
let quiet: ReturnType<typeof spyOn> | null = null
|
|
16
|
+
afterEach(() => {
|
|
17
|
+
quiet?.mockRestore()
|
|
18
|
+
quiet = null
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
describe('dashboardFileFailure', () => {
|
|
22
|
+
test('keeps the status, message and fields of an error written to be shown', async () => {
|
|
23
|
+
const reply = dashboardFileFailure(
|
|
24
|
+
new DashboardFileError('Choose a limit between 1 and 5000.', 422, { limit: 'Too high.' }),
|
|
25
|
+
'Files could not be loaded.',
|
|
26
|
+
'FileIndexAction',
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
expect(reply.status).toBe(422)
|
|
30
|
+
expect(await reply.json()).toEqual({ message: 'Choose a limit between 1 and 5000.', fields: { limit: 'Too high.' } })
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
test('answers any other failure 503 with the safe message and logs the real one', async () => {
|
|
34
|
+
quiet = spyOn(console, 'error').mockImplementation(() => {})
|
|
35
|
+
const failure = new Error(driverMessage)
|
|
36
|
+
|
|
37
|
+
const reply = dashboardFileFailure(failure, 'Files could not be loaded.', 'FileIndexAction')
|
|
38
|
+
|
|
39
|
+
expect(reply.status).toBe(503)
|
|
40
|
+
expect(await reply.json()).toEqual({ message: 'Files could not be loaded.' })
|
|
41
|
+
expect(quiet).toHaveBeenCalledWith('[dashboard/api] FileIndexAction failed:', failure)
|
|
42
|
+
})
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
describe('FileIndexAction', () => {
|
|
46
|
+
test('does not send a driver error to the browser', async () => {
|
|
47
|
+
quiet = spyOn(console, 'error').mockImplementation(() => {})
|
|
48
|
+
const request = {
|
|
49
|
+
get: () => {
|
|
50
|
+
throw new Error(driverMessage)
|
|
51
|
+
},
|
|
52
|
+
} as unknown as RequestInstance
|
|
53
|
+
|
|
54
|
+
const reply = await FileIndexAction.handle(request) as Response
|
|
55
|
+
|
|
56
|
+
expect(reply.status).toBe(503)
|
|
57
|
+
const body = await reply.text()
|
|
58
|
+
expect(body).not.toContain('storage_items')
|
|
59
|
+
expect(JSON.parse(body)).toEqual({ message: 'Files could not be loaded.' })
|
|
60
|
+
})
|
|
61
|
+
})
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { response } from '@stacksjs/router'
|
|
2
|
+
import { dashboardOperationalError } from '../dashboard-response'
|
|
3
|
+
import { DashboardFileError } from './file-manager'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The response for a file action that threw.
|
|
7
|
+
*
|
|
8
|
+
* A `DashboardFileError` is written to be shown, so it keeps its status,
|
|
9
|
+
* message and fields. Anything else - the database behind `storage_items`
|
|
10
|
+
* being down or not migrated, a driver failing - is logged and answered 503
|
|
11
|
+
* with `message`, because rethrowing it let the router send the raw driver
|
|
12
|
+
* message to the browser in every environment (stacksjs/stacks#3174).
|
|
13
|
+
*/
|
|
14
|
+
export function dashboardFileFailure(error: unknown, message: string, action: string): Response {
|
|
15
|
+
if (error instanceof DashboardFileError)
|
|
16
|
+
return response.json({ message: error.message, fields: error.fields }, error.status)
|
|
17
|
+
return dashboardOperationalError(error, message, action)
|
|
18
|
+
}
|
|
@@ -1,12 +1,32 @@
|
|
|
1
1
|
import type { ResponseStatus } from '@stacksjs/bun-router'
|
|
2
2
|
import { response } from '@stacksjs/router'
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* The feature whose models this error says were never loaded, if it is the
|
|
6
|
+
* ORM's `ModelUnavailableError` for a feature that is off.
|
|
7
|
+
*/
|
|
8
|
+
function disabledFeature(error: unknown): string | undefined {
|
|
9
|
+
if (!(error instanceof Error) || error.name !== 'ModelUnavailableError')
|
|
10
|
+
return undefined
|
|
11
|
+
const feature = (error as Error & { feature?: unknown }).feature
|
|
12
|
+
return typeof feature === 'string' && feature ? feature : undefined
|
|
13
|
+
}
|
|
14
|
+
|
|
4
15
|
export function dashboardOperationalError(
|
|
5
16
|
error: unknown,
|
|
6
17
|
message: string,
|
|
7
18
|
action: string,
|
|
8
19
|
status: ResponseStatus = 503,
|
|
9
20
|
): Response {
|
|
21
|
+
// A page whose feature is off is not an outage, and saying "could not be
|
|
22
|
+
// read" sent people looking at their database (stacksjs/stacks#3184).
|
|
23
|
+
const feature = disabledFeature(error)
|
|
24
|
+
if (feature) {
|
|
25
|
+
console.warn(`[dashboard/api] ${action}: the '${feature}' feature is off`)
|
|
26
|
+
return response.json({
|
|
27
|
+
message: `${feature.charAt(0).toUpperCase()}${feature.slice(1)} is turned off for this app, so this page has no data. Set \`enabled: true\` in config/${feature}.ts to use it.`,
|
|
28
|
+
}, 404)
|
|
29
|
+
}
|
|
10
30
|
console.error(`[dashboard/api] ${action} failed:`, error)
|
|
11
31
|
return response.json({ message }, status)
|
|
12
32
|
}
|