@nextsparkjs/core 0.1.0-beta.195 → 0.1.0-beta.197
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/README.md +2 -0
- package/dist/components/auth/forms/SignupForm.d.ts.map +1 -1
- package/dist/components/auth/forms/SignupForm.js +55 -45
- package/dist/components/billing/InvoicesPagination.js +2 -2
- package/dist/components/dashboard/block-editor/config-panel.d.ts.map +1 -1
- package/dist/components/dashboard/block-editor/config-panel.js +3 -2
- package/dist/components/dashboard/block-editor/entity-fields-sidebar.d.ts.map +1 -1
- package/dist/components/dashboard/block-editor/entity-fields-sidebar.js +3 -2
- package/dist/components/dashboard/navigation/DynamicNavigation.js +2 -2
- package/dist/components/settings/layouts/SettingsSidebar.d.ts.map +1 -1
- package/dist/components/settings/layouts/SettingsSidebar.js +0 -1
- package/dist/components/teams/CreateTeamButton.js +2 -2
- package/dist/components/teams/CreateTeamDialog.js +1 -1
- package/dist/components/teams/InviteMemberButton.js +3 -3
- package/dist/components/teams/InviteMemberDialog.js +1 -1
- package/dist/components/teams/TeamPendingInvitations.js +2 -2
- package/dist/components/users/tables/UsersTable.d.ts.map +1 -1
- package/dist/components/users/tables/UsersTable.js +3 -4
- package/dist/hooks/useAuthReadiness.d.ts +1 -0
- package/dist/hooks/useAuthReadiness.d.ts.map +1 -1
- package/dist/hooks/useAuthReadiness.js +3 -1
- package/dist/lib/actions/entity.actions.js +2 -2
- package/dist/lib/actions/team.actions.js +2 -2
- package/dist/lib/actions/user.actions.js +4 -4
- package/dist/lib/api/api-error.d.ts +2 -0
- package/dist/lib/api/api-error.d.ts.map +1 -1
- package/dist/lib/api/api-error.js +3 -1
- package/dist/lib/api/auth/dual-auth.d.ts +2 -1
- package/dist/lib/api/auth/dual-auth.d.ts.map +1 -1
- package/dist/lib/api/auth/dual-auth.js +25 -6
- package/dist/lib/api/auth/scope-policy.d.ts +6 -3
- package/dist/lib/api/auth/scope-policy.d.ts.map +1 -1
- package/dist/lib/api/auth.d.ts.map +1 -1
- package/dist/lib/api/auth.js +7 -0
- package/dist/lib/api/cors-response.d.ts +3 -2
- package/dist/lib/api/cors-response.d.ts.map +1 -1
- package/dist/lib/api/cors-response.js +8 -6
- package/dist/lib/api/entity/generic-handler.d.ts.map +1 -1
- package/dist/lib/api/entity/generic-handler.js +66 -15
- package/dist/lib/api/entity-handler.js +2 -2
- package/dist/lib/api/helpers.d.ts.map +1 -1
- package/dist/lib/api/helpers.js +9 -24
- package/dist/lib/api/permission-middleware.d.ts.map +1 -1
- package/dist/lib/api/permission-middleware.js +0 -2
- package/dist/lib/api/post-categories.d.ts +29 -0
- package/dist/lib/api/post-categories.d.ts.map +1 -0
- package/dist/lib/api/post-categories.js +33 -0
- package/dist/lib/api/rate-limit.d.ts +8 -0
- package/dist/lib/api/rate-limit.d.ts.map +1 -1
- package/dist/lib/api/rate-limit.js +34 -3
- package/dist/lib/api/request-origin.d.ts.map +1 -1
- package/dist/lib/api/request-origin.js +1 -1
- package/dist/lib/auth/auth-methods.d.ts +5 -2
- package/dist/lib/auth/auth-methods.d.ts.map +1 -1
- package/dist/lib/auth/auth-methods.js +4 -2
- package/dist/lib/auth/authorization-session.d.ts +14 -0
- package/dist/lib/auth/authorization-session.d.ts.map +1 -0
- package/dist/lib/auth/authorization-session.js +10 -0
- package/dist/lib/auth/request-session.d.ts +5 -0
- package/dist/lib/auth/request-session.d.ts.map +1 -1
- package/dist/lib/auth/request-session.js +3 -0
- package/dist/lib/auth/runtime-readiness.d.ts +7 -4
- package/dist/lib/auth/runtime-readiness.d.ts.map +1 -1
- package/dist/lib/auth/runtime-readiness.js +9 -6
- package/dist/lib/auth/sample-accounts.d.ts +18 -0
- package/dist/lib/auth/sample-accounts.d.ts.map +1 -0
- package/dist/lib/auth/sample-accounts.js +25 -0
- package/dist/lib/auth/suspension.d.ts +22 -0
- package/dist/lib/auth/suspension.d.ts.map +1 -0
- package/dist/lib/auth/suspension.js +43 -0
- package/dist/lib/auth.d.ts.map +1 -1
- package/dist/lib/auth.js +20 -17
- package/dist/lib/cache/public-entity-cache.d.ts +21 -0
- package/dist/lib/cache/public-entity-cache.d.ts.map +1 -0
- package/dist/lib/cache/public-entity-cache.js +25 -0
- package/dist/lib/config/app.config.d.ts.map +1 -1
- package/dist/lib/config/app.config.js +6 -7
- package/dist/lib/config/types.d.ts +8 -6
- package/dist/lib/config/types.d.ts.map +1 -1
- package/dist/lib/db-pool.d.ts +31 -0
- package/dist/lib/db-pool.d.ts.map +1 -0
- package/dist/lib/db-pool.js +75 -0
- package/dist/lib/db.d.ts +1 -1
- package/dist/lib/db.d.ts.map +1 -1
- package/dist/lib/db.js +11 -14
- package/dist/lib/entities/api-generator.js +5 -5
- package/dist/lib/entities/entity-hooks.d.ts.map +1 -1
- package/dist/lib/entities/entity-hooks.js +4 -0
- package/dist/lib/mcp/errors.d.ts +2 -0
- package/dist/lib/mcp/errors.d.ts.map +1 -1
- package/dist/lib/mcp/errors.js +3 -1
- package/dist/lib/mcp/index.d.ts +1 -1
- package/dist/lib/mcp/index.d.ts.map +1 -1
- package/dist/lib/mcp/index.js +2 -1
- package/dist/lib/oauth/token-refresh.d.ts.map +1 -1
- package/dist/lib/oauth/token-refresh.js +3 -6
- package/dist/lib/permissions/check.d.ts +9 -0
- package/dist/lib/permissions/check.d.ts.map +1 -1
- package/dist/lib/permissions/check.js +11 -1
- package/dist/lib/services/generic-entity.service.d.ts.map +1 -1
- package/dist/lib/services/generic-entity.service.js +41 -7
- package/dist/lib/services/transactional-meta.service.d.ts.map +1 -1
- package/dist/lib/services/transactional-meta.service.js +7 -8
- package/dist/lib/teams/actions.d.ts.map +1 -1
- package/dist/lib/teams/actions.js +0 -1
- package/dist/lib/validation.d.ts +5 -0
- package/dist/lib/validation.d.ts.map +1 -1
- package/dist/lib/validation.js +2 -0
- package/dist/messages/de/billing.json +12 -1
- package/dist/messages/de/common.json +2 -0
- package/dist/messages/de/docs.json +1 -0
- package/dist/messages/de/features.json +16 -4
- package/dist/messages/de/home.json +5 -0
- package/dist/messages/de/index.d.ts +68 -25
- package/dist/messages/de/index.d.ts.map +1 -1
- package/dist/messages/de/index.js +2 -0
- package/dist/messages/de/index.ts +2 -0
- package/dist/messages/de/settings.json +1 -0
- package/dist/messages/de/teams.json +3 -18
- package/dist/messages/en/billing.json +1 -1
- package/dist/messages/en/common.json +2 -0
- package/dist/messages/en/docs.json +1 -0
- package/dist/messages/en/features.json +16 -4
- package/dist/messages/en/home.json +5 -0
- package/dist/messages/en/index.d.ts +58 -25
- package/dist/messages/en/index.d.ts.map +1 -1
- package/dist/messages/en/index.js +2 -0
- package/dist/messages/en/index.ts +2 -0
- package/dist/messages/en/settings.json +1 -0
- package/dist/messages/en/teams.json +3 -18
- package/dist/messages/es/billing.json +1 -1
- package/dist/messages/es/common.json +2 -0
- package/dist/messages/es/docs.json +1 -0
- package/dist/messages/es/features.json +16 -4
- package/dist/messages/es/home.json +5 -0
- package/dist/messages/es/index.d.ts +41 -8
- package/dist/messages/es/index.d.ts.map +1 -1
- package/dist/messages/es/index.js +2 -0
- package/dist/messages/es/index.ts +2 -0
- package/dist/messages/es/settings.json +1 -0
- package/dist/messages/es/teams.json +3 -0
- package/dist/messages/fr/billing.json +12 -1
- package/dist/messages/fr/common.json +2 -0
- package/dist/messages/fr/docs.json +1 -0
- package/dist/messages/fr/features.json +16 -4
- package/dist/messages/fr/home.json +5 -0
- package/dist/messages/fr/index.d.ts +68 -25
- package/dist/messages/fr/index.d.ts.map +1 -1
- package/dist/messages/fr/index.js +2 -0
- package/dist/messages/fr/index.ts +2 -0
- package/dist/messages/fr/settings.json +1 -0
- package/dist/messages/fr/teams.json +3 -18
- package/dist/messages/it/billing.json +12 -1
- package/dist/messages/it/common.json +2 -0
- package/dist/messages/it/docs.json +1 -0
- package/dist/messages/it/features.json +16 -4
- package/dist/messages/it/home.json +5 -0
- package/dist/messages/it/index.d.ts +68 -25
- package/dist/messages/it/index.d.ts.map +1 -1
- package/dist/messages/it/index.js +2 -0
- package/dist/messages/it/index.ts +2 -0
- package/dist/messages/it/settings.json +1 -0
- package/dist/messages/it/teams.json +3 -18
- package/dist/messages/pt/billing.json +12 -1
- package/dist/messages/pt/common.json +2 -0
- package/dist/messages/pt/docs.json +1 -0
- package/dist/messages/pt/features.json +16 -4
- package/dist/messages/pt/home.json +5 -0
- package/dist/messages/pt/index.d.ts +68 -25
- package/dist/messages/pt/index.d.ts.map +1 -1
- package/dist/messages/pt/index.js +2 -0
- package/dist/messages/pt/index.ts +2 -0
- package/dist/messages/pt/settings.json +1 -0
- package/dist/messages/pt/teams.json +3 -18
- package/dist/migrations/029_sample_accounts_outside_development.sql +55 -0
- package/dist/migrations/030_taxonomies_team_writes.sql +29 -0
- package/dist/migrations/031_users_role_suspended.sql +41 -0
- package/dist/migrations/090_sample_data.sql +10 -0
- package/dist/routes/(auth)/signup/page.cc.d.ts +3 -1
- package/dist/routes/(auth)/signup/page.cc.d.ts.map +1 -1
- package/dist/routes/(auth)/signup/page.cc.js +2 -2
- package/dist/routes/(auth)/signup/page.d.ts +3 -1
- package/dist/routes/(auth)/signup/page.d.ts.map +1 -1
- package/dist/routes/(auth)/signup/page.js +4 -3
- package/dist/routes/_internal/area-access.js +2 -2
- package/dist/routes/_internal/entity-permission-layout.d.ts.map +1 -1
- package/dist/routes/_internal/entity-permission-layout.js +0 -7
- package/dist/routes/api/devtools/config/entities/route.js +2 -2
- package/dist/routes/api/devtools/config/theme/route.js +2 -2
- package/dist/routes/api/devtools/tests/[...path]/route.js +2 -2
- package/dist/routes/api/devtools/tests/route.js +2 -2
- package/dist/routes/api/mcp/route.d.ts.map +1 -1
- package/dist/routes/api/mcp/route.js +7 -1
- package/dist/routes/api/superadmin/subscriptions/route.js +2 -2
- package/dist/routes/api/superadmin/teams/[teamId]/route.js +2 -2
- package/dist/routes/api/superadmin/teams/route.js +2 -2
- package/dist/routes/api/superadmin/users/[userId]/route.d.ts +5 -3
- package/dist/routes/api/superadmin/users/[userId]/route.d.ts.map +1 -1
- package/dist/routes/api/superadmin/users/[userId]/route.js +46 -23
- package/dist/routes/api/superadmin/users/route.js +2 -2
- package/dist/routes/api/user/delete-account/route.d.ts.map +1 -1
- package/dist/routes/api/user/delete-account/route.js +2 -3
- package/dist/routes/api/user/plan-flags/route.d.ts.map +1 -1
- package/dist/routes/api/user/plan-flags/route.js +5 -5
- package/dist/routes/api/user/profile/route.js +3 -3
- package/dist/routes/api/v1/auth/signup-with-invite/route.d.ts.map +1 -1
- package/dist/routes/api/v1/auth/signup-with-invite/route.js +80 -44
- package/dist/routes/api/v1/media/upload/route.d.ts +2 -1
- package/dist/routes/api/v1/media/upload/route.d.ts.map +1 -1
- package/dist/routes/api/v1/media/upload/route.js +10 -2
- package/dist/routes/api/v1/post-categories/[id]/route.d.ts.map +1 -1
- package/dist/routes/api/v1/post-categories/[id]/route.js +39 -34
- package/dist/routes/api/v1/post-categories/route.d.ts.map +1 -1
- package/dist/routes/api/v1/post-categories/route.js +18 -14
- package/dist/routes/api/v1/team-invitations/route.d.ts.map +1 -1
- package/dist/routes/api/v1/team-invitations/route.js +12 -5
- package/dist/routes/api/v1/teams/[teamId]/members/route.d.ts.map +1 -1
- package/dist/routes/api/v1/teams/[teamId]/members/route.js +12 -10
- package/dist/routes/api/v1/teams/switch/route.d.ts.map +1 -1
- package/dist/routes/api/v1/teams/switch/route.js +4 -1
- package/dist/routes/dashboard/settings/password/page.d.ts.map +1 -1
- package/dist/routes/dashboard/settings/password/page.js +10 -12
- package/dist/routes/devtools/config/page.js +1 -1
- package/dist/routes/devtools/page.js +1 -1
- package/dist/routes/devtools/scheduled-actions/page.js +1 -1
- package/dist/routes/devtools/tests/[[...path]]/page.js +1 -1
- package/dist/routes/superadmin/users/page.js +2 -2
- package/dist/templates/ci-workflows/github/cypress-regression.yml +1 -1
- package/dist/templates/ci-workflows/github/cypress-smoke.yml +2 -1
- package/dist/templates/next.config.mjs +11 -31
- package/dist/templates/projects/blog/package.json +1 -1
- package/dist/templates/projects/crm/package.json +1 -1
- package/dist/templates/projects/productivity/package.json +1 -1
- package/dist/templates/projects/starter/README.md +2 -0
- package/dist/templates/projects/starter/config/app.config.ts +8 -0
- package/dist/templates/projects/starter/docs/public/01-overview/01-introduction.md +2 -0
- package/dist/templates/projects/starter/templates/dashboard/analytics/layout.tsx +14 -0
- package/dist/templates/proxy.ts +18 -8
- package/dist/templates/public/uploads/README.md +5 -94
- package/migrations/029_sample_accounts_outside_development.sql +55 -0
- package/migrations/030_taxonomies_team_writes.sql +29 -0
- package/migrations/031_users_role_suspended.sql +41 -0
- package/migrations/090_sample_data.sql +10 -0
- package/package.json +3 -3
- package/scripts/build/registry/__tests__/build-output.test.mjs +1 -1
- package/scripts/build/registry/__tests__/project-mode-root-first.test.mjs +6 -6
- package/scripts/build/registry/__tests__/write-places.test.mjs +1 -1
- package/scripts/build/registry/contracts/__tests__/contracts-wire.test.mjs +1 -1
- package/scripts/build/registry/contracts/__tests__/contracts.test.mjs +1 -1
- package/scripts/build/registry/host/README.md +2 -2
- package/scripts/build/registry/host/__tests__/facade-emitter.test.mjs +14 -13
- package/scripts/build/registry/host/__tests__/host-mode.test.mjs +1 -1
- package/scripts/build/registry/host/__tests__/host-project-composition.test.mjs +1 -1
- package/scripts/build/registry/host/__tests__/host-project.test.mjs +2 -2
- package/scripts/build/registry/host/__tests__/host-proxy-areas.test.mjs +99 -1
- package/scripts/build/registry/host/__tests__/host-robustness.test.mjs +1 -1
- package/scripts/build/registry/host/facade-emitter.mjs +1 -1
- package/scripts/build/registry/host/next-route-exports.json +2 -2
- package/scripts/build/registry/host/proxy-areas.mjs +92 -2
- package/scripts/db/run-migrations.mjs +30 -10
- package/scripts/db/sample-data.mjs +44 -0
- package/scripts/db/verify-theme-migrations.mjs +7 -1
- package/templates/ci-workflows/github/cypress-regression.yml +1 -1
- package/templates/ci-workflows/github/cypress-smoke.yml +2 -1
- package/templates/next.config.mjs +11 -31
- package/templates/projects/blog/package.json +1 -1
- package/templates/projects/crm/package.json +1 -1
- package/templates/projects/productivity/package.json +1 -1
- package/templates/projects/starter/README.md +2 -0
- package/templates/projects/starter/config/app.config.ts +8 -0
- package/templates/projects/starter/docs/public/01-overview/01-introduction.md +2 -0
- package/templates/projects/starter/templates/dashboard/analytics/layout.tsx +14 -0
- package/templates/proxy.ts +18 -8
- package/templates/public/uploads/README.md +5 -94
- package/tests/jest/__mocks__/@nextsparkjs/registries/api-presets-registry.ts +2 -0
- package/tests/jest/__mocks__/@nextsparkjs/registries/mcp-registry.ts +2 -0
- package/tests/jest/__mocks__/@nextsparkjs/registries/permissions-registry.ts +5 -4
- package/dist/templates/projects/starter/public/brand/.gitkeep +0 -0
- package/dist/templates/public/uploads/.gitignore +0 -6
- package/dist/templates/public/uploads/temp/.gitkeep +0 -1
- package/templates/projects/starter/public/brand/.gitkeep +0 -0
- package/templates/public/uploads/.gitignore +0 -6
- package/templates/public/uploads/temp/.gitkeep +0 -1
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { NextIntlClientProvider } from 'next-intl'
|
|
2
|
+
import { getMessages } from 'next-intl/server'
|
|
3
|
+
import { selectMessages } from '@nextsparkjs/core/lib/i18n/client-messages'
|
|
4
|
+
|
|
5
|
+
// TasksChart and RecentActivity are client components that read the `analytics`
|
|
6
|
+
// namespace, which the dashboard group does not carry to the browser by default.
|
|
7
|
+
export default async function AnalyticsLayout({ children }: { children: React.ReactNode }) {
|
|
8
|
+
const messages = await getMessages()
|
|
9
|
+
return (
|
|
10
|
+
<NextIntlClientProvider messages={selectMessages(messages, 'dashboard', ['analytics'])}>
|
|
11
|
+
{children}
|
|
12
|
+
</NextIntlClientProvider>
|
|
13
|
+
)
|
|
14
|
+
}
|
package/templates/proxy.ts
CHANGED
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
* themselves and use only x-pathname from here, as a routing hint; the
|
|
21
21
|
* identity headers are still stripped and re-set for project code.
|
|
22
22
|
*/
|
|
23
|
-
import { betterFetch } from '@better-fetch/fetch'
|
|
24
23
|
import { NextRequest, NextResponse } from 'next/server'
|
|
24
|
+
import { auth } from '@nextsparkjs/core/lib/auth'
|
|
25
25
|
import {
|
|
26
26
|
hasProjectMiddleware,
|
|
27
27
|
executeProjectMiddleware,
|
|
@@ -181,14 +181,25 @@ function redirectAccessDenied(request: NextRequest): NextResponse {
|
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
/**
|
|
184
|
-
* The session the request's cookies carry,
|
|
185
|
-
*
|
|
184
|
+
* The session the request's cookies carry, read in this process the way core's
|
|
185
|
+
* server code reads it. Asking the app's own /api/auth/get-session over HTTP
|
|
186
|
+
* built the URL from the request's origin, which behind a proxy that
|
|
187
|
+
* terminates TLS (X-Forwarded-Proto: https) is https on a port that speaks
|
|
188
|
+
* plain HTTP: the fetch failed and every signed-in user was sent to /login.
|
|
189
|
+
* Nothing here leaves the process, so no forwarded scheme or host can point
|
|
190
|
+
* the check anywhere. `disableRefresh`: this response cannot carry the renewed
|
|
191
|
+
* session cookie, so the rolling renewal is left to the auth route
|
|
192
|
+
* (lib/auth/session-refresh). `disableCookieCache`: the session comes from the
|
|
193
|
+
* database, not the signed session_data cookie, so a sign-out, a revoked
|
|
194
|
+
* session or a role change counts at once (lib/auth/authorization-session).
|
|
195
|
+
* A suspended account's session is no session (lib/auth/suspension).
|
|
186
196
|
*/
|
|
187
|
-
function getSession(request: NextRequest) {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
197
|
+
async function getSession(request: NextRequest): Promise<Session | null> {
|
|
198
|
+
const session = await auth.api.getSession({
|
|
199
|
+
headers: new Headers({ cookie: request.headers.get('cookie') || '' }),
|
|
200
|
+
query: { disableRefresh: true, disableCookieCache: true },
|
|
191
201
|
})
|
|
202
|
+
return session && (session.user as { role?: unknown }).role !== 'suspended' ? (session as Session) : null
|
|
192
203
|
}
|
|
193
204
|
|
|
194
205
|
/**
|
|
@@ -490,7 +501,6 @@ export async function proxy(request: NextRequest) {
|
|
|
490
501
|
const verifiedSession = async (): Promise<Session | null> => {
|
|
491
502
|
if (!sessionPromise) {
|
|
492
503
|
sessionPromise = getSession(request)
|
|
493
|
-
.then(({ data }) => data)
|
|
494
504
|
.catch(error => {
|
|
495
505
|
sessionError = error
|
|
496
506
|
return null
|
|
@@ -1,97 +1,8 @@
|
|
|
1
|
-
# Media
|
|
1
|
+
# Media uploads
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
This application uses **Vercel Blob Storage** for all media uploads. Files are stored in the cloud, not on the local filesystem.
|
|
3
|
+
`POST /api/v1/media/upload` stores files in **Vercel Blob** when `BLOB_READ_WRITE_TOKEN` is set. The media library lists the Blob URLs.
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
- **Development without a token:** files are written to `public/uploads/temp/` (git-ignored) so the library works offline.
|
|
6
|
+
- **Production without a token:** the upload answers `503` with code `STORAGE_NOT_CONFIGURED`. Nothing is written to disk: a file under `public/` is not served until the next restart and does not survive a redeploy.
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
**POST** `/api/v1/media/upload`
|
|
10
|
-
|
|
11
|
-
### Authentication
|
|
12
|
-
Requires valid user session (Better Auth)
|
|
13
|
-
|
|
14
|
-
### Request
|
|
15
|
-
- **Content-Type**: `multipart/form-data`
|
|
16
|
-
- **Field name**: `files` (accepts multiple files)
|
|
17
|
-
|
|
18
|
-
### Supported File Types
|
|
19
|
-
- Images: JPEG, PNG, GIF, WebP
|
|
20
|
-
- Videos: MP4, MPEG, QuickTime, WebM
|
|
21
|
-
|
|
22
|
-
### File Size Limit
|
|
23
|
-
- Maximum: 10MB per file
|
|
24
|
-
|
|
25
|
-
### Response
|
|
26
|
-
```json
|
|
27
|
-
{
|
|
28
|
-
"message": "Files uploaded successfully",
|
|
29
|
-
"urls": [
|
|
30
|
-
"https://xxxxx.public.blob.vercel-storage.com/uploads/temp/1234567890_abc123.jpg",
|
|
31
|
-
"https://xxxxx.public.blob.vercel-storage.com/uploads/temp/1234567890_def456.png"
|
|
32
|
-
],
|
|
33
|
-
"count": 2
|
|
34
|
-
}
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
## File Naming Convention
|
|
38
|
-
Files are automatically renamed using the pattern:
|
|
39
|
-
```
|
|
40
|
-
{timestamp}_{randomString}.{extension}
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
Example: `1704067200000_k9x2m4p.jpg`
|
|
44
|
-
|
|
45
|
-
## Storage Location
|
|
46
|
-
- **Storage Provider**: Vercel Blob (cloud object storage)
|
|
47
|
-
- **Blob Path**: `uploads/temp/{filename}` (organizational prefix, not a filesystem path)
|
|
48
|
-
- **Public URL**: `https://xxxxx.public.blob.vercel-storage.com/uploads/temp/{filename}`
|
|
49
|
-
|
|
50
|
-
### How It Works
|
|
51
|
-
|
|
52
|
-
**Local Development:**
|
|
53
|
-
- Files are uploaded directly to Vercel Blob using `BLOB_READ_WRITE_TOKEN` from `.env`
|
|
54
|
-
- No files are saved to your local filesystem
|
|
55
|
-
- URLs point to Vercel's CDN
|
|
56
|
-
|
|
57
|
-
**Production/Staging:**
|
|
58
|
-
- Same behavior - files go directly to Vercel Blob
|
|
59
|
-
- Uses environment-specific Blob token
|
|
60
|
-
- No filesystem writes (Vercel serverless is read-only)
|
|
61
|
-
|
|
62
|
-
## Usage in AI Content Generation
|
|
63
|
-
The generate-content endpoint (`/api/content-buddy/generate-content`) automatically processes images for AI analysis.
|
|
64
|
-
|
|
65
|
-
**Supported URL formats:**
|
|
66
|
-
- Vercel Blob URLs: `https://xxxxx.public.blob.vercel-storage.com/uploads/temp/image.jpg`
|
|
67
|
-
- External URLs: `https://example.com/image.jpg` (also supported)
|
|
68
|
-
|
|
69
|
-
## Configuration
|
|
70
|
-
Requires `BLOB_READ_WRITE_TOKEN` environment variable:
|
|
71
|
-
|
|
72
|
-
```env
|
|
73
|
-
BLOB_READ_WRITE_TOKEN="vercel_blob_rw_..."
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
## Cleanup
|
|
77
|
-
Files are managed through Vercel Blob's retention policies.
|
|
78
|
-
|
|
79
|
-
**Manual cleanup** (if needed):
|
|
80
|
-
```typescript
|
|
81
|
-
import { del } from '@vercel/blob'
|
|
82
|
-
|
|
83
|
-
// Delete specific file
|
|
84
|
-
await del(fileUrl)
|
|
85
|
-
|
|
86
|
-
// Or list and delete old files
|
|
87
|
-
import { list } from '@vercel/blob'
|
|
88
|
-
const { blobs } = await list({ prefix: 'uploads/temp/' })
|
|
89
|
-
// Filter and delete as needed
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
## Security Notes
|
|
93
|
-
- All uploads require authentication
|
|
94
|
-
- File type validation prevents malicious uploads
|
|
95
|
-
- File size limits prevent DoS attacks
|
|
96
|
-
- Random filenames prevent enumeration attacks
|
|
97
|
-
- Files stored in secure Vercel Blob infrastructure
|
|
8
|
+
Self-hosting needs a storage provider: set `BLOB_READ_WRITE_TOKEN` (a Vercel Blob token, starts with `vercel_blob_`). See the media library docs.
|
|
@@ -37,12 +37,13 @@ export const TEAM_PERMISSIONS_BY_ROLE: Record<string, string[]> = {
|
|
|
37
37
|
viewer: ['team.view'],
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
// Entity permissions used by service tests (mirrors the default theme's customers entity
|
|
40
|
+
// Entity permissions used by service tests (mirrors the default theme's customers entity, and the starter's
|
|
41
|
+
// posts entity, whose `publish` action is owner/admin only)
|
|
41
42
|
const ENTITY_PERMISSIONS_BY_ROLE: Record<string, string[]> = {
|
|
42
|
-
owner: ['customers.create', 'customers.read', 'customers.list', 'customers.update', 'customers.delete'],
|
|
43
|
-
admin: ['customers.create', 'customers.read', 'customers.list', 'customers.update'],
|
|
43
|
+
owner: ['customers.create', 'customers.read', 'customers.list', 'customers.update', 'customers.delete', 'posts.create', 'posts.update', 'posts.publish'],
|
|
44
|
+
admin: ['customers.create', 'customers.read', 'customers.list', 'customers.update', 'posts.create', 'posts.update', 'posts.publish'],
|
|
44
45
|
editor: ['customers.read', 'customers.list'],
|
|
45
|
-
member: ['customers.read', 'customers.list'],
|
|
46
|
+
member: ['customers.read', 'customers.list', 'posts.create', 'posts.update'],
|
|
46
47
|
viewer: [],
|
|
47
48
|
}
|
|
48
49
|
|
|
File without changes
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
# Keep this directory in git but ignore uploaded files
|
|
File without changes
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
# Keep this directory in git but ignore uploaded files
|