Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a695ec7319 | ||
|
|
c6730335ef | ||
|
|
247b849759 | ||
|
|
0dee178ded | ||
|
|
9359f26788 | ||
|
|
5630765215 | ||
|
|
ed4a78b109 | ||
|
|
9acb22e2f9 | ||
|
|
6a8361d710 | ||
|
|
502ffee31f | ||
|
|
5a322230ae | ||
|
|
f919c288b2 |
+4
@@ -14,6 +14,10 @@ type BuildSiteIntegrationsArgs = {
|
|||||||
* impossible to enter.)
|
* impossible to enter.)
|
||||||
*
|
*
|
||||||
* Unnamed tabs keep data flat (siteIntegrations.ga4MeasurementId).
|
* Unnamed tabs keep data flat (siteIntegrations.ga4MeasurementId).
|
||||||
|
*
|
||||||
|
* Note: R2 storage credentials are NOT here — storage is infrastructure and
|
||||||
|
* binds at boot, so its config lives in .env (R2_BUCKET, R2_ENDPOINT, ...),
|
||||||
|
* consumed by buildR2Storage. See docs/storage.md.
|
||||||
*/
|
*/
|
||||||
export declare function buildSiteIntegrations({ additionalFields, }?: BuildSiteIntegrationsArgs): GlobalConfig;
|
export declare function buildSiteIntegrations({ additionalFields, }?: BuildSiteIntegrationsArgs): GlobalConfig;
|
||||||
export {};
|
export {};
|
||||||
|
|||||||
+4
-5
@@ -1,7 +1,6 @@
|
|||||||
import { isAdmin } from '../../modules/access/index.js';
|
import { isAdmin } from '../../modules/access/index.js';
|
||||||
import { analyticsFields } from './fields/analytics.js';
|
import { analyticsFields } from './fields/analytics.js';
|
||||||
import { smtpFields } from './fields/smtp.js';
|
import { smtpFields } from './fields/smtp.js';
|
||||||
import { storageFields } from './fields/storage.js';
|
|
||||||
import { turnstileFields } from './fields/turnstile.js';
|
import { turnstileFields } from './fields/turnstile.js';
|
||||||
/**
|
/**
|
||||||
* Builds the SiteIntegrations global.
|
* Builds the SiteIntegrations global.
|
||||||
@@ -14,6 +13,10 @@ import { turnstileFields } from './fields/turnstile.js';
|
|||||||
* impossible to enter.)
|
* impossible to enter.)
|
||||||
*
|
*
|
||||||
* Unnamed tabs keep data flat (siteIntegrations.ga4MeasurementId).
|
* Unnamed tabs keep data flat (siteIntegrations.ga4MeasurementId).
|
||||||
|
*
|
||||||
|
* Note: R2 storage credentials are NOT here — storage is infrastructure and
|
||||||
|
* binds at boot, so its config lives in .env (R2_BUCKET, R2_ENDPOINT, ...),
|
||||||
|
* consumed by buildR2Storage. See docs/storage.md.
|
||||||
*/ export function buildSiteIntegrations({ additionalFields } = {}) {
|
*/ export function buildSiteIntegrations({ additionalFields } = {}) {
|
||||||
return {
|
return {
|
||||||
slug: 'site-integrations',
|
slug: 'site-integrations',
|
||||||
@@ -42,10 +45,6 @@ import { turnstileFields } from './fields/turnstile.js';
|
|||||||
fields: smtpFields,
|
fields: smtpFields,
|
||||||
label: 'SMTP'
|
label: 'SMTP'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
fields: storageFields,
|
|
||||||
label: 'Storage'
|
|
||||||
},
|
|
||||||
...additionalFields?.length ? [
|
...additionalFields?.length ? [
|
||||||
{
|
{
|
||||||
fields: additionalFields,
|
fields: additionalFields,
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
{"version":3,"sources":["../../../src/globals/SiteIntegrations/index.ts"],"sourcesContent":["import type { Field, GlobalConfig } from 'payload'\n\nimport { isAdmin } from '../../modules/access/index.js'\nimport { analyticsFields } from './fields/analytics.js'\nimport { smtpFields } from './fields/smtp.js'\nimport { storageFields } from './fields/storage.js'\nimport { turnstileFields } from './fields/turnstile.js'\n\ntype BuildSiteIntegrationsArgs = {\n /** Extra fields injected by the client project */\n additionalFields?: Field[]\n}\n\n/**\n * Builds the SiteIntegrations global.\n *\n * Holds third-party service credentials. Access is enforced at the global\n * level — the whole global requires an authenticated user — so secrets stay\n * out of anonymous API responses while remaining editable in the admin panel\n * and readable via the server-side Local API. (Field-level read:false was\n * avoided because it also hides fields from the admin UI, making them\n * impossible to enter.)\n *\n * Unnamed tabs keep data flat (siteIntegrations.ga4MeasurementId).\n */\nexport function buildSiteIntegrations({\n additionalFields,\n}: BuildSiteIntegrationsArgs = {}): GlobalConfig {\n return {\n slug: 'site-integrations',\n access: {\n // Admin-only — secrets live here. Anonymous and non-admin users get\n // nothing through the API; admins read/edit in the panel and via Local API.\n read: ({ req: { user } }) => isAdmin(user),\n update: ({ req: { user } }) => isAdmin(user),\n },\n admin: {\n group: 'Settings',\n },\n fields: [\n {\n type: 'tabs',\n tabs: [\n { fields: analyticsFields, label: 'Analytics' },\n { fields: turnstileFields, label: 'Turnstile' },\n { fields: smtpFields, label: 'SMTP' },\n { fields: storageFields, label: 'Storage' },\n ...(additionalFields?.length ? [{ fields: additionalFields, label: 'Custom' }] : []),\n ],\n },\n ],\n label: 'Site Integrations',\n }\n}\n"],"names":["isAdmin","analyticsFields","smtpFields","storageFields","turnstileFields","buildSiteIntegrations","additionalFields","slug","access","read","req","user","update","admin","group","fields","type","tabs","label","length"],"mappings":"AAEA,SAASA,OAAO,QAAQ,gCAA+B;AACvD,SAASC,eAAe,QAAQ,wBAAuB;AACvD,SAASC,UAAU,QAAQ,mBAAkB;AAC7C,SAASC,aAAa,QAAQ,sBAAqB;AACnD,SAASC,eAAe,QAAQ,wBAAuB;AAOvD;;;;;;;;;;;CAWC,GACD,OAAO,SAASC,sBAAsB,EACpCC,gBAAgB,EACU,GAAG,CAAC,CAAC;IAC/B,OAAO;QACLC,MAAM;QACNC,QAAQ;YACN,oEAAoE;YACpE,4EAA4E;YAC5EC,MAAM,CAAC,EAAEC,KAAK,EAAEC,IAAI,EAAE,EAAE,GAAKX,QAAQW;YACrCC,QAAQ,CAAC,EAAEF,KAAK,EAAEC,IAAI,EAAE,EAAE,GAAKX,QAAQW;QACzC;QACAE,OAAO;YACLC,OAAO;QACT;QACAC,QAAQ;YACN;gBACEC,MAAM;gBACNC,MAAM;oBACJ;wBAAEF,QAAQd;wBAAiBiB,OAAO;oBAAY;oBAC9C;wBAAEH,QAAQX;wBAAiBc,OAAO;oBAAY;oBAC9C;wBAAEH,QAAQb;wBAAYgB,OAAO;oBAAO;oBACpC;wBAAEH,QAAQZ;wBAAee,OAAO;oBAAU;uBACtCZ,kBAAkBa,SAAS;wBAAC;4BAAEJ,QAAQT;4BAAkBY,OAAO;wBAAS;qBAAE,GAAG,EAAE;iBACpF;YACH;SACD;QACDA,OAAO;IACT;AACF"}
|
{"version":3,"sources":["../../../src/globals/SiteIntegrations/index.ts"],"sourcesContent":["import type { Field, GlobalConfig } from 'payload'\n\nimport { isAdmin } from '../../modules/access/index.js'\nimport { analyticsFields } from './fields/analytics.js'\nimport { smtpFields } from './fields/smtp.js'\nimport { turnstileFields } from './fields/turnstile.js'\n\ntype BuildSiteIntegrationsArgs = {\n /** Extra fields injected by the client project */\n additionalFields?: Field[]\n}\n\n/**\n * Builds the SiteIntegrations global.\n *\n * Holds third-party service credentials. Access is enforced at the global\n * level — the whole global requires an authenticated user — so secrets stay\n * out of anonymous API responses while remaining editable in the admin panel\n * and readable via the server-side Local API. (Field-level read:false was\n * avoided because it also hides fields from the admin UI, making them\n * impossible to enter.)\n *\n * Unnamed tabs keep data flat (siteIntegrations.ga4MeasurementId).\n *\n * Note: R2 storage credentials are NOT here — storage is infrastructure and\n * binds at boot, so its config lives in .env (R2_BUCKET, R2_ENDPOINT, ...),\n * consumed by buildR2Storage. See docs/storage.md.\n */\nexport function buildSiteIntegrations({\n additionalFields,\n}: BuildSiteIntegrationsArgs = {}): GlobalConfig {\n return {\n slug: 'site-integrations',\n access: {\n // Admin-only — secrets live here. Anonymous and non-admin users get\n // nothing through the API; admins read/edit in the panel and via Local API.\n read: ({ req: { user } }) => isAdmin(user),\n update: ({ req: { user } }) => isAdmin(user),\n },\n admin: {\n group: 'Settings',\n },\n fields: [\n {\n type: 'tabs',\n tabs: [\n { fields: analyticsFields, label: 'Analytics' },\n { fields: turnstileFields, label: 'Turnstile' },\n { fields: smtpFields, label: 'SMTP' },\n ...(additionalFields?.length ? [{ fields: additionalFields, label: 'Custom' }] : []),\n ],\n },\n ],\n label: 'Site Integrations',\n }\n}\n"],"names":["isAdmin","analyticsFields","smtpFields","turnstileFields","buildSiteIntegrations","additionalFields","slug","access","read","req","user","update","admin","group","fields","type","tabs","label","length"],"mappings":"AAEA,SAASA,OAAO,QAAQ,gCAA+B;AACvD,SAASC,eAAe,QAAQ,wBAAuB;AACvD,SAASC,UAAU,QAAQ,mBAAkB;AAC7C,SAASC,eAAe,QAAQ,wBAAuB;AAOvD;;;;;;;;;;;;;;;CAeC,GACD,OAAO,SAASC,sBAAsB,EACpCC,gBAAgB,EACU,GAAG,CAAC,CAAC;IAC/B,OAAO;QACLC,MAAM;QACNC,QAAQ;YACN,oEAAoE;YACpE,4EAA4E;YAC5EC,MAAM,CAAC,EAAEC,KAAK,EAAEC,IAAI,EAAE,EAAE,GAAKV,QAAQU;YACrCC,QAAQ,CAAC,EAAEF,KAAK,EAAEC,IAAI,EAAE,EAAE,GAAKV,QAAQU;QACzC;QACAE,OAAO;YACLC,OAAO;QACT;QACAC,QAAQ;YACN;gBACEC,MAAM;gBACNC,MAAM;oBACJ;wBAAEF,QAAQb;wBAAiBgB,OAAO;oBAAY;oBAC9C;wBAAEH,QAAQX;wBAAiBc,OAAO;oBAAY;oBAC9C;wBAAEH,QAAQZ;wBAAYe,OAAO;oBAAO;uBAChCZ,kBAAkBa,SAAS;wBAAC;4BAAEJ,QAAQT;4BAAkBY,OAAO;wBAAS;qBAAE,GAAG,EAAE;iBACpF;YACH;SACD;QACDA,OAAO;IACT;AACF"}
|
||||||
Vendored
+4
-2
@@ -20,6 +20,9 @@ export type { I18nConfig, LocaleDefinition, LocalizedSlugs } from './modules/i18
|
|||||||
export { buildLocalizedPath, getDefaultLocale, getLocaleCodes, getLocaleDefinition, getLocalizedSlugs, isValidLocale, LOCALE_COOKIE_NAME, matchAcceptLanguage, negotiateLocale, switchLocalePath, } from './modules/i18n/index.js';
|
export { buildLocalizedPath, getDefaultLocale, getLocaleCodes, getLocaleDefinition, getLocalizedSlugs, isValidLocale, LOCALE_COOKIE_NAME, matchAcceptLanguage, negotiateLocale, switchLocalePath, } from './modules/i18n/index.js';
|
||||||
export type { LocaleMiddlewareResult } from './modules/i18n/index.js';
|
export type { LocaleMiddlewareResult } from './modules/i18n/index.js';
|
||||||
export { createLocaleMiddleware, DEFAULT_MIDDLEWARE_MATCHER } from './modules/i18n/index.js';
|
export { createLocaleMiddleware, DEFAULT_MIDDLEWARE_MATCHER } from './modules/i18n/index.js';
|
||||||
|
export { normalizeFilename, normalizeFilenameHook } from './modules/media/index.js';
|
||||||
|
export { getNotificationTexts, NOTIFICATION_FALLBACK, resolveFormMessage, } from './modules/notifications/index.js';
|
||||||
|
export type { FormNotificationTexts, NotificationsData, NotificationTexts, } from './modules/notifications/index.js';
|
||||||
export type { PagesOption, SystemPageRole } from './modules/pages/index.js';
|
export type { PagesOption, SystemPageRole } from './modules/pages/index.js';
|
||||||
export { ALL_SYSTEM_PAGE_ROLES, getSystemPagePath } from './modules/pages/index.js';
|
export { ALL_SYSTEM_PAGE_ROLES, getSystemPagePath } from './modules/pages/index.js';
|
||||||
export type { GlobalQueryOptions } from './modules/payload/index.js';
|
export type { GlobalQueryOptions } from './modules/payload/index.js';
|
||||||
@@ -31,7 +34,6 @@ export { buildHreflangAlternates, buildMetadata, composeTitle } from './modules/
|
|||||||
export type { AutoFillMapping, RobotsRules, SitemapEntry } from './modules/seo/index.js';
|
export type { AutoFillMapping, RobotsRules, SitemapEntry } from './modules/seo/index.js';
|
||||||
export { buildAutoFillMetaHook, buildRobots, buildSitemapEntries, createMetadataGenerator, createPageMetadata, injectAutoFillMeta, } from './modules/seo/index.js';
|
export { buildAutoFillMetaHook, buildRobots, buildSitemapEntries, createMetadataGenerator, createPageMetadata, injectAutoFillMeta, } from './modules/seo/index.js';
|
||||||
export { buildSlugField, toSlug } from './modules/slug/index.js';
|
export { buildSlugField, toSlug } from './modules/slug/index.js';
|
||||||
export { NOTIFICATION_FALLBACK, getNotificationTexts, resolveFormMessage, } from './modules/notifications/index.js';
|
export { buildR2Storage } from './modules/storage/index.js';
|
||||||
export type { FormNotificationTexts, NotificationsData, NotificationTexts, } from './modules/notifications/index.js';
|
|
||||||
export { ipalKit } from './plugin.js';
|
export { ipalKit } from './plugin.js';
|
||||||
export type { IpalOptions } from './types.js';
|
export type { IpalOptions } from './types.js';
|
||||||
|
|||||||
Vendored
+5
-1
@@ -12,13 +12,17 @@ export { buildFormsPlugin } from './modules/forms/formsPluginConfig.js';
|
|||||||
export { createContentHelpers } from './modules/frontend/index.js';
|
export { createContentHelpers } from './modules/frontend/index.js';
|
||||||
export { buildLocalizedPath, getDefaultLocale, getLocaleCodes, getLocaleDefinition, getLocalizedSlugs, isValidLocale, LOCALE_COOKIE_NAME, matchAcceptLanguage, negotiateLocale, switchLocalePath } from './modules/i18n/index.js';
|
export { buildLocalizedPath, getDefaultLocale, getLocaleCodes, getLocaleDefinition, getLocalizedSlugs, isValidLocale, LOCALE_COOKIE_NAME, matchAcceptLanguage, negotiateLocale, switchLocalePath } from './modules/i18n/index.js';
|
||||||
export { createLocaleMiddleware, DEFAULT_MIDDLEWARE_MATCHER } from './modules/i18n/index.js';
|
export { createLocaleMiddleware, DEFAULT_MIDDLEWARE_MATCHER } from './modules/i18n/index.js';
|
||||||
|
// Media — filename normalization hook for upload collections (Media).
|
||||||
|
export { normalizeFilename, normalizeFilenameHook } from './modules/media/index.js';
|
||||||
|
export { getNotificationTexts, NOTIFICATION_FALLBACK, resolveFormMessage } from './modules/notifications/index.js';
|
||||||
export { ALL_SYSTEM_PAGE_ROLES, getSystemPagePath } from './modules/pages/index.js';
|
export { ALL_SYSTEM_PAGE_ROLES, getSystemPagePath } from './modules/pages/index.js';
|
||||||
export { getGlobal, getSiteIntegrations, getSiteSettings, SITE_INTEGRATIONS_SLUG, SITE_SETTINGS_SLUG } from './modules/payload/index.js';
|
export { getGlobal, getSiteIntegrations, getSiteSettings, SITE_INTEGRATIONS_SLUG, SITE_SETTINGS_SLUG } from './modules/payload/index.js';
|
||||||
export { buildSecurityHeaders } from './modules/security/index.js';
|
export { buildSecurityHeaders } from './modules/security/index.js';
|
||||||
export { buildHreflangAlternates, buildMetadata, composeTitle } from './modules/seo/index.js';
|
export { buildHreflangAlternates, buildMetadata, composeTitle } from './modules/seo/index.js';
|
||||||
export { buildAutoFillMetaHook, buildRobots, buildSitemapEntries, createMetadataGenerator, createPageMetadata, injectAutoFillMeta } from './modules/seo/index.js';
|
export { buildAutoFillMetaHook, buildRobots, buildSitemapEntries, createMetadataGenerator, createPageMetadata, injectAutoFillMeta } from './modules/seo/index.js';
|
||||||
export { buildSlugField, toSlug } from './modules/slug/index.js';
|
export { buildSlugField, toSlug } from './modules/slug/index.js';
|
||||||
export { NOTIFICATION_FALLBACK, getNotificationTexts, resolveFormMessage } from './modules/notifications/index.js';
|
// Storage — Cloudflare R2 media offload, configured from .env.
|
||||||
|
export { buildR2Storage } from './modules/storage/index.js';
|
||||||
export { ipalKit } from './plugin.js';
|
export { ipalKit } from './plugin.js';
|
||||||
|
|
||||||
//# sourceMappingURL=index.js.map
|
//# sourceMappingURL=index.js.map
|
||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+8
-1
@@ -1,6 +1,13 @@
|
|||||||
import type { I18nConfig } from './types.js';
|
import type { I18nConfig } from './types.js';
|
||||||
/** Cookie name the template uses to persist a visitor's locale choice. */
|
/** Cookie name the template uses to persist a visitor's locale choice. */
|
||||||
export declare const LOCALE_COOKIE_NAME = "ipal-locale";
|
/**
|
||||||
|
* Cookie name for the persisted locale choice. Uses NEXT_LOCALE — the convention
|
||||||
|
* Next.js and its i18n ecosystem expect — so the cookie is interoperable with
|
||||||
|
* other libraries that read the active locale (instead of a plugin-specific
|
||||||
|
* name). Written only under functional consent; cleared when that consent is
|
||||||
|
* withdrawn (see consent cookieMap).
|
||||||
|
*/
|
||||||
|
export declare const LOCALE_COOKIE_NAME = "NEXT_LOCALE";
|
||||||
type NegotiateLocaleArgs = {
|
type NegotiateLocaleArgs = {
|
||||||
/** Raw Accept-Language header value */
|
/** Raw Accept-Language header value */
|
||||||
acceptLanguage?: null | string;
|
acceptLanguage?: null | string;
|
||||||
|
|||||||
Vendored
+7
-1
@@ -1,5 +1,11 @@
|
|||||||
import { getLocaleCodes, isValidLocale } from './helpers.js';
|
import { getLocaleCodes, isValidLocale } from './helpers.js';
|
||||||
/** Cookie name the template uses to persist a visitor's locale choice. */ export const LOCALE_COOKIE_NAME = 'ipal-locale';
|
/** Cookie name the template uses to persist a visitor's locale choice. */ /**
|
||||||
|
* Cookie name for the persisted locale choice. Uses NEXT_LOCALE — the convention
|
||||||
|
* Next.js and its i18n ecosystem expect — so the cookie is interoperable with
|
||||||
|
* other libraries that read the active locale (instead of a plugin-specific
|
||||||
|
* name). Written only under functional consent; cleared when that consent is
|
||||||
|
* withdrawn (see consent cookieMap).
|
||||||
|
*/ export const LOCALE_COOKIE_NAME = 'NEXT_LOCALE';
|
||||||
/**
|
/**
|
||||||
* Resolves which locale to serve, in priority order:
|
* Resolves which locale to serve, in priority order:
|
||||||
* 1. Cookie (explicit prior choice)
|
* 1. Cookie (explicit prior choice)
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
export { normalizeFilename, normalizeFilenameHook } from './normalizeFilename.js';
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
export { normalizeFilename, normalizeFilenameHook } from './normalizeFilename.js';
|
||||||
|
|
||||||
|
//# sourceMappingURL=index.js.map
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"sources":["../../../src/modules/media/index.ts"],"sourcesContent":["export { normalizeFilename, normalizeFilenameHook } from './normalizeFilename.js'\n"],"names":["normalizeFilename","normalizeFilenameHook"],"mappings":"AAAA,SAASA,iBAAiB,EAAEC,qBAAqB,QAAQ,yBAAwB"}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
import type { CollectionBeforeOperationHook } from 'payload';
|
||||||
|
/**
|
||||||
|
* Normalizes a filename: slugifies the NAME part (diacritics, spaces, case)
|
||||||
|
* while preserving the extension. Keeps uploaded media URLs clean and portable.
|
||||||
|
*
|
||||||
|
* "Zdjęcie jeden nad morzem.jpg" → "zdjecie-jeden-nad-morzem.jpg"
|
||||||
|
* "Faktura #12 (2024).PDF" → "faktura-12-2024.pdf"
|
||||||
|
* "already-clean.webp" → "already-clean.webp"
|
||||||
|
*
|
||||||
|
* Why not toSlug(): toSlug uses strict:true, which would strip the dot and
|
||||||
|
* merge name+extension. Here we split on the LAST dot, slug the stem, lowercase
|
||||||
|
* the extension, and rejoin.
|
||||||
|
*/
|
||||||
|
export declare function normalizeFilename(filename: string): string;
|
||||||
|
/**
|
||||||
|
* beforeOperation hook for an upload collection (e.g. Media). Rewrites the
|
||||||
|
* incoming file's name to its normalized form before Payload stores it, so both
|
||||||
|
* the stored file and its DB filename are clean. Works with local disk and with
|
||||||
|
* cloud storage adapters (R2/S3) — it runs before the storage layer.
|
||||||
|
*
|
||||||
|
* Wire into your Media collection:
|
||||||
|
* import { normalizeFilenameHook } from '@intecion/ipal-kit'
|
||||||
|
* hooks: { beforeOperation: [normalizeFilenameHook] }
|
||||||
|
*/
|
||||||
|
export declare const normalizeFilenameHook: CollectionBeforeOperationHook;
|
||||||
+57
@@ -0,0 +1,57 @@
|
|||||||
|
import slugify from 'slugify';
|
||||||
|
/**
|
||||||
|
* Normalizes a filename: slugifies the NAME part (diacritics, spaces, case)
|
||||||
|
* while preserving the extension. Keeps uploaded media URLs clean and portable.
|
||||||
|
*
|
||||||
|
* "Zdjęcie jeden nad morzem.jpg" → "zdjecie-jeden-nad-morzem.jpg"
|
||||||
|
* "Faktura #12 (2024).PDF" → "faktura-12-2024.pdf"
|
||||||
|
* "already-clean.webp" → "already-clean.webp"
|
||||||
|
*
|
||||||
|
* Why not toSlug(): toSlug uses strict:true, which would strip the dot and
|
||||||
|
* merge name+extension. Here we split on the LAST dot, slug the stem, lowercase
|
||||||
|
* the extension, and rejoin.
|
||||||
|
*/ export function normalizeFilename(filename) {
|
||||||
|
const lastDot = filename.lastIndexOf('.');
|
||||||
|
// No extension (or leading-dot dotfile) → slug the whole thing.
|
||||||
|
if (lastDot <= 0) {
|
||||||
|
return slugify(filename, {
|
||||||
|
lower: true,
|
||||||
|
strict: true,
|
||||||
|
trim: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const stem = filename.slice(0, lastDot);
|
||||||
|
const ext = filename.slice(lastDot + 1).toLowerCase();
|
||||||
|
const cleanStem = slugify(stem, {
|
||||||
|
lower: true,
|
||||||
|
strict: true,
|
||||||
|
trim: true
|
||||||
|
});
|
||||||
|
const cleanExt = slugify(ext, {
|
||||||
|
lower: true,
|
||||||
|
strict: true,
|
||||||
|
trim: true
|
||||||
|
});
|
||||||
|
// Stem could slug to empty (e.g. filename was all symbols) — fall back so we
|
||||||
|
// never produce a nameless file.
|
||||||
|
const safeStem = cleanStem || 'plik';
|
||||||
|
return cleanExt ? `${safeStem}.${cleanExt}` : safeStem;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* beforeOperation hook for an upload collection (e.g. Media). Rewrites the
|
||||||
|
* incoming file's name to its normalized form before Payload stores it, so both
|
||||||
|
* the stored file and its DB filename are clean. Works with local disk and with
|
||||||
|
* cloud storage adapters (R2/S3) — it runs before the storage layer.
|
||||||
|
*
|
||||||
|
* Wire into your Media collection:
|
||||||
|
* import { normalizeFilenameHook } from '@intecion/ipal-kit'
|
||||||
|
* hooks: { beforeOperation: [normalizeFilenameHook] }
|
||||||
|
*/ export const normalizeFilenameHook = ({ req, operation })=>{
|
||||||
|
if (operation !== 'create' && operation !== 'update') return;
|
||||||
|
const file = req.file;
|
||||||
|
if (file?.name) {
|
||||||
|
file.name = normalizeFilename(file.name);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//# sourceMappingURL=normalizeFilename.js.map
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"sources":["../../../src/modules/media/normalizeFilename.ts"],"sourcesContent":["import type { CollectionBeforeOperationHook } from 'payload'\nimport slugify from 'slugify'\n\n/**\n * Normalizes a filename: slugifies the NAME part (diacritics, spaces, case)\n * while preserving the extension. Keeps uploaded media URLs clean and portable.\n *\n * \"Zdjęcie jeden nad morzem.jpg\" → \"zdjecie-jeden-nad-morzem.jpg\"\n * \"Faktura #12 (2024).PDF\" → \"faktura-12-2024.pdf\"\n * \"already-clean.webp\" → \"already-clean.webp\"\n *\n * Why not toSlug(): toSlug uses strict:true, which would strip the dot and\n * merge name+extension. Here we split on the LAST dot, slug the stem, lowercase\n * the extension, and rejoin.\n */\nexport function normalizeFilename(filename: string): string {\n const lastDot = filename.lastIndexOf('.')\n\n // No extension (or leading-dot dotfile) → slug the whole thing.\n if (lastDot <= 0) {\n return slugify(filename, { lower: true, strict: true, trim: true })\n }\n\n const stem = filename.slice(0, lastDot)\n const ext = filename.slice(lastDot + 1).toLowerCase()\n\n const cleanStem = slugify(stem, { lower: true, strict: true, trim: true })\n const cleanExt = slugify(ext, { lower: true, strict: true, trim: true })\n\n // Stem could slug to empty (e.g. filename was all symbols) — fall back so we\n // never produce a nameless file.\n const safeStem = cleanStem || 'plik'\n\n return cleanExt ? `${safeStem}.${cleanExt}` : safeStem\n}\n\n/**\n * beforeOperation hook for an upload collection (e.g. Media). Rewrites the\n * incoming file's name to its normalized form before Payload stores it, so both\n * the stored file and its DB filename are clean. Works with local disk and with\n * cloud storage adapters (R2/S3) — it runs before the storage layer.\n *\n * Wire into your Media collection:\n * import { normalizeFilenameHook } from '@intecion/ipal-kit'\n * hooks: { beforeOperation: [normalizeFilenameHook] }\n */\nexport const normalizeFilenameHook: CollectionBeforeOperationHook = ({ req, operation }) => {\n if (operation !== 'create' && operation !== 'update') return\n const file = req.file\n if (file?.name) {\n file.name = normalizeFilename(file.name)\n }\n}\n"],"names":["slugify","normalizeFilename","filename","lastDot","lastIndexOf","lower","strict","trim","stem","slice","ext","toLowerCase","cleanStem","cleanExt","safeStem","normalizeFilenameHook","req","operation","file","name"],"mappings":"AACA,OAAOA,aAAa,UAAS;AAE7B;;;;;;;;;;;CAWC,GACD,OAAO,SAASC,kBAAkBC,QAAgB;IAChD,MAAMC,UAAUD,SAASE,WAAW,CAAC;IAErC,gEAAgE;IAChE,IAAID,WAAW,GAAG;QAChB,OAAOH,QAAQE,UAAU;YAAEG,OAAO;YAAMC,QAAQ;YAAMC,MAAM;QAAK;IACnE;IAEA,MAAMC,OAAON,SAASO,KAAK,CAAC,GAAGN;IAC/B,MAAMO,MAAMR,SAASO,KAAK,CAACN,UAAU,GAAGQ,WAAW;IAEnD,MAAMC,YAAYZ,QAAQQ,MAAM;QAAEH,OAAO;QAAMC,QAAQ;QAAMC,MAAM;IAAK;IACxE,MAAMM,WAAWb,QAAQU,KAAK;QAAEL,OAAO;QAAMC,QAAQ;QAAMC,MAAM;IAAK;IAEtE,6EAA6E;IAC7E,iCAAiC;IACjC,MAAMO,WAAWF,aAAa;IAE9B,OAAOC,WAAW,GAAGC,SAAS,CAAC,EAAED,UAAU,GAAGC;AAChD;AAEA;;;;;;;;;CASC,GACD,OAAO,MAAMC,wBAAuD,CAAC,EAAEC,GAAG,EAAEC,SAAS,EAAE;IACrF,IAAIA,cAAc,YAAYA,cAAc,UAAU;IACtD,MAAMC,OAAOF,IAAIE,IAAI;IACrB,IAAIA,MAAMC,MAAM;QACdD,KAAKC,IAAI,GAAGlB,kBAAkBiB,KAAKC,IAAI;IACzC;AACF,EAAC"}
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
import type { Plugin } from 'payload';
|
||||||
|
/**
|
||||||
|
* Cloudflare R2 media storage — configured from environment variables (agency
|
||||||
|
* infrastructure, not per-project panel data). R2 is S3-compatible, so we use
|
||||||
|
* @payloadcms/storage-s3 pointed at the R2 endpoint.
|
||||||
|
*
|
||||||
|
* Storage is infrastructure (like the database or PAYLOAD_SECRET): it binds at
|
||||||
|
* boot, and its credentials are agency-owned — so it lives in .env, not the
|
||||||
|
* panel. See docs/storage.md for the required variables.
|
||||||
|
*
|
||||||
|
* Returns the storage plugin when all R2 vars are present; otherwise returns a
|
||||||
|
* no-op passthrough so the project falls back to Payload's default local disk
|
||||||
|
* storage (useful in dev without R2). This mirrors how mailAdapter degrades
|
||||||
|
* gracefully when a transport isn't configured.
|
||||||
|
*
|
||||||
|
* @param collections - slugs of upload collections to offload to R2 (e.g. ['media'])
|
||||||
|
*/
|
||||||
|
export declare const buildR2Storage: (collections?: string[]) => Plugin;
|
||||||
+72
@@ -0,0 +1,72 @@
|
|||||||
|
import { s3Storage } from '@payloadcms/storage-s3';
|
||||||
|
/**
|
||||||
|
* Cloudflare R2 media storage — configured from environment variables (agency
|
||||||
|
* infrastructure, not per-project panel data). R2 is S3-compatible, so we use
|
||||||
|
* @payloadcms/storage-s3 pointed at the R2 endpoint.
|
||||||
|
*
|
||||||
|
* Storage is infrastructure (like the database or PAYLOAD_SECRET): it binds at
|
||||||
|
* boot, and its credentials are agency-owned — so it lives in .env, not the
|
||||||
|
* panel. See docs/storage.md for the required variables.
|
||||||
|
*
|
||||||
|
* Returns the storage plugin when all R2 vars are present; otherwise returns a
|
||||||
|
* no-op passthrough so the project falls back to Payload's default local disk
|
||||||
|
* storage (useful in dev without R2). This mirrors how mailAdapter degrades
|
||||||
|
* gracefully when a transport isn't configured.
|
||||||
|
*
|
||||||
|
* @param collections - slugs of upload collections to offload to R2 (e.g. ['media'])
|
||||||
|
*/ export const buildR2Storage = (collections = [
|
||||||
|
'media'
|
||||||
|
])=>{
|
||||||
|
const bucket = process.env.R2_BUCKET;
|
||||||
|
const endpoint = process.env.R2_ENDPOINT;
|
||||||
|
const accessKeyId = process.env.R2_ACCESS_KEY_ID;
|
||||||
|
const secretAccessKey = process.env.R2_SECRET_ACCESS_KEY;
|
||||||
|
// Any missing → skip R2, fall back to local disk. Warn so it's not silent.
|
||||||
|
if (!bucket || !endpoint || !accessKeyId || !secretAccessKey) {
|
||||||
|
return (config)=>{
|
||||||
|
// Only warn when SOME vars are set (partial config = likely a mistake).
|
||||||
|
if (bucket || endpoint || accessKeyId || secretAccessKey) {
|
||||||
|
console.warn('[ipal] R2 storage: incomplete env (need R2_BUCKET, R2_ENDPOINT, ' + 'R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY). Falling back to local disk.');
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// Public URL for served media. R2 is private by default; its S3 endpoint only
|
||||||
|
// accepts uploads and won't serve files (403). With a custom domain
|
||||||
|
// (media.klient.pl → bucket) set R2_PUBLIC_URL so Payload generates URLs
|
||||||
|
// pointing there. Without it, uploads work but images don't display publicly.
|
||||||
|
// See docs/storage.md.
|
||||||
|
const publicUrl = process.env.R2_PUBLIC_URL?.replace(/\/$/, '') // strip trailing slash
|
||||||
|
;
|
||||||
|
// generateFileURL is a PER-COLLECTION option in @payloadcms/storage-s3 (not a
|
||||||
|
// top-level one) — R2 needs it to point served URLs at the custom domain
|
||||||
|
// instead of the private S3 endpoint. Each collection gets either `true`
|
||||||
|
// (plain offload) or an object carrying generateFileURL when a public URL is set.
|
||||||
|
const generateFileURL = publicUrl ? ({ filename, prefix })=>[
|
||||||
|
publicUrl,
|
||||||
|
prefix,
|
||||||
|
filename
|
||||||
|
].filter(Boolean).join('/') : undefined;
|
||||||
|
const collectionsConfig = {};
|
||||||
|
for (const slug of collections){
|
||||||
|
collectionsConfig[slug] = generateFileURL ? {
|
||||||
|
generateFileURL
|
||||||
|
} : true;
|
||||||
|
}
|
||||||
|
return s3Storage({
|
||||||
|
bucket,
|
||||||
|
collections: collectionsConfig,
|
||||||
|
config: {
|
||||||
|
credentials: {
|
||||||
|
accessKeyId,
|
||||||
|
secretAccessKey
|
||||||
|
},
|
||||||
|
endpoint,
|
||||||
|
region: 'auto',
|
||||||
|
// R2 requires path-style addressing for S3 compatibility.
|
||||||
|
forcePathStyle: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
//# sourceMappingURL=buildR2Storage.js.map
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"sources":["../../../src/modules/storage/buildR2Storage.ts"],"sourcesContent":["import type { Plugin } from 'payload'\n\nimport { s3Storage } from '@payloadcms/storage-s3'\n\n/**\n * Cloudflare R2 media storage — configured from environment variables (agency\n * infrastructure, not per-project panel data). R2 is S3-compatible, so we use\n * @payloadcms/storage-s3 pointed at the R2 endpoint.\n *\n * Storage is infrastructure (like the database or PAYLOAD_SECRET): it binds at\n * boot, and its credentials are agency-owned — so it lives in .env, not the\n * panel. See docs/storage.md for the required variables.\n *\n * Returns the storage plugin when all R2 vars are present; otherwise returns a\n * no-op passthrough so the project falls back to Payload's default local disk\n * storage (useful in dev without R2). This mirrors how mailAdapter degrades\n * gracefully when a transport isn't configured.\n *\n * @param collections - slugs of upload collections to offload to R2 (e.g. ['media'])\n */\nexport const buildR2Storage = (collections: string[] = ['media']): Plugin => {\n const bucket = process.env.R2_BUCKET\n const endpoint = process.env.R2_ENDPOINT\n const accessKeyId = process.env.R2_ACCESS_KEY_ID\n const secretAccessKey = process.env.R2_SECRET_ACCESS_KEY\n\n // Any missing → skip R2, fall back to local disk. Warn so it's not silent.\n if (!bucket || !endpoint || !accessKeyId || !secretAccessKey) {\n return (config) => {\n // Only warn when SOME vars are set (partial config = likely a mistake).\n if (bucket || endpoint || accessKeyId || secretAccessKey) {\n console.warn(\n '[ipal] R2 storage: incomplete env (need R2_BUCKET, R2_ENDPOINT, ' +\n 'R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY). Falling back to local disk.',\n )\n }\n return config\n }\n }\n\n // Public URL for served media. R2 is private by default; its S3 endpoint only\n // accepts uploads and won't serve files (403). With a custom domain\n // (media.klient.pl → bucket) set R2_PUBLIC_URL so Payload generates URLs\n // pointing there. Without it, uploads work but images don't display publicly.\n // See docs/storage.md.\n const publicUrl = process.env.R2_PUBLIC_URL?.replace(/\\/$/, '') // strip trailing slash\n\n // generateFileURL is a PER-COLLECTION option in @payloadcms/storage-s3 (not a\n // top-level one) — R2 needs it to point served URLs at the custom domain\n // instead of the private S3 endpoint. Each collection gets either `true`\n // (plain offload) or an object carrying generateFileURL when a public URL is set.\n const generateFileURL = publicUrl\n ? ({ filename, prefix }: { filename: string; prefix?: string }) =>\n [publicUrl, prefix, filename].filter(Boolean).join('/')\n : undefined\n\n const collectionsConfig: Record<string, { generateFileURL: typeof generateFileURL } | true> = {}\n for (const slug of collections) {\n collectionsConfig[slug] = generateFileURL ? { generateFileURL } : true\n }\n\n return s3Storage({\n bucket,\n collections: collectionsConfig,\n config: {\n credentials: { accessKeyId, secretAccessKey },\n endpoint,\n region: 'auto', // R2 uses 'auto'\n // R2 requires path-style addressing for S3 compatibility.\n forcePathStyle: true,\n },\n })\n}\n"],"names":["s3Storage","buildR2Storage","collections","bucket","process","env","R2_BUCKET","endpoint","R2_ENDPOINT","accessKeyId","R2_ACCESS_KEY_ID","secretAccessKey","R2_SECRET_ACCESS_KEY","config","console","warn","publicUrl","R2_PUBLIC_URL","replace","generateFileURL","filename","prefix","filter","Boolean","join","undefined","collectionsConfig","slug","credentials","region","forcePathStyle"],"mappings":"AAEA,SAASA,SAAS,QAAQ,yBAAwB;AAElD;;;;;;;;;;;;;;;CAeC,GACD,OAAO,MAAMC,iBAAiB,CAACC,cAAwB;IAAC;CAAQ;IAC9D,MAAMC,SAASC,QAAQC,GAAG,CAACC,SAAS;IACpC,MAAMC,WAAWH,QAAQC,GAAG,CAACG,WAAW;IACxC,MAAMC,cAAcL,QAAQC,GAAG,CAACK,gBAAgB;IAChD,MAAMC,kBAAkBP,QAAQC,GAAG,CAACO,oBAAoB;IAExD,2EAA2E;IAC3E,IAAI,CAACT,UAAU,CAACI,YAAY,CAACE,eAAe,CAACE,iBAAiB;QAC5D,OAAO,CAACE;YACN,wEAAwE;YACxE,IAAIV,UAAUI,YAAYE,eAAeE,iBAAiB;gBACxDG,QAAQC,IAAI,CACV,qEACE;YAEN;YACA,OAAOF;QACT;IACF;IAEA,8EAA8E;IAC9E,oEAAoE;IACpE,yEAAyE;IACzE,8EAA8E;IAC9E,uBAAuB;IACvB,MAAMG,YAAYZ,QAAQC,GAAG,CAACY,aAAa,EAAEC,QAAQ,OAAO,IAAI,uBAAuB;;IAEvF,8EAA8E;IAC9E,yEAAyE;IACzE,yEAAyE;IACzE,kFAAkF;IAClF,MAAMC,kBAAkBH,YACpB,CAAC,EAAEI,QAAQ,EAAEC,MAAM,EAAyC,GAC1D;YAACL;YAAWK;YAAQD;SAAS,CAACE,MAAM,CAACC,SAASC,IAAI,CAAC,OACrDC;IAEJ,MAAMC,oBAAwF,CAAC;IAC/F,KAAK,MAAMC,QAAQzB,YAAa;QAC9BwB,iBAAiB,CAACC,KAAK,GAAGR,kBAAkB;YAAEA;QAAgB,IAAI;IACpE;IAEA,OAAOnB,UAAU;QACfG;QACAD,aAAawB;QACbb,QAAQ;YACNe,aAAa;gBAAEnB;gBAAaE;YAAgB;YAC5CJ;YACAsB,QAAQ;YACR,0DAA0D;YAC1DC,gBAAgB;QAClB;IACF;AACF,EAAC"}
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
export { buildR2Storage } from './buildR2Storage.js';
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
export { buildR2Storage } from './buildR2Storage.js';
|
||||||
|
|
||||||
|
//# sourceMappingURL=index.js.map
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"sources":["../../../src/modules/storage/index.ts"],"sourcesContent":["export { buildR2Storage } from './buildR2Storage.js'\n"],"names":["buildR2Storage"],"mappings":"AAAA,SAASA,cAAc,QAAQ,sBAAqB"}
|
||||||
+17
-2
@@ -4,12 +4,13 @@ Sztywna procedura dla pracownika albo AI (Antigravity). Mówi CO robić, W JAKIE
|
|||||||
KOLEJNOŚCI, i CZYM SIĘ KIEROWAĆ. Zasady są twarde, przykłady realne — wzięte z
|
KOLEJNOŚCI, i CZYM SIĘ KIEROWAĆ. Zasady są twarde, przykłady realne — wzięte z
|
||||||
faktycznych błędów, które się zdarzyły. Odstępstwa tylko za świadomą decyzją.
|
faktycznych błędów, które się zdarzyły. Odstępstwa tylko za świadomą decyzją.
|
||||||
|
|
||||||
Powiązane: [publishing.md](./publishing.md) (cykl publikacji), [getting-started.md](./getting-started.md)
|
Powiązane: [standardy-kodu.md](./standardy-kodu.md) (dobre praktyki senior),
|
||||||
|
[publishing.md](./publishing.md) (cykl publikacji), [getting-started.md](./getting-started.md)
|
||||||
(nowy projekt), ../ANTIGRAVITY-ZASADY-AGENT.md (zasady dla AI).
|
(nowy projekt), ../ANTIGRAVITY-ZASADY-AGENT.md (zasady dla AI).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ZŁOTE ZASADY
|
## ZŁOTE ZASADY (łam tylko świadomie)
|
||||||
|
|
||||||
1. **Nic na sztywno.** Tekst, obraz, link, dane firmy → panel/baza, nie kod.
|
1. **Nic na sztywno.** Tekst, obraz, link, dane firmy → panel/baza, nie kod.
|
||||||
2. **Logika w pluginie, projekt podłącza.** Jeśli piszesz w projekcie coś, co
|
2. **Logika w pluginie, projekt podłącza.** Jeśli piszesz w projekcie coś, co
|
||||||
@@ -18,6 +19,8 @@ Powiązane: [publishing.md](./publishing.md) (cykl publikacji), [getting-started
|
|||||||
4. **Weryfikuj każdy etap grepem.** Nie zakładaj, że zadziałało. Sprawdź.
|
4. **Weryfikuj każdy etap grepem.** Nie zakładaj, że zadziałało. Sprawdź.
|
||||||
5. **Napraw u źródła, nie łataj.** Bez `as any`, `@ts-ignore`, kopii logiki.
|
5. **Napraw u źródła, nie łataj.** Bez `as any`, `@ts-ignore`, kopii logiki.
|
||||||
6. **Zmiana w pluginie nie działa, dopóki nie: build → publish → wciągnięcie.**
|
6. **Zmiana w pluginie nie działa, dopóki nie: build → publish → wciągnięcie.**
|
||||||
|
7. **Zmieniłeś API → zaktualizuj docs w tym samym commicie.** Docs jadą w
|
||||||
|
pakiecie; rozjazd kod↔docs = agent dostaje złą mapę.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -39,6 +42,11 @@ cd ~/payload-cms/ipal-kit
|
|||||||
# 1. ŹRÓDŁA — nanieś zmianę, ZWERYFIKUJ że jest
|
# 1. ŹRÓDŁA — nanieś zmianę, ZWERYFIKUJ że jest
|
||||||
grep -c "<symbol-zmiany>" src/<ścieżka> # MUSI być >0
|
grep -c "<symbol-zmiany>" src/<ścieżka> # MUSI być >0
|
||||||
|
|
||||||
|
# 1b. DOCS — jeśli zmiana dotyka API/zachowania, ZAKTUALIZUJ docs/
|
||||||
|
# (nowa funkcja, zmiana sygnatury, nowe pole panelu, nowy adapter...).
|
||||||
|
# Docs jadą w pakiecie (files: dist, docs) — nieaktualne docs = agent
|
||||||
|
# dostaje złą mapę. Kod i docs publikuj RAZEM.
|
||||||
|
|
||||||
# 2. BUILD — zbuduj, ZWERYFIKUJ że dist ma zmianę
|
# 2. BUILD — zbuduj, ZWERYFIKUJ że dist ma zmianę
|
||||||
pnpm build
|
pnpm build
|
||||||
grep -c "<symbol-zmiany>" dist/<ścieżka> # MUSI być >0
|
grep -c "<symbol-zmiany>" dist/<ścieżka> # MUSI być >0
|
||||||
@@ -83,6 +91,9 @@ pokazał 0. Naprawa: dodać eksport, przejść łańcuch od nowa.
|
|||||||
publish, grep dist po buildzie.
|
publish, grep dist po buildzie.
|
||||||
- **`pnpm add` przy działającym dev** → proces ma stary adapter w pamięci.
|
- **`pnpm add` przy działającym dev** → proces ma stary adapter w pamięci.
|
||||||
Payload czyta email/config przy starcie. ZAWSZE restart po wciągnięciu.
|
Payload czyta email/config przy starcie. ZAWSZE restart po wciągnięciu.
|
||||||
|
- **Publikacja bez aktualizacji docs** → agent (Antigravity) po `pnpm add`
|
||||||
|
czyta `node_modules/@intecion/ipal-kit/docs/` z NIEAKTUALNĄ mapą. Jeśli
|
||||||
|
zmieniłeś API — docs w tym samym commicie.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -237,3 +248,7 @@ Nie mów „działa", dopóki:
|
|||||||
- [ ] grep potwierdza wersję pluginu w node_modules
|
- [ ] grep potwierdza wersję pluginu w node_modules
|
||||||
- [ ] sekrety w .env (nie w repo), maskowane w panelu
|
- [ ] sekrety w .env (nie w repo), maskowane w panelu
|
||||||
- [ ] brak plików middleware.ts, brak zaszytej mapy slugów
|
- [ ] brak plików middleware.ts, brak zaszytej mapy slugów
|
||||||
|
- [ ] strona 404 (not-found.tsx) — edytowalna, per język, link powrotu
|
||||||
|
- [ ] formularze z buildera w panelu (NIE własne hardkodowane)
|
||||||
|
- [ ] compliance: polityki, baner cookies, zgoda RODO w formularzach
|
||||||
|
(patrz [wymagania-prawne.md](./wymagania-prawne.md))
|
||||||
@@ -108,6 +108,7 @@ export default buildConfig({
|
|||||||
| access | Role admin > editor > user, kontrola dostępu | [access.md](./access.md) |
|
| access | Role admin > editor > user, kontrola dostępu | [access.md](./access.md) |
|
||||||
| payload-helpers | getSiteSettings / getSiteIntegrations | [payload-helpers.md](./payload-helpers.md) |
|
| payload-helpers | getSiteSettings / getSiteIntegrations | [payload-helpers.md](./payload-helpers.md) |
|
||||||
| seo | Metadata, hreflang, auto-fill, plugin-seo | [seo.md](./seo.md) |
|
| seo | Metadata, hreflang, auto-fill, plugin-seo | [seo.md](./seo.md) |
|
||||||
|
| architektura-tresci | **Jak budować, żeby klient wszystko edytował** (filozofia CMS) | [architektura-tresci.md](./architektura-tresci.md) |
|
||||||
| blocks | RenderBlocks — silnik renderowania bloków | [blocks.md](./blocks.md) |
|
| blocks | RenderBlocks — silnik renderowania bloków | [blocks.md](./blocks.md) |
|
||||||
| consent | Banner cookies GDPR, Google Consent Mode | [consent.md](./consent.md) |
|
| consent | Banner cookies GDPR, Google Consent Mode | [consent.md](./consent.md) |
|
||||||
| turnstile | Cloudflare Turnstile (widget + verify) | [turnstile.md](./turnstile.md) |
|
| turnstile | Cloudflare Turnstile (widget + verify) | [turnstile.md](./turnstile.md) |
|
||||||
|
|||||||
+36
-1
@@ -109,7 +109,7 @@ Dostępne tokeny (każdy ma odpowiednik `-dark` używany pod `dark:`):
|
|||||||
| `--ipal-hover` | `#f5f5f5` | hover przycisków drugorzędnych |
|
| `--ipal-hover` | `#f5f5f5` | hover przycisków drugorzędnych |
|
||||||
| `--ipal-radius` | `0.375rem` | zaokrąglenie przycisków |
|
| `--ipal-radius` | `0.375rem` | zaokrąglenie przycisków |
|
||||||
|
|
||||||
Wymaga `@source` skanującego pakiet (patrz frontend-setup.md) — inaczej Tailwind
|
Wymaga `@source` skanującego pakiet (patrz getting-started.md) — inaczej Tailwind
|
||||||
nie wygeneruje tych klas.
|
nie wygeneruje tych klas.
|
||||||
|
|
||||||
### Gdy tokeny nie wystarczą
|
### Gdy tokeny nie wystarczą
|
||||||
@@ -132,3 +132,38 @@ domyślny (nie dokleja się).
|
|||||||
|
|
||||||
Elementy mają też `data-ipal="banner"` i `data-ipal="cookie-button"` — stabilne
|
Elementy mają też `data-ipal="banner"` i `data-ipal="cookie-button"` — stabilne
|
||||||
uchwyty do CSS albo testów e2e.
|
uchwyty do CSS albo testów e2e.
|
||||||
|
|
||||||
|
## Locale jako cookie functional (wbudowane)
|
||||||
|
|
||||||
|
Plugin sam zarządza jedną cookie functional: **`NEXT_LOCALE`** (wybór języka).
|
||||||
|
Nie musisz nic konfigurować — działa out of the box:
|
||||||
|
|
||||||
|
- **Zapis za zgodą.** Middleware zapisuje `NEXT_LOCALE` tylko, gdy użytkownik
|
||||||
|
zaakceptował kategorię **functional**. Bez zgody język działa (negocjacja per
|
||||||
|
żądanie), ale nie jest utrwalany w cookie.
|
||||||
|
- **Sprzątanie po cofnięciu.** Gdy użytkownik cofnie zgodę na functional, hook
|
||||||
|
consent usuwa `NEXT_LOCALE` automatycznie. Odpowiada za to `DEFAULT_COOKIE_MAP`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const DEFAULT_COOKIE_MAP = {
|
||||||
|
functional: [LOCALE_COOKIE_NAME], // 'NEXT_LOCALE' — plugin zna własną cookie
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Twoje własne cookie functional/analytics
|
||||||
|
|
||||||
|
Jeśli ustawiasz własne cookie podlegające zgodzie, rozszerz mapę — hook wtedy
|
||||||
|
sprzątnie też Twoje po cofnięciu zgody:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
useConsent({
|
||||||
|
functional: ['NEXT_LOCALE', 'moje-ustawienie'],
|
||||||
|
analytics: ['_ga', '_gid'],
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Przekazana mapa zastępuje domyślną — pamiętaj dołączyć `NEXT_LOCALE`, jeśli
|
||||||
|
chcesz zachować sprzątanie locale (albo zaimportuj `LOCALE_COOKIE_NAME` i dodaj).
|
||||||
|
|
||||||
|
> Mechanizm zgody dla locale jest opisany też od strony i18n:
|
||||||
|
> [i18n.md](./i18n.md#cookie-locale-a-zgoda-rodo).
|
||||||
@@ -4,6 +4,31 @@ Wpina `@payloadcms/plugin-form-builder` (kolekcje forms + form-submissions) i
|
|||||||
dostarcza `submitForm` — wywoływalną z frontu funkcję, która spina: weryfikację
|
dostarcza `submitForm` — wywoływalną z frontu funkcję, która spina: weryfikację
|
||||||
Turnstile → zapis zgłoszenia → wysyłkę maili (naszym senderem).
|
Turnstile → zapis zgłoszenia → wysyłkę maili (naszym senderem).
|
||||||
|
|
||||||
|
## ⚠️ ZASADA: formularz POCHODZI z buildera w panelu (obowiązkowe)
|
||||||
|
|
||||||
|
**Formularze buduje redaktor w panelu** (kolekcja Forms), NIE deweloper w kodzie.
|
||||||
|
To jest CMS — klient sam definiuje pola, etykiety, komunikaty, odbiorcę. Front
|
||||||
|
tylko RENDERUJE formularz z panelu i wysyła przez `submitForm`.
|
||||||
|
|
||||||
|
**NIGDY nie twórz własnego, hardkodowanego formularza** — z ręcznie wpisanymi
|
||||||
|
polami, etykietami w JSX, własną walidacją. To łamie „nic na sztywno" (klient nie
|
||||||
|
zmieni pól ani tekstów) i omija cały mechanizm pluginu (Turnstile, rate-limit,
|
||||||
|
consent RODO, powiadomienia).
|
||||||
|
|
||||||
|
| ŹLE (własny formularz) | DOBRZE (builder pluginu) |
|
||||||
|
|---|---|
|
||||||
|
| `<input name="email" placeholder="Email" />` w JSX | pola z kolekcji Forms (panel) |
|
||||||
|
| etykiety/komunikaty w kodzie | etykiety per język w panelu |
|
||||||
|
| własna walidacja/wysyłka | `submitForm` (Turnstile+consent+mail) |
|
||||||
|
| klient nie zmieni formularza | klient edytuje pola w panelu |
|
||||||
|
|
||||||
|
**Jak poprawnie:** redaktor tworzy formularz w kolekcji Forms → front pobiera
|
||||||
|
jego definicję → renderuje pola dynamicznie → wysyła przez `submitForm`. Pola,
|
||||||
|
etykiety, komunikaty, odbiorca — wszystko z panelu.
|
||||||
|
|
||||||
|
Jeśli formularz wymaga pola, którego builder nie ma — dodaj je przez konfigurację
|
||||||
|
`fields` (patrz niżej) albo rozbuduj plugin. NIE hardkoduj własnego formularza.
|
||||||
|
|
||||||
## Zależność
|
## Zależność
|
||||||
|
|
||||||
```json
|
```json
|
||||||
|
|||||||
@@ -172,6 +172,9 @@ export const blockRegistry: BlockComponentMap = {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> **Jak budować treść, żeby klient mógł wszystko edytować** (filozofia
|
||||||
|
> CMS, kolejność komponent→blok→strona): [architektura-tresci.md](./architektura-tresci.md).
|
||||||
|
|
||||||
**Puste `blocks: []` crashuje** (traverseFields) — zawsze co najmniej jeden blok.
|
**Puste `blocks: []` crashuje** (traverseFields) — zawsze co najmniej jeden blok.
|
||||||
|
|
||||||
### enhanceProps — wstrzykiwanie danych server-side do bloków
|
### enhanceProps — wstrzykiwanie danych server-side do bloków
|
||||||
|
|||||||
@@ -108,3 +108,35 @@ Zachowanie:
|
|||||||
- wybrany locale zapisany w cookie (`LOCALE_COOKIE_NAME`)
|
- wybrany locale zapisany w cookie (`LOCALE_COOKIE_NAME`)
|
||||||
|
|
||||||
`DEFAULT_MIDDLEWARE_MATCHER` wyklucza `api`, `admin`, `_next`, pliki statyczne.
|
`DEFAULT_MIDDLEWARE_MATCHER` wyklucza `api`, `admin`, `_next`, pliki statyczne.
|
||||||
|
|
||||||
|
## Cookie locale a zgoda (RODO)
|
||||||
|
|
||||||
|
Wybór języka zapisywany jest w cookie **`NEXT_LOCALE`** (konwencja Next.js —
|
||||||
|
kompatybilna z innymi bibliotekami i18n, które czytają aktywny locale). Ale
|
||||||
|
zapis podlega zgodzie: to cookie kategorii **functional**, więc:
|
||||||
|
|
||||||
|
- **Zapis TYLKO za zgodą.** Middleware zapisuje `NEXT_LOCALE` jedynie, gdy
|
||||||
|
użytkownik zgodził się na kategorię functional (`mayPersistLocale` sprawdza
|
||||||
|
zgodę). Bez zgody język działa per żądanie (negocjacja z Accept-Language),
|
||||||
|
ale nie jest utrwalany.
|
||||||
|
- **Sprzątanie po cofnięciu zgody.** Gdy użytkownik cofnie zgodę na functional,
|
||||||
|
cookie `NEXT_LOCALE` jest usuwane automatycznie (consent zna tę cookie przez
|
||||||
|
`DEFAULT_COOKIE_MAP` — patrz [consent.md](./consent.md)).
|
||||||
|
|
||||||
|
Nazwa cookie to jedna stała `LOCALE_COOKIE_NAME` (`modules/i18n/negotiateLocale`),
|
||||||
|
propagująca do middleware i sprzątania consent. Można nadpisać w
|
||||||
|
`createLocaleMiddleware({ cookieName })`, ale domyślnie `NEXT_LOCALE` jest
|
||||||
|
zalecane (interop).
|
||||||
|
|
||||||
|
### Kolejność negocjacji locale
|
||||||
|
|
||||||
|
1. Cookie `NEXT_LOCALE` (jeśli jest — czyli był wybór za zgodą)
|
||||||
|
2. Nagłówek `Accept-Language` (preferencje przeglądarki)
|
||||||
|
3. `defaultLocale` z konfiguracji
|
||||||
|
|
||||||
|
Wejście na `/` → negocjacja → redirect na `/pl` (albo wynik negocjacji).
|
||||||
|
Zmiana języka (URL `/en` różny od cookie) → zapis nowego wyboru (za zgodą).
|
||||||
|
|
||||||
|
> **Migracja ze starej nazwy:** wcześniej cookie nazywało się `ipal-locale`.
|
||||||
|
> Po zmianie na `NEXT_LOCALE` użytkownicy ze starą cookie przejdą raz ponowną
|
||||||
|
> negocjację (stara cookie ignorowana). Jednorazowe, bez wpływu na nowe projekty.
|
||||||
+186
@@ -0,0 +1,186 @@
|
|||||||
|
# storage — media na Cloudflare R2
|
||||||
|
|
||||||
|
Offload mediów (obrazy, pliki) do Cloudflare R2 zamiast lokalnego dysku. R2 jest
|
||||||
|
S3-kompatybilny; plugin dostarcza `buildR2Storage`, który czyta dane z `.env`
|
||||||
|
i konfiguruje adapter.
|
||||||
|
|
||||||
|
> **Storage to infrastruktura, nie treść.** Dane R2 (klucze, bucket) idą do
|
||||||
|
> `.env` — jak DATABASE_URI, PAYLOAD_SECRET, GRAPH_*. NIE do panelu (to sekrety
|
||||||
|
> agencyjne, wiążą się przy starcie, nie zmienia ich redaktor).
|
||||||
|
|
||||||
|
## Zależność
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm add @payloadcms/storage-s3
|
||||||
|
```
|
||||||
|
|
||||||
|
## Zmienne .env
|
||||||
|
|
||||||
|
Patrz [R2-ENV-przyklad](../R2-ENV-przyklad.md) po pełną instrukcję skąd wziąć wartości.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
R2_BUCKET=nazwa-bucketa
|
||||||
|
R2_ENDPOINT=https://<ACCOUNT_ID>.r2.cloudflarestorage.com
|
||||||
|
R2_ACCESS_KEY_ID=<access-key-id>
|
||||||
|
R2_SECRET_ACCESS_KEY=<secret-access-key>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Wpięcie (payload.config.ts)
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { buildR2Storage } from '@intecion/ipal-kit'
|
||||||
|
|
||||||
|
export default buildConfig({
|
||||||
|
// ...
|
||||||
|
plugins: [
|
||||||
|
ipalKit({ /* ... */ }),
|
||||||
|
buildR2Storage(['media']), // slugi kolekcji upload do offloadu
|
||||||
|
],
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
`buildR2Storage` przyjmuje listę kolekcji upload (domyślnie `['media']`). Jeśli
|
||||||
|
masz więcej kolekcji plików: `buildR2Storage(['media', 'documents'])`.
|
||||||
|
|
||||||
|
## Zachowanie (fallback)
|
||||||
|
|
||||||
|
- **Wszystkie 4 zmienne** → media w R2.
|
||||||
|
- **Brak zmiennych** → fallback na lokalny dysk (dev działa bez R2, zero konfiguracji).
|
||||||
|
- **Część zmiennych** → ostrzeżenie w logu + fallback (częściowa konfiguracja =
|
||||||
|
pewnie pomyłka).
|
||||||
|
|
||||||
|
To wzorzec „degrade gracefully" — jak mailAdapter, który wraca do SMTP, gdy brak
|
||||||
|
Graph. Projekt działa niezależnie od tego, czy R2 jest skonfigurowany.
|
||||||
|
|
||||||
|
## Publiczny dostęp + custom domena (WAŻNE — krok po kroku)
|
||||||
|
|
||||||
|
R2 domyślnie prywatny. Upload zadziała, ale obrazy się NIE wyświetlą (403),
|
||||||
|
dopóki nie skonfigurujesz publicznego odczytu przez custom domenę. To proces
|
||||||
|
w Cloudflare (nie w kodzie), wieloetapowy — poniżej dokładnie.
|
||||||
|
|
||||||
|
### Dlaczego custom domena, nie „r2.dev"
|
||||||
|
|
||||||
|
R2 oferuje szybki publiczny URL `*.r2.dev`, ALE:
|
||||||
|
- jest rate-limitowany (nie do produkcji)
|
||||||
|
- nie przechodzi przez cache Cloudflare (brak CDN, wolniej, drożej)
|
||||||
|
- brzydki URL (nie Twoja domena)
|
||||||
|
|
||||||
|
Dla produkcji ZAWSZE custom domena (np. `media.klient.pl`) — daje CDN, cache,
|
||||||
|
własny URL. r2.dev tylko do szybkiego testu.
|
||||||
|
|
||||||
|
### Warunek wstępny: domena w Cloudflare
|
||||||
|
|
||||||
|
Custom domena dla R2 wymaga, żeby domena (albo subdomena) była zarządzana przez
|
||||||
|
Cloudflare (nameservery klienta wskazują na Cloudflare). Jeśli domena klienta
|
||||||
|
jest u innego rejestratora — trzeba ją najpierw dodać do Cloudflare (Add Site)
|
||||||
|
i przełączyć nameservery. Sama subdomena `media.klient.pl` wystarczy, jeśli
|
||||||
|
główna domena jest już w Cloudflare.
|
||||||
|
|
||||||
|
### Krok po kroku — podpięcie custom domeny
|
||||||
|
|
||||||
|
1. **Cloudflare Dashboard → R2 → wybierz bucket**
|
||||||
|
2. Zakładka **Settings** → sekcja **Public access** → **Custom Domains**
|
||||||
|
3. **Connect Domain** → wpisz subdomenę, np. `media.klient.pl`
|
||||||
|
4. Cloudflare automatycznie doda rekord CNAME (bo domena jest w Cloudflare) i
|
||||||
|
wystawi certyfikat SSL. Poczekaj, aż status = **Active** (kilka minut).
|
||||||
|
5. Od tej chwili pliki są publiczne pod `https://media.klient.pl/<klucz-pliku>`.
|
||||||
|
|
||||||
|
### Krok: ustaw publiczny URL w projekcie
|
||||||
|
|
||||||
|
Payload musi generować URL-e mediów wskazujące na custom domenę, nie na endpoint
|
||||||
|
S3. Dodaj zmienną i przekaż ją do adaptera:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# .env
|
||||||
|
R2_PUBLIC_URL=https://media.klient.pl
|
||||||
|
```
|
||||||
|
|
||||||
|
Adapter `buildR2Storage` czyta ją i ustawia jako bazowy URL mediów (jeśli
|
||||||
|
ustawiona). Bez niej Payload zwróci URL wskazujący na prywatny endpoint S3 →
|
||||||
|
403 na froncie. (Patrz aktualizacja buildR2Storage niżej.)
|
||||||
|
|
||||||
|
### Weryfikacja
|
||||||
|
|
||||||
|
1. Wgraj obraz w panelu (Media).
|
||||||
|
2. Sprawdź URL obrazu w panelu — powinien być `https://media.klient.pl/...`,
|
||||||
|
NIE `https://<account>.r2.cloudflarestorage.com/...`.
|
||||||
|
3. Otwórz URL w przeglądarce — obraz się pokazuje (nie 403).
|
||||||
|
4. Na froncie `<img src>` działa.
|
||||||
|
|
||||||
|
### Częsty błąd: 403 mimo custom domeny
|
||||||
|
|
||||||
|
- **URL wskazuje na endpoint S3, nie custom domenę** → brakuje `R2_PUBLIC_URL`
|
||||||
|
albo adapter jej nie używa. Sprawdź URL w panelu.
|
||||||
|
- **Custom domena nie Active** → poczekaj na SSL/CNAME w Cloudflare.
|
||||||
|
- **Public access wyłączony** → w bucket Settings sprawdź, czy custom domena jest
|
||||||
|
podpięta (nie tylko utworzona).
|
||||||
|
|
||||||
|
Bez tego media wgrają się do R2, ale front pokaże 403. Konfiguracja domeny jest
|
||||||
|
po stronie Cloudflare, publiczny URL po stronie projektu (.env).
|
||||||
|
|
||||||
|
## Migracja istniejących mediów
|
||||||
|
|
||||||
|
Jeśli projekt miał media lokalnie i przełączasz na R2 — nowe uploady idą do R2,
|
||||||
|
ale STARE zostają na dysku (i znikną przy redeployu bez wolumenu). Przed
|
||||||
|
przełączeniem na produkcji przenieś istniejące pliki do bucketa (np. `rclone`
|
||||||
|
albo ręcznie przez R2 dashboard), inaczej stare obrazy znikną.
|
||||||
|
|
||||||
|
## Weryfikacja
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# po wpięciu i ustawieniu .env:
|
||||||
|
pnpm dev
|
||||||
|
# wgraj obraz w panelu (Media) → sprawdź w Cloudflare R2, czy plik się pojawił
|
||||||
|
```
|
||||||
|
|
||||||
|
## Dev na lokalnym I na R2 (seedowanie podczas developmentu)
|
||||||
|
|
||||||
|
Fallback (brak zmiennych → lokalny dysk) oznacza, że **dev działa w obu trybach**:
|
||||||
|
|
||||||
|
- **Dev bez R2 w .env** → media na lokalnym dysku. Szybki start, zero konfiguracji.
|
||||||
|
- **Dev z R2 w .env** → media w R2 już podczas developmentu. Przydatne, gdy
|
||||||
|
seedujesz treść w devie i chcesz, żeby od razu lądowała w buckecie (np. wspólny
|
||||||
|
bucket dev, albo test realnego flow przed produkcją).
|
||||||
|
|
||||||
|
Przełączasz trybem po prostu obecnością zmiennych R2 w `.env`. Ten sam kod,
|
||||||
|
`buildR2Storage` sam wykrywa. Nie musisz nic zmieniać w configu między trybami.
|
||||||
|
|
||||||
|
> Jeśli seedujesz w devie do R2 — pamiętaj, że to realny bucket. Używaj osobnego
|
||||||
|
> bucketa dev (nie produkcyjnego), żeby nie mieszać danych testowych z realnymi.
|
||||||
|
|
||||||
|
## Normalizacja nazw plików (automatyczna)
|
||||||
|
|
||||||
|
Plik `normalizeFilenameHook` czyści nazwy wgrywanych plików — slugifikuje nazwę,
|
||||||
|
zachowuje rozszerzenie:
|
||||||
|
|
||||||
|
```
|
||||||
|
"Zdjęcie jeden nad morzem.jpg" → "zdjecie-jeden-nad-morzem.jpg"
|
||||||
|
"Faktura #12 (2024).PDF" → "faktura-12-2024.pdf"
|
||||||
|
```
|
||||||
|
|
||||||
|
Wpięcie w kolekcję Media (projekt):
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { normalizeFilenameHook } from '@intecion/ipal-kit'
|
||||||
|
|
||||||
|
export const Media: CollectionConfig = {
|
||||||
|
slug: 'media',
|
||||||
|
upload: { staticDir: 'media' /* ... */ },
|
||||||
|
hooks: {
|
||||||
|
beforeOperation: [normalizeFilenameHook], // czyści nazwę przed zapisem
|
||||||
|
},
|
||||||
|
fields: [ /* alt itd. */ ],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Działa z lokalnym dyskiem i z R2/S3 (hook biegnie PRZED warstwą storage, więc
|
||||||
|
czysta nazwa trafia i do bazy, i do bucketa). Dlaczego to ważne:
|
||||||
|
|
||||||
|
- **URL-e mediów są czyste** — `/media/zdjecie-nad-morzem.jpg`, nie
|
||||||
|
`/media/Zdjęcie%20jeden%20nad%20morzem.jpg` (spacje/diakrytyki w URL = problemy).
|
||||||
|
- **Przenośność** — nazwa bez polskich znaków/spacji działa wszędzie (CDN, S3, systemy plików).
|
||||||
|
- **Bez kolizji kodowania** — spacje i `#`, `()` w nazwach plików potrafią psuć
|
||||||
|
ścieżki i cache.
|
||||||
|
|
||||||
|
Sama funkcja `normalizeFilename(name)` też jest wyeksportowana, gdybyś potrzebował
|
||||||
|
jej poza hookiem.
|
||||||
+2
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@intecion/ipal-kit",
|
"name": "@intecion/ipal-kit",
|
||||||
"version": "1.0.16",
|
"version": "1.0.22",
|
||||||
"description": "Intecion Payload Advanced Library — a Payload CMS 3 plugin: i18n, SEO, forms, consent, analytics, blog/archives.",
|
"description": "Intecion Payload Advanced Library — a Payload CMS 3 plugin: i18n, SEO, forms, consent, analytics, blog/archives.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": {
|
"repository": {
|
||||||
@@ -60,6 +60,7 @@
|
|||||||
"test:int": "vitest"
|
"test:int": "vitest"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@payloadcms/storage-s3": "^3.88.0",
|
||||||
"lucide-react": "^0.400.0",
|
"lucide-react": "^0.400.0",
|
||||||
"nodemailer": "^8.0.1",
|
"nodemailer": "^8.0.1",
|
||||||
"server-only": "^0.0.1",
|
"server-only": "^0.0.1",
|
||||||
|
|||||||
Generated
+509
@@ -8,6 +8,9 @@ importers:
|
|||||||
|
|
||||||
.:
|
.:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@payloadcms/storage-s3':
|
||||||
|
specifier: ^3.88.0
|
||||||
|
version: 3.88.0(@types/[email protected])([email protected])([email protected](@babel/[email protected])(@playwright/[email protected])([email protected]([email protected]))([email protected])([email protected]))([email protected]([email protected])([email protected]))([email protected]([email protected]))([email protected])([email protected])
|
||||||
lucide-react:
|
lucide-react:
|
||||||
specifier: ^0.400.0
|
specifier: ^0.400.0
|
||||||
version: 0.400.0([email protected])
|
version: 0.400.0([email protected])
|
||||||
@@ -133,6 +136,88 @@ packages:
|
|||||||
resolution: {integrity: sha512-60vepv88RwcJtSHrD6MjIL6Ta3SOYbgfnkHb+ppAVK+o9mXprRtulx7VlRl3lN3bbvysAfCS7WMVfhUYemB0IQ==}
|
resolution: {integrity: sha512-60vepv88RwcJtSHrD6MjIL6Ta3SOYbgfnkHb+ppAVK+o9mXprRtulx7VlRl3lN3bbvysAfCS7WMVfhUYemB0IQ==}
|
||||||
engines: {node: '>= 16'}
|
engines: {node: '>= 16'}
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
resolution: {integrity: sha512-Dtu0gr4dnATZAPwEYbpCsG+MpLM7OAliy2gTepEFQwl1vZ6DL3QMH2FveMa3HLvPsOdhJsPRB3KtxVhph9T75A==}
|
||||||
|
engines: {node: '>=20.0.0'}
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
resolution: {integrity: sha512-8+UH1uBWwjbRu0ugTBhJ/cu3rL/vzf1tm9/3+xZGf1uybIO3HTF2xLJJaTKkRPvzxz8/n/w+YrwoHGZ2Q/a2Zg==}
|
||||||
|
engines: {node: '>=20.0.0'}
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
resolution: {integrity: sha512-reqPFEQrZxDZpeGj4PFMepBeR5LGYHRqq/L0motTzgFkCRBA4rFdaVXDSLYyGHhxVz7sT2PDnPN9CluGSfgyJA==}
|
||||||
|
engines: {node: '>=20.0.0'}
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
resolution: {integrity: sha512-H404B7dJl2mCrBqahDEYsanB0xhdDp6tXnXcTUnXmmpy2Q3J0Ho0bUajZ2jr/RdwzCyS59Gi8xXIFwPLGBl6Uw==}
|
||||||
|
engines: {node: '>=20.0.0'}
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
resolution: {integrity: sha512-X98zYOrVOeuosCX+6ktf29FC2N2GHPLia7qv6mzPzTc+RPAuHWCDS++Z6JK7eGYqb/v6uaW7bAXaOvDBfol+0w==}
|
||||||
|
engines: {node: '>=20.0.0'}
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
resolution: {integrity: sha512-Rykg6s5ceBuynMOGWgoowO4N+27JfnqXAnVaSunZl0hOO1XodSrxGNz6sCEbnmS0lAfQZDKyb3fbr46gSuv6Sg==}
|
||||||
|
engines: {node: '>=20.0.0'}
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
resolution: {integrity: sha512-Jb59xfEISoN5mmbnA+HYqdtrSX3CgCtJoof+V5D8/TgUI56W63GEEd5Y58WijU3Ou6+WEgaLD1feVzaRXV5IDQ==}
|
||||||
|
engines: {node: '>=20.0.0'}
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
resolution: {integrity: sha512-Rml+WitoFvXmv6JZ18U/xGdGDGGvB/mOin0ya0lTnTrdC0Z1lrVxTYh7iNklZBcvcRMrs4DoEf6xy1KWyrLQQw==}
|
||||||
|
engines: {node: '>=20.0.0'}
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
resolution: {integrity: sha512-2ry03fGRJr4sV3jI+ocjj5JqALnFD6ymM5KiNCDZMvq8bX2GSbE0vji4aM43TVCl2nXqqLRZaUxdq/KeWRAY4Q==}
|
||||||
|
engines: {node: '>=20.0.0'}
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
resolution: {integrity: sha512-jkhg/8ocAAoc0RFyLMhCw+/zZh7gystQgd4F4hznNa8P4Cc501PQmxd+jGLiMHodPJ+7Zv/3znM62gZojyasmA==}
|
||||||
|
engines: {node: '>=20.0.0'}
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
resolution: {integrity: sha512-d3AGyVu759PGr35mEB2s22xxlNEA5rpdxtSPJthfPFJvoQ8dt357iVPECqWfUxXp1toJAvKmbtcIYVGigaGsCA==}
|
||||||
|
engines: {node: '>=20.0.0'}
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
resolution: {integrity: sha512-4dxJX2pueKHtFyxdtT/IH385NpAWjbNjpbbIN6L9YK58dbae6ldyiLSom1EV5nPoOxKtWLXiqch+yo3NjXfleQ==}
|
||||||
|
engines: {node: '>=20.0.0'}
|
||||||
|
peerDependencies:
|
||||||
|
'@aws-sdk/client-s3': ^3.1119.0
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
resolution: {integrity: sha512-wMIsNumRVKaNMKhvU/s9VrdEwE8S6gSzXp4RygFG5BEMnGkkXf8cjh8zf7cKJBpUDpqTWqwbz5isEgp9rH6Lng==}
|
||||||
|
engines: {node: '>=20.0.0'}
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
resolution: {integrity: sha512-NhEgryjlBF9w38ZXqGymQV28IhkYa1mKhlbYnqIis57AYwWGVYfUPgg/qC2rLRqOUfblxx++irvju10kVTa8Vw==}
|
||||||
|
engines: {node: '>=20.0.0'}
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
resolution: {integrity: sha512-yEqb0ispm9uXZ7nk5stErMB7yn43j3XCAaHM15MsdWaCk7RvEmGjYdbyHZcH86JpUg7mk1v1m2xwzLj2o+3uCg==}
|
||||||
|
engines: {node: '>=20.0.0'}
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
resolution: {integrity: sha512-L+2xZTye/2T96f3lwCws0Zw6GG2JHZW9e8FpVgGBeeExSKyeoZ6CWRpBml/7DNiK/O26jrgPM9F+Ay8VkgzUWQ==}
|
||||||
|
engines: {node: '>=20.0.0'}
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
resolution: {integrity: sha512-ygIivKqh8aHzNkucOCXHyIBgBpLPfrSI0mCqXF+vLBsPTUKqj0VSqAY0GFPe7lQl4HntjOcQ+KSyS7oUV2C54Q==}
|
||||||
|
engines: {node: '>=20.0.0'}
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
resolution: {integrity: sha512-LkwLL2BLbC6wNNm4JaH9mbEqBMdOZCct6VAYqhdN4U1xrWM+fUJQEfbHwQgDypapOWTRtlk25akb5afM0P8CIQ==}
|
||||||
|
engines: {node: '>=20.0.0'}
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
resolution: {integrity: sha512-wlFmCIGUlwF4zx/kncw+bmxTQh1HeSJq4mYV/V5cZUSJadDP3kXvGW8Rn21cimj/7y9ju+47oYWXi97vF7czaA==}
|
||||||
|
engines: {node: '>=20.0.0'}
|
||||||
|
|
||||||
|
'@aws/[email protected]':
|
||||||
|
resolution: {integrity: sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ==}
|
||||||
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@babel/[email protected]':
|
'@babel/[email protected]':
|
||||||
resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==}
|
resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
@@ -1646,6 +1731,13 @@ packages:
|
|||||||
next: '>=15.2.9 <15.3.0 || >=15.3.9 <15.4.0 || >=15.4.11 <15.5.0 || >=16.2.6 <17.0.0'
|
next: '>=15.2.9 <15.3.0 || >=15.3.9 <15.4.0 || >=15.4.11 <15.5.0 || >=16.2.6 <17.0.0'
|
||||||
payload: 3.88.0
|
payload: 3.88.0
|
||||||
|
|
||||||
|
'@payloadcms/[email protected]':
|
||||||
|
resolution: {integrity: sha512-wIcRVedtBZIQMu7dpSE1TOJKJd0HuVSUNPrV2KxIbtqQFm+ly34NCJYY0m1+K0YS6my8BKdcB4jj2exg8454Ig==}
|
||||||
|
peerDependencies:
|
||||||
|
payload: 3.88.0
|
||||||
|
react: ^19.0.1 || ^19.1.2 || ^19.2.1
|
||||||
|
react-dom: ^19.0.1 || ^19.1.2 || ^19.2.1
|
||||||
|
|
||||||
'@payloadcms/[email protected]':
|
'@payloadcms/[email protected]':
|
||||||
resolution: {integrity: sha512-C915jEHADVN9xW7fSq/bYIZig1zjfQo+t4wrgiqjOCmB81oMgyqLRB3RlL2e6y4PzBUtgss2VS40vn/tVD/61Q==}
|
resolution: {integrity: sha512-C915jEHADVN9xW7fSq/bYIZig1zjfQo+t4wrgiqjOCmB81oMgyqLRB3RlL2e6y4PzBUtgss2VS40vn/tVD/61Q==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -1671,6 +1763,12 @@ packages:
|
|||||||
react: ^19.0.1 || ^19.1.2 || ^19.2.1
|
react: ^19.0.1 || ^19.1.2 || ^19.2.1
|
||||||
react-dom: ^19.0.1 || ^19.1.2 || ^19.2.1
|
react-dom: ^19.0.1 || ^19.1.2 || ^19.2.1
|
||||||
|
|
||||||
|
'@payloadcms/[email protected]':
|
||||||
|
resolution: {integrity: sha512-+35JRD4y7ImnIJuPSBhECHGGml0A+xju9BT/zW+lRUycDvvA0cqZNP+t95OVoZrxIB6V75Vg8GKPvAaRAmgOEw==}
|
||||||
|
engines: {node: ^18.20.2 || >=20.9.0}
|
||||||
|
peerDependencies:
|
||||||
|
payload: 3.88.0
|
||||||
|
|
||||||
'@payloadcms/[email protected]':
|
'@payloadcms/[email protected]':
|
||||||
resolution: {integrity: sha512-AZVQjjW5pKxO+K9ODeh6yw6/EfXK1hxGPw55KzzDC5srO3hjNskgyWtkauKvbz+S0+xFspANbRc4OD/Rg/74WA==}
|
resolution: {integrity: sha512-AZVQjjW5pKxO+K9ODeh6yw6/EfXK1hxGPw55KzzDC5srO3hjNskgyWtkauKvbz+S0+xFspANbRc4OD/Rg/74WA==}
|
||||||
|
|
||||||
@@ -1839,6 +1937,30 @@ packages:
|
|||||||
resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==}
|
resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==}
|
||||||
engines: {node: '>=14.16'}
|
engines: {node: '>=14.16'}
|
||||||
|
|
||||||
|
'@smithy/[email protected]':
|
||||||
|
resolution: {integrity: sha512-CsOeKq/9kA3y6VJHt+/+VTCtBaxJ4OTFpgrjIUhPpDIKxBci1k2bJaQASF2h/ELWrulGp+t97DZ0mevfAD8idg==}
|
||||||
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
|
'@smithy/[email protected]':
|
||||||
|
resolution: {integrity: sha512-A9uSdn72ozbRUSit0eib0TW7nXuNPlaeM0zcGkJ+nE6tFcSDbnmtwoxbTCFBukVQcszDAyvsd7+rTduPTXpygg==}
|
||||||
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
|
'@smithy/[email protected]':
|
||||||
|
resolution: {integrity: sha512-nZyWTmSpJEXl6VtWVMBJve/7x12DZu6sIX1z1a+ZMaHlQQRs9Zpu6NbTe/gmxYXVRpkjxyDYpZ5gx2IM6f/Wkw==}
|
||||||
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
|
'@smithy/[email protected]':
|
||||||
|
resolution: {integrity: sha512-2jY1tSpERfPfWqyBV2pH+iGFaghVsIJszJNsT7hxtQYhVJpWDyc0LqOWI+nXOxOAHaEfZ4PXXtp1wW1TGpHhkA==}
|
||||||
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
|
'@smithy/[email protected]':
|
||||||
|
resolution: {integrity: sha512-7ImGm+FkHRLcBaRttIAMZ6bzJZWb2cJGoYjq46F2UjycujWzrL9GEN9h4w7eQyXJYnltrUhxbbieBAIRrdqpow==}
|
||||||
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
|
'@smithy/[email protected]':
|
||||||
|
resolution: {integrity: sha512-FOKpVZob9MPTn2znRzGrnsMHv7BOsKVw3XiP/cOyYLDVZ9qKp4nifIiSCuUU/fIj5Vu0UOAxCFr+qRAtG0NUkA==}
|
||||||
|
engines: {node: '>=18.0.0'}
|
||||||
|
|
||||||
'@standard-schema/[email protected]':
|
'@standard-schema/[email protected]':
|
||||||
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
|
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
|
||||||
|
|
||||||
@@ -2563,6 +2685,9 @@ packages:
|
|||||||
[email protected]:
|
[email protected]:
|
||||||
resolution: {integrity: sha512-a7tP5+0Mw3YlUJcGAKUqIBkYYGlYxk2fnCasq/FUph1hadxlTRjF+gAcZksxANnaMnALjxEddmSi/H3OR8ugcQ==}
|
resolution: {integrity: sha512-a7tP5+0Mw3YlUJcGAKUqIBkYYGlYxk2fnCasq/FUph1hadxlTRjF+gAcZksxANnaMnALjxEddmSi/H3OR8ugcQ==}
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
resolution: {integrity: sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==}
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
resolution: {integrity: sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==}
|
resolution: {integrity: sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==}
|
||||||
|
|
||||||
@@ -2596,6 +2721,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-nEh+kZOPY1w+gcCMobZ6ETUp9WfibndnosbpwB1iJk/8Gt5ZF2bhS6+B6bPYz424KtwsR6Rflc3tCz1/ghX2dQ==}
|
resolution: {integrity: sha512-nEh+kZOPY1w+gcCMobZ6ETUp9WfibndnosbpwB1iJk/8Gt5ZF2bhS6+B6bPYz424KtwsR6Rflc3tCz1/ghX2dQ==}
|
||||||
engines: {node: '>=4.0'}
|
engines: {node: '>=4.0'}
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
resolution: {integrity: sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==}
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
|
resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
|
||||||
|
|
||||||
@@ -2866,6 +2994,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
|
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
resolution: {integrity: sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
resolution: {integrity: sha512-y+8xyqdGLL+6sh0tVeHcfP/QDd8gUgbasolJJpY7NgeQGSZ739bDtSiaiDgtoicy+mtYB81dKLxO9xRhCyIB3A==}
|
resolution: {integrity: sha512-y+8xyqdGLL+6sh0tVeHcfP/QDd8gUgbasolJJpY7NgeQGSZ739bDtSiaiDgtoicy+mtYB81dKLxO9xRhCyIB3A==}
|
||||||
engines: {node: '>=12.20'}
|
engines: {node: '>=12.20'}
|
||||||
@@ -3363,10 +3495,18 @@ packages:
|
|||||||
[email protected]:
|
[email protected]:
|
||||||
resolution: {integrity: sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==}
|
resolution: {integrity: sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==}
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
|
||||||
|
engines: {node: '>=0.8.x'}
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
|
resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
resolution: {integrity: sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==}
|
resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==}
|
||||||
engines: {node: '>=12.0.0'}
|
engines: {node: '>=12.0.0'}
|
||||||
@@ -3455,6 +3595,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==}
|
resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
resolution: {integrity: sha512-UC2I2+nx1ZuOBclWVNdcnbDR5dlrOdVb7xNjmT/lHE+LsgztWks3dG7boJ37yTS/venXw84B/mAW9uHVoC5QRg==}
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==}
|
resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==}
|
||||||
|
|
||||||
@@ -3470,6 +3613,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-+iwzCJ7C5v5KgcBuueqVoNiHVoQpwiUK5XFLjf0affFTep+Wcw93tPvmb8tqujDNmzhBDPddnWV/qgWSXgq+Hg==}
|
resolution: {integrity: sha512-+iwzCJ7C5v5KgcBuueqVoNiHVoQpwiUK5XFLjf0affFTep+Wcw93tPvmb8tqujDNmzhBDPddnWV/qgWSXgq+Hg==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
resolution: {integrity: sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==}
|
||||||
|
engines: {node: '>= 8'}
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
|
resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
|
||||||
engines: {node: '>=16'}
|
engines: {node: '>=16'}
|
||||||
@@ -3577,6 +3724,14 @@ packages:
|
|||||||
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
|
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
|
||||||
deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting [email protected]
|
deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting [email protected]
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
resolution: {integrity: sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
resolution: {integrity: sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
|
resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@@ -3672,6 +3827,10 @@ packages:
|
|||||||
[email protected]:
|
[email protected]:
|
||||||
resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==}
|
resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==}
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==}
|
resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==}
|
||||||
|
|
||||||
@@ -3725,6 +3884,9 @@ packages:
|
|||||||
[email protected]:
|
[email protected]:
|
||||||
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
resolution: {integrity: sha512-MAQUJuIo7Xqk8EVNP+6d3CKq9c80hi4tjIbIAT6lmGW9W6WzlHiu9PS8uSuUYU+Do+j1baiFp3H25XEVxDIG2g==}
|
resolution: {integrity: sha512-MAQUJuIo7Xqk8EVNP+6d3CKq9c80hi4tjIbIAT6lmGW9W6WzlHiu9PS8uSuUYU+Do+j1baiFp3H25XEVxDIG2g==}
|
||||||
|
|
||||||
@@ -3894,6 +4056,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==}
|
resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==}
|
resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==}
|
||||||
engines: {node: '>=16'}
|
engines: {node: '>=16'}
|
||||||
@@ -4098,6 +4264,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
|
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
resolution: {integrity: sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==}
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==}
|
resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==}
|
||||||
|
|
||||||
@@ -4430,6 +4599,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
|
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
resolution: {integrity: sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
|
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -4682,6 +4855,10 @@ packages:
|
|||||||
[email protected]:
|
[email protected]:
|
||||||
resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==}
|
resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==}
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
|
||||||
|
engines: {node: '>= 6'}
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
|
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
|
||||||
engines: {node: '>=8.10.0'}
|
engines: {node: '>=8.10.0'}
|
||||||
@@ -4721,6 +4898,10 @@ packages:
|
|||||||
[email protected]:
|
[email protected]:
|
||||||
resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==}
|
resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==}
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
resolution: {integrity: sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
|
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
@@ -4966,6 +5147,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
|
resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==}
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
|
resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
|
||||||
engines: {node: '>=10.0.0'}
|
engines: {node: '>=10.0.0'}
|
||||||
@@ -5393,6 +5577,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==}
|
resolution: {integrity: sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
|
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
@@ -5490,6 +5678,190 @@ snapshots:
|
|||||||
'@types/json-schema': 7.0.15
|
'@types/json-schema': 7.0.15
|
||||||
js-yaml: 4.3.0
|
js-yaml: 4.3.0
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
dependencies:
|
||||||
|
'@aws-sdk/core': 3.977.9
|
||||||
|
'@aws-sdk/types': 3.974.5
|
||||||
|
'@smithy/core': 3.33.3
|
||||||
|
'@smithy/types': 4.17.2
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
dependencies:
|
||||||
|
'@aws-sdk/checksums': 3.1000.29
|
||||||
|
'@aws-sdk/core': 3.977.9
|
||||||
|
'@aws-sdk/credential-provider-node': 3.972.81
|
||||||
|
'@aws-sdk/middleware-sdk-s3': 3.972.75
|
||||||
|
'@aws-sdk/signature-v4-multi-region': 3.996.46
|
||||||
|
'@aws-sdk/types': 3.974.5
|
||||||
|
'@smithy/core': 3.33.3
|
||||||
|
'@smithy/fetch-http-handler': 5.7.2
|
||||||
|
'@smithy/node-http-handler': 4.11.3
|
||||||
|
'@smithy/types': 4.17.2
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
dependencies:
|
||||||
|
'@aws-sdk/types': 3.974.5
|
||||||
|
'@aws-sdk/xml-builder': 3.972.40
|
||||||
|
'@aws/lambda-invoke-store': 0.3.0
|
||||||
|
'@smithy/core': 3.33.3
|
||||||
|
'@smithy/signature-v4': 5.7.3
|
||||||
|
'@smithy/types': 4.17.2
|
||||||
|
bowser: 2.14.1
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
dependencies:
|
||||||
|
'@aws-sdk/core': 3.977.9
|
||||||
|
'@aws-sdk/types': 3.974.5
|
||||||
|
'@smithy/core': 3.33.3
|
||||||
|
'@smithy/types': 4.17.2
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
dependencies:
|
||||||
|
'@aws-sdk/core': 3.977.9
|
||||||
|
'@aws-sdk/types': 3.974.5
|
||||||
|
'@smithy/core': 3.33.3
|
||||||
|
'@smithy/fetch-http-handler': 5.7.2
|
||||||
|
'@smithy/node-http-handler': 4.11.3
|
||||||
|
'@smithy/types': 4.17.2
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
dependencies:
|
||||||
|
'@aws-sdk/core': 3.977.9
|
||||||
|
'@aws-sdk/credential-provider-env': 3.972.70
|
||||||
|
'@aws-sdk/credential-provider-http': 3.972.72
|
||||||
|
'@aws-sdk/credential-provider-login': 3.972.77
|
||||||
|
'@aws-sdk/credential-provider-process': 3.972.70
|
||||||
|
'@aws-sdk/credential-provider-sso': 3.973.14
|
||||||
|
'@aws-sdk/credential-provider-web-identity': 3.972.76
|
||||||
|
'@aws-sdk/nested-clients': 3.997.44
|
||||||
|
'@aws-sdk/types': 3.974.5
|
||||||
|
'@smithy/core': 3.33.3
|
||||||
|
'@smithy/credential-provider-imds': 4.5.2
|
||||||
|
'@smithy/types': 4.17.2
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
dependencies:
|
||||||
|
'@aws-sdk/core': 3.977.9
|
||||||
|
'@aws-sdk/nested-clients': 3.997.44
|
||||||
|
'@aws-sdk/types': 3.974.5
|
||||||
|
'@smithy/core': 3.33.3
|
||||||
|
'@smithy/types': 4.17.2
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
dependencies:
|
||||||
|
'@aws-sdk/credential-provider-env': 3.972.70
|
||||||
|
'@aws-sdk/credential-provider-http': 3.972.72
|
||||||
|
'@aws-sdk/credential-provider-ini': 3.973.15
|
||||||
|
'@aws-sdk/credential-provider-process': 3.972.70
|
||||||
|
'@aws-sdk/credential-provider-sso': 3.973.14
|
||||||
|
'@aws-sdk/credential-provider-web-identity': 3.972.76
|
||||||
|
'@aws-sdk/types': 3.974.5
|
||||||
|
'@smithy/core': 3.33.3
|
||||||
|
'@smithy/credential-provider-imds': 4.5.2
|
||||||
|
'@smithy/types': 4.17.2
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
dependencies:
|
||||||
|
'@aws-sdk/core': 3.977.9
|
||||||
|
'@aws-sdk/types': 3.974.5
|
||||||
|
'@smithy/core': 3.33.3
|
||||||
|
'@smithy/types': 4.17.2
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
dependencies:
|
||||||
|
'@aws-sdk/core': 3.977.9
|
||||||
|
'@aws-sdk/nested-clients': 3.997.44
|
||||||
|
'@aws-sdk/token-providers': 3.1116.0
|
||||||
|
'@aws-sdk/types': 3.974.5
|
||||||
|
'@smithy/core': 3.33.3
|
||||||
|
'@smithy/types': 4.17.2
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
dependencies:
|
||||||
|
'@aws-sdk/core': 3.977.9
|
||||||
|
'@aws-sdk/nested-clients': 3.997.44
|
||||||
|
'@aws-sdk/types': 3.974.5
|
||||||
|
'@smithy/core': 3.33.3
|
||||||
|
'@smithy/types': 4.17.2
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected](@aws-sdk/[email protected])':
|
||||||
|
dependencies:
|
||||||
|
'@aws-sdk/client-s3': 3.1119.0
|
||||||
|
'@smithy/core': 3.33.3
|
||||||
|
'@smithy/types': 4.17.2
|
||||||
|
buffer: 5.6.0
|
||||||
|
events: 3.3.0
|
||||||
|
stream-browserify: 3.0.0
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
dependencies:
|
||||||
|
'@aws-sdk/core': 3.977.9
|
||||||
|
'@aws-sdk/signature-v4-multi-region': 3.996.46
|
||||||
|
'@aws-sdk/types': 3.974.5
|
||||||
|
'@smithy/core': 3.33.3
|
||||||
|
'@smithy/types': 4.17.2
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
dependencies:
|
||||||
|
'@aws-sdk/core': 3.977.9
|
||||||
|
'@aws-sdk/signature-v4-multi-region': 3.996.46
|
||||||
|
'@aws-sdk/types': 3.974.5
|
||||||
|
'@smithy/core': 3.33.3
|
||||||
|
'@smithy/fetch-http-handler': 5.7.2
|
||||||
|
'@smithy/node-http-handler': 4.11.3
|
||||||
|
'@smithy/types': 4.17.2
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
dependencies:
|
||||||
|
'@aws-sdk/core': 3.977.9
|
||||||
|
'@aws-sdk/signature-v4-multi-region': 3.996.46
|
||||||
|
'@aws-sdk/types': 3.974.5
|
||||||
|
'@smithy/core': 3.33.3
|
||||||
|
'@smithy/types': 4.17.2
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
dependencies:
|
||||||
|
'@aws-sdk/types': 3.974.5
|
||||||
|
'@smithy/signature-v4': 5.7.3
|
||||||
|
'@smithy/types': 4.17.2
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
dependencies:
|
||||||
|
'@aws-sdk/core': 3.977.9
|
||||||
|
'@aws-sdk/nested-clients': 3.997.44
|
||||||
|
'@aws-sdk/types': 3.974.5
|
||||||
|
'@smithy/core': 3.33.3
|
||||||
|
'@smithy/types': 4.17.2
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
dependencies:
|
||||||
|
'@smithy/types': 4.17.2
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@aws-sdk/[email protected]':
|
||||||
|
dependencies:
|
||||||
|
'@smithy/types': 4.17.2
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@aws/[email protected]': {}
|
||||||
|
|
||||||
'@babel/[email protected]':
|
'@babel/[email protected]':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/helper-validator-identifier': 7.29.7
|
'@babel/helper-validator-identifier': 7.29.7
|
||||||
@@ -7020,6 +7392,21 @@ snapshots:
|
|||||||
- supports-color
|
- supports-color
|
||||||
- typescript
|
- typescript
|
||||||
|
|
||||||
|
'@payloadcms/[email protected](@types/[email protected])([email protected])([email protected](@babel/[email protected])(@playwright/[email protected])([email protected]([email protected]))([email protected])([email protected]))([email protected]([email protected])([email protected]))([email protected]([email protected]))([email protected])([email protected])':
|
||||||
|
dependencies:
|
||||||
|
'@payloadcms/ui': 3.88.0(@types/[email protected])([email protected])([email protected](@babel/[email protected])(@playwright/[email protected])([email protected]([email protected]))([email protected])([email protected]))([email protected]([email protected])([email protected]))([email protected]([email protected]))([email protected])([email protected])
|
||||||
|
find-node-modules: 2.1.3
|
||||||
|
payload: 3.88.0([email protected])([email protected])
|
||||||
|
range-parser: 1.2.1
|
||||||
|
react: 19.2.6
|
||||||
|
react-dom: 19.2.6([email protected])
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@types/react'
|
||||||
|
- monaco-editor
|
||||||
|
- next
|
||||||
|
- supports-color
|
||||||
|
- typescript
|
||||||
|
|
||||||
'@payloadcms/[email protected](@types/[email protected])([email protected])([email protected](@babel/[email protected])(@playwright/[email protected])([email protected]([email protected]))([email protected])([email protected]))([email protected]([email protected])([email protected]))([email protected]([email protected]))([email protected])([email protected])':
|
'@payloadcms/[email protected](@types/[email protected])([email protected])([email protected](@babel/[email protected])(@playwright/[email protected])([email protected]([email protected]))([email protected])([email protected]))([email protected]([email protected])([email protected]))([email protected]([email protected]))([email protected])([email protected])':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@payloadcms/translations': 3.88.0
|
'@payloadcms/translations': 3.88.0
|
||||||
@@ -7094,6 +7481,22 @@ snapshots:
|
|||||||
- utf-8-validate
|
- utf-8-validate
|
||||||
- yjs
|
- yjs
|
||||||
|
|
||||||
|
'@payloadcms/[email protected](@types/[email protected])([email protected])([email protected](@babel/[email protected])(@playwright/[email protected])([email protected]([email protected]))([email protected])([email protected]))([email protected]([email protected])([email protected]))([email protected]([email protected]))([email protected])([email protected])':
|
||||||
|
dependencies:
|
||||||
|
'@aws-sdk/client-s3': 3.1119.0
|
||||||
|
'@aws-sdk/lib-storage': 3.1119.0(@aws-sdk/[email protected])
|
||||||
|
'@aws-sdk/s3-request-presigner': 3.1119.0
|
||||||
|
'@payloadcms/plugin-cloud-storage': 3.88.0(@types/[email protected])([email protected])([email protected](@babel/[email protected])(@playwright/[email protected])([email protected]([email protected]))([email protected])([email protected]))([email protected]([email protected])([email protected]))([email protected]([email protected]))([email protected])([email protected])
|
||||||
|
payload: 3.88.0([email protected])([email protected])
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@types/react'
|
||||||
|
- monaco-editor
|
||||||
|
- next
|
||||||
|
- react
|
||||||
|
- react-dom
|
||||||
|
- supports-color
|
||||||
|
- typescript
|
||||||
|
|
||||||
'@payloadcms/[email protected]':
|
'@payloadcms/[email protected]':
|
||||||
dependencies:
|
dependencies:
|
||||||
date-fns: 4.1.0
|
date-fns: 4.1.0
|
||||||
@@ -7220,6 +7623,39 @@ snapshots:
|
|||||||
|
|
||||||
'@sindresorhus/[email protected]': {}
|
'@sindresorhus/[email protected]': {}
|
||||||
|
|
||||||
|
'@smithy/[email protected]':
|
||||||
|
dependencies:
|
||||||
|
'@smithy/types': 4.17.2
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@smithy/[email protected]':
|
||||||
|
dependencies:
|
||||||
|
'@smithy/core': 3.33.3
|
||||||
|
'@smithy/types': 4.17.2
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@smithy/[email protected]':
|
||||||
|
dependencies:
|
||||||
|
'@smithy/core': 3.33.3
|
||||||
|
'@smithy/types': 4.17.2
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@smithy/[email protected]':
|
||||||
|
dependencies:
|
||||||
|
'@smithy/core': 3.33.3
|
||||||
|
'@smithy/types': 4.17.2
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@smithy/[email protected]':
|
||||||
|
dependencies:
|
||||||
|
'@smithy/core': 3.33.3
|
||||||
|
'@smithy/types': 4.17.2
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@smithy/[email protected]':
|
||||||
|
dependencies:
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@standard-schema/[email protected]': {}
|
'@standard-schema/[email protected]': {}
|
||||||
|
|
||||||
'@swc-node/[email protected](@swc/[email protected])(@swc/[email protected])':
|
'@swc-node/[email protected](@swc/[email protected])(@swc/[email protected])':
|
||||||
@@ -8043,6 +8479,8 @@ snapshots:
|
|||||||
|
|
||||||
[email protected]: {}
|
[email protected]: {}
|
||||||
|
|
||||||
|
[email protected]: {}
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
dependencies:
|
dependencies:
|
||||||
balanced-match: 1.0.2
|
balanced-match: 1.0.2
|
||||||
@@ -8078,6 +8516,11 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 22.19.9
|
'@types/node': 22.19.9
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
dependencies:
|
||||||
|
base64-js: 1.5.1
|
||||||
|
ieee754: 1.2.1
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
dependencies:
|
dependencies:
|
||||||
base64-js: 1.5.1
|
base64-js: 1.5.1
|
||||||
@@ -8330,6 +8773,8 @@ snapshots:
|
|||||||
|
|
||||||
[email protected]: {}
|
[email protected]: {}
|
||||||
|
|
||||||
|
[email protected]: {}
|
||||||
|
|
||||||
[email protected]: {}
|
[email protected]: {}
|
||||||
|
|
||||||
[email protected]: {}
|
[email protected]: {}
|
||||||
@@ -9098,6 +9543,8 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- bare-abort-controller
|
- bare-abort-controller
|
||||||
|
|
||||||
|
[email protected]: {}
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
dependencies:
|
dependencies:
|
||||||
cross-spawn: 7.0.6
|
cross-spawn: 7.0.6
|
||||||
@@ -9110,6 +9557,10 @@ snapshots:
|
|||||||
signal-exit: 3.0.7
|
signal-exit: 3.0.7
|
||||||
strip-final-newline: 2.0.0
|
strip-final-newline: 2.0.0
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
dependencies:
|
||||||
|
homedir-polyfill: 1.0.3
|
||||||
|
|
||||||
[email protected]: {}
|
[email protected]: {}
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
@@ -9204,6 +9655,11 @@ snapshots:
|
|||||||
make-dir: 3.1.0
|
make-dir: 3.1.0
|
||||||
pkg-dir: 4.2.0
|
pkg-dir: 4.2.0
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
dependencies:
|
||||||
|
findup-sync: 4.0.0
|
||||||
|
merge: 2.1.1
|
||||||
|
|
||||||
[email protected]: {}
|
[email protected]: {}
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
@@ -9220,6 +9676,13 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
semver-regex: 4.0.5
|
semver-regex: 4.0.5
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
dependencies:
|
||||||
|
detect-file: 1.0.0
|
||||||
|
is-glob: 4.0.3
|
||||||
|
micromatch: 4.0.8
|
||||||
|
resolve-dir: 1.0.1
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
dependencies:
|
dependencies:
|
||||||
flatted: 3.4.2
|
flatted: 3.4.2
|
||||||
@@ -9330,6 +9793,20 @@ snapshots:
|
|||||||
once: 1.4.0
|
once: 1.4.0
|
||||||
path-is-absolute: 1.0.1
|
path-is-absolute: 1.0.1
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
dependencies:
|
||||||
|
global-prefix: 1.0.2
|
||||||
|
is-windows: 1.0.2
|
||||||
|
resolve-dir: 1.0.1
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
dependencies:
|
||||||
|
expand-tilde: 2.0.2
|
||||||
|
homedir-polyfill: 1.0.3
|
||||||
|
ini: 1.3.8
|
||||||
|
is-windows: 1.0.2
|
||||||
|
which: 1.3.1
|
||||||
|
|
||||||
[email protected]: {}
|
[email protected]: {}
|
||||||
|
|
||||||
[email protected]: {}
|
[email protected]: {}
|
||||||
@@ -9425,6 +9902,10 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
react-is: 16.13.1
|
react-is: 16.13.1
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
dependencies:
|
||||||
|
parse-passwd: 1.0.0
|
||||||
|
|
||||||
[email protected]: {}
|
[email protected]: {}
|
||||||
|
|
||||||
[email protected]: {}
|
[email protected]: {}
|
||||||
@@ -9467,6 +9948,8 @@ snapshots:
|
|||||||
|
|
||||||
[email protected]: {}
|
[email protected]: {}
|
||||||
|
|
||||||
|
[email protected]: {}
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
dependencies:
|
dependencies:
|
||||||
kind-of: 6.0.3
|
kind-of: 6.0.3
|
||||||
@@ -9630,6 +10113,8 @@ snapshots:
|
|||||||
call-bound: 1.0.4
|
call-bound: 1.0.4
|
||||||
get-intrinsic: 1.3.0
|
get-intrinsic: 1.3.0
|
||||||
|
|
||||||
|
[email protected]: {}
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
dependencies:
|
dependencies:
|
||||||
is-inside-container: 1.0.0
|
is-inside-container: 1.0.0
|
||||||
@@ -9855,6 +10340,8 @@ snapshots:
|
|||||||
|
|
||||||
[email protected]: {}
|
[email protected]: {}
|
||||||
|
|
||||||
|
[email protected]: {}
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
dependencies:
|
dependencies:
|
||||||
decode-named-character-reference: 1.3.0
|
decode-named-character-reference: 1.3.0
|
||||||
@@ -10320,6 +10807,8 @@ snapshots:
|
|||||||
json-parse-even-better-errors: 2.3.1
|
json-parse-even-better-errors: 2.3.1
|
||||||
lines-and-columns: 1.2.4
|
lines-and-columns: 1.2.4
|
||||||
|
|
||||||
|
[email protected]: {}
|
||||||
|
|
||||||
[email protected]: {}
|
[email protected]: {}
|
||||||
|
|
||||||
[email protected]: {}
|
[email protected]: {}
|
||||||
@@ -10610,6 +11099,12 @@ snapshots:
|
|||||||
string_decoder: 1.1.1
|
string_decoder: 1.1.1
|
||||||
util-deprecate: 1.0.2
|
util-deprecate: 1.0.2
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
dependencies:
|
||||||
|
inherits: 2.0.4
|
||||||
|
string_decoder: 1.1.1
|
||||||
|
util-deprecate: 1.0.2
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
dependencies:
|
dependencies:
|
||||||
picomatch: 2.3.2
|
picomatch: 2.3.2
|
||||||
@@ -10653,6 +11148,11 @@ snapshots:
|
|||||||
|
|
||||||
[email protected]: {}
|
[email protected]: {}
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
dependencies:
|
||||||
|
expand-tilde: 2.0.2
|
||||||
|
global-modules: 1.0.0
|
||||||
|
|
||||||
[email protected]: {}
|
[email protected]: {}
|
||||||
|
|
||||||
[email protected]: {}
|
[email protected]: {}
|
||||||
@@ -10979,6 +11479,11 @@ snapshots:
|
|||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
internal-slot: 1.1.0
|
internal-slot: 1.1.0
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
dependencies:
|
||||||
|
inherits: 2.0.4
|
||||||
|
readable-stream: 3.6.2
|
||||||
|
|
||||||
[email protected]: {}
|
[email protected]: {}
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
@@ -11479,6 +11984,10 @@ snapshots:
|
|||||||
gopd: 1.2.0
|
gopd: 1.2.0
|
||||||
has-tostringtag: 1.0.2
|
has-tostringtag: 1.0.2
|
||||||
|
|
||||||
|
[email protected]:
|
||||||
|
dependencies:
|
||||||
|
isexe: 2.0.0
|
||||||
|
|
||||||
[email protected]:
|
[email protected]:
|
||||||
dependencies:
|
dependencies:
|
||||||
isexe: 2.0.0
|
isexe: 2.0.0
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
import type { Field } from 'payload'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cloudflare R2 storage credentials.
|
|
||||||
* Reserved for future use — media offloading to R2.
|
|
||||||
*
|
|
||||||
* Protected at the global level (SiteIntegrations requires an authenticated
|
|
||||||
* user), so the access keys stay editable in the admin panel while remaining
|
|
||||||
* inaccessible to anonymous API requests.
|
|
||||||
*/
|
|
||||||
export const storageFields: Field[] = [
|
|
||||||
{
|
|
||||||
name: 'r2Bucket',
|
|
||||||
type: 'text',
|
|
||||||
admin: {
|
|
||||||
description: 'R2 bucket name.',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'r2Endpoint',
|
|
||||||
type: 'text',
|
|
||||||
admin: {
|
|
||||||
description: 'R2 S3-compatible endpoint URL.',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'r2AccessKeyId',
|
|
||||||
type: 'text',
|
|
||||||
admin: {
|
|
||||||
description: 'R2 access key ID.',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'r2SecretAccessKey',
|
|
||||||
type: 'text',
|
|
||||||
admin: {
|
|
||||||
description: 'R2 secret access key.',
|
|
||||||
// Masked in the UI (••••) — stored plaintext, readable for R2 auth.
|
|
||||||
components: {
|
|
||||||
Field: '@intecion/ipal-kit/client#MaskedField',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
@@ -3,7 +3,6 @@ import type { Field, GlobalConfig } from 'payload'
|
|||||||
import { isAdmin } from '../../modules/access/index.js'
|
import { isAdmin } from '../../modules/access/index.js'
|
||||||
import { analyticsFields } from './fields/analytics.js'
|
import { analyticsFields } from './fields/analytics.js'
|
||||||
import { smtpFields } from './fields/smtp.js'
|
import { smtpFields } from './fields/smtp.js'
|
||||||
import { storageFields } from './fields/storage.js'
|
|
||||||
import { turnstileFields } from './fields/turnstile.js'
|
import { turnstileFields } from './fields/turnstile.js'
|
||||||
|
|
||||||
type BuildSiteIntegrationsArgs = {
|
type BuildSiteIntegrationsArgs = {
|
||||||
@@ -22,6 +21,10 @@ type BuildSiteIntegrationsArgs = {
|
|||||||
* impossible to enter.)
|
* impossible to enter.)
|
||||||
*
|
*
|
||||||
* Unnamed tabs keep data flat (siteIntegrations.ga4MeasurementId).
|
* Unnamed tabs keep data flat (siteIntegrations.ga4MeasurementId).
|
||||||
|
*
|
||||||
|
* Note: R2 storage credentials are NOT here — storage is infrastructure and
|
||||||
|
* binds at boot, so its config lives in .env (R2_BUCKET, R2_ENDPOINT, ...),
|
||||||
|
* consumed by buildR2Storage. See docs/storage.md.
|
||||||
*/
|
*/
|
||||||
export function buildSiteIntegrations({
|
export function buildSiteIntegrations({
|
||||||
additionalFields,
|
additionalFields,
|
||||||
@@ -44,7 +47,6 @@ export function buildSiteIntegrations({
|
|||||||
{ fields: analyticsFields, label: 'Analytics' },
|
{ fields: analyticsFields, label: 'Analytics' },
|
||||||
{ fields: turnstileFields, label: 'Turnstile' },
|
{ fields: turnstileFields, label: 'Turnstile' },
|
||||||
{ fields: smtpFields, label: 'SMTP' },
|
{ fields: smtpFields, label: 'SMTP' },
|
||||||
{ fields: storageFields, label: 'Storage' },
|
|
||||||
...(additionalFields?.length ? [{ fields: additionalFields, label: 'Custom' }] : []),
|
...(additionalFields?.length ? [{ fields: additionalFields, label: 'Custom' }] : []),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
+14
-12
@@ -75,6 +75,18 @@ export {
|
|||||||
} from './modules/i18n/index.js'
|
} from './modules/i18n/index.js'
|
||||||
export type { LocaleMiddlewareResult } from './modules/i18n/index.js'
|
export type { LocaleMiddlewareResult } from './modules/i18n/index.js'
|
||||||
export { createLocaleMiddleware, DEFAULT_MIDDLEWARE_MATCHER } from './modules/i18n/index.js'
|
export { createLocaleMiddleware, DEFAULT_MIDDLEWARE_MATCHER } from './modules/i18n/index.js'
|
||||||
|
// Media — filename normalization hook for upload collections (Media).
|
||||||
|
export { normalizeFilename, normalizeFilenameHook } from './modules/media/index.js'
|
||||||
|
export {
|
||||||
|
getNotificationTexts,
|
||||||
|
NOTIFICATION_FALLBACK,
|
||||||
|
resolveFormMessage,
|
||||||
|
} from './modules/notifications/index.js'
|
||||||
|
export type {
|
||||||
|
FormNotificationTexts,
|
||||||
|
NotificationsData,
|
||||||
|
NotificationTexts,
|
||||||
|
} from './modules/notifications/index.js'
|
||||||
export type { PagesOption, SystemPageRole } from './modules/pages/index.js'
|
export type { PagesOption, SystemPageRole } from './modules/pages/index.js'
|
||||||
export { ALL_SYSTEM_PAGE_ROLES, getSystemPagePath } from './modules/pages/index.js'
|
export { ALL_SYSTEM_PAGE_ROLES, getSystemPagePath } from './modules/pages/index.js'
|
||||||
export type { GlobalQueryOptions } from './modules/payload/index.js'
|
export type { GlobalQueryOptions } from './modules/payload/index.js'
|
||||||
@@ -99,18 +111,8 @@ export {
|
|||||||
injectAutoFillMeta,
|
injectAutoFillMeta,
|
||||||
} from './modules/seo/index.js'
|
} from './modules/seo/index.js'
|
||||||
export { buildSlugField, toSlug } from './modules/slug/index.js'
|
export { buildSlugField, toSlug } from './modules/slug/index.js'
|
||||||
export {
|
// Storage — Cloudflare R2 media offload, configured from .env.
|
||||||
NOTIFICATION_FALLBACK,
|
export { buildR2Storage } from './modules/storage/index.js'
|
||||||
getNotificationTexts,
|
|
||||||
resolveFormMessage,
|
|
||||||
} from './modules/notifications/index.js'
|
|
||||||
export type {
|
|
||||||
FormNotificationTexts,
|
|
||||||
NotificationsData,
|
|
||||||
NotificationTexts,
|
|
||||||
} from './modules/notifications/index.js'
|
|
||||||
|
|
||||||
export { ipalKit } from './plugin.js'
|
export { ipalKit } from './plugin.js'
|
||||||
export type { IpalOptions } from './types.js'
|
export type { IpalOptions } from './types.js'
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,14 @@ import type { I18nConfig } from './types.js'
|
|||||||
import { getLocaleCodes, isValidLocale } from './helpers.js'
|
import { getLocaleCodes, isValidLocale } from './helpers.js'
|
||||||
|
|
||||||
/** Cookie name the template uses to persist a visitor's locale choice. */
|
/** Cookie name the template uses to persist a visitor's locale choice. */
|
||||||
export const LOCALE_COOKIE_NAME = 'ipal-locale'
|
/**
|
||||||
|
* Cookie name for the persisted locale choice. Uses NEXT_LOCALE — the convention
|
||||||
|
* Next.js and its i18n ecosystem expect — so the cookie is interoperable with
|
||||||
|
* other libraries that read the active locale (instead of a plugin-specific
|
||||||
|
* name). Written only under functional consent; cleared when that consent is
|
||||||
|
* withdrawn (see consent cookieMap).
|
||||||
|
*/
|
||||||
|
export const LOCALE_COOKIE_NAME = 'NEXT_LOCALE'
|
||||||
|
|
||||||
type NegotiateLocaleArgs = {
|
type NegotiateLocaleArgs = {
|
||||||
/** Raw Accept-Language header value */
|
/** Raw Accept-Language header value */
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
export { normalizeFilename, normalizeFilenameHook } from './normalizeFilename.js'
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
import type { CollectionBeforeOperationHook } from 'payload'
|
||||||
|
import slugify from 'slugify'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalizes a filename: slugifies the NAME part (diacritics, spaces, case)
|
||||||
|
* while preserving the extension. Keeps uploaded media URLs clean and portable.
|
||||||
|
*
|
||||||
|
* "Zdjęcie jeden nad morzem.jpg" → "zdjecie-jeden-nad-morzem.jpg"
|
||||||
|
* "Faktura #12 (2024).PDF" → "faktura-12-2024.pdf"
|
||||||
|
* "already-clean.webp" → "already-clean.webp"
|
||||||
|
*
|
||||||
|
* Why not toSlug(): toSlug uses strict:true, which would strip the dot and
|
||||||
|
* merge name+extension. Here we split on the LAST dot, slug the stem, lowercase
|
||||||
|
* the extension, and rejoin.
|
||||||
|
*/
|
||||||
|
export function normalizeFilename(filename: string): string {
|
||||||
|
const lastDot = filename.lastIndexOf('.')
|
||||||
|
|
||||||
|
// No extension (or leading-dot dotfile) → slug the whole thing.
|
||||||
|
if (lastDot <= 0) {
|
||||||
|
return slugify(filename, { lower: true, strict: true, trim: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
const stem = filename.slice(0, lastDot)
|
||||||
|
const ext = filename.slice(lastDot + 1).toLowerCase()
|
||||||
|
|
||||||
|
const cleanStem = slugify(stem, { lower: true, strict: true, trim: true })
|
||||||
|
const cleanExt = slugify(ext, { lower: true, strict: true, trim: true })
|
||||||
|
|
||||||
|
// Stem could slug to empty (e.g. filename was all symbols) — fall back so we
|
||||||
|
// never produce a nameless file.
|
||||||
|
const safeStem = cleanStem || 'plik'
|
||||||
|
|
||||||
|
return cleanExt ? `${safeStem}.${cleanExt}` : safeStem
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* beforeOperation hook for an upload collection (e.g. Media). Rewrites the
|
||||||
|
* incoming file's name to its normalized form before Payload stores it, so both
|
||||||
|
* the stored file and its DB filename are clean. Works with local disk and with
|
||||||
|
* cloud storage adapters (R2/S3) — it runs before the storage layer.
|
||||||
|
*
|
||||||
|
* Wire into your Media collection:
|
||||||
|
* import { normalizeFilenameHook } from '@intecion/ipal-kit'
|
||||||
|
* hooks: { beforeOperation: [normalizeFilenameHook] }
|
||||||
|
*/
|
||||||
|
export const normalizeFilenameHook: CollectionBeforeOperationHook = ({ req, operation }) => {
|
||||||
|
if (operation !== 'create' && operation !== 'update') return
|
||||||
|
const file = req.file
|
||||||
|
if (file?.name) {
|
||||||
|
file.name = normalizeFilename(file.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
import type { Plugin } from 'payload'
|
||||||
|
|
||||||
|
import { s3Storage } from '@payloadcms/storage-s3'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cloudflare R2 media storage — configured from environment variables (agency
|
||||||
|
* infrastructure, not per-project panel data). R2 is S3-compatible, so we use
|
||||||
|
* @payloadcms/storage-s3 pointed at the R2 endpoint.
|
||||||
|
*
|
||||||
|
* Storage is infrastructure (like the database or PAYLOAD_SECRET): it binds at
|
||||||
|
* boot, and its credentials are agency-owned — so it lives in .env, not the
|
||||||
|
* panel. See docs/storage.md for the required variables.
|
||||||
|
*
|
||||||
|
* Returns the storage plugin when all R2 vars are present; otherwise returns a
|
||||||
|
* no-op passthrough so the project falls back to Payload's default local disk
|
||||||
|
* storage (useful in dev without R2). This mirrors how mailAdapter degrades
|
||||||
|
* gracefully when a transport isn't configured.
|
||||||
|
*
|
||||||
|
* @param collections - slugs of upload collections to offload to R2 (e.g. ['media'])
|
||||||
|
*/
|
||||||
|
export const buildR2Storage = (collections: string[] = ['media']): Plugin => {
|
||||||
|
const bucket = process.env.R2_BUCKET
|
||||||
|
const endpoint = process.env.R2_ENDPOINT
|
||||||
|
const accessKeyId = process.env.R2_ACCESS_KEY_ID
|
||||||
|
const secretAccessKey = process.env.R2_SECRET_ACCESS_KEY
|
||||||
|
|
||||||
|
// Any missing → skip R2, fall back to local disk. Warn so it's not silent.
|
||||||
|
if (!bucket || !endpoint || !accessKeyId || !secretAccessKey) {
|
||||||
|
return (config) => {
|
||||||
|
// Only warn when SOME vars are set (partial config = likely a mistake).
|
||||||
|
if (bucket || endpoint || accessKeyId || secretAccessKey) {
|
||||||
|
console.warn(
|
||||||
|
'[ipal] R2 storage: incomplete env (need R2_BUCKET, R2_ENDPOINT, ' +
|
||||||
|
'R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY). Falling back to local disk.',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public URL for served media. R2 is private by default; its S3 endpoint only
|
||||||
|
// accepts uploads and won't serve files (403). With a custom domain
|
||||||
|
// (media.klient.pl → bucket) set R2_PUBLIC_URL so Payload generates URLs
|
||||||
|
// pointing there. Without it, uploads work but images don't display publicly.
|
||||||
|
// See docs/storage.md.
|
||||||
|
const publicUrl = process.env.R2_PUBLIC_URL?.replace(/\/$/, '') // strip trailing slash
|
||||||
|
|
||||||
|
// generateFileURL is a PER-COLLECTION option in @payloadcms/storage-s3 (not a
|
||||||
|
// top-level one) — R2 needs it to point served URLs at the custom domain
|
||||||
|
// instead of the private S3 endpoint. Each collection gets either `true`
|
||||||
|
// (plain offload) or an object carrying generateFileURL when a public URL is set.
|
||||||
|
const generateFileURL = publicUrl
|
||||||
|
? ({ filename, prefix }: { filename: string; prefix?: string }) =>
|
||||||
|
[publicUrl, prefix, filename].filter(Boolean).join('/')
|
||||||
|
: undefined
|
||||||
|
|
||||||
|
const collectionsConfig: Record<string, { generateFileURL: typeof generateFileURL } | true> = {}
|
||||||
|
for (const slug of collections) {
|
||||||
|
collectionsConfig[slug] = generateFileURL ? { generateFileURL } : true
|
||||||
|
}
|
||||||
|
|
||||||
|
return s3Storage({
|
||||||
|
bucket,
|
||||||
|
collections: collectionsConfig,
|
||||||
|
config: {
|
||||||
|
credentials: { accessKeyId, secretAccessKey },
|
||||||
|
endpoint,
|
||||||
|
region: 'auto', // R2 uses 'auto'
|
||||||
|
// R2 requires path-style addressing for S3 compatibility.
|
||||||
|
forcePathStyle: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { buildR2Storage } from './buildR2Storage.js'
|
||||||
Reference in New Issue
Block a user