@payloadcms/plugin-multi-tenant 3.49.0 → 3.50.0-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/dist/components/GlobalViewRedirect/index.d.ts +4 -0
  2. package/dist/components/GlobalViewRedirect/index.d.ts.map +1 -1
  3. package/dist/components/GlobalViewRedirect/index.js +3 -0
  4. package/dist/components/GlobalViewRedirect/index.js.map +1 -1
  5. package/dist/endpoints/getTenantOptionsEndpoint.d.ts +10 -0
  6. package/dist/endpoints/getTenantOptionsEndpoint.d.ts.map +1 -0
  7. package/dist/endpoints/getTenantOptionsEndpoint.js +26 -0
  8. package/dist/endpoints/getTenantOptionsEndpoint.js.map +1 -0
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +19 -2
  11. package/dist/index.js.map +1 -1
  12. package/dist/providers/TenantSelectionProvider/index.client.d.ts +2 -4
  13. package/dist/providers/TenantSelectionProvider/index.client.d.ts.map +1 -1
  14. package/dist/providers/TenantSelectionProvider/index.client.js +8 -12
  15. package/dist/providers/TenantSelectionProvider/index.client.js.map +1 -1
  16. package/dist/providers/TenantSelectionProvider/index.d.ts +6 -2
  17. package/dist/providers/TenantSelectionProvider/index.d.ts.map +1 -1
  18. package/dist/providers/TenantSelectionProvider/index.js +13 -23
  19. package/dist/providers/TenantSelectionProvider/index.js.map +1 -1
  20. package/dist/utilities/getGlobalViewRedirect.d.ts +5 -1
  21. package/dist/utilities/getGlobalViewRedirect.d.ts.map +1 -1
  22. package/dist/utilities/getGlobalViewRedirect.js +12 -6
  23. package/dist/utilities/getGlobalViewRedirect.js.map +1 -1
  24. package/dist/utilities/getTenantOptions.d.ts +12 -0
  25. package/dist/utilities/getTenantOptions.d.ts.map +1 -0
  26. package/dist/utilities/getTenantOptions.js +63 -0
  27. package/dist/utilities/getTenantOptions.js.map +1 -0
  28. package/package.json +6 -6
  29. package/dist/queries/findTenantOptions.d.ts +0 -11
  30. package/dist/queries/findTenantOptions.d.ts.map +0 -1
  31. package/dist/queries/findTenantOptions.js +0 -19
  32. package/dist/queries/findTenantOptions.js.map +0 -1
@@ -1,12 +1,16 @@
1
1
  import type { CollectionSlug, ServerProps, ViewTypes } from 'payload';
2
+ import type { MultiTenantPluginConfig } from '../../types.js';
2
3
  type Args = {
3
4
  basePath?: string;
4
5
  collectionSlug: CollectionSlug;
5
6
  docID?: number | string;
6
7
  globalSlugs: string[];
8
+ tenantArrayFieldName: string;
9
+ tenantArrayTenantFieldName: string;
7
10
  tenantFieldName: string;
8
11
  tenantsCollectionSlug: string;
9
12
  useAsTitle: string;
13
+ userHasAccessToAllTenants: Required<MultiTenantPluginConfig<any>>['userHasAccessToAllTenants'];
10
14
  viewType: ViewTypes;
11
15
  } & ServerProps;
12
16
  export declare const GlobalViewRedirect: (args: Args) => Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/GlobalViewRedirect/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAOrE,KAAK,IAAI,GAAG;IACV,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,cAAc,EAAE,cAAc,CAAA;IAC9B,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACvB,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,eAAe,EAAE,MAAM,CAAA;IACvB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,SAAS,CAAA;CACpB,GAAG,WAAW,CAAA;AAEf,eAAO,MAAM,kBAAkB,SAAgB,IAAI,kBAqBlD,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/GlobalViewRedirect/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAKrE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAA;AAI7D,KAAK,IAAI,GAAG;IACV,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,cAAc,EAAE,cAAc,CAAA;IAC9B,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACvB,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,oBAAoB,EAAE,MAAM,CAAA;IAC5B,0BAA0B,EAAE,MAAM,CAAA;IAClC,eAAe,EAAE,MAAM,CAAA;IACvB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,yBAAyB,EAAE,QAAQ,CAAC,uBAAuB,CAAC,GAAG,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAA;IAC9F,QAAQ,EAAE,SAAS,CAAA;CACpB,GAAG,WAAW,CAAA;AAEf,eAAO,MAAM,kBAAkB,SAAgB,IAAI,kBAwBlD,CAAA"}
@@ -12,9 +12,12 @@ export const GlobalViewRedirect = async (args)=>{
12
12
  headers,
13
13
  payload: args.payload,
14
14
  tenantFieldName: args.tenantFieldName,
15
+ tenantsArrayFieldName: args.tenantArrayFieldName,
16
+ tenantsArrayTenantFieldName: args.tenantArrayTenantFieldName,
15
17
  tenantsCollectionSlug: args.tenantsCollectionSlug,
16
18
  useAsTitle: args.useAsTitle,
17
19
  user: args.user,
20
+ userHasAccessToAllTenants: args.userHasAccessToAllTenants,
18
21
  view: args.viewType
19
22
  });
20
23
  if (redirectRoute) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/GlobalViewRedirect/index.ts"],"sourcesContent":["import type { CollectionSlug, ServerProps, ViewTypes } from 'payload'\n\nimport { headers as getHeaders } from 'next/headers.js'\nimport { redirect } from 'next/navigation.js'\n\nimport { getGlobalViewRedirect } from '../../utilities/getGlobalViewRedirect.js'\n\ntype Args = {\n basePath?: string\n collectionSlug: CollectionSlug\n docID?: number | string\n globalSlugs: string[]\n tenantFieldName: string\n tenantsCollectionSlug: string\n useAsTitle: string\n viewType: ViewTypes\n} & ServerProps\n\nexport const GlobalViewRedirect = async (args: Args) => {\n const collectionSlug = args?.collectionSlug\n if (collectionSlug && args.globalSlugs?.includes(collectionSlug)) {\n const headers = await getHeaders()\n const redirectRoute = await getGlobalViewRedirect({\n slug: collectionSlug,\n basePath: args.basePath,\n docID: args.docID,\n headers,\n payload: args.payload,\n tenantFieldName: args.tenantFieldName,\n tenantsCollectionSlug: args.tenantsCollectionSlug,\n useAsTitle: args.useAsTitle,\n user: args.user,\n view: args.viewType,\n })\n\n if (redirectRoute) {\n redirect(redirectRoute)\n }\n }\n}\n"],"names":["headers","getHeaders","redirect","getGlobalViewRedirect","GlobalViewRedirect","args","collectionSlug","globalSlugs","includes","redirectRoute","slug","basePath","docID","payload","tenantFieldName","tenantsCollectionSlug","useAsTitle","user","view","viewType"],"mappings":"AAEA,SAASA,WAAWC,UAAU,QAAQ,kBAAiB;AACvD,SAASC,QAAQ,QAAQ,qBAAoB;AAE7C,SAASC,qBAAqB,QAAQ,2CAA0C;AAahF,OAAO,MAAMC,qBAAqB,OAAOC;IACvC,MAAMC,iBAAiBD,MAAMC;IAC7B,IAAIA,kBAAkBD,KAAKE,WAAW,EAAEC,SAASF,iBAAiB;QAChE,MAAMN,UAAU,MAAMC;QACtB,MAAMQ,gBAAgB,MAAMN,sBAAsB;YAChDO,MAAMJ;YACNK,UAAUN,KAAKM,QAAQ;YACvBC,OAAOP,KAAKO,KAAK;YACjBZ;YACAa,SAASR,KAAKQ,OAAO;YACrBC,iBAAiBT,KAAKS,eAAe;YACrCC,uBAAuBV,KAAKU,qBAAqB;YACjDC,YAAYX,KAAKW,UAAU;YAC3BC,MAAMZ,KAAKY,IAAI;YACfC,MAAMb,KAAKc,QAAQ;QACrB;QAEA,IAAIV,eAAe;YACjBP,SAASO;QACX;IACF;AACF,EAAC"}
1
+ {"version":3,"sources":["../../../src/components/GlobalViewRedirect/index.ts"],"sourcesContent":["import type { CollectionSlug, ServerProps, ViewTypes } from 'payload'\n\nimport { headers as getHeaders } from 'next/headers.js'\nimport { redirect } from 'next/navigation.js'\n\nimport type { MultiTenantPluginConfig } from '../../types.js'\n\nimport { getGlobalViewRedirect } from '../../utilities/getGlobalViewRedirect.js'\n\ntype Args = {\n basePath?: string\n collectionSlug: CollectionSlug\n docID?: number | string\n globalSlugs: string[]\n tenantArrayFieldName: string\n tenantArrayTenantFieldName: string\n tenantFieldName: string\n tenantsCollectionSlug: string\n useAsTitle: string\n userHasAccessToAllTenants: Required<MultiTenantPluginConfig<any>>['userHasAccessToAllTenants']\n viewType: ViewTypes\n} & ServerProps\n\nexport const GlobalViewRedirect = async (args: Args) => {\n const collectionSlug = args?.collectionSlug\n if (collectionSlug && args.globalSlugs?.includes(collectionSlug)) {\n const headers = await getHeaders()\n const redirectRoute = await getGlobalViewRedirect({\n slug: collectionSlug,\n basePath: args.basePath,\n docID: args.docID,\n headers,\n payload: args.payload,\n tenantFieldName: args.tenantFieldName,\n tenantsArrayFieldName: args.tenantArrayFieldName,\n tenantsArrayTenantFieldName: args.tenantArrayTenantFieldName,\n tenantsCollectionSlug: args.tenantsCollectionSlug,\n useAsTitle: args.useAsTitle,\n user: args.user,\n userHasAccessToAllTenants: args.userHasAccessToAllTenants,\n view: args.viewType,\n })\n\n if (redirectRoute) {\n redirect(redirectRoute)\n }\n }\n}\n"],"names":["headers","getHeaders","redirect","getGlobalViewRedirect","GlobalViewRedirect","args","collectionSlug","globalSlugs","includes","redirectRoute","slug","basePath","docID","payload","tenantFieldName","tenantsArrayFieldName","tenantArrayFieldName","tenantsArrayTenantFieldName","tenantArrayTenantFieldName","tenantsCollectionSlug","useAsTitle","user","userHasAccessToAllTenants","view","viewType"],"mappings":"AAEA,SAASA,WAAWC,UAAU,QAAQ,kBAAiB;AACvD,SAASC,QAAQ,QAAQ,qBAAoB;AAI7C,SAASC,qBAAqB,QAAQ,2CAA0C;AAgBhF,OAAO,MAAMC,qBAAqB,OAAOC;IACvC,MAAMC,iBAAiBD,MAAMC;IAC7B,IAAIA,kBAAkBD,KAAKE,WAAW,EAAEC,SAASF,iBAAiB;QAChE,MAAMN,UAAU,MAAMC;QACtB,MAAMQ,gBAAgB,MAAMN,sBAAsB;YAChDO,MAAMJ;YACNK,UAAUN,KAAKM,QAAQ;YACvBC,OAAOP,KAAKO,KAAK;YACjBZ;YACAa,SAASR,KAAKQ,OAAO;YACrBC,iBAAiBT,KAAKS,eAAe;YACrCC,uBAAuBV,KAAKW,oBAAoB;YAChDC,6BAA6BZ,KAAKa,0BAA0B;YAC5DC,uBAAuBd,KAAKc,qBAAqB;YACjDC,YAAYf,KAAKe,UAAU;YAC3BC,MAAMhB,KAAKgB,IAAI;YACfC,2BAA2BjB,KAAKiB,yBAAyB;YACzDC,MAAMlB,KAAKmB,QAAQ;QACrB;QAEA,IAAIf,eAAe;YACjBP,SAASO;QACX;IACF;AACF,EAAC"}
@@ -0,0 +1,10 @@
1
+ import type { Endpoint } from 'payload';
2
+ import type { MultiTenantPluginConfig } from '../types.js';
3
+ export declare const getTenantOptionsEndpoint: <ConfigType>({ tenantsArrayFieldName, tenantsArrayTenantFieldName, tenantsCollectionSlug, useAsTitle, userHasAccessToAllTenants, }: {
4
+ tenantsArrayFieldName: string;
5
+ tenantsArrayTenantFieldName: string;
6
+ tenantsCollectionSlug: string;
7
+ useAsTitle: string;
8
+ userHasAccessToAllTenants: Required<MultiTenantPluginConfig<ConfigType>>["userHasAccessToAllTenants"];
9
+ }) => Endpoint;
10
+ //# sourceMappingURL=getTenantOptionsEndpoint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getTenantOptionsEndpoint.d.ts","sourceRoot":"","sources":["../../src/endpoints/getTenantOptionsEndpoint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAIvC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAI1D,eAAO,MAAM,wBAAwB,GAAI,UAAU,yHAMhD;IACD,qBAAqB,EAAE,MAAM,CAAA;IAC7B,2BAA2B,EAAE,MAAM,CAAA;IACnC,qBAAqB,EAAE,MAAM,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,yBAAyB,EAAE,QAAQ,CACjC,uBAAuB,CAAC,UAAU,CAAC,CACpC,CAAC,2BAA2B,CAAC,CAAA;CAC/B,KAAG,QAsBF,CAAA"}
@@ -0,0 +1,26 @@
1
+ import { APIError } from 'payload';
2
+ import { getTenantOptions } from '../utilities/getTenantOptions.js';
3
+ export const getTenantOptionsEndpoint = ({ tenantsArrayFieldName, tenantsArrayTenantFieldName, tenantsCollectionSlug, useAsTitle, userHasAccessToAllTenants })=>({
4
+ handler: async (req)=>{
5
+ const { payload, user } = req;
6
+ if (!user) {
7
+ throw new APIError('Unauthorized', 401);
8
+ }
9
+ const tenantOptions = await getTenantOptions({
10
+ payload,
11
+ tenantsArrayFieldName,
12
+ tenantsArrayTenantFieldName,
13
+ tenantsCollectionSlug,
14
+ useAsTitle,
15
+ user,
16
+ userHasAccessToAllTenants
17
+ });
18
+ return new Response(JSON.stringify({
19
+ tenantOptions
20
+ }));
21
+ },
22
+ method: 'get',
23
+ path: '/populate-tenant-options'
24
+ });
25
+
26
+ //# sourceMappingURL=getTenantOptionsEndpoint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/endpoints/getTenantOptionsEndpoint.ts"],"sourcesContent":["import type { Endpoint } from 'payload'\n\nimport { APIError } from 'payload'\n\nimport type { MultiTenantPluginConfig } from '../types.js'\n\nimport { getTenantOptions } from '../utilities/getTenantOptions.js'\n\nexport const getTenantOptionsEndpoint = <ConfigType>({\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n useAsTitle,\n userHasAccessToAllTenants,\n}: {\n tenantsArrayFieldName: string\n tenantsArrayTenantFieldName: string\n tenantsCollectionSlug: string\n useAsTitle: string\n userHasAccessToAllTenants: Required<\n MultiTenantPluginConfig<ConfigType>\n >['userHasAccessToAllTenants']\n}): Endpoint => ({\n handler: async (req) => {\n const { payload, user } = req\n\n if (!user) {\n throw new APIError('Unauthorized', 401)\n }\n\n const tenantOptions = await getTenantOptions({\n payload,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n useAsTitle,\n user,\n userHasAccessToAllTenants,\n })\n\n return new Response(JSON.stringify({ tenantOptions }))\n },\n method: 'get',\n path: '/populate-tenant-options',\n})\n"],"names":["APIError","getTenantOptions","getTenantOptionsEndpoint","tenantsArrayFieldName","tenantsArrayTenantFieldName","tenantsCollectionSlug","useAsTitle","userHasAccessToAllTenants","handler","req","payload","user","tenantOptions","Response","JSON","stringify","method","path"],"mappings":"AAEA,SAASA,QAAQ,QAAQ,UAAS;AAIlC,SAASC,gBAAgB,QAAQ,mCAAkC;AAEnE,OAAO,MAAMC,2BAA2B,CAAa,EACnDC,qBAAqB,EACrBC,2BAA2B,EAC3BC,qBAAqB,EACrBC,UAAU,EACVC,yBAAyB,EAS1B,GAAgB,CAAA;QACfC,SAAS,OAAOC;YACd,MAAM,EAAEC,OAAO,EAAEC,IAAI,EAAE,GAAGF;YAE1B,IAAI,CAACE,MAAM;gBACT,MAAM,IAAIX,SAAS,gBAAgB;YACrC;YAEA,MAAMY,gBAAgB,MAAMX,iBAAiB;gBAC3CS;gBACAP;gBACAC;gBACAC;gBACAC;gBACAK;gBACAJ;YACF;YAEA,OAAO,IAAIM,SAASC,KAAKC,SAAS,CAAC;gBAAEH;YAAc;QACrD;QACAI,QAAQ;QACRC,MAAM;IACR,CAAA,EAAE"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAoB,MAAM,EAAE,MAAM,SAAS,CAAA;AAKvD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAA;AAczD,eAAO,MAAM,iBAAiB,GAC3B,UAAU,gBAAgB,uBAAuB,CAAC,UAAU,CAAC,sBAC7C,MAAM,KAAG,MAwWzB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAoB,MAAM,EAAE,MAAM,SAAS,CAAA;AAKvD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAA;AAezD,eAAO,MAAM,iBAAiB,GAC3B,UAAU,gBAAgB,uBAAuB,CAAC,UAAU,CAAC,sBAC7C,MAAM,KAAG,MAyXzB,CAAA"}
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { deepMergeSimple } from 'payload';
2
2
  import { defaults } from './defaults.js';
3
+ import { getTenantOptionsEndpoint } from './endpoints/getTenantOptionsEndpoint.js';
3
4
  import { tenantField } from './fields/tenantField/index.js';
4
5
  import { tenantsArrayField } from './fields/tenantsArrayField/index.js';
5
6
  import { addTenantCleanup } from './hooks/afterTenantDelete.js';
@@ -198,6 +199,16 @@ export const multiTenantPlugin = (pluginConfig)=>(incomingConfig)=>{
198
199
  }
199
200
  }
200
201
  });
202
+ collection.endpoints = [
203
+ ...collection.endpoints || [],
204
+ getTenantOptionsEndpoint({
205
+ tenantsArrayFieldName,
206
+ tenantsArrayTenantFieldName,
207
+ tenantsCollectionSlug,
208
+ useAsTitle: tenantCollection.admin?.useAsTitle || 'id',
209
+ userHasAccessToAllTenants
210
+ })
211
+ ];
201
212
  } else if (pluginConfig.collections?.[collection.slug]) {
202
213
  const isGlobal = Boolean(pluginConfig.collections[collection.slug]?.isGlobal);
203
214
  if (isGlobal) {
@@ -259,8 +270,11 @@ export const multiTenantPlugin = (pluginConfig)=>(incomingConfig)=>{
259
270
  * Add TenantSelectionProvider to admin providers
260
271
  */ incomingConfig.admin.components.providers.push({
261
272
  clientProps: {
273
+ tenantsArrayFieldName,
274
+ tenantsArrayTenantFieldName,
262
275
  tenantsCollectionSlug: tenantCollection.slug,
263
- useAsTitle: tenantCollection.admin?.useAsTitle || 'id'
276
+ useAsTitle: tenantCollection.admin?.useAsTitle || 'id',
277
+ userHasAccessToAllTenants
264
278
  },
265
279
  path: '@payloadcms/plugin-multi-tenant/rsc#TenantSelectionProvider'
266
280
  });
@@ -273,8 +287,11 @@ export const multiTenantPlugin = (pluginConfig)=>(incomingConfig)=>{
273
287
  basePath,
274
288
  globalSlugs: globalCollectionSlugs,
275
289
  tenantFieldName,
290
+ tenantsArrayFieldName,
291
+ tenantsArrayTenantFieldName,
276
292
  tenantsCollectionSlug,
277
- useAsTitle: tenantCollection.admin?.useAsTitle || 'id'
293
+ useAsTitle: tenantCollection.admin?.useAsTitle || 'id',
294
+ userHasAccessToAllTenants
278
295
  }
279
296
  });
280
297
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { AcceptedLanguages } from '@payloadcms/translations'\nimport type { CollectionConfig, Config } from 'payload'\n\nimport { deepMergeSimple } from 'payload'\n\nimport type { PluginDefaultTranslationsObject } from './translations/types.js'\nimport type { MultiTenantPluginConfig } from './types.js'\n\nimport { defaults } from './defaults.js'\nimport { tenantField } from './fields/tenantField/index.js'\nimport { tenantsArrayField } from './fields/tenantsArrayField/index.js'\nimport { addTenantCleanup } from './hooks/afterTenantDelete.js'\nimport { filterDocumentsBySelectedTenant } from './list-filters/filterDocumentsBySelectedTenant.js'\nimport { filterTenantsBySelectedTenant } from './list-filters/filterTenantsBySelectedTenant.js'\nimport { filterUsersBySelectedTenant } from './list-filters/filterUsersBySelectedTenant.js'\nimport { translations } from './translations/index.js'\nimport { addCollectionAccess } from './utilities/addCollectionAccess.js'\nimport { addFilterOptionsToFields } from './utilities/addFilterOptionsToFields.js'\nimport { combineListFilters } from './utilities/combineListFilters.js'\n\nexport const multiTenantPlugin =\n <ConfigType>(pluginConfig: MultiTenantPluginConfig<ConfigType>) =>\n (incomingConfig: Config): Config => {\n if (pluginConfig.enabled === false) {\n return incomingConfig\n }\n\n /**\n * Set defaults\n */\n const userHasAccessToAllTenants: Required<\n MultiTenantPluginConfig<ConfigType>\n >['userHasAccessToAllTenants'] =\n typeof pluginConfig.userHasAccessToAllTenants === 'function'\n ? pluginConfig.userHasAccessToAllTenants\n : () => false\n const tenantsCollectionSlug = (pluginConfig.tenantsSlug =\n pluginConfig.tenantsSlug || defaults.tenantCollectionSlug)\n const tenantFieldName = pluginConfig?.tenantField?.name || defaults.tenantFieldName\n const tenantsArrayFieldName =\n pluginConfig?.tenantsArrayField?.arrayFieldName || defaults.tenantsArrayFieldName\n const tenantsArrayTenantFieldName =\n pluginConfig?.tenantsArrayField?.arrayTenantFieldName || defaults.tenantsArrayTenantFieldName\n const tenantSelectorLabel = pluginConfig.tenantSelectorLabel || defaults.tenantSelectorLabel\n const basePath = pluginConfig.basePath || defaults.basePath\n\n /**\n * Add defaults for admin properties\n */\n if (!incomingConfig.admin) {\n incomingConfig.admin = {}\n }\n if (!incomingConfig.admin?.components) {\n incomingConfig.admin.components = {\n actions: [],\n beforeNavLinks: [],\n providers: [],\n }\n }\n if (!incomingConfig.admin.components?.providers) {\n incomingConfig.admin.components.providers = []\n }\n if (!incomingConfig.admin.components?.actions) {\n incomingConfig.admin.components.actions = []\n }\n if (!incomingConfig.admin.components?.beforeNavLinks) {\n incomingConfig.admin.components.beforeNavLinks = []\n }\n if (!incomingConfig.collections) {\n incomingConfig.collections = []\n }\n\n /**\n * Add tenant selector localized labels\n */\n if (typeof tenantSelectorLabel === 'object') {\n if (!incomingConfig.i18n) {\n incomingConfig.i18n = {}\n }\n Object.entries(tenantSelectorLabel).forEach(([_locale, label]) => {\n const locale = _locale as AcceptedLanguages\n if (!incomingConfig.i18n) {\n incomingConfig.i18n = {}\n }\n if (!incomingConfig.i18n.translations) {\n incomingConfig.i18n.translations = {}\n }\n if (!(locale in incomingConfig.i18n.translations)) {\n incomingConfig.i18n.translations[locale] = {}\n }\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n if (!('multiTenant' in incomingConfig.i18n.translations[locale])) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n incomingConfig.i18n.translations[locale].multiTenant = {}\n }\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n incomingConfig.i18n.translations[locale].multiTenant.selectorLabel = label\n })\n }\n\n /**\n * Add tenants array field to users collection\n */\n const adminUsersCollection = incomingConfig.collections.find(({ slug, auth }) => {\n if (incomingConfig.admin?.user) {\n return slug === incomingConfig.admin.user\n } else if (auth) {\n return true\n }\n })\n\n if (!adminUsersCollection) {\n throw Error('An auth enabled collection was not found')\n }\n\n /**\n * Add tenants array field to users collection\n */\n if (pluginConfig?.tenantsArrayField?.includeDefaultField !== false) {\n adminUsersCollection.fields.push(\n tenantsArrayField({\n ...(pluginConfig?.tenantsArrayField || {}),\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n }),\n )\n }\n\n addCollectionAccess({\n adminUsersSlug: adminUsersCollection.slug,\n collection: adminUsersCollection,\n fieldName: `${tenantsArrayFieldName}.${tenantsArrayTenantFieldName}`,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n })\n\n if (pluginConfig.useUsersTenantFilter !== false) {\n if (!adminUsersCollection.admin) {\n adminUsersCollection.admin = {}\n }\n\n adminUsersCollection.admin.baseListFilter = combineListFilters({\n baseListFilter: adminUsersCollection.admin?.baseListFilter,\n customFilter: (args) =>\n filterUsersBySelectedTenant({\n req: args.req,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n }),\n })\n }\n\n let tenantCollection: CollectionConfig | undefined\n\n const [collectionSlugs, globalCollectionSlugs] = Object.keys(pluginConfig.collections).reduce<\n [string[], string[]]\n >(\n (acc, slug) => {\n if (pluginConfig?.collections?.[slug]?.isGlobal) {\n acc[1].push(slug)\n } else {\n acc[0].push(slug)\n }\n\n return acc\n },\n [[], []],\n )\n\n /**\n * Modify collections\n */\n incomingConfig.collections.forEach((collection) => {\n /**\n * Modify tenants collection\n */\n if (collection.slug === tenantsCollectionSlug) {\n tenantCollection = collection\n\n if (pluginConfig.useTenantsCollectionAccess !== false) {\n /**\n * Add access control constraint to tenants collection\n * - constrains access a users assigned tenants\n */\n addCollectionAccess({\n adminUsersSlug: adminUsersCollection.slug,\n collection,\n fieldName: 'id',\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n })\n }\n\n if (pluginConfig.useTenantsListFilter !== false) {\n /**\n * Add list filter to tenants collection\n * - filter by selected tenant\n */\n if (!collection.admin) {\n collection.admin = {}\n }\n\n collection.admin.baseListFilter = combineListFilters({\n baseListFilter: collection.admin?.baseListFilter,\n customFilter: (args) =>\n filterTenantsBySelectedTenant({\n req: args.req,\n tenantsCollectionSlug,\n }),\n })\n }\n\n if (pluginConfig.cleanupAfterTenantDelete !== false) {\n /**\n * Add cleanup logic when tenant is deleted\n * - delete documents related to tenant\n * - remove tenant from users\n */\n addTenantCleanup({\n collection,\n enabledSlugs: [...collectionSlugs, ...globalCollectionSlugs],\n tenantFieldName,\n tenantsCollectionSlug,\n usersSlug: adminUsersCollection.slug,\n usersTenantsArrayFieldName: tenantsArrayFieldName,\n usersTenantsArrayTenantFieldName: tenantsArrayTenantFieldName,\n })\n }\n\n /**\n * Add custom tenant field that watches and dispatches updates to the selector\n */\n collection.fields.push({\n name: '_watchTenant',\n type: 'ui',\n admin: {\n components: {\n Field: {\n path: '@payloadcms/plugin-multi-tenant/client#WatchTenantCollection',\n },\n },\n },\n })\n } else if (pluginConfig.collections?.[collection.slug]) {\n const isGlobal = Boolean(pluginConfig.collections[collection.slug]?.isGlobal)\n\n if (isGlobal) {\n collection.disableDuplicate = true\n }\n\n /**\n * Modify enabled collections\n */\n addFilterOptionsToFields({\n config: incomingConfig,\n fields: collection.fields,\n tenantEnabledCollectionSlugs: collectionSlugs,\n tenantEnabledGlobalSlugs: globalCollectionSlugs,\n tenantFieldName,\n tenantsCollectionSlug,\n })\n\n /**\n * Add tenant field to enabled collections\n */\n collection.fields.splice(\n 0,\n 0,\n tenantField({\n ...(pluginConfig?.tenantField || {}),\n name: tenantFieldName,\n debug: pluginConfig.debug,\n tenantsCollectionSlug,\n unique: isGlobal,\n }),\n )\n\n if (pluginConfig.collections[collection.slug]?.useBaseListFilter !== false) {\n /**\n * Add list filter to enabled collections\n * - filters results by selected tenant\n */\n if (!collection.admin) {\n collection.admin = {}\n }\n\n collection.admin.baseListFilter = combineListFilters({\n baseListFilter: collection.admin?.baseListFilter,\n customFilter: (args) =>\n filterDocumentsBySelectedTenant({\n req: args.req,\n tenantFieldName,\n tenantsCollectionSlug,\n }),\n })\n }\n\n if (pluginConfig.collections[collection.slug]?.useTenantAccess !== false) {\n /**\n * Add access control constraint to tenant enabled collection\n */\n addCollectionAccess({\n adminUsersSlug: adminUsersCollection.slug,\n collection,\n fieldName: tenantFieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n })\n }\n }\n })\n\n if (!tenantCollection) {\n throw new Error(`Tenants collection not found with slug: ${tenantsCollectionSlug}`)\n }\n\n /**\n * Add TenantSelectionProvider to admin providers\n */\n incomingConfig.admin.components.providers.push({\n clientProps: {\n tenantsCollectionSlug: tenantCollection.slug,\n useAsTitle: tenantCollection.admin?.useAsTitle || 'id',\n },\n path: '@payloadcms/plugin-multi-tenant/rsc#TenantSelectionProvider',\n })\n\n /**\n * Add global redirect action\n */\n if (globalCollectionSlugs.length) {\n incomingConfig.admin.components.actions.push({\n path: '@payloadcms/plugin-multi-tenant/rsc#GlobalViewRedirect',\n serverProps: {\n basePath,\n globalSlugs: globalCollectionSlugs,\n tenantFieldName,\n tenantsCollectionSlug,\n useAsTitle: tenantCollection.admin?.useAsTitle || 'id',\n },\n })\n }\n\n /**\n * Add tenant selector to admin UI\n */\n incomingConfig.admin.components.beforeNavLinks.push({\n clientProps: {\n label: tenantSelectorLabel,\n },\n path: '@payloadcms/plugin-multi-tenant/client#TenantSelector',\n })\n\n /**\n * Merge plugin translations\n */\n\n const simplifiedTranslations = Object.entries(translations).reduce(\n (acc, [key, value]) => {\n acc[key] = value.translations\n return acc\n },\n {} as Record<string, PluginDefaultTranslationsObject>,\n )\n\n incomingConfig.i18n = {\n ...incomingConfig.i18n,\n translations: deepMergeSimple(\n simplifiedTranslations,\n incomingConfig.i18n?.translations ?? {},\n ),\n }\n\n return incomingConfig\n }\n"],"names":["deepMergeSimple","defaults","tenantField","tenantsArrayField","addTenantCleanup","filterDocumentsBySelectedTenant","filterTenantsBySelectedTenant","filterUsersBySelectedTenant","translations","addCollectionAccess","addFilterOptionsToFields","combineListFilters","multiTenantPlugin","pluginConfig","incomingConfig","enabled","userHasAccessToAllTenants","tenantsCollectionSlug","tenantsSlug","tenantCollectionSlug","tenantFieldName","name","tenantsArrayFieldName","arrayFieldName","tenantsArrayTenantFieldName","arrayTenantFieldName","tenantSelectorLabel","basePath","admin","components","actions","beforeNavLinks","providers","collections","i18n","Object","entries","forEach","_locale","label","locale","multiTenant","selectorLabel","adminUsersCollection","find","slug","auth","user","Error","includeDefaultField","fields","push","adminUsersSlug","collection","fieldName","useUsersTenantFilter","baseListFilter","customFilter","args","req","tenantCollection","collectionSlugs","globalCollectionSlugs","keys","reduce","acc","isGlobal","useTenantsCollectionAccess","useTenantsListFilter","cleanupAfterTenantDelete","enabledSlugs","usersSlug","usersTenantsArrayFieldName","usersTenantsArrayTenantFieldName","type","Field","path","Boolean","disableDuplicate","config","tenantEnabledCollectionSlugs","tenantEnabledGlobalSlugs","splice","debug","unique","useBaseListFilter","useTenantAccess","clientProps","useAsTitle","length","serverProps","globalSlugs","simplifiedTranslations","key","value"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { AcceptedLanguages } from '@payloadcms/translations'\nimport type { CollectionConfig, Config } from 'payload'\n\nimport { deepMergeSimple } from 'payload'\n\nimport type { PluginDefaultTranslationsObject } from './translations/types.js'\nimport type { MultiTenantPluginConfig } from './types.js'\n\nimport { defaults } from './defaults.js'\nimport { getTenantOptionsEndpoint } from './endpoints/getTenantOptionsEndpoint.js'\nimport { tenantField } from './fields/tenantField/index.js'\nimport { tenantsArrayField } from './fields/tenantsArrayField/index.js'\nimport { addTenantCleanup } from './hooks/afterTenantDelete.js'\nimport { filterDocumentsBySelectedTenant } from './list-filters/filterDocumentsBySelectedTenant.js'\nimport { filterTenantsBySelectedTenant } from './list-filters/filterTenantsBySelectedTenant.js'\nimport { filterUsersBySelectedTenant } from './list-filters/filterUsersBySelectedTenant.js'\nimport { translations } from './translations/index.js'\nimport { addCollectionAccess } from './utilities/addCollectionAccess.js'\nimport { addFilterOptionsToFields } from './utilities/addFilterOptionsToFields.js'\nimport { combineListFilters } from './utilities/combineListFilters.js'\n\nexport const multiTenantPlugin =\n <ConfigType>(pluginConfig: MultiTenantPluginConfig<ConfigType>) =>\n (incomingConfig: Config): Config => {\n if (pluginConfig.enabled === false) {\n return incomingConfig\n }\n\n /**\n * Set defaults\n */\n const userHasAccessToAllTenants: Required<\n MultiTenantPluginConfig<ConfigType>\n >['userHasAccessToAllTenants'] =\n typeof pluginConfig.userHasAccessToAllTenants === 'function'\n ? pluginConfig.userHasAccessToAllTenants\n : () => false\n const tenantsCollectionSlug = (pluginConfig.tenantsSlug =\n pluginConfig.tenantsSlug || defaults.tenantCollectionSlug)\n const tenantFieldName = pluginConfig?.tenantField?.name || defaults.tenantFieldName\n const tenantsArrayFieldName =\n pluginConfig?.tenantsArrayField?.arrayFieldName || defaults.tenantsArrayFieldName\n const tenantsArrayTenantFieldName =\n pluginConfig?.tenantsArrayField?.arrayTenantFieldName || defaults.tenantsArrayTenantFieldName\n const tenantSelectorLabel = pluginConfig.tenantSelectorLabel || defaults.tenantSelectorLabel\n const basePath = pluginConfig.basePath || defaults.basePath\n\n /**\n * Add defaults for admin properties\n */\n if (!incomingConfig.admin) {\n incomingConfig.admin = {}\n }\n if (!incomingConfig.admin?.components) {\n incomingConfig.admin.components = {\n actions: [],\n beforeNavLinks: [],\n providers: [],\n }\n }\n if (!incomingConfig.admin.components?.providers) {\n incomingConfig.admin.components.providers = []\n }\n if (!incomingConfig.admin.components?.actions) {\n incomingConfig.admin.components.actions = []\n }\n if (!incomingConfig.admin.components?.beforeNavLinks) {\n incomingConfig.admin.components.beforeNavLinks = []\n }\n if (!incomingConfig.collections) {\n incomingConfig.collections = []\n }\n\n /**\n * Add tenant selector localized labels\n */\n if (typeof tenantSelectorLabel === 'object') {\n if (!incomingConfig.i18n) {\n incomingConfig.i18n = {}\n }\n Object.entries(tenantSelectorLabel).forEach(([_locale, label]) => {\n const locale = _locale as AcceptedLanguages\n if (!incomingConfig.i18n) {\n incomingConfig.i18n = {}\n }\n if (!incomingConfig.i18n.translations) {\n incomingConfig.i18n.translations = {}\n }\n if (!(locale in incomingConfig.i18n.translations)) {\n incomingConfig.i18n.translations[locale] = {}\n }\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n if (!('multiTenant' in incomingConfig.i18n.translations[locale])) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n incomingConfig.i18n.translations[locale].multiTenant = {}\n }\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n incomingConfig.i18n.translations[locale].multiTenant.selectorLabel = label\n })\n }\n\n /**\n * Add tenants array field to users collection\n */\n const adminUsersCollection = incomingConfig.collections.find(({ slug, auth }) => {\n if (incomingConfig.admin?.user) {\n return slug === incomingConfig.admin.user\n } else if (auth) {\n return true\n }\n })\n\n if (!adminUsersCollection) {\n throw Error('An auth enabled collection was not found')\n }\n\n /**\n * Add tenants array field to users collection\n */\n if (pluginConfig?.tenantsArrayField?.includeDefaultField !== false) {\n adminUsersCollection.fields.push(\n tenantsArrayField({\n ...(pluginConfig?.tenantsArrayField || {}),\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n }),\n )\n }\n\n addCollectionAccess({\n adminUsersSlug: adminUsersCollection.slug,\n collection: adminUsersCollection,\n fieldName: `${tenantsArrayFieldName}.${tenantsArrayTenantFieldName}`,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n })\n\n if (pluginConfig.useUsersTenantFilter !== false) {\n if (!adminUsersCollection.admin) {\n adminUsersCollection.admin = {}\n }\n\n adminUsersCollection.admin.baseListFilter = combineListFilters({\n baseListFilter: adminUsersCollection.admin?.baseListFilter,\n customFilter: (args) =>\n filterUsersBySelectedTenant({\n req: args.req,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n }),\n })\n }\n\n let tenantCollection: CollectionConfig | undefined\n\n const [collectionSlugs, globalCollectionSlugs] = Object.keys(pluginConfig.collections).reduce<\n [string[], string[]]\n >(\n (acc, slug) => {\n if (pluginConfig?.collections?.[slug]?.isGlobal) {\n acc[1].push(slug)\n } else {\n acc[0].push(slug)\n }\n\n return acc\n },\n [[], []],\n )\n\n /**\n * Modify collections\n */\n incomingConfig.collections.forEach((collection) => {\n /**\n * Modify tenants collection\n */\n if (collection.slug === tenantsCollectionSlug) {\n tenantCollection = collection\n\n if (pluginConfig.useTenantsCollectionAccess !== false) {\n /**\n * Add access control constraint to tenants collection\n * - constrains access a users assigned tenants\n */\n addCollectionAccess({\n adminUsersSlug: adminUsersCollection.slug,\n collection,\n fieldName: 'id',\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n })\n }\n\n if (pluginConfig.useTenantsListFilter !== false) {\n /**\n * Add list filter to tenants collection\n * - filter by selected tenant\n */\n if (!collection.admin) {\n collection.admin = {}\n }\n\n collection.admin.baseListFilter = combineListFilters({\n baseListFilter: collection.admin?.baseListFilter,\n customFilter: (args) =>\n filterTenantsBySelectedTenant({\n req: args.req,\n tenantsCollectionSlug,\n }),\n })\n }\n\n if (pluginConfig.cleanupAfterTenantDelete !== false) {\n /**\n * Add cleanup logic when tenant is deleted\n * - delete documents related to tenant\n * - remove tenant from users\n */\n addTenantCleanup({\n collection,\n enabledSlugs: [...collectionSlugs, ...globalCollectionSlugs],\n tenantFieldName,\n tenantsCollectionSlug,\n usersSlug: adminUsersCollection.slug,\n usersTenantsArrayFieldName: tenantsArrayFieldName,\n usersTenantsArrayTenantFieldName: tenantsArrayTenantFieldName,\n })\n }\n\n /**\n * Add custom tenant field that watches and dispatches updates to the selector\n */\n collection.fields.push({\n name: '_watchTenant',\n type: 'ui',\n admin: {\n components: {\n Field: {\n path: '@payloadcms/plugin-multi-tenant/client#WatchTenantCollection',\n },\n },\n },\n })\n\n collection.endpoints = [\n ...(collection.endpoints || []),\n getTenantOptionsEndpoint<ConfigType>({\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n useAsTitle: tenantCollection.admin?.useAsTitle || 'id',\n userHasAccessToAllTenants,\n }),\n ]\n } else if (pluginConfig.collections?.[collection.slug]) {\n const isGlobal = Boolean(pluginConfig.collections[collection.slug]?.isGlobal)\n\n if (isGlobal) {\n collection.disableDuplicate = true\n }\n\n /**\n * Modify enabled collections\n */\n addFilterOptionsToFields({\n config: incomingConfig,\n fields: collection.fields,\n tenantEnabledCollectionSlugs: collectionSlugs,\n tenantEnabledGlobalSlugs: globalCollectionSlugs,\n tenantFieldName,\n tenantsCollectionSlug,\n })\n\n /**\n * Add tenant field to enabled collections\n */\n collection.fields.splice(\n 0,\n 0,\n tenantField({\n ...(pluginConfig?.tenantField || {}),\n name: tenantFieldName,\n debug: pluginConfig.debug,\n tenantsCollectionSlug,\n unique: isGlobal,\n }),\n )\n\n if (pluginConfig.collections[collection.slug]?.useBaseListFilter !== false) {\n /**\n * Add list filter to enabled collections\n * - filters results by selected tenant\n */\n if (!collection.admin) {\n collection.admin = {}\n }\n\n collection.admin.baseListFilter = combineListFilters({\n baseListFilter: collection.admin?.baseListFilter,\n customFilter: (args) =>\n filterDocumentsBySelectedTenant({\n req: args.req,\n tenantFieldName,\n tenantsCollectionSlug,\n }),\n })\n }\n\n if (pluginConfig.collections[collection.slug]?.useTenantAccess !== false) {\n /**\n * Add access control constraint to tenant enabled collection\n */\n addCollectionAccess({\n adminUsersSlug: adminUsersCollection.slug,\n collection,\n fieldName: tenantFieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n })\n }\n }\n })\n\n if (!tenantCollection) {\n throw new Error(`Tenants collection not found with slug: ${tenantsCollectionSlug}`)\n }\n\n /**\n * Add TenantSelectionProvider to admin providers\n */\n incomingConfig.admin.components.providers.push({\n clientProps: {\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug: tenantCollection.slug,\n useAsTitle: tenantCollection.admin?.useAsTitle || 'id',\n userHasAccessToAllTenants,\n },\n path: '@payloadcms/plugin-multi-tenant/rsc#TenantSelectionProvider',\n })\n\n /**\n * Add global redirect action\n */\n if (globalCollectionSlugs.length) {\n incomingConfig.admin.components.actions.push({\n path: '@payloadcms/plugin-multi-tenant/rsc#GlobalViewRedirect',\n serverProps: {\n basePath,\n globalSlugs: globalCollectionSlugs,\n tenantFieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n useAsTitle: tenantCollection.admin?.useAsTitle || 'id',\n userHasAccessToAllTenants,\n },\n })\n }\n\n /**\n * Add tenant selector to admin UI\n */\n incomingConfig.admin.components.beforeNavLinks.push({\n clientProps: {\n label: tenantSelectorLabel,\n },\n path: '@payloadcms/plugin-multi-tenant/client#TenantSelector',\n })\n\n /**\n * Merge plugin translations\n */\n\n const simplifiedTranslations = Object.entries(translations).reduce(\n (acc, [key, value]) => {\n acc[key] = value.translations\n return acc\n },\n {} as Record<string, PluginDefaultTranslationsObject>,\n )\n\n incomingConfig.i18n = {\n ...incomingConfig.i18n,\n translations: deepMergeSimple(\n simplifiedTranslations,\n incomingConfig.i18n?.translations ?? {},\n ),\n }\n\n return incomingConfig\n }\n"],"names":["deepMergeSimple","defaults","getTenantOptionsEndpoint","tenantField","tenantsArrayField","addTenantCleanup","filterDocumentsBySelectedTenant","filterTenantsBySelectedTenant","filterUsersBySelectedTenant","translations","addCollectionAccess","addFilterOptionsToFields","combineListFilters","multiTenantPlugin","pluginConfig","incomingConfig","enabled","userHasAccessToAllTenants","tenantsCollectionSlug","tenantsSlug","tenantCollectionSlug","tenantFieldName","name","tenantsArrayFieldName","arrayFieldName","tenantsArrayTenantFieldName","arrayTenantFieldName","tenantSelectorLabel","basePath","admin","components","actions","beforeNavLinks","providers","collections","i18n","Object","entries","forEach","_locale","label","locale","multiTenant","selectorLabel","adminUsersCollection","find","slug","auth","user","Error","includeDefaultField","fields","push","adminUsersSlug","collection","fieldName","useUsersTenantFilter","baseListFilter","customFilter","args","req","tenantCollection","collectionSlugs","globalCollectionSlugs","keys","reduce","acc","isGlobal","useTenantsCollectionAccess","useTenantsListFilter","cleanupAfterTenantDelete","enabledSlugs","usersSlug","usersTenantsArrayFieldName","usersTenantsArrayTenantFieldName","type","Field","path","endpoints","useAsTitle","Boolean","disableDuplicate","config","tenantEnabledCollectionSlugs","tenantEnabledGlobalSlugs","splice","debug","unique","useBaseListFilter","useTenantAccess","clientProps","length","serverProps","globalSlugs","simplifiedTranslations","key","value"],"mappings":"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"}
@@ -51,13 +51,11 @@ type ContextType = {
51
51
  label: string;
52
52
  }) => void;
53
53
  };
54
- export declare const TenantSelectionProviderClient: ({ children, initialValue, tenantCookie, tenantOptions: tenantOptionsFromProps, tenantsCollectionSlug, useAsTitle, }: {
54
+ export declare const TenantSelectionProviderClient: ({ children, initialTenantOptions, initialValue, tenantsCollectionSlug, }: {
55
55
  children: React.ReactNode;
56
+ initialTenantOptions: OptionObject[];
56
57
  initialValue?: number | string;
57
- tenantCookie?: string;
58
- tenantOptions: OptionObject[];
59
58
  tenantsCollectionSlug: string;
60
- useAsTitle: string;
61
59
  }) => React.JSX.Element;
62
60
  export declare const useTenantSelection: () => ContextType;
63
61
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"index.client.d.ts","sourceRoot":"","sources":["../../../src/providers/TenantSelectionProvider/index.client.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAI3C,OAAO,KAAwB,MAAM,OAAO,CAAA;AAE5C,KAAK,WAAW,GAAG;IACjB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAA;IAClC;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;OAEG;IACH,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB;;OAEG;IACH,gBAAgB,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;IAC7C;;OAEG;IACH,aAAa,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAA;IACtF;;OAEG;IACH,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAA;IAC1D;;;;;OAKG;IACH,SAAS,EAAE,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAA;IACjF;;OAEG;IACH,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAChC;;OAEG;IACH,aAAa,EAAE,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAA;CACtE,CAAA;AAaD,eAAO,MAAM,6BAA6B,wHAOvC;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,EAAE,YAAY,EAAE,CAAA;IAC7B,qBAAqB,EAAE,MAAM,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;CACnB,sBAsJA,CAAA;AAED,eAAO,MAAM,kBAAkB,mBAA2B,CAAA"}
1
+ {"version":3,"file":"index.client.d.ts","sourceRoot":"","sources":["../../../src/providers/TenantSelectionProvider/index.client.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAI3C,OAAO,KAAwB,MAAM,OAAO,CAAA;AAE5C,KAAK,WAAW,GAAG;IACjB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAA;IAClC;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;OAEG;IACH,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB;;OAEG;IACH,gBAAgB,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;IAC7C;;OAEG;IACH,aAAa,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAA;IACtF;;OAEG;IACH,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAA;IAC1D;;;;;OAKG;IACH,SAAS,EAAE,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAA;IACjF;;OAEG;IACH,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAChC;;OAEG;IACH,aAAa,EAAE,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAA;CACtE,CAAA;AAaD,eAAO,MAAM,6BAA6B,6EAKvC;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,oBAAoB,EAAE,YAAY,EAAE,CAAA;IACpC,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAC9B,qBAAqB,EAAE,MAAM,CAAA;CAC9B,sBAiJA,CAAA;AAED,eAAO,MAAM,kBAAkB,mBAA2B,CAAA"}
@@ -13,7 +13,7 @@ const Context = /*#__PURE__*/ createContext({
13
13
  syncTenants: ()=>Promise.resolve(),
14
14
  updateTenants: ()=>null
15
15
  });
16
- export const TenantSelectionProviderClient = ({ children, initialValue, tenantCookie, tenantOptions: tenantOptionsFromProps, tenantsCollectionSlug, useAsTitle })=>{
16
+ export const TenantSelectionProviderClient = ({ children, initialTenantOptions, initialValue, tenantsCollectionSlug })=>{
17
17
  const [selectedTenantID, setSelectedTenantID] = React.useState(initialValue);
18
18
  const [modified, setModified] = React.useState(false);
19
19
  const [entityType, setEntityType] = React.useState(undefined);
@@ -24,7 +24,7 @@ export const TenantSelectionProviderClient = ({ children, initialValue, tenantCo
24
24
  ]);
25
25
  const prevUserID = React.useRef(userID);
26
26
  const userChanged = userID !== prevUserID.current;
27
- const [tenantOptions, setTenantOptions] = React.useState(()=>tenantOptionsFromProps);
27
+ const [tenantOptions, setTenantOptions] = React.useState(()=>initialTenantOptions);
28
28
  const selectedTenantLabel = React.useMemo(()=>tenantOptions.find((option)=>option.value === selectedTenantID)?.label, [
29
29
  selectedTenantID,
30
30
  tenantOptions
@@ -79,19 +79,16 @@ export const TenantSelectionProviderClient = ({ children, initialValue, tenantCo
79
79
  ]);
80
80
  const syncTenants = React.useCallback(async ()=>{
81
81
  try {
82
- const req = await fetch(`${config.serverURL}${config.routes.api}/${tenantsCollectionSlug}?select[${useAsTitle}]=true&limit=0&depth=0`, {
82
+ const req = await fetch(`${config.serverURL}${config.routes.api}/${tenantsCollectionSlug}/populate-tenant-options`, {
83
83
  credentials: 'include',
84
84
  method: 'GET'
85
85
  });
86
86
  const result = await req.json();
87
- if (result.docs && userID) {
88
- setTenantOptions(result.docs.map((doc)=>({
89
- label: doc[useAsTitle],
90
- value: doc.id
91
- })));
92
- if (result.totalDocs === 1) {
93
- setSelectedTenantID(result.docs[0].id);
94
- setCookie(String(result.docs[0].id));
87
+ if (result.tenantOptions && userID) {
88
+ setTenantOptions(result.tenantOptions);
89
+ if (result.tenantOptions.length === 1) {
90
+ setSelectedTenantID(result.tenantOptions[0].value);
91
+ setCookie(String(result.tenantOptions[0].value));
95
92
  }
96
93
  }
97
94
  } catch (e) {
@@ -101,7 +98,6 @@ export const TenantSelectionProviderClient = ({ children, initialValue, tenantCo
101
98
  config.serverURL,
102
99
  config.routes.api,
103
100
  tenantsCollectionSlug,
104
- useAsTitle,
105
101
  setCookie,
106
102
  userID
107
103
  ]);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/providers/TenantSelectionProvider/index.client.tsx"],"sourcesContent":["'use client'\n\nimport type { OptionObject } from 'payload'\n\nimport { toast, useAuth, useConfig } from '@payloadcms/ui'\nimport { useRouter } from 'next/navigation.js'\nimport React, { createContext } from 'react'\n\ntype ContextType = {\n /**\n * What is the context of the selector? It is either 'document' | 'global' | undefined.\n *\n * - 'document' means you are viewing a document in the context of a tenant\n * - 'global' means you are viewing a \"global\" (globals are collection documents but prevent you from viewing the list view) document in the context of a tenant\n * - undefined means you are not viewing a document at all\n */\n entityType?: 'document' | 'global'\n /**\n * Hoists the forms modified state\n */\n modified?: boolean\n /**\n * Array of options to select from\n */\n options: OptionObject[]\n /**\n * The currently selected tenant ID\n */\n selectedTenantID: number | string | undefined\n /**\n * Sets the entityType when a document is loaded and sets it to undefined when the document unmounts.\n */\n setEntityType: React.Dispatch<React.SetStateAction<'document' | 'global' | undefined>>\n /**\n * Sets the modified state\n */\n setModified: React.Dispatch<React.SetStateAction<boolean>>\n /**\n * Sets the selected tenant ID\n *\n * @param args.id - The ID of the tenant to select\n * @param args.refresh - Whether to refresh the page after changing the tenant\n */\n setTenant: (args: { id: number | string | undefined; refresh?: boolean }) => void\n /**\n * Used to sync tenants displayed in the tenant selector when updates are made to the tenants collection.\n */\n syncTenants: () => Promise<void>\n /**\n *\n */\n updateTenants: (args: { id: number | string; label: string }) => void\n}\n\nconst Context = createContext<ContextType>({\n entityType: undefined,\n options: [],\n selectedTenantID: undefined,\n setEntityType: () => undefined,\n setModified: () => undefined,\n setTenant: () => null,\n syncTenants: () => Promise.resolve(),\n updateTenants: () => null,\n})\n\nexport const TenantSelectionProviderClient = ({\n children,\n initialValue,\n tenantCookie,\n tenantOptions: tenantOptionsFromProps,\n tenantsCollectionSlug,\n useAsTitle,\n}: {\n children: React.ReactNode\n initialValue?: number | string\n tenantCookie?: string\n tenantOptions: OptionObject[]\n tenantsCollectionSlug: string\n useAsTitle: string\n}) => {\n const [selectedTenantID, setSelectedTenantID] = React.useState<number | string | undefined>(\n initialValue,\n )\n const [modified, setModified] = React.useState<boolean>(false)\n const [entityType, setEntityType] = React.useState<'document' | 'global' | undefined>(undefined)\n const { user } = useAuth()\n const { config } = useConfig()\n const userID = React.useMemo(() => user?.id, [user?.id])\n const prevUserID = React.useRef(userID)\n const userChanged = userID !== prevUserID.current\n const [tenantOptions, setTenantOptions] = React.useState<OptionObject[]>(\n () => tenantOptionsFromProps,\n )\n const selectedTenantLabel = React.useMemo(\n () => tenantOptions.find((option) => option.value === selectedTenantID)?.label,\n [selectedTenantID, tenantOptions],\n )\n\n const router = useRouter()\n\n const setCookie = React.useCallback((value?: string) => {\n const expires = '; expires=Fri, 31 Dec 9999 23:59:59 GMT'\n document.cookie = 'payload-tenant=' + (value || '') + expires + '; path=/'\n }, [])\n\n const deleteCookie = React.useCallback(() => {\n // eslint-disable-next-line react-compiler/react-compiler -- TODO: fix\n document.cookie = 'payload-tenant=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/'\n }, [])\n\n const setTenant = React.useCallback<ContextType['setTenant']>(\n ({ id, refresh }) => {\n if (id === undefined) {\n if (tenantOptions.length > 1) {\n // users with multiple tenants can clear the tenant selection\n setSelectedTenantID(undefined)\n deleteCookie()\n } else if (tenantOptions[0]) {\n // if there is only one tenant, force the selection of that tenant\n setSelectedTenantID(tenantOptions[0].value)\n setCookie(String(tenantOptions[0].value))\n }\n } else if (!tenantOptions.find((option) => option.value === id)) {\n // if the tenant is not valid, set the first tenant as selected\n if (tenantOptions[0]?.value) {\n setTenant({ id: tenantOptions[0]?.value, refresh: true })\n } else {\n setTenant({ id: undefined, refresh: true })\n }\n } else {\n // if the tenant is in the options, set it as selected\n setSelectedTenantID(id)\n setCookie(String(id))\n }\n if (entityType !== 'document' && refresh) {\n router.refresh()\n }\n },\n [deleteCookie, entityType, router, setCookie, tenantOptions],\n )\n\n const syncTenants = React.useCallback(async () => {\n try {\n const req = await fetch(\n `${config.serverURL}${config.routes.api}/${tenantsCollectionSlug}?select[${useAsTitle}]=true&limit=0&depth=0`,\n {\n credentials: 'include',\n method: 'GET',\n },\n )\n\n const result = await req.json()\n\n if (result.docs && userID) {\n setTenantOptions(\n result.docs.map((doc: Record<string, number | string>) => ({\n label: doc[useAsTitle],\n value: doc.id,\n })),\n )\n\n if (result.totalDocs === 1) {\n setSelectedTenantID(result.docs[0].id)\n setCookie(String(result.docs[0].id))\n }\n }\n } catch (e) {\n toast.error(`Error fetching tenants`)\n }\n }, [config.serverURL, config.routes.api, tenantsCollectionSlug, useAsTitle, setCookie, userID])\n\n const updateTenants = React.useCallback<ContextType['updateTenants']>(\n ({ id, label }) => {\n setTenantOptions((prev) => {\n return prev.map((currentTenant) => {\n if (id === currentTenant.value) {\n return {\n label,\n value: id,\n }\n }\n return currentTenant\n })\n })\n\n void syncTenants()\n },\n [syncTenants],\n )\n\n React.useEffect(() => {\n if (userChanged) {\n if (userID) {\n // user logging in\n void syncTenants()\n } else {\n // user logging out\n setSelectedTenantID(undefined)\n deleteCookie()\n if (tenantOptions.length > 0) {\n setTenantOptions([])\n }\n }\n prevUserID.current = userID\n }\n }, [userID, userChanged, syncTenants, deleteCookie, tenantOptions])\n\n return (\n <span\n data-selected-tenant-id={selectedTenantID}\n data-selected-tenant-title={selectedTenantLabel}\n >\n <Context\n value={{\n entityType,\n modified,\n options: tenantOptions,\n selectedTenantID,\n setEntityType,\n setModified,\n setTenant,\n syncTenants,\n updateTenants,\n }}\n >\n {children}\n </Context>\n </span>\n )\n}\n\nexport const useTenantSelection = () => React.use(Context)\n"],"names":["toast","useAuth","useConfig","useRouter","React","createContext","Context","entityType","undefined","options","selectedTenantID","setEntityType","setModified","setTenant","syncTenants","Promise","resolve","updateTenants","TenantSelectionProviderClient","children","initialValue","tenantCookie","tenantOptions","tenantOptionsFromProps","tenantsCollectionSlug","useAsTitle","setSelectedTenantID","useState","modified","user","config","userID","useMemo","id","prevUserID","useRef","userChanged","current","setTenantOptions","selectedTenantLabel","find","option","value","label","router","setCookie","useCallback","expires","document","cookie","deleteCookie","refresh","length","String","req","fetch","serverURL","routes","api","credentials","method","result","json","docs","map","doc","totalDocs","e","error","prev","currentTenant","useEffect","span","data-selected-tenant-id","data-selected-tenant-title","useTenantSelection","use"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/providers/TenantSelectionProvider/index.client.tsx"],"sourcesContent":["'use client'\n\nimport type { OptionObject } from 'payload'\n\nimport { toast, useAuth, useConfig } from '@payloadcms/ui'\nimport { useRouter } from 'next/navigation.js'\nimport React, { createContext } from 'react'\n\ntype ContextType = {\n /**\n * What is the context of the selector? It is either 'document' | 'global' | undefined.\n *\n * - 'document' means you are viewing a document in the context of a tenant\n * - 'global' means you are viewing a \"global\" (globals are collection documents but prevent you from viewing the list view) document in the context of a tenant\n * - undefined means you are not viewing a document at all\n */\n entityType?: 'document' | 'global'\n /**\n * Hoists the forms modified state\n */\n modified?: boolean\n /**\n * Array of options to select from\n */\n options: OptionObject[]\n /**\n * The currently selected tenant ID\n */\n selectedTenantID: number | string | undefined\n /**\n * Sets the entityType when a document is loaded and sets it to undefined when the document unmounts.\n */\n setEntityType: React.Dispatch<React.SetStateAction<'document' | 'global' | undefined>>\n /**\n * Sets the modified state\n */\n setModified: React.Dispatch<React.SetStateAction<boolean>>\n /**\n * Sets the selected tenant ID\n *\n * @param args.id - The ID of the tenant to select\n * @param args.refresh - Whether to refresh the page after changing the tenant\n */\n setTenant: (args: { id: number | string | undefined; refresh?: boolean }) => void\n /**\n * Used to sync tenants displayed in the tenant selector when updates are made to the tenants collection.\n */\n syncTenants: () => Promise<void>\n /**\n *\n */\n updateTenants: (args: { id: number | string; label: string }) => void\n}\n\nconst Context = createContext<ContextType>({\n entityType: undefined,\n options: [],\n selectedTenantID: undefined,\n setEntityType: () => undefined,\n setModified: () => undefined,\n setTenant: () => null,\n syncTenants: () => Promise.resolve(),\n updateTenants: () => null,\n})\n\nexport const TenantSelectionProviderClient = ({\n children,\n initialTenantOptions,\n initialValue,\n tenantsCollectionSlug,\n}: {\n children: React.ReactNode\n initialTenantOptions: OptionObject[]\n initialValue?: number | string\n tenantsCollectionSlug: string\n}) => {\n const [selectedTenantID, setSelectedTenantID] = React.useState<number | string | undefined>(\n initialValue,\n )\n const [modified, setModified] = React.useState<boolean>(false)\n const [entityType, setEntityType] = React.useState<'document' | 'global' | undefined>(undefined)\n const { user } = useAuth()\n const { config } = useConfig()\n const userID = React.useMemo(() => user?.id, [user?.id])\n const prevUserID = React.useRef(userID)\n const userChanged = userID !== prevUserID.current\n const [tenantOptions, setTenantOptions] = React.useState<OptionObject[]>(\n () => initialTenantOptions,\n )\n const selectedTenantLabel = React.useMemo(\n () => tenantOptions.find((option) => option.value === selectedTenantID)?.label,\n [selectedTenantID, tenantOptions],\n )\n\n const router = useRouter()\n\n const setCookie = React.useCallback((value?: string) => {\n const expires = '; expires=Fri, 31 Dec 9999 23:59:59 GMT'\n document.cookie = 'payload-tenant=' + (value || '') + expires + '; path=/'\n }, [])\n\n const deleteCookie = React.useCallback(() => {\n // eslint-disable-next-line react-compiler/react-compiler -- TODO: fix\n document.cookie = 'payload-tenant=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/'\n }, [])\n\n const setTenant = React.useCallback<ContextType['setTenant']>(\n ({ id, refresh }) => {\n if (id === undefined) {\n if (tenantOptions.length > 1) {\n // users with multiple tenants can clear the tenant selection\n setSelectedTenantID(undefined)\n deleteCookie()\n } else if (tenantOptions[0]) {\n // if there is only one tenant, force the selection of that tenant\n setSelectedTenantID(tenantOptions[0].value)\n setCookie(String(tenantOptions[0].value))\n }\n } else if (!tenantOptions.find((option) => option.value === id)) {\n // if the tenant is not valid, set the first tenant as selected\n if (tenantOptions[0]?.value) {\n setTenant({ id: tenantOptions[0]?.value, refresh: true })\n } else {\n setTenant({ id: undefined, refresh: true })\n }\n } else {\n // if the tenant is in the options, set it as selected\n setSelectedTenantID(id)\n setCookie(String(id))\n }\n if (entityType !== 'document' && refresh) {\n router.refresh()\n }\n },\n [deleteCookie, entityType, router, setCookie, tenantOptions],\n )\n\n const syncTenants = React.useCallback(async () => {\n try {\n const req = await fetch(\n `${config.serverURL}${config.routes.api}/${tenantsCollectionSlug}/populate-tenant-options`,\n {\n credentials: 'include',\n method: 'GET',\n },\n )\n\n const result = await req.json()\n\n if (result.tenantOptions && userID) {\n setTenantOptions(result.tenantOptions)\n\n if (result.tenantOptions.length === 1) {\n setSelectedTenantID(result.tenantOptions[0].value)\n setCookie(String(result.tenantOptions[0].value))\n }\n }\n } catch (e) {\n toast.error(`Error fetching tenants`)\n }\n }, [config.serverURL, config.routes.api, tenantsCollectionSlug, setCookie, userID])\n\n const updateTenants = React.useCallback<ContextType['updateTenants']>(\n ({ id, label }) => {\n setTenantOptions((prev) => {\n return prev.map((currentTenant) => {\n if (id === currentTenant.value) {\n return {\n label,\n value: id,\n }\n }\n return currentTenant\n })\n })\n\n void syncTenants()\n },\n [syncTenants],\n )\n\n React.useEffect(() => {\n if (userChanged) {\n if (userID) {\n // user logging in\n void syncTenants()\n } else {\n // user logging out\n setSelectedTenantID(undefined)\n deleteCookie()\n if (tenantOptions.length > 0) {\n setTenantOptions([])\n }\n }\n prevUserID.current = userID\n }\n }, [userID, userChanged, syncTenants, deleteCookie, tenantOptions])\n\n return (\n <span\n data-selected-tenant-id={selectedTenantID}\n data-selected-tenant-title={selectedTenantLabel}\n >\n <Context\n value={{\n entityType,\n modified,\n options: tenantOptions,\n selectedTenantID,\n setEntityType,\n setModified,\n setTenant,\n syncTenants,\n updateTenants,\n }}\n >\n {children}\n </Context>\n </span>\n )\n}\n\nexport const useTenantSelection = () => React.use(Context)\n"],"names":["toast","useAuth","useConfig","useRouter","React","createContext","Context","entityType","undefined","options","selectedTenantID","setEntityType","setModified","setTenant","syncTenants","Promise","resolve","updateTenants","TenantSelectionProviderClient","children","initialTenantOptions","initialValue","tenantsCollectionSlug","setSelectedTenantID","useState","modified","user","config","userID","useMemo","id","prevUserID","useRef","userChanged","current","tenantOptions","setTenantOptions","selectedTenantLabel","find","option","value","label","router","setCookie","useCallback","expires","document","cookie","deleteCookie","refresh","length","String","req","fetch","serverURL","routes","api","credentials","method","result","json","e","error","prev","map","currentTenant","useEffect","span","data-selected-tenant-id","data-selected-tenant-title","useTenantSelection","use"],"mappings":"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"}
@@ -1,11 +1,15 @@
1
1
  import type { Payload, TypedUser } from 'payload';
2
- type Args = {
2
+ import type { MultiTenantPluginConfig } from '../../types.js';
3
+ type Args<ConfigType> = {
3
4
  children: React.ReactNode;
4
5
  payload: Payload;
6
+ tenantsArrayFieldName: string;
7
+ tenantsArrayTenantFieldName: string;
5
8
  tenantsCollectionSlug: string;
6
9
  useAsTitle: string;
7
10
  user: TypedUser;
11
+ userHasAccessToAllTenants: Required<MultiTenantPluginConfig<ConfigType>>['userHasAccessToAllTenants'];
8
12
  };
9
- export declare const TenantSelectionProvider: ({ children, payload, tenantsCollectionSlug, useAsTitle, user, }: Args) => Promise<import("react").JSX.Element>;
13
+ export declare const TenantSelectionProvider: ({ children, payload, tenantsArrayFieldName, tenantsArrayTenantFieldName, tenantsCollectionSlug, useAsTitle, user, userHasAccessToAllTenants, }: Args<any>) => Promise<import("react").JSX.Element>;
10
14
  export {};
11
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/TenantSelectionProvider/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgB,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAO/D,KAAK,IAAI,GAAG;IACV,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,OAAO,EAAE,OAAO,CAAA;IAChB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,SAAS,CAAA;CAChB,CAAA;AAED,eAAO,MAAM,uBAAuB,oEAMjC,IAAI,yCAoDN,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/TenantSelectionProvider/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAIjD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAA;AAK7D,KAAK,IAAI,CAAC,UAAU,IAAI;IACtB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,OAAO,EAAE,OAAO,CAAA;IAChB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,2BAA2B,EAAE,MAAM,CAAA;IACnC,qBAAqB,EAAE,MAAM,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,SAAS,CAAA;IACf,yBAAyB,EAAE,QAAQ,CACjC,uBAAuB,CAAC,UAAU,CAAC,CACpC,CAAC,2BAA2B,CAAC,CAAA;CAC/B,CAAA;AAED,eAAO,MAAM,uBAAuB,mJASjC,IAAI,CAAC,GAAG,CAAC,yCAyCX,CAAA"}
@@ -1,26 +1,19 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { cookies as getCookies } from 'next/headers.js';
3
- import { findTenantOptions } from '../../queries/findTenantOptions.js';
3
+ import { getTenantOptions } from '../../utilities/getTenantOptions.js';
4
4
  import { TenantSelectionProviderClient } from './index.client.js';
5
- export const TenantSelectionProvider = async ({ children, payload, tenantsCollectionSlug, useAsTitle, user })=>{
6
- let tenantOptions = [];
7
- try {
8
- const { docs } = await findTenantOptions({
9
- limit: 0,
10
- payload,
11
- tenantsCollectionSlug,
12
- useAsTitle,
13
- user
14
- });
15
- tenantOptions = docs.map((doc)=>({
16
- label: String(doc[useAsTitle]),
17
- value: doc.id
18
- }));
19
- } catch (_) {
20
- // user likely does not have access
21
- }
5
+ export const TenantSelectionProvider = async ({ children, payload, tenantsArrayFieldName, tenantsArrayTenantFieldName, tenantsCollectionSlug, useAsTitle, user, userHasAccessToAllTenants })=>{
6
+ const tenantOptions = await getTenantOptions({
7
+ payload,
8
+ tenantsArrayFieldName,
9
+ tenantsArrayTenantFieldName,
10
+ tenantsCollectionSlug,
11
+ useAsTitle,
12
+ user,
13
+ userHasAccessToAllTenants
14
+ });
22
15
  const cookies = await getCookies();
23
- let tenantCookie = cookies.get('payload-tenant')?.value;
16
+ const tenantCookie = cookies.get('payload-tenant')?.value;
24
17
  let initialValue = undefined;
25
18
  /**
26
19
  * Ensure the cookie is a valid tenant
@@ -33,15 +26,12 @@ export const TenantSelectionProvider = async ({ children, payload, tenantsCollec
33
26
  /**
34
27
  * If the there was no cookie or the cookie was an invalid tenantID set intialValue
35
28
  */ if (!initialValue) {
36
- tenantCookie = undefined;
37
29
  initialValue = tenantOptions.length > 1 ? undefined : tenantOptions[0]?.value;
38
30
  }
39
31
  return /*#__PURE__*/ _jsx(TenantSelectionProviderClient, {
32
+ initialTenantOptions: tenantOptions,
40
33
  initialValue: initialValue,
41
- tenantCookie: tenantCookie,
42
- tenantOptions: tenantOptions,
43
34
  tenantsCollectionSlug: tenantsCollectionSlug,
44
- useAsTitle: useAsTitle,
45
35
  children: children
46
36
  });
47
37
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/providers/TenantSelectionProvider/index.tsx"],"sourcesContent":["import type { OptionObject, Payload, TypedUser } from 'payload'\n\nimport { cookies as getCookies } from 'next/headers.js'\n\nimport { findTenantOptions } from '../../queries/findTenantOptions.js'\nimport { TenantSelectionProviderClient } from './index.client.js'\n\ntype Args = {\n children: React.ReactNode\n payload: Payload\n tenantsCollectionSlug: string\n useAsTitle: string\n user: TypedUser\n}\n\nexport const TenantSelectionProvider = async ({\n children,\n payload,\n tenantsCollectionSlug,\n useAsTitle,\n user,\n}: Args) => {\n let tenantOptions: OptionObject[] = []\n\n try {\n const { docs } = await findTenantOptions({\n limit: 0,\n payload,\n tenantsCollectionSlug,\n useAsTitle,\n user,\n })\n tenantOptions = docs.map((doc) => ({\n label: String(doc[useAsTitle]),\n value: doc.id,\n }))\n } catch (_) {\n // user likely does not have access\n }\n\n const cookies = await getCookies()\n let tenantCookie = cookies.get('payload-tenant')?.value\n let initialValue = undefined\n\n /**\n * Ensure the cookie is a valid tenant\n */\n if (tenantCookie) {\n const matchingOption = tenantOptions.find((option) => String(option.value) === tenantCookie)\n if (matchingOption) {\n initialValue = matchingOption.value\n }\n }\n\n /**\n * If the there was no cookie or the cookie was an invalid tenantID set intialValue\n */\n if (!initialValue) {\n tenantCookie = undefined\n initialValue = tenantOptions.length > 1 ? undefined : tenantOptions[0]?.value\n }\n\n return (\n <TenantSelectionProviderClient\n initialValue={initialValue}\n tenantCookie={tenantCookie}\n tenantOptions={tenantOptions}\n tenantsCollectionSlug={tenantsCollectionSlug}\n useAsTitle={useAsTitle}\n >\n {children}\n </TenantSelectionProviderClient>\n )\n}\n"],"names":["cookies","getCookies","findTenantOptions","TenantSelectionProviderClient","TenantSelectionProvider","children","payload","tenantsCollectionSlug","useAsTitle","user","tenantOptions","docs","limit","map","doc","label","String","value","id","_","tenantCookie","get","initialValue","undefined","matchingOption","find","option","length"],"mappings":";AAEA,SAASA,WAAWC,UAAU,QAAQ,kBAAiB;AAEvD,SAASC,iBAAiB,QAAQ,qCAAoC;AACtE,SAASC,6BAA6B,QAAQ,oBAAmB;AAUjE,OAAO,MAAMC,0BAA0B,OAAO,EAC5CC,QAAQ,EACRC,OAAO,EACPC,qBAAqB,EACrBC,UAAU,EACVC,IAAI,EACC;IACL,IAAIC,gBAAgC,EAAE;IAEtC,IAAI;QACF,MAAM,EAAEC,IAAI,EAAE,GAAG,MAAMT,kBAAkB;YACvCU,OAAO;YACPN;YACAC;YACAC;YACAC;QACF;QACAC,gBAAgBC,KAAKE,GAAG,CAAC,CAACC,MAAS,CAAA;gBACjCC,OAAOC,OAAOF,GAAG,CAACN,WAAW;gBAC7BS,OAAOH,IAAII,EAAE;YACf,CAAA;IACF,EAAE,OAAOC,GAAG;IACV,mCAAmC;IACrC;IAEA,MAAMnB,UAAU,MAAMC;IACtB,IAAImB,eAAepB,QAAQqB,GAAG,CAAC,mBAAmBJ;IAClD,IAAIK,eAAeC;IAEnB;;GAEC,GACD,IAAIH,cAAc;QAChB,MAAMI,iBAAiBd,cAAce,IAAI,CAAC,CAACC,SAAWV,OAAOU,OAAOT,KAAK,MAAMG;QAC/E,IAAII,gBAAgB;YAClBF,eAAeE,eAAeP,KAAK;QACrC;IACF;IAEA;;GAEC,GACD,IAAI,CAACK,cAAc;QACjBF,eAAeG;QACfD,eAAeZ,cAAciB,MAAM,GAAG,IAAIJ,YAAYb,aAAa,CAAC,EAAE,EAAEO;IAC1E;IAEA,qBACE,KAACd;QACCmB,cAAcA;QACdF,cAAcA;QACdV,eAAeA;QACfH,uBAAuBA;QACvBC,YAAYA;kBAEXH;;AAGP,EAAC"}
1
+ {"version":3,"sources":["../../../src/providers/TenantSelectionProvider/index.tsx"],"sourcesContent":["import type { Payload, TypedUser } from 'payload'\n\nimport { cookies as getCookies } from 'next/headers.js'\n\nimport type { MultiTenantPluginConfig } from '../../types.js'\n\nimport { getTenantOptions } from '../../utilities/getTenantOptions.js'\nimport { TenantSelectionProviderClient } from './index.client.js'\n\ntype Args<ConfigType> = {\n children: React.ReactNode\n payload: Payload\n tenantsArrayFieldName: string\n tenantsArrayTenantFieldName: string\n tenantsCollectionSlug: string\n useAsTitle: string\n user: TypedUser\n userHasAccessToAllTenants: Required<\n MultiTenantPluginConfig<ConfigType>\n >['userHasAccessToAllTenants']\n}\n\nexport const TenantSelectionProvider = async ({\n children,\n payload,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n useAsTitle,\n user,\n userHasAccessToAllTenants,\n}: Args<any>) => {\n const tenantOptions = await getTenantOptions({\n payload,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n useAsTitle,\n user,\n userHasAccessToAllTenants,\n })\n\n const cookies = await getCookies()\n const tenantCookie = cookies.get('payload-tenant')?.value\n let initialValue = undefined\n\n /**\n * Ensure the cookie is a valid tenant\n */\n if (tenantCookie) {\n const matchingOption = tenantOptions.find((option) => String(option.value) === tenantCookie)\n if (matchingOption) {\n initialValue = matchingOption.value\n }\n }\n\n /**\n * If the there was no cookie or the cookie was an invalid tenantID set intialValue\n */\n if (!initialValue) {\n initialValue = tenantOptions.length > 1 ? undefined : tenantOptions[0]?.value\n }\n\n return (\n <TenantSelectionProviderClient\n initialTenantOptions={tenantOptions}\n initialValue={initialValue}\n tenantsCollectionSlug={tenantsCollectionSlug}\n >\n {children}\n </TenantSelectionProviderClient>\n )\n}\n"],"names":["cookies","getCookies","getTenantOptions","TenantSelectionProviderClient","TenantSelectionProvider","children","payload","tenantsArrayFieldName","tenantsArrayTenantFieldName","tenantsCollectionSlug","useAsTitle","user","userHasAccessToAllTenants","tenantOptions","tenantCookie","get","value","initialValue","undefined","matchingOption","find","option","String","length","initialTenantOptions"],"mappings":";AAEA,SAASA,WAAWC,UAAU,QAAQ,kBAAiB;AAIvD,SAASC,gBAAgB,QAAQ,sCAAqC;AACtE,SAASC,6BAA6B,QAAQ,oBAAmB;AAejE,OAAO,MAAMC,0BAA0B,OAAO,EAC5CC,QAAQ,EACRC,OAAO,EACPC,qBAAqB,EACrBC,2BAA2B,EAC3BC,qBAAqB,EACrBC,UAAU,EACVC,IAAI,EACJC,yBAAyB,EACf;IACV,MAAMC,gBAAgB,MAAMX,iBAAiB;QAC3CI;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;IACF;IAEA,MAAMZ,UAAU,MAAMC;IACtB,MAAMa,eAAed,QAAQe,GAAG,CAAC,mBAAmBC;IACpD,IAAIC,eAAeC;IAEnB;;GAEC,GACD,IAAIJ,cAAc;QAChB,MAAMK,iBAAiBN,cAAcO,IAAI,CAAC,CAACC,SAAWC,OAAOD,OAAOL,KAAK,MAAMF;QAC/E,IAAIK,gBAAgB;YAClBF,eAAeE,eAAeH,KAAK;QACrC;IACF;IAEA;;GAEC,GACD,IAAI,CAACC,cAAc;QACjBA,eAAeJ,cAAcU,MAAM,GAAG,IAAIL,YAAYL,aAAa,CAAC,EAAE,EAAEG;IAC1E;IAEA,qBACE,KAACb;QACCqB,sBAAsBX;QACtBI,cAAcA;QACdR,uBAAuBA;kBAEtBJ;;AAGP,EAAC"}
@@ -1,4 +1,5 @@
1
1
  import type { Payload, TypedUser, ViewTypes } from 'payload';
2
+ import type { MultiTenantPluginConfig } from '../types.js';
2
3
  type Args = {
3
4
  basePath?: string;
4
5
  docID?: number | string;
@@ -6,11 +7,14 @@ type Args = {
6
7
  payload: Payload;
7
8
  slug: string;
8
9
  tenantFieldName: string;
10
+ tenantsArrayFieldName: string;
11
+ tenantsArrayTenantFieldName: string;
9
12
  tenantsCollectionSlug: string;
10
13
  useAsTitle: string;
11
14
  user?: TypedUser;
15
+ userHasAccessToAllTenants: Required<MultiTenantPluginConfig<any>>['userHasAccessToAllTenants'];
12
16
  view: ViewTypes;
13
17
  };
14
- export declare function getGlobalViewRedirect({ slug, basePath, docID, headers, payload, tenantFieldName, tenantsCollectionSlug, useAsTitle, user, view, }: Args): Promise<string | void>;
18
+ export declare function getGlobalViewRedirect({ slug, basePath, docID, headers, payload, tenantFieldName, tenantsArrayFieldName, tenantsArrayTenantFieldName, tenantsCollectionSlug, useAsTitle, user, userHasAccessToAllTenants, view, }: Args): Promise<string | void>;
15
19
  export {};
16
20
  //# sourceMappingURL=getGlobalViewRedirect.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"getGlobalViewRedirect.d.ts","sourceRoot":"","sources":["../../src/utilities/getGlobalViewRedirect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAQ5D,KAAK,IAAI,GAAG;IACV,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACvB,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,OAAO,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,eAAe,EAAE,MAAM,CAAA;IACvB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,IAAI,EAAE,SAAS,CAAA;CAChB,CAAA;AACD,wBAAsB,qBAAqB,CAAC,EAC1C,IAAI,EACJ,QAAQ,EACR,KAAK,EACL,OAAO,EACP,OAAO,EACP,eAAe,EACf,qBAAqB,EACrB,UAAU,EACV,IAAI,EACJ,IAAI,GACL,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAuE/B"}
1
+ {"version":3,"file":"getGlobalViewRedirect.d.ts","sourceRoot":"","sources":["../../src/utilities/getGlobalViewRedirect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAK5D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAM1D,KAAK,IAAI,GAAG;IACV,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACvB,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,OAAO,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,eAAe,EAAE,MAAM,CAAA;IACvB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,2BAA2B,EAAE,MAAM,CAAA;IACnC,qBAAqB,EAAE,MAAM,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,yBAAyB,EAAE,QAAQ,CAAC,uBAAuB,CAAC,GAAG,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAA;IAC9F,IAAI,EAAE,SAAS,CAAA;CAChB,CAAA;AACD,wBAAsB,qBAAqB,CAAC,EAC1C,IAAI,EACJ,QAAQ,EACR,KAAK,EACL,OAAO,EACP,OAAO,EACP,eAAe,EACf,qBAAqB,EACrB,2BAA2B,EAC3B,qBAAqB,EACrB,UAAU,EACV,IAAI,EACJ,yBAAyB,EACzB,IAAI,GACL,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA6E/B"}
@@ -1,23 +1,29 @@
1
+ import { unauthorized } from 'next/navigation.js';
1
2
  import { formatAdminURL } from 'payload/shared';
2
- import { findTenantOptions } from '../queries/findTenantOptions.js';
3
3
  import { getCollectionIDType } from './getCollectionIDType.js';
4
4
  import { getTenantFromCookie } from './getTenantFromCookie.js';
5
- export async function getGlobalViewRedirect({ slug, basePath, docID, headers, payload, tenantFieldName, tenantsCollectionSlug, useAsTitle, user, view }) {
5
+ import { getTenantOptions } from './getTenantOptions.js';
6
+ export async function getGlobalViewRedirect({ slug, basePath, docID, headers, payload, tenantFieldName, tenantsArrayFieldName, tenantsArrayTenantFieldName, tenantsCollectionSlug, useAsTitle, user, userHasAccessToAllTenants, view }) {
6
7
  const idType = getCollectionIDType({
7
8
  collectionSlug: tenantsCollectionSlug,
8
9
  payload
9
10
  });
10
11
  let tenant = getTenantFromCookie(headers, idType);
11
12
  let redirectRoute = undefined;
13
+ if (!user) {
14
+ return unauthorized();
15
+ }
12
16
  if (!tenant) {
13
- const tenantsQuery = await findTenantOptions({
14
- limit: 1,
17
+ const tenantOptions = await getTenantOptions({
15
18
  payload,
19
+ tenantsArrayFieldName,
20
+ tenantsArrayTenantFieldName,
16
21
  tenantsCollectionSlug,
17
22
  useAsTitle,
18
- user
23
+ user,
24
+ userHasAccessToAllTenants
19
25
  });
20
- tenant = tenantsQuery.docs[0]?.id || null;
26
+ tenant = tenantOptions[0]?.value || null;
21
27
  }
22
28
  try {
23
29
  const { docs } = await payload.find({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utilities/getGlobalViewRedirect.ts"],"sourcesContent":["import type { Payload, TypedUser, ViewTypes } from 'payload'\n\nimport { formatAdminURL } from 'payload/shared'\n\nimport { findTenantOptions } from '../queries/findTenantOptions.js'\nimport { getCollectionIDType } from './getCollectionIDType.js'\nimport { getTenantFromCookie } from './getTenantFromCookie.js'\n\ntype Args = {\n basePath?: string\n docID?: number | string\n headers: Headers\n payload: Payload\n slug: string\n tenantFieldName: string\n tenantsCollectionSlug: string\n useAsTitle: string\n user?: TypedUser\n view: ViewTypes\n}\nexport async function getGlobalViewRedirect({\n slug,\n basePath,\n docID,\n headers,\n payload,\n tenantFieldName,\n tenantsCollectionSlug,\n useAsTitle,\n user,\n view,\n}: Args): Promise<string | void> {\n const idType = getCollectionIDType({\n collectionSlug: tenantsCollectionSlug,\n payload,\n })\n let tenant = getTenantFromCookie(headers, idType)\n let redirectRoute: `/${string}` | void = undefined\n\n if (!tenant) {\n const tenantsQuery = await findTenantOptions({\n limit: 1,\n payload,\n tenantsCollectionSlug,\n useAsTitle,\n user,\n })\n\n tenant = tenantsQuery.docs[0]?.id || null\n }\n\n try {\n const { docs } = await payload.find({\n collection: slug,\n depth: 0,\n limit: 1,\n overrideAccess: false,\n pagination: false,\n user,\n where: {\n [tenantFieldName]: {\n equals: tenant,\n },\n },\n })\n\n const tenantDocID = docs?.[0]?.id\n\n if (view === 'document') {\n if (docID && !tenantDocID) {\n // viewing a document with an id but does not match the selected tenant, redirect to create route\n redirectRoute = `/collections/${slug}/create`\n } else if (tenantDocID && docID !== tenantDocID) {\n // tenant document already exists but does not match current route doc ID, redirect to matching tenant doc\n redirectRoute = `/collections/${slug}/${tenantDocID}`\n }\n } else if (view === 'list') {\n if (tenantDocID) {\n // tenant document exists, redirect to edit view\n redirectRoute = `/collections/${slug}/${tenantDocID}`\n } else {\n // tenant document does not exist, redirect to create route\n redirectRoute = `/collections/${slug}/create`\n }\n }\n } catch (e: unknown) {\n payload.logger.error(\n e,\n `${typeof e === 'object' && e && 'message' in e ? `e?.message - ` : ''}Multi Tenant Redirect Error`,\n )\n }\n\n if (redirectRoute) {\n return formatAdminURL({\n adminRoute: payload.config.routes.admin,\n basePath,\n path: redirectRoute,\n serverURL: payload.config.serverURL,\n })\n }\n\n return undefined\n}\n"],"names":["formatAdminURL","findTenantOptions","getCollectionIDType","getTenantFromCookie","getGlobalViewRedirect","slug","basePath","docID","headers","payload","tenantFieldName","tenantsCollectionSlug","useAsTitle","user","view","idType","collectionSlug","tenant","redirectRoute","undefined","tenantsQuery","limit","docs","id","find","collection","depth","overrideAccess","pagination","where","equals","tenantDocID","e","logger","error","adminRoute","config","routes","admin","path","serverURL"],"mappings":"AAEA,SAASA,cAAc,QAAQ,iBAAgB;AAE/C,SAASC,iBAAiB,QAAQ,kCAAiC;AACnE,SAASC,mBAAmB,QAAQ,2BAA0B;AAC9D,SAASC,mBAAmB,QAAQ,2BAA0B;AAc9D,OAAO,eAAeC,sBAAsB,EAC1CC,IAAI,EACJC,QAAQ,EACRC,KAAK,EACLC,OAAO,EACPC,OAAO,EACPC,eAAe,EACfC,qBAAqB,EACrBC,UAAU,EACVC,IAAI,EACJC,IAAI,EACC;IACL,MAAMC,SAASb,oBAAoB;QACjCc,gBAAgBL;QAChBF;IACF;IACA,IAAIQ,SAASd,oBAAoBK,SAASO;IAC1C,IAAIG,gBAAqCC;IAEzC,IAAI,CAACF,QAAQ;QACX,MAAMG,eAAe,MAAMnB,kBAAkB;YAC3CoB,OAAO;YACPZ;YACAE;YACAC;YACAC;QACF;QAEAI,SAASG,aAAaE,IAAI,CAAC,EAAE,EAAEC,MAAM;IACvC;IAEA,IAAI;QACF,MAAM,EAAED,IAAI,EAAE,GAAG,MAAMb,QAAQe,IAAI,CAAC;YAClCC,YAAYpB;YACZqB,OAAO;YACPL,OAAO;YACPM,gBAAgB;YAChBC,YAAY;YACZf;YACAgB,OAAO;gBACL,CAACnB,gBAAgB,EAAE;oBACjBoB,QAAQb;gBACV;YACF;QACF;QAEA,MAAMc,cAAcT,MAAM,CAAC,EAAE,EAAEC;QAE/B,IAAIT,SAAS,YAAY;YACvB,IAAIP,SAAS,CAACwB,aAAa;gBACzB,iGAAiG;gBACjGb,gBAAgB,CAAC,aAAa,EAAEb,KAAK,OAAO,CAAC;YAC/C,OAAO,IAAI0B,eAAexB,UAAUwB,aAAa;gBAC/C,0GAA0G;gBAC1Gb,gBAAgB,CAAC,aAAa,EAAEb,KAAK,CAAC,EAAE0B,aAAa;YACvD;QACF,OAAO,IAAIjB,SAAS,QAAQ;YAC1B,IAAIiB,aAAa;gBACf,gDAAgD;gBAChDb,gBAAgB,CAAC,aAAa,EAAEb,KAAK,CAAC,EAAE0B,aAAa;YACvD,OAAO;gBACL,2DAA2D;gBAC3Db,gBAAgB,CAAC,aAAa,EAAEb,KAAK,OAAO,CAAC;YAC/C;QACF;IACF,EAAE,OAAO2B,GAAY;QACnBvB,QAAQwB,MAAM,CAACC,KAAK,CAClBF,GACA,GAAG,OAAOA,MAAM,YAAYA,KAAK,aAAaA,IAAI,CAAC,aAAa,CAAC,GAAG,GAAG,2BAA2B,CAAC;IAEvG;IAEA,IAAId,eAAe;QACjB,OAAOlB,eAAe;YACpBmC,YAAY1B,QAAQ2B,MAAM,CAACC,MAAM,CAACC,KAAK;YACvChC;YACAiC,MAAMrB;YACNsB,WAAW/B,QAAQ2B,MAAM,CAACI,SAAS;QACrC;IACF;IAEA,OAAOrB;AACT"}
1
+ {"version":3,"sources":["../../src/utilities/getGlobalViewRedirect.ts"],"sourcesContent":["import type { Payload, TypedUser, ViewTypes } from 'payload'\n\nimport { unauthorized } from 'next/navigation.js'\nimport { formatAdminURL } from 'payload/shared'\n\nimport type { MultiTenantPluginConfig } from '../types.js'\n\nimport { getCollectionIDType } from './getCollectionIDType.js'\nimport { getTenantFromCookie } from './getTenantFromCookie.js'\nimport { getTenantOptions } from './getTenantOptions.js'\n\ntype Args = {\n basePath?: string\n docID?: number | string\n headers: Headers\n payload: Payload\n slug: string\n tenantFieldName: string\n tenantsArrayFieldName: string\n tenantsArrayTenantFieldName: string\n tenantsCollectionSlug: string\n useAsTitle: string\n user?: TypedUser\n userHasAccessToAllTenants: Required<MultiTenantPluginConfig<any>>['userHasAccessToAllTenants']\n view: ViewTypes\n}\nexport async function getGlobalViewRedirect({\n slug,\n basePath,\n docID,\n headers,\n payload,\n tenantFieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n useAsTitle,\n user,\n userHasAccessToAllTenants,\n view,\n}: Args): Promise<string | void> {\n const idType = getCollectionIDType({\n collectionSlug: tenantsCollectionSlug,\n payload,\n })\n let tenant = getTenantFromCookie(headers, idType)\n let redirectRoute: `/${string}` | void = undefined\n\n if (!user) {\n return unauthorized()\n }\n\n if (!tenant) {\n const tenantOptions = await getTenantOptions({\n payload,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n useAsTitle,\n user,\n userHasAccessToAllTenants,\n })\n\n tenant = tenantOptions[0]?.value || null\n }\n\n try {\n const { docs } = await payload.find({\n collection: slug,\n depth: 0,\n limit: 1,\n overrideAccess: false,\n pagination: false,\n user,\n where: {\n [tenantFieldName]: {\n equals: tenant,\n },\n },\n })\n\n const tenantDocID = docs?.[0]?.id\n\n if (view === 'document') {\n if (docID && !tenantDocID) {\n // viewing a document with an id but does not match the selected tenant, redirect to create route\n redirectRoute = `/collections/${slug}/create`\n } else if (tenantDocID && docID !== tenantDocID) {\n // tenant document already exists but does not match current route doc ID, redirect to matching tenant doc\n redirectRoute = `/collections/${slug}/${tenantDocID}`\n }\n } else if (view === 'list') {\n if (tenantDocID) {\n // tenant document exists, redirect to edit view\n redirectRoute = `/collections/${slug}/${tenantDocID}`\n } else {\n // tenant document does not exist, redirect to create route\n redirectRoute = `/collections/${slug}/create`\n }\n }\n } catch (e: unknown) {\n payload.logger.error(\n e,\n `${typeof e === 'object' && e && 'message' in e ? `e?.message - ` : ''}Multi Tenant Redirect Error`,\n )\n }\n\n if (redirectRoute) {\n return formatAdminURL({\n adminRoute: payload.config.routes.admin,\n basePath,\n path: redirectRoute,\n serverURL: payload.config.serverURL,\n })\n }\n\n return undefined\n}\n"],"names":["unauthorized","formatAdminURL","getCollectionIDType","getTenantFromCookie","getTenantOptions","getGlobalViewRedirect","slug","basePath","docID","headers","payload","tenantFieldName","tenantsArrayFieldName","tenantsArrayTenantFieldName","tenantsCollectionSlug","useAsTitle","user","userHasAccessToAllTenants","view","idType","collectionSlug","tenant","redirectRoute","undefined","tenantOptions","value","docs","find","collection","depth","limit","overrideAccess","pagination","where","equals","tenantDocID","id","e","logger","error","adminRoute","config","routes","admin","path","serverURL"],"mappings":"AAEA,SAASA,YAAY,QAAQ,qBAAoB;AACjD,SAASC,cAAc,QAAQ,iBAAgB;AAI/C,SAASC,mBAAmB,QAAQ,2BAA0B;AAC9D,SAASC,mBAAmB,QAAQ,2BAA0B;AAC9D,SAASC,gBAAgB,QAAQ,wBAAuB;AAiBxD,OAAO,eAAeC,sBAAsB,EAC1CC,IAAI,EACJC,QAAQ,EACRC,KAAK,EACLC,OAAO,EACPC,OAAO,EACPC,eAAe,EACfC,qBAAqB,EACrBC,2BAA2B,EAC3BC,qBAAqB,EACrBC,UAAU,EACVC,IAAI,EACJC,yBAAyB,EACzBC,IAAI,EACC;IACL,MAAMC,SAASjB,oBAAoB;QACjCkB,gBAAgBN;QAChBJ;IACF;IACA,IAAIW,SAASlB,oBAAoBM,SAASU;IAC1C,IAAIG,gBAAqCC;IAEzC,IAAI,CAACP,MAAM;QACT,OAAOhB;IACT;IAEA,IAAI,CAACqB,QAAQ;QACX,MAAMG,gBAAgB,MAAMpB,iBAAiB;YAC3CM;YACAE;YACAC;YACAC;YACAC;YACAC;YACAC;QACF;QAEAI,SAASG,aAAa,CAAC,EAAE,EAAEC,SAAS;IACtC;IAEA,IAAI;QACF,MAAM,EAAEC,IAAI,EAAE,GAAG,MAAMhB,QAAQiB,IAAI,CAAC;YAClCC,YAAYtB;YACZuB,OAAO;YACPC,OAAO;YACPC,gBAAgB;YAChBC,YAAY;YACZhB;YACAiB,OAAO;gBACL,CAACtB,gBAAgB,EAAE;oBACjBuB,QAAQb;gBACV;YACF;QACF;QAEA,MAAMc,cAAcT,MAAM,CAAC,EAAE,EAAEU;QAE/B,IAAIlB,SAAS,YAAY;YACvB,IAAIV,SAAS,CAAC2B,aAAa;gBACzB,iGAAiG;gBACjGb,gBAAgB,CAAC,aAAa,EAAEhB,KAAK,OAAO,CAAC;YAC/C,OAAO,IAAI6B,eAAe3B,UAAU2B,aAAa;gBAC/C,0GAA0G;gBAC1Gb,gBAAgB,CAAC,aAAa,EAAEhB,KAAK,CAAC,EAAE6B,aAAa;YACvD;QACF,OAAO,IAAIjB,SAAS,QAAQ;YAC1B,IAAIiB,aAAa;gBACf,gDAAgD;gBAChDb,gBAAgB,CAAC,aAAa,EAAEhB,KAAK,CAAC,EAAE6B,aAAa;YACvD,OAAO;gBACL,2DAA2D;gBAC3Db,gBAAgB,CAAC,aAAa,EAAEhB,KAAK,OAAO,CAAC;YAC/C;QACF;IACF,EAAE,OAAO+B,GAAY;QACnB3B,QAAQ4B,MAAM,CAACC,KAAK,CAClBF,GACA,GAAG,OAAOA,MAAM,YAAYA,KAAK,aAAaA,IAAI,CAAC,aAAa,CAAC,GAAG,GAAG,2BAA2B,CAAC;IAEvG;IAEA,IAAIf,eAAe;QACjB,OAAOrB,eAAe;YACpBuC,YAAY9B,QAAQ+B,MAAM,CAACC,MAAM,CAACC,KAAK;YACvCpC;YACAqC,MAAMtB;YACNuB,WAAWnC,QAAQ+B,MAAM,CAACI,SAAS;QACrC;IACF;IAEA,OAAOtB;AACT"}
@@ -0,0 +1,12 @@
1
+ import type { OptionObject, Payload, TypedUser } from 'payload';
2
+ import type { MultiTenantPluginConfig } from '../types.js';
3
+ export declare const getTenantOptions: ({ payload, tenantsArrayFieldName, tenantsArrayTenantFieldName, tenantsCollectionSlug, useAsTitle, user, userHasAccessToAllTenants, }: {
4
+ payload: Payload;
5
+ tenantsArrayFieldName: string;
6
+ tenantsArrayTenantFieldName: string;
7
+ tenantsCollectionSlug: string;
8
+ useAsTitle: string;
9
+ user: TypedUser;
10
+ userHasAccessToAllTenants: Required<MultiTenantPluginConfig<any>>["userHasAccessToAllTenants"];
11
+ }) => Promise<OptionObject[]>;
12
+ //# sourceMappingURL=getTenantOptions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getTenantOptions.d.ts","sourceRoot":"","sources":["../../src/utilities/getTenantOptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAE/D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAE1D,eAAO,MAAM,gBAAgB,yIAQ1B;IACD,OAAO,EAAE,OAAO,CAAA;IAChB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,2BAA2B,EAAE,MAAM,CAAA;IACnC,qBAAqB,EAAE,MAAM,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,SAAS,CAAA;IACf,yBAAyB,EAAE,QAAQ,CAAC,uBAAuB,CAAC,GAAG,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAA;CAC/F,KAAG,OAAO,CAAC,YAAY,EAAE,CAiEzB,CAAA"}
@@ -0,0 +1,63 @@
1
+ export const getTenantOptions = async ({ payload, tenantsArrayFieldName, tenantsArrayTenantFieldName, tenantsCollectionSlug, useAsTitle, user, userHasAccessToAllTenants })=>{
2
+ let tenantOptions = [];
3
+ if (!user) {
4
+ return tenantOptions;
5
+ }
6
+ if (userHasAccessToAllTenants(user)) {
7
+ // If the user has access to all tenants get them from the DB
8
+ const isOrderable = payload.collections[tenantsCollectionSlug]?.config?.orderable || false;
9
+ const tenants = await payload.find({
10
+ collection: tenantsCollectionSlug,
11
+ depth: 0,
12
+ limit: 0,
13
+ overrideAccess: false,
14
+ select: {
15
+ [useAsTitle]: true,
16
+ ...isOrderable ? {
17
+ _order: true
18
+ } : {}
19
+ },
20
+ sort: isOrderable ? '_order' : useAsTitle,
21
+ user
22
+ });
23
+ tenantOptions = tenants.docs.map((doc)=>({
24
+ label: String(doc[useAsTitle]),
25
+ value: doc.id
26
+ }));
27
+ } else {
28
+ const tenantsToPopulate = [];
29
+ (user[tenantsArrayFieldName] || []).map((tenantRow)=>{
30
+ const tenantField = tenantRow[tenantsArrayTenantFieldName] // tenants.tenant
31
+ ;
32
+ if (typeof tenantField === 'string' || typeof tenantField === 'number') {
33
+ tenantsToPopulate.push(tenantField);
34
+ } else if (tenantField && typeof tenantField === 'object') {
35
+ tenantOptions.push({
36
+ label: String(tenantField[useAsTitle]),
37
+ value: tenantField.id
38
+ });
39
+ }
40
+ });
41
+ if (tenantsToPopulate.length > 0) {
42
+ const populatedTenants = await payload.find({
43
+ collection: tenantsCollectionSlug,
44
+ depth: 0,
45
+ limit: 0,
46
+ overrideAccess: false,
47
+ user,
48
+ where: {
49
+ id: {
50
+ in: tenantsToPopulate
51
+ }
52
+ }
53
+ });
54
+ tenantOptions = populatedTenants.docs.map((doc)=>({
55
+ label: String(doc[useAsTitle]),
56
+ value: doc.id
57
+ }));
58
+ }
59
+ }
60
+ return tenantOptions;
61
+ };
62
+
63
+ //# sourceMappingURL=getTenantOptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utilities/getTenantOptions.ts"],"sourcesContent":["import type { OptionObject, Payload, TypedUser } from 'payload'\n\nimport type { MultiTenantPluginConfig } from '../types.js'\n\nexport const getTenantOptions = async ({\n payload,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n useAsTitle,\n user,\n userHasAccessToAllTenants,\n}: {\n payload: Payload\n tenantsArrayFieldName: string\n tenantsArrayTenantFieldName: string\n tenantsCollectionSlug: string\n useAsTitle: string\n user: TypedUser\n userHasAccessToAllTenants: Required<MultiTenantPluginConfig<any>>['userHasAccessToAllTenants']\n}): Promise<OptionObject[]> => {\n let tenantOptions: OptionObject[] = []\n\n if (!user) {\n return tenantOptions\n }\n\n if (userHasAccessToAllTenants(user)) {\n // If the user has access to all tenants get them from the DB\n const isOrderable = payload.collections[tenantsCollectionSlug]?.config?.orderable || false\n const tenants = await payload.find({\n collection: tenantsCollectionSlug,\n depth: 0,\n limit: 0,\n overrideAccess: false,\n select: {\n [useAsTitle]: true,\n ...(isOrderable ? { _order: true } : {}),\n },\n sort: isOrderable ? '_order' : useAsTitle,\n user,\n })\n\n tenantOptions = tenants.docs.map((doc) => ({\n label: String(doc[useAsTitle as 'id']), // useAsTitle is dynamic but the type thinks we are only selecting `id` | `_order`\n value: doc.id as string,\n }))\n } else {\n const tenantsToPopulate: (number | string)[] = []\n\n // i.e. users.tenants\n ;((user[tenantsArrayFieldName] as { [key: string]: any }[]) || []).map((tenantRow) => {\n const tenantField = tenantRow[tenantsArrayTenantFieldName] // tenants.tenant\n if (typeof tenantField === 'string' || typeof tenantField === 'number') {\n tenantsToPopulate.push(tenantField)\n } else if (tenantField && typeof tenantField === 'object') {\n tenantOptions.push({\n label: String(tenantField[useAsTitle]),\n value: tenantField.id,\n })\n }\n })\n\n if (tenantsToPopulate.length > 0) {\n const populatedTenants = await payload.find({\n collection: tenantsCollectionSlug,\n depth: 0,\n limit: 0,\n overrideAccess: false,\n user,\n where: {\n id: {\n in: tenantsToPopulate,\n },\n },\n })\n\n tenantOptions = populatedTenants.docs.map((doc) => ({\n label: String(doc[useAsTitle]),\n value: doc.id as string,\n }))\n }\n }\n\n return tenantOptions\n}\n"],"names":["getTenantOptions","payload","tenantsArrayFieldName","tenantsArrayTenantFieldName","tenantsCollectionSlug","useAsTitle","user","userHasAccessToAllTenants","tenantOptions","isOrderable","collections","config","orderable","tenants","find","collection","depth","limit","overrideAccess","select","_order","sort","docs","map","doc","label","String","value","id","tenantsToPopulate","tenantRow","tenantField","push","length","populatedTenants","where","in"],"mappings":"AAIA,OAAO,MAAMA,mBAAmB,OAAO,EACrCC,OAAO,EACPC,qBAAqB,EACrBC,2BAA2B,EAC3BC,qBAAqB,EACrBC,UAAU,EACVC,IAAI,EACJC,yBAAyB,EAS1B;IACC,IAAIC,gBAAgC,EAAE;IAEtC,IAAI,CAACF,MAAM;QACT,OAAOE;IACT;IAEA,IAAID,0BAA0BD,OAAO;QACnC,6DAA6D;QAC7D,MAAMG,cAAcR,QAAQS,WAAW,CAACN,sBAAsB,EAAEO,QAAQC,aAAa;QACrF,MAAMC,UAAU,MAAMZ,QAAQa,IAAI,CAAC;YACjCC,YAAYX;YACZY,OAAO;YACPC,OAAO;YACPC,gBAAgB;YAChBC,QAAQ;gBACN,CAACd,WAAW,EAAE;gBACd,GAAII,cAAc;oBAAEW,QAAQ;gBAAK,IAAI,CAAC,CAAC;YACzC;YACAC,MAAMZ,cAAc,WAAWJ;YAC/BC;QACF;QAEAE,gBAAgBK,QAAQS,IAAI,CAACC,GAAG,CAAC,CAACC,MAAS,CAAA;gBACzCC,OAAOC,OAAOF,GAAG,CAACnB,WAAmB;gBACrCsB,OAAOH,IAAII,EAAE;YACf,CAAA;IACF,OAAO;QACL,MAAMC,oBAAyC,EAAE;QAG/C,CAAA,AAACvB,IAAI,CAACJ,sBAAsB,IAAiC,EAAE,AAAD,EAAGqB,GAAG,CAAC,CAACO;YACtE,MAAMC,cAAcD,SAAS,CAAC3B,4BAA4B,CAAC,iBAAiB;;YAC5E,IAAI,OAAO4B,gBAAgB,YAAY,OAAOA,gBAAgB,UAAU;gBACtEF,kBAAkBG,IAAI,CAACD;YACzB,OAAO,IAAIA,eAAe,OAAOA,gBAAgB,UAAU;gBACzDvB,cAAcwB,IAAI,CAAC;oBACjBP,OAAOC,OAAOK,WAAW,CAAC1B,WAAW;oBACrCsB,OAAOI,YAAYH,EAAE;gBACvB;YACF;QACF;QAEA,IAAIC,kBAAkBI,MAAM,GAAG,GAAG;YAChC,MAAMC,mBAAmB,MAAMjC,QAAQa,IAAI,CAAC;gBAC1CC,YAAYX;gBACZY,OAAO;gBACPC,OAAO;gBACPC,gBAAgB;gBAChBZ;gBACA6B,OAAO;oBACLP,IAAI;wBACFQ,IAAIP;oBACN;gBACF;YACF;YAEArB,gBAAgB0B,iBAAiBZ,IAAI,CAACC,GAAG,CAAC,CAACC,MAAS,CAAA;oBAClDC,OAAOC,OAAOF,GAAG,CAACnB,WAAW;oBAC7BsB,OAAOH,IAAII,EAAE;gBACf,CAAA;QACF;IACF;IAEA,OAAOpB;AACT,EAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@payloadcms/plugin-multi-tenant",
3
- "version": "3.49.0",
3
+ "version": "3.50.0-canary.0",
4
4
  "description": "Multi Tenant plugin for Payload",
5
5
  "keywords": [
6
6
  "payload",
@@ -81,14 +81,14 @@
81
81
  ],
82
82
  "devDependencies": {
83
83
  "@payloadcms/eslint-config": "3.28.0",
84
- "@payloadcms/translations": "3.49.0",
85
- "@payloadcms/ui": "3.49.0",
86
- "payload": "3.49.0"
84
+ "@payloadcms/translations": "3.50.0-canary.0",
85
+ "@payloadcms/ui": "3.50.0-canary.0",
86
+ "payload": "3.50.0-canary.0"
87
87
  },
88
88
  "peerDependencies": {
89
89
  "next": "^15.2.3",
90
- "@payloadcms/ui": "3.49.0",
91
- "payload": "3.49.0"
90
+ "@payloadcms/ui": "3.50.0-canary.0",
91
+ "payload": "3.50.0-canary.0"
92
92
  },
93
93
  "homepage:": "https://payloadcms.com",
94
94
  "scripts": {
@@ -1,11 +0,0 @@
1
- import type { PaginatedDocs, Payload, TypedUser } from 'payload';
2
- type Args = {
3
- limit: number;
4
- payload: Payload;
5
- tenantsCollectionSlug: string;
6
- useAsTitle: string;
7
- user?: TypedUser;
8
- };
9
- export declare const findTenantOptions: ({ limit, payload, tenantsCollectionSlug, useAsTitle, user, }: Args) => Promise<PaginatedDocs>;
10
- export {};
11
- //# sourceMappingURL=findTenantOptions.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"findTenantOptions.d.ts","sourceRoot":"","sources":["../../src/queries/findTenantOptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAEhE,KAAK,IAAI,GAAG;IACV,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,OAAO,CAAA;IAChB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAE,SAAS,CAAA;CACjB,CAAA;AACD,eAAO,MAAM,iBAAiB,iEAM3B,IAAI,KAAG,OAAO,CAAC,aAAa,CAc9B,CAAA"}
@@ -1,19 +0,0 @@
1
- export const findTenantOptions = async ({ limit, payload, tenantsCollectionSlug, useAsTitle, user })=>{
2
- const isOrderable = payload.collections[tenantsCollectionSlug]?.config?.orderable || false;
3
- return payload.find({
4
- collection: tenantsCollectionSlug,
5
- depth: 0,
6
- limit,
7
- overrideAccess: false,
8
- select: {
9
- [useAsTitle]: true,
10
- ...isOrderable ? {
11
- _order: true
12
- } : {}
13
- },
14
- sort: isOrderable ? '_order' : useAsTitle,
15
- user
16
- });
17
- };
18
-
19
- //# sourceMappingURL=findTenantOptions.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/queries/findTenantOptions.ts"],"sourcesContent":["import type { PaginatedDocs, Payload, TypedUser } from 'payload'\n\ntype Args = {\n limit: number\n payload: Payload\n tenantsCollectionSlug: string\n useAsTitle: string\n user?: TypedUser\n}\nexport const findTenantOptions = async ({\n limit,\n payload,\n tenantsCollectionSlug,\n useAsTitle,\n user,\n}: Args): Promise<PaginatedDocs> => {\n const isOrderable = payload.collections[tenantsCollectionSlug]?.config?.orderable || false\n return payload.find({\n collection: tenantsCollectionSlug,\n depth: 0,\n limit,\n overrideAccess: false,\n select: {\n [useAsTitle]: true,\n ...(isOrderable ? { _order: true } : {}),\n },\n sort: isOrderable ? '_order' : useAsTitle,\n user,\n })\n}\n"],"names":["findTenantOptions","limit","payload","tenantsCollectionSlug","useAsTitle","user","isOrderable","collections","config","orderable","find","collection","depth","overrideAccess","select","_order","sort"],"mappings":"AASA,OAAO,MAAMA,oBAAoB,OAAO,EACtCC,KAAK,EACLC,OAAO,EACPC,qBAAqB,EACrBC,UAAU,EACVC,IAAI,EACC;IACL,MAAMC,cAAcJ,QAAQK,WAAW,CAACJ,sBAAsB,EAAEK,QAAQC,aAAa;IACrF,OAAOP,QAAQQ,IAAI,CAAC;QAClBC,YAAYR;QACZS,OAAO;QACPX;QACAY,gBAAgB;QAChBC,QAAQ;YACN,CAACV,WAAW,EAAE;YACd,GAAIE,cAAc;gBAAES,QAAQ;YAAK,IAAI,CAAC,CAAC;QACzC;QACAC,MAAMV,cAAc,WAAWF;QAC/BC;IACF;AACF,EAAC"}