@payloadcms/plugin-multi-tenant 0.0.1 → 3.18.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 (104) hide show
  1. package/README.md +130 -95
  2. package/dist/components/GlobalViewRedirect/index.d.ts +3 -2
  3. package/dist/components/GlobalViewRedirect/index.d.ts.map +1 -1
  4. package/dist/components/GlobalViewRedirect/index.js +1 -0
  5. package/dist/components/GlobalViewRedirect/index.js.map +1 -1
  6. package/dist/components/TenantField/index.client.d.ts +3 -3
  7. package/dist/components/TenantField/index.client.d.ts.map +1 -1
  8. package/dist/components/TenantField/index.client.js +55 -17
  9. package/dist/components/TenantField/index.client.js.map +1 -1
  10. package/dist/components/TenantField/index.scss +14 -0
  11. package/dist/components/TenantSelector/index.d.ts +5 -8
  12. package/dist/components/TenantSelector/index.d.ts.map +1 -1
  13. package/dist/components/TenantSelector/index.js +35 -24
  14. package/dist/components/TenantSelector/index.js.map +1 -1
  15. package/dist/constants.d.ts +2 -0
  16. package/dist/constants.d.ts.map +1 -0
  17. package/dist/constants.js +4 -0
  18. package/dist/constants.js.map +1 -0
  19. package/dist/exports/client.d.ts +3 -0
  20. package/dist/exports/client.d.ts.map +1 -0
  21. package/dist/exports/client.js +4 -0
  22. package/dist/exports/client.js.map +1 -0
  23. package/dist/exports/fields.d.ts +3 -0
  24. package/dist/exports/fields.d.ts.map +1 -0
  25. package/dist/exports/fields.js +4 -0
  26. package/dist/exports/fields.js.map +1 -0
  27. package/dist/exports/rsc.d.ts +1 -2
  28. package/dist/exports/rsc.d.ts.map +1 -1
  29. package/dist/exports/rsc.js +1 -2
  30. package/dist/exports/rsc.js.map +1 -1
  31. package/dist/fields/tenantField/index.d.ts +2 -3
  32. package/dist/fields/tenantField/index.d.ts.map +1 -1
  33. package/dist/fields/tenantField/index.js +8 -4
  34. package/dist/fields/tenantField/index.js.map +1 -1
  35. package/dist/fields/tenantsArrayField/index.d.ts +7 -0
  36. package/dist/fields/tenantsArrayField/index.d.ts.map +1 -0
  37. package/dist/fields/{userTenantsArrayField → tenantsArrayField}/index.js +3 -3
  38. package/dist/fields/tenantsArrayField/index.js.map +1 -0
  39. package/dist/hooks/afterTenantDelete.d.ts +16 -0
  40. package/dist/hooks/afterTenantDelete.d.ts.map +1 -0
  41. package/dist/hooks/afterTenantDelete.js +71 -0
  42. package/dist/hooks/afterTenantDelete.js.map +1 -0
  43. package/dist/index.d.ts +1 -1
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +112 -49
  46. package/dist/index.js.map +1 -1
  47. package/dist/providers/TenantSelectionProvider/index.client.d.ts +19 -0
  48. package/dist/providers/TenantSelectionProvider/index.client.d.ts.map +1 -0
  49. package/dist/providers/TenantSelectionProvider/index.client.js +69 -0
  50. package/dist/providers/TenantSelectionProvider/index.client.js.map +1 -0
  51. package/dist/providers/TenantSelectionProvider/index.d.ts +11 -0
  52. package/dist/providers/TenantSelectionProvider/index.d.ts.map +1 -0
  53. package/dist/providers/TenantSelectionProvider/index.js +31 -0
  54. package/dist/providers/TenantSelectionProvider/index.js.map +1 -0
  55. package/dist/types.d.ts +54 -17
  56. package/dist/types.d.ts.map +1 -1
  57. package/dist/types.js.map +1 -1
  58. package/dist/utilities/addCollectionAccess.d.ts +13 -0
  59. package/dist/utilities/addCollectionAccess.d.ts.map +1 -0
  60. package/dist/utilities/addCollectionAccess.js +29 -0
  61. package/dist/utilities/addCollectionAccess.js.map +1 -0
  62. package/dist/utilities/addFilterOptionsToFields.d.ts +9 -0
  63. package/dist/utilities/addFilterOptionsToFields.d.ts.map +1 -0
  64. package/dist/utilities/addFilterOptionsToFields.js +107 -0
  65. package/dist/utilities/addFilterOptionsToFields.js.map +1 -0
  66. package/dist/utilities/combineWhereConstraints.js +2 -2
  67. package/dist/utilities/combineWhereConstraints.js.map +1 -1
  68. package/dist/utilities/getGlobalViewRedirect.d.ts +4 -3
  69. package/dist/utilities/getGlobalViewRedirect.d.ts.map +1 -1
  70. package/dist/utilities/getGlobalViewRedirect.js +6 -5
  71. package/dist/utilities/getGlobalViewRedirect.js.map +1 -1
  72. package/dist/utilities/getTenantAccess.d.ts +7 -3
  73. package/dist/utilities/getTenantAccess.d.ts.map +1 -1
  74. package/dist/utilities/getTenantAccess.js +6 -9
  75. package/dist/utilities/getTenantAccess.js.map +1 -1
  76. package/dist/utilities/getTenantFromCookie.d.ts +8 -1
  77. package/dist/utilities/getTenantFromCookie.d.ts.map +1 -1
  78. package/dist/utilities/getTenantFromCookie.js +7 -1
  79. package/dist/utilities/getTenantFromCookie.js.map +1 -1
  80. package/dist/utilities/getTenantListFilter.d.ts.map +1 -1
  81. package/dist/utilities/getTenantListFilter.js +8 -8
  82. package/dist/utilities/getTenantListFilter.js.map +1 -1
  83. package/dist/utilities/getUserTenantIDs.d.ts +1 -2
  84. package/dist/utilities/getUserTenantIDs.d.ts.map +1 -1
  85. package/dist/utilities/getUserTenantIDs.js +2 -6
  86. package/dist/utilities/getUserTenantIDs.js.map +1 -1
  87. package/dist/utilities/withTenantAccess.d.ts +4 -3
  88. package/dist/utilities/withTenantAccess.d.ts.map +1 -1
  89. package/dist/utilities/withTenantAccess.js +12 -16
  90. package/dist/utilities/withTenantAccess.js.map +1 -1
  91. package/dist/utilities/withTenantListFilter.js +1 -1
  92. package/dist/utilities/withTenantListFilter.js.map +1 -1
  93. package/package.json +20 -10
  94. package/dist/components/TenantField/index.d.ts +0 -3
  95. package/dist/components/TenantField/index.d.ts.map +0 -1
  96. package/dist/components/TenantField/index.js +0 -33
  97. package/dist/components/TenantField/index.js.map +0 -1
  98. package/dist/components/TenantSelector/index.client.d.ts +0 -11
  99. package/dist/components/TenantSelector/index.client.d.ts.map +0 -1
  100. package/dist/components/TenantSelector/index.client.js +0 -61
  101. package/dist/components/TenantSelector/index.client.js.map +0 -1
  102. package/dist/fields/userTenantsArrayField/index.d.ts +0 -4
  103. package/dist/fields/userTenantsArrayField/index.d.ts.map +0 -1
  104. package/dist/fields/userTenantsArrayField/index.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/exports/rsc.ts"],"sourcesContent":["export { GlobalViewRedirect } from '../components/GlobalViewRedirect/index.js'\nexport { TenantField } from '../components/TenantField/index.js'\nexport { TenantSelector } from '../components/TenantSelector/index.js'\n"],"names":["GlobalViewRedirect","TenantField","TenantSelector"],"mappings":"AAAA,SAASA,kBAAkB,QAAQ,4CAA2C;AAC9E,SAASC,WAAW,QAAQ,qCAAoC;AAChE,SAASC,cAAc,QAAQ,wCAAuC"}
1
+ {"version":3,"sources":["../../src/exports/rsc.ts"],"sourcesContent":["export { GlobalViewRedirect } from '../components/GlobalViewRedirect/index.js'\nexport { TenantSelectionProvider } from '../providers/TenantSelectionProvider/index.js'\n"],"names":["GlobalViewRedirect","TenantSelectionProvider"],"mappings":"AAAA,SAASA,kBAAkB,QAAQ,4CAA2C;AAC9E,SAASC,uBAAuB,QAAQ,gDAA+C"}
@@ -1,10 +1,9 @@
1
1
  import { type RelationshipField } from 'payload';
2
- import type { MultiTenantPluginConfig } from '../../types.js';
3
2
  type Args = {
4
- access: MultiTenantPluginConfig['documentTenantField']['access'];
3
+ access?: RelationshipField['access'];
5
4
  debug?: boolean;
6
5
  name: string;
7
- tenantsCollectionSlug: MultiTenantPluginConfig['tenantsSlug'];
6
+ tenantsCollectionSlug: string;
8
7
  unique: boolean;
9
8
  };
10
9
  export declare const tenantField: ({ name, access, debug, tenantsCollectionSlug, unique, }: Args) => RelationshipField;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/fields/tenantField/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAGhD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAA;AAI7D,KAAK,IAAI,GAAG;IACV,MAAM,EAAE,uBAAuB,CAAC,qBAAqB,CAAC,CAAC,QAAQ,CAAC,CAAA;IAChE,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,qBAAqB,EAAE,uBAAuB,CAAC,aAAa,CAAC,CAAA;IAC7D,MAAM,EAAE,OAAO,CAAA;CAChB,CAAA;AACD,eAAO,MAAM,WAAW,4DAMrB,IAAI,KAAG,iBAiCR,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/fields/tenantField/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAKhD,KAAK,IAAI,GAAG;IACV,MAAM,CAAC,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAA;IACpC,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,qBAAqB,EAAE,MAAM,CAAA;IAC7B,MAAM,EAAE,OAAO,CAAA;CAChB,CAAA;AACD,eAAO,MAAM,WAAW,4DAMrB,IAAI,KAAG,iBAqCR,CAAA"}
@@ -1,20 +1,23 @@
1
1
  import { APIError } from 'payload';
2
2
  import { getTenantFromCookie } from '../../utilities/getTenantFromCookie.js';
3
- export const tenantField = ({ name, access, debug, tenantsCollectionSlug, unique })=>({
3
+ export const tenantField = ({ name, access = undefined, debug, tenantsCollectionSlug, unique })=>({
4
4
  name,
5
5
  type: 'relationship',
6
6
  access,
7
7
  admin: {
8
+ allowCreate: false,
9
+ allowEdit: false,
8
10
  components: {
9
11
  Field: {
10
12
  clientProps: {
11
13
  debug,
12
- tenantsCollectionSlug
14
+ unique
13
15
  },
14
- path: '@payloadcms/plugin-multi-tenant/rsc#TenantField'
16
+ path: '@payloadcms/plugin-multi-tenant/client#TenantField'
15
17
  }
16
18
  },
17
- position: debug ? 'sidebar' : undefined
19
+ disableListColumn: true,
20
+ disableListFilter: true
18
21
  },
19
22
  hasMany: false,
20
23
  hooks: {
@@ -31,6 +34,7 @@ export const tenantField = ({ name, access, debug, tenantsCollectionSlug, unique
31
34
  ]
32
35
  },
33
36
  index: true,
37
+ label: 'Assigned Tenant',
34
38
  relationTo: tenantsCollectionSlug,
35
39
  unique
36
40
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/fields/tenantField/index.ts"],"sourcesContent":["import { type RelationshipField } from 'payload'\nimport { APIError } from 'payload'\n\nimport type { MultiTenantPluginConfig } from '../../types.js'\n\nimport { getTenantFromCookie } from '../../utilities/getTenantFromCookie.js'\n\ntype Args = {\n access: MultiTenantPluginConfig['documentTenantField']['access']\n debug?: boolean\n name: string\n tenantsCollectionSlug: MultiTenantPluginConfig['tenantsSlug']\n unique: boolean\n}\nexport const tenantField = ({\n name,\n access,\n debug,\n tenantsCollectionSlug,\n unique,\n}: Args): RelationshipField => ({\n name,\n type: 'relationship',\n access,\n admin: {\n components: {\n Field: {\n clientProps: {\n debug,\n tenantsCollectionSlug,\n },\n path: '@payloadcms/plugin-multi-tenant/rsc#TenantField',\n },\n },\n position: debug ? 'sidebar' : undefined,\n },\n hasMany: false,\n hooks: {\n beforeChange: [\n ({ req, value }) => {\n if (!value) {\n const tenantFromCookie = getTenantFromCookie(req.headers, req.payload.db.defaultIDType)\n if (tenantFromCookie) {\n return tenantFromCookie\n }\n throw new APIError('You must select a tenant', 400, null, true)\n }\n },\n ],\n },\n index: true,\n relationTo: tenantsCollectionSlug,\n unique,\n})\n"],"names":["APIError","getTenantFromCookie","tenantField","name","access","debug","tenantsCollectionSlug","unique","type","admin","components","Field","clientProps","path","position","undefined","hasMany","hooks","beforeChange","req","value","tenantFromCookie","headers","payload","db","defaultIDType","index","relationTo"],"mappings":"AACA,SAASA,QAAQ,QAAQ,UAAS;AAIlC,SAASC,mBAAmB,QAAQ,yCAAwC;AAS5E,OAAO,MAAMC,cAAc,CAAC,EAC1BC,IAAI,EACJC,MAAM,EACNC,KAAK,EACLC,qBAAqB,EACrBC,MAAM,EACD,GAAyB,CAAA;QAC9BJ;QACAK,MAAM;QACNJ;QACAK,OAAO;YACLC,YAAY;gBACVC,OAAO;oBACLC,aAAa;wBACXP;wBACAC;oBACF;oBACAO,MAAM;gBACR;YACF;YACAC,UAAUT,QAAQ,YAAYU;QAChC;QACAC,SAAS;QACTC,OAAO;YACLC,cAAc;gBACZ,CAAC,EAAEC,GAAG,EAAEC,KAAK,EAAE;oBACb,IAAI,CAACA,OAAO;wBACV,MAAMC,mBAAmBpB,oBAAoBkB,IAAIG,OAAO,EAAEH,IAAII,OAAO,CAACC,EAAE,CAACC,aAAa;wBACtF,IAAIJ,kBAAkB;4BACpB,OAAOA;wBACT;wBACA,MAAM,IAAIrB,SAAS,4BAA4B,KAAK,MAAM;oBAC5D;gBACF;aACD;QACH;QACA0B,OAAO;QACPC,YAAYrB;QACZC;IACF,CAAA,EAAE"}
1
+ {"version":3,"sources":["../../../src/fields/tenantField/index.ts"],"sourcesContent":["import { type RelationshipField } from 'payload'\nimport { APIError } from 'payload'\n\nimport { getTenantFromCookie } from '../../utilities/getTenantFromCookie.js'\n\ntype Args = {\n access?: RelationshipField['access']\n debug?: boolean\n name: string\n tenantsCollectionSlug: string\n unique: boolean\n}\nexport const tenantField = ({\n name,\n access = undefined,\n debug,\n tenantsCollectionSlug,\n unique,\n}: Args): RelationshipField => ({\n name,\n type: 'relationship',\n access,\n admin: {\n allowCreate: false,\n allowEdit: false,\n components: {\n Field: {\n clientProps: {\n debug,\n unique,\n },\n path: '@payloadcms/plugin-multi-tenant/client#TenantField',\n },\n },\n disableListColumn: true,\n disableListFilter: true,\n },\n hasMany: false,\n hooks: {\n beforeChange: [\n ({ req, value }) => {\n if (!value) {\n const tenantFromCookie = getTenantFromCookie(req.headers, req.payload.db.defaultIDType)\n if (tenantFromCookie) {\n return tenantFromCookie\n }\n throw new APIError('You must select a tenant', 400, null, true)\n }\n },\n ],\n },\n index: true,\n label: 'Assigned Tenant',\n relationTo: tenantsCollectionSlug,\n unique,\n})\n"],"names":["APIError","getTenantFromCookie","tenantField","name","access","undefined","debug","tenantsCollectionSlug","unique","type","admin","allowCreate","allowEdit","components","Field","clientProps","path","disableListColumn","disableListFilter","hasMany","hooks","beforeChange","req","value","tenantFromCookie","headers","payload","db","defaultIDType","index","label","relationTo"],"mappings":"AACA,SAASA,QAAQ,QAAQ,UAAS;AAElC,SAASC,mBAAmB,QAAQ,yCAAwC;AAS5E,OAAO,MAAMC,cAAc,CAAC,EAC1BC,IAAI,EACJC,SAASC,SAAS,EAClBC,KAAK,EACLC,qBAAqB,EACrBC,MAAM,EACD,GAAyB,CAAA;QAC9BL;QACAM,MAAM;QACNL;QACAM,OAAO;YACLC,aAAa;YACbC,WAAW;YACXC,YAAY;gBACVC,OAAO;oBACLC,aAAa;wBACXT;wBACAE;oBACF;oBACAQ,MAAM;gBACR;YACF;YACAC,mBAAmB;YACnBC,mBAAmB;QACrB;QACAC,SAAS;QACTC,OAAO;YACLC,cAAc;gBACZ,CAAC,EAAEC,GAAG,EAAEC,KAAK,EAAE;oBACb,IAAI,CAACA,OAAO;wBACV,MAAMC,mBAAmBvB,oBAAoBqB,IAAIG,OAAO,EAAEH,IAAII,OAAO,CAACC,EAAE,CAACC,aAAa;wBACtF,IAAIJ,kBAAkB;4BACpB,OAAOA;wBACT;wBACA,MAAM,IAAIxB,SAAS,4BAA4B,KAAK,MAAM;oBAC5D;gBACF;aACD;QACH;QACA6B,OAAO;QACPC,OAAO;QACPC,YAAYxB;QACZC;IACF,CAAA,EAAE"}
@@ -0,0 +1,7 @@
1
+ import type { ArrayField, RelationshipField } from 'payload';
2
+ export declare const tenantsArrayField: (args: {
3
+ arrayFieldAccess?: ArrayField["access"];
4
+ rowFields?: ArrayField["fields"];
5
+ tenantFieldAccess?: RelationshipField["access"];
6
+ }) => ArrayField;
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/fields/tenantsArrayField/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAE5D,eAAO,MAAM,iBAAiB,SAAU;IACtC,gBAAgB,CAAC,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAA;IACvC,SAAS,CAAC,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAA;IAChC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAA;CAChD,KAAG,UAiBF,CAAA"}
@@ -1,12 +1,12 @@
1
- export const userTenantsField = (args)=>({
1
+ export const tenantsArrayField = (args)=>({
2
2
  name: 'tenants',
3
3
  type: 'array',
4
- access: args?.access,
4
+ access: args?.arrayFieldAccess,
5
5
  fields: [
6
6
  {
7
7
  name: 'tenant',
8
8
  type: 'relationship',
9
- access: args.access,
9
+ access: args.tenantFieldAccess,
10
10
  index: true,
11
11
  relationTo: 'tenants',
12
12
  required: true,
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/fields/tenantsArrayField/index.ts"],"sourcesContent":["import type { ArrayField, RelationshipField } from 'payload'\n\nexport const tenantsArrayField = (args: {\n arrayFieldAccess?: ArrayField['access']\n rowFields?: ArrayField['fields']\n tenantFieldAccess?: RelationshipField['access']\n}): ArrayField => ({\n name: 'tenants',\n type: 'array',\n access: args?.arrayFieldAccess,\n fields: [\n {\n name: 'tenant',\n type: 'relationship',\n access: args.tenantFieldAccess,\n index: true,\n relationTo: 'tenants',\n required: true,\n saveToJWT: true,\n },\n ...(args?.rowFields || []),\n ],\n saveToJWT: true,\n})\n"],"names":["tenantsArrayField","args","name","type","access","arrayFieldAccess","fields","tenantFieldAccess","index","relationTo","required","saveToJWT","rowFields"],"mappings":"AAEA,OAAO,MAAMA,oBAAoB,CAACC,OAIf,CAAA;QACjBC,MAAM;QACNC,MAAM;QACNC,QAAQH,MAAMI;QACdC,QAAQ;YACN;gBACEJ,MAAM;gBACNC,MAAM;gBACNC,QAAQH,KAAKM,iBAAiB;gBAC9BC,OAAO;gBACPC,YAAY;gBACZC,UAAU;gBACVC,WAAW;YACb;eACIV,MAAMW,aAAa,EAAE;SAC1B;QACDD,WAAW;IACb,CAAA,EAAE"}
@@ -0,0 +1,16 @@
1
+ import type { CollectionAfterDeleteHook, CollectionConfig } from 'payload';
2
+ type Args = {
3
+ collection: CollectionConfig;
4
+ enabledSlugs: string[];
5
+ tenantFieldName: string;
6
+ usersSlug: string;
7
+ };
8
+ /**
9
+ * Add cleanup logic when tenant is deleted
10
+ * - delete documents related to tenant
11
+ * - remove tenant from users
12
+ */
13
+ export declare const addTenantCleanup: ({ collection, enabledSlugs, tenantFieldName, usersSlug, }: Args) => void;
14
+ export declare const afterTenantDelete: ({ enabledSlugs, tenantFieldName, usersSlug, }: Omit<Args, "collection">) => CollectionAfterDeleteHook;
15
+ export {};
16
+ //# sourceMappingURL=afterTenantDelete.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"afterTenantDelete.d.ts","sourceRoot":"","sources":["../../src/hooks/afterTenantDelete.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,yBAAyB,EACzB,gBAAgB,EAGjB,MAAM,SAAS,CAAA;AAQhB,KAAK,IAAI,GAAG;IACV,UAAU,EAAE,gBAAgB,CAAA;IAC5B,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,eAAe,EAAE,MAAM,CAAA;IACvB,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AACD;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,8DAK1B,IAAI,SAcN,CAAA;AAED,eAAO,MAAM,iBAAiB,kDAKzB,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,KAAG,yBA4D7B,CAAA"}
@@ -0,0 +1,71 @@
1
+ import { generateCookie, mergeHeaders } from 'payload';
2
+ import { getTenantFromCookie } from '../utilities/getTenantFromCookie.js';
3
+ /**
4
+ * Add cleanup logic when tenant is deleted
5
+ * - delete documents related to tenant
6
+ * - remove tenant from users
7
+ */ export const addTenantCleanup = ({ collection, enabledSlugs, tenantFieldName, usersSlug })=>{
8
+ if (!collection.hooks) {
9
+ collection.hooks = {};
10
+ }
11
+ if (!collection.hooks?.afterDelete) {
12
+ collection.hooks.afterDelete = [];
13
+ }
14
+ collection.hooks.afterDelete.push(afterTenantDelete({
15
+ enabledSlugs,
16
+ tenantFieldName,
17
+ usersSlug
18
+ }));
19
+ };
20
+ export const afterTenantDelete = ({ enabledSlugs, tenantFieldName, usersSlug })=>async ({ id, req })=>{
21
+ const currentTenantCookieID = getTenantFromCookie(req.headers, req.payload.db.defaultIDType);
22
+ if (currentTenantCookieID === id) {
23
+ const newHeaders = new Headers({
24
+ 'Set-Cookie': generateCookie({
25
+ name: 'payload-tenant',
26
+ expires: new Date(Date.now() - 1000),
27
+ path: '/',
28
+ returnCookieAsObject: false,
29
+ value: ''
30
+ })
31
+ });
32
+ req.responseHeaders = req.responseHeaders ? mergeHeaders(req.responseHeaders, newHeaders) : newHeaders;
33
+ }
34
+ const cleanupPromises = [];
35
+ enabledSlugs.forEach((slug)=>{
36
+ cleanupPromises.push(req.payload.delete({
37
+ collection: slug,
38
+ where: {
39
+ [tenantFieldName]: {
40
+ equals: id
41
+ }
42
+ }
43
+ }));
44
+ });
45
+ try {
46
+ const usersWithTenant = await req.payload.find({
47
+ collection: usersSlug,
48
+ depth: 0,
49
+ limit: 0,
50
+ where: {
51
+ 'tenants.tenant': {
52
+ equals: id
53
+ }
54
+ }
55
+ });
56
+ usersWithTenant?.docs?.forEach((user)=>{
57
+ cleanupPromises.push(req.payload.update({
58
+ id: user.id,
59
+ collection: usersSlug,
60
+ data: {
61
+ tenants: (user.tenants || []).filter(({ tenant: tenantID })=>tenantID !== id)
62
+ }
63
+ }));
64
+ });
65
+ } catch (e) {
66
+ console.error('Error deleting tenants from users:', e);
67
+ }
68
+ await Promise.all(cleanupPromises);
69
+ };
70
+
71
+ //# sourceMappingURL=afterTenantDelete.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/hooks/afterTenantDelete.ts"],"sourcesContent":["import type {\n CollectionAfterDeleteHook,\n CollectionConfig,\n JsonObject,\n PaginatedDocs,\n} from 'payload'\n\nimport { generateCookie, mergeHeaders } from 'payload'\n\nimport type { UserWithTenantsField } from '../types.js'\n\nimport { getTenantFromCookie } from '../utilities/getTenantFromCookie.js'\n\ntype Args = {\n collection: CollectionConfig\n enabledSlugs: string[]\n tenantFieldName: string\n usersSlug: string\n}\n/**\n * Add cleanup logic when tenant is deleted\n * - delete documents related to tenant\n * - remove tenant from users\n */\nexport const addTenantCleanup = ({\n collection,\n enabledSlugs,\n tenantFieldName,\n usersSlug,\n}: Args) => {\n if (!collection.hooks) {\n collection.hooks = {}\n }\n if (!collection.hooks?.afterDelete) {\n collection.hooks.afterDelete = []\n }\n collection.hooks.afterDelete.push(\n afterTenantDelete({\n enabledSlugs,\n tenantFieldName,\n usersSlug,\n }),\n )\n}\n\nexport const afterTenantDelete =\n ({\n enabledSlugs,\n tenantFieldName,\n usersSlug,\n }: Omit<Args, 'collection'>): CollectionAfterDeleteHook =>\n async ({ id, req }) => {\n const currentTenantCookieID = getTenantFromCookie(req.headers, req.payload.db.defaultIDType)\n if (currentTenantCookieID === id) {\n const newHeaders = new Headers({\n 'Set-Cookie': generateCookie<string>({\n name: 'payload-tenant',\n expires: new Date(Date.now() - 1000),\n path: '/',\n returnCookieAsObject: false,\n value: '',\n }),\n })\n\n req.responseHeaders = req.responseHeaders\n ? mergeHeaders(req.responseHeaders, newHeaders)\n : newHeaders\n }\n const cleanupPromises: Promise<JsonObject>[] = []\n enabledSlugs.forEach((slug) => {\n cleanupPromises.push(\n req.payload.delete({\n collection: slug,\n where: {\n [tenantFieldName]: {\n equals: id,\n },\n },\n }),\n )\n })\n\n try {\n const usersWithTenant = (await req.payload.find({\n collection: usersSlug,\n depth: 0,\n limit: 0,\n where: {\n 'tenants.tenant': {\n equals: id,\n },\n },\n })) as PaginatedDocs<UserWithTenantsField>\n\n usersWithTenant?.docs?.forEach((user) => {\n cleanupPromises.push(\n req.payload.update({\n id: user.id,\n collection: usersSlug,\n data: {\n tenants: (user.tenants || []).filter(({ tenant: tenantID }) => tenantID !== id),\n },\n }),\n )\n })\n } catch (e) {\n console.error('Error deleting tenants from users:', e)\n }\n\n await Promise.all(cleanupPromises)\n }\n"],"names":["generateCookie","mergeHeaders","getTenantFromCookie","addTenantCleanup","collection","enabledSlugs","tenantFieldName","usersSlug","hooks","afterDelete","push","afterTenantDelete","id","req","currentTenantCookieID","headers","payload","db","defaultIDType","newHeaders","Headers","name","expires","Date","now","path","returnCookieAsObject","value","responseHeaders","cleanupPromises","forEach","slug","delete","where","equals","usersWithTenant","find","depth","limit","docs","user","update","data","tenants","filter","tenant","tenantID","e","console","error","Promise","all"],"mappings":"AAOA,SAASA,cAAc,EAAEC,YAAY,QAAQ,UAAS;AAItD,SAASC,mBAAmB,QAAQ,sCAAqC;AAQzE;;;;CAIC,GACD,OAAO,MAAMC,mBAAmB,CAAC,EAC/BC,UAAU,EACVC,YAAY,EACZC,eAAe,EACfC,SAAS,EACJ;IACL,IAAI,CAACH,WAAWI,KAAK,EAAE;QACrBJ,WAAWI,KAAK,GAAG,CAAC;IACtB;IACA,IAAI,CAACJ,WAAWI,KAAK,EAAEC,aAAa;QAClCL,WAAWI,KAAK,CAACC,WAAW,GAAG,EAAE;IACnC;IACAL,WAAWI,KAAK,CAACC,WAAW,CAACC,IAAI,CAC/BC,kBAAkB;QAChBN;QACAC;QACAC;IACF;AAEJ,EAAC;AAED,OAAO,MAAMI,oBACX,CAAC,EACCN,YAAY,EACZC,eAAe,EACfC,SAAS,EACgB,GAC3B,OAAO,EAAEK,EAAE,EAAEC,GAAG,EAAE;QAChB,MAAMC,wBAAwBZ,oBAAoBW,IAAIE,OAAO,EAAEF,IAAIG,OAAO,CAACC,EAAE,CAACC,aAAa;QAC3F,IAAIJ,0BAA0BF,IAAI;YAChC,MAAMO,aAAa,IAAIC,QAAQ;gBAC7B,cAAcpB,eAAuB;oBACnCqB,MAAM;oBACNC,SAAS,IAAIC,KAAKA,KAAKC,GAAG,KAAK;oBAC/BC,MAAM;oBACNC,sBAAsB;oBACtBC,OAAO;gBACT;YACF;YAEAd,IAAIe,eAAe,GAAGf,IAAIe,eAAe,GACrC3B,aAAaY,IAAIe,eAAe,EAAET,cAClCA;QACN;QACA,MAAMU,kBAAyC,EAAE;QACjDxB,aAAayB,OAAO,CAAC,CAACC;YACpBF,gBAAgBnB,IAAI,CAClBG,IAAIG,OAAO,CAACgB,MAAM,CAAC;gBACjB5B,YAAY2B;gBACZE,OAAO;oBACL,CAAC3B,gBAAgB,EAAE;wBACjB4B,QAAQtB;oBACV;gBACF;YACF;QAEJ;QAEA,IAAI;YACF,MAAMuB,kBAAmB,MAAMtB,IAAIG,OAAO,CAACoB,IAAI,CAAC;gBAC9ChC,YAAYG;gBACZ8B,OAAO;gBACPC,OAAO;gBACPL,OAAO;oBACL,kBAAkB;wBAChBC,QAAQtB;oBACV;gBACF;YACF;YAEAuB,iBAAiBI,MAAMT,QAAQ,CAACU;gBAC9BX,gBAAgBnB,IAAI,CAClBG,IAAIG,OAAO,CAACyB,MAAM,CAAC;oBACjB7B,IAAI4B,KAAK5B,EAAE;oBACXR,YAAYG;oBACZmC,MAAM;wBACJC,SAAS,AAACH,CAAAA,KAAKG,OAAO,IAAI,EAAE,AAAD,EAAGC,MAAM,CAAC,CAAC,EAAEC,QAAQC,QAAQ,EAAE,GAAKA,aAAalC;oBAC9E;gBACF;YAEJ;QACF,EAAE,OAAOmC,GAAG;YACVC,QAAQC,KAAK,CAAC,sCAAsCF;QACtD;QAEA,MAAMG,QAAQC,GAAG,CAACtB;IACpB,EAAC"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import type { Config } from 'payload';
2
2
  import type { MultiTenantPluginConfig } from './types.js';
3
- export declare const multiTenantPlugin: (pluginConfig: MultiTenantPluginConfig) => (incomingConfig: Config) => Config;
3
+ export declare const multiTenantPlugin: <ConfigType>(pluginConfig: MultiTenantPluginConfig<ConfigType>) => (incomingConfig: Config) => Config;
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAErC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAA;AAazD,eAAO,MAAM,iBAAiB,iBACb,uBAAuB,sBACrB,MAAM,KAAG,MA+HzB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoB,MAAM,EAAE,MAAM,SAAS,CAAA;AAEvD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAA;AAezD,eAAO,MAAM,iBAAiB,GAC3B,UAAU,gBAAgB,uBAAuB,CAAC,UAAU,CAAC,sBAC7C,MAAM,KAAG,MA6MzB,CAAA"}
package/dist/index.js CHANGED
@@ -1,6 +1,8 @@
1
1
  import { tenantField } from './fields/tenantField/index.js';
2
- import { userTenantsField } from './fields/userTenantsArrayField/index.js';
3
- import { withTenantAccess } from './utilities/withTenantAccess.js';
2
+ import { tenantsArrayField } from './fields/tenantsArrayField/index.js';
3
+ import { addTenantCleanup } from './hooks/afterTenantDelete.js';
4
+ import { addCollectionAccess } from './utilities/addCollectionAccess.js';
5
+ import { addFilterOptionsToFields } from './utilities/addFilterOptionsToFields.js';
4
6
  import { withTenantListFilter } from './utilities/withTenantListFilter.js';
5
7
  const defaults = {
6
8
  tenantCollectionSlug: 'tenants',
@@ -13,9 +15,33 @@ export const multiTenantPlugin = (pluginConfig)=>(incomingConfig)=>{
13
15
  }
14
16
  /**
15
17
  * Set defaults
16
- */ pluginConfig.userHasAccessToAllTenants = typeof pluginConfig.userHasAccessToAllTenants === 'function' ? pluginConfig.userHasAccessToAllTenants : ()=>false;
18
+ */ const userHasAccessToAllTenants = typeof pluginConfig.userHasAccessToAllTenants === 'function' ? pluginConfig.userHasAccessToAllTenants : ()=>false;
17
19
  const tenantsCollectionSlug = pluginConfig.tenantsSlug = pluginConfig.tenantsSlug || defaults.tenantCollectionSlug;
18
- const tenantFieldName = pluginConfig.documentTenantField.name || defaults.tenantFieldName;
20
+ const tenantFieldName = pluginConfig?.tenantField?.name || defaults.tenantFieldName;
21
+ /**
22
+ * Add defaults for admin properties
23
+ */ if (!incomingConfig.admin) {
24
+ incomingConfig.admin = {};
25
+ }
26
+ if (!incomingConfig.admin?.components) {
27
+ incomingConfig.admin.components = {
28
+ actions: [],
29
+ beforeNavLinks: [],
30
+ providers: []
31
+ };
32
+ }
33
+ if (!incomingConfig.admin.components?.providers) {
34
+ incomingConfig.admin.components.providers = [];
35
+ }
36
+ if (!incomingConfig.admin.components?.actions) {
37
+ incomingConfig.admin.components.actions = [];
38
+ }
39
+ if (!incomingConfig.admin.components?.beforeNavLinks) {
40
+ incomingConfig.admin.components.beforeNavLinks = [];
41
+ }
42
+ if (!incomingConfig.collections) {
43
+ incomingConfig.collections = [];
44
+ }
19
45
  /**
20
46
  * Add tenants array field to users collection
21
47
  */ const adminUsersCollection = incomingConfig.collections.find(({ slug, auth })=>{
@@ -25,86 +51,123 @@ export const multiTenantPlugin = (pluginConfig)=>(incomingConfig)=>{
25
51
  return true;
26
52
  }
27
53
  });
28
- adminUsersCollection.fields.push(userTenantsField(pluginConfig?.userTenantsField || {}));
29
- const globalCollectionSlugs = [];
54
+ if (!adminUsersCollection) {
55
+ throw Error('An auth enabled collection was not found');
56
+ }
57
+ /**
58
+ * Add tenants array field to users collection
59
+ */ if (pluginConfig?.tenantsArrayField?.includeDefaultField !== false) {
60
+ adminUsersCollection.fields.push(tenantsArrayField(pluginConfig?.tenantsArrayField || {}));
61
+ }
62
+ let tenantCollection;
63
+ const [collectionSlugs, globalCollectionSlugs] = Object.keys(pluginConfig.collections).reduce((acc, slug)=>{
64
+ if (pluginConfig?.collections?.[slug]?.isGlobal) {
65
+ acc[1].push(slug);
66
+ } else {
67
+ acc[0].push(slug);
68
+ }
69
+ return acc;
70
+ }, [
71
+ [],
72
+ []
73
+ ]);
30
74
  /**
31
75
  * Modify collections
32
76
  */ incomingConfig.collections.forEach((collection)=>{
33
- if (collection.slug === tenantsCollectionSlug) {
34
- /**
35
- * Modify tenants collection
36
- */ collection.access = Object.keys(collection.access || {}).reduce((acc, key)=>{
37
- const accessFunction = collection.access[key];
38
- acc[key] = withTenantAccess({
39
- accessFunction,
40
- userHasAccessToAllTenants: pluginConfig.userHasAccessToAllTenants
77
+ /**
78
+ * Modify tenants collection
79
+ */ if (collection.slug === tenantsCollectionSlug) {
80
+ tenantCollection = collection;
81
+ addCollectionAccess({
82
+ collection,
83
+ fieldName: 'id',
84
+ userHasAccessToAllTenants
85
+ });
86
+ if (pluginConfig.cleanupAfterTenantDelete !== false) {
87
+ /**
88
+ * Add cleanup logic when tenant is deleted
89
+ * - delete documents related to tenant
90
+ * - remove tenant from users
91
+ */ addTenantCleanup({
92
+ collection,
93
+ enabledSlugs: [
94
+ ...collectionSlugs,
95
+ ...globalCollectionSlugs
96
+ ],
97
+ tenantFieldName,
98
+ usersSlug: adminUsersCollection.slug
41
99
  });
42
- return acc;
43
- }, {});
100
+ }
44
101
  } else if (pluginConfig.collections?.[collection.slug]) {
45
- if (!collection.admin) {
46
- collection.admin = {};
102
+ const isGlobal = Boolean(pluginConfig.collections[collection.slug]?.isGlobal);
103
+ if (isGlobal) {
104
+ collection.disableDuplicate = true;
47
105
  }
48
106
  /**
107
+ * Modify enabled collections
108
+ */ addFilterOptionsToFields({
109
+ fields: collection.fields,
110
+ tenantEnabledCollectionSlugs: collectionSlugs,
111
+ tenantEnabledGlobalSlugs: globalCollectionSlugs
112
+ });
113
+ /**
49
114
  * Add tenant field to enabled collections
50
- */ collection.fields.push(tenantField({
51
- ...pluginConfig.documentTenantField,
115
+ */ collection.fields.splice(0, 0, tenantField({
116
+ ...pluginConfig?.tenantField || {},
52
117
  name: tenantFieldName,
53
118
  debug: pluginConfig.debug,
54
119
  tenantsCollectionSlug,
55
- unique: Boolean(pluginConfig.collections[collection.slug].isGlobal)
120
+ unique: isGlobal
56
121
  }));
57
- if (pluginConfig.collections[collection.slug].useBaseListFilter !== false) {
122
+ if (pluginConfig.collections[collection.slug]?.useBaseListFilter !== false) {
58
123
  /**
59
124
  * Collection baseListFilter with selected tenant constraint (if selected)
60
- */ collection.admin.baseListFilter = withTenantListFilter({
125
+ */ if (!collection.admin) {
126
+ collection.admin = {};
127
+ }
128
+ collection.admin.baseListFilter = withTenantListFilter({
61
129
  baseListFilter: collection.admin?.baseListFilter,
62
130
  tenantFieldName
63
131
  });
64
132
  }
65
- if (pluginConfig.collections[collection.slug].useTenantAccess !== false) {
133
+ if (pluginConfig.collections[collection.slug]?.useTenantAccess !== false) {
66
134
  /**
67
- * Collection access functions with user assigned tenant constraints
68
- */ collection.access = Object.keys(collection.access || {}).reduce((acc, key)=>{
69
- const accessFunction = collection.access[key];
70
- acc[key] = withTenantAccess({
71
- accessFunction,
72
- userHasAccessToAllTenants: pluginConfig.userHasAccessToAllTenants
73
- });
74
- return acc;
75
- }, {});
76
- }
77
- if (pluginConfig.collections[collection.slug].isGlobal) {
78
- globalCollectionSlugs.push(collection.slug);
135
+ * Add access control constraint to tenant enabled collection
136
+ */ addCollectionAccess({
137
+ collection,
138
+ fieldName: tenantFieldName,
139
+ userHasAccessToAllTenants
140
+ });
79
141
  }
80
142
  }
81
143
  });
82
- if (!incomingConfig.admin?.components) {
83
- incomingConfig.admin.components = {
84
- actions: [],
85
- beforeNavLinks: []
86
- };
144
+ if (!tenantCollection) {
145
+ throw new Error(`Tenants collection not found with slug: ${tenantsCollectionSlug}`);
87
146
  }
88
147
  /**
148
+ * Add TenantSelectionProvider to admin providers
149
+ */ incomingConfig.admin.components.providers.push({
150
+ clientProps: {
151
+ tenantsCollectionSlug: tenantCollection.slug,
152
+ useAsTitle: tenantCollection.admin?.useAsTitle || 'id'
153
+ },
154
+ path: '@payloadcms/plugin-multi-tenant/rsc#TenantSelectionProvider'
155
+ });
156
+ /**
89
157
  * Add global redirect action
90
158
  */ if (globalCollectionSlugs.length) {
91
159
  incomingConfig.admin.components.actions.push({
92
160
  path: '@payloadcms/plugin-multi-tenant/rsc#GlobalViewRedirect',
93
161
  serverProps: {
94
- globalSlugs: globalCollectionSlugs
162
+ globalSlugs: globalCollectionSlugs,
163
+ tenantFieldName
95
164
  }
96
165
  });
97
166
  }
98
- if (!incomingConfig.admin.components.beforeNavLinks) {
99
- incomingConfig.admin.components.beforeNavLinks = [];
100
- }
101
167
  /**
102
168
  * Add tenant selector to admin UI
103
169
  */ incomingConfig.admin.components.beforeNavLinks.push({
104
- clientProps: {
105
- tenantsCollectionSlug
106
- },
107
- path: '@payloadcms/plugin-multi-tenant/rsc#TenantSelector'
170
+ path: '@payloadcms/plugin-multi-tenant/client#TenantSelector'
108
171
  });
109
172
  return incomingConfig;
110
173
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { Config } from 'payload'\n\nimport type { MultiTenantPluginConfig } from './types.js'\n\nimport { tenantField } from './fields/tenantField/index.js'\nimport { userTenantsField } from './fields/userTenantsArrayField/index.js'\nimport { withTenantAccess } from './utilities/withTenantAccess.js'\nimport { withTenantListFilter } from './utilities/withTenantListFilter.js'\n\nconst defaults = {\n tenantCollectionSlug: 'tenants',\n tenantFieldName: 'tenant',\n userTenantsArrayFieldName: 'tenants',\n}\n\nexport const multiTenantPlugin =\n (pluginConfig: MultiTenantPluginConfig) =>\n (incomingConfig: Config): Config => {\n if (pluginConfig.enabled === false) {\n return incomingConfig\n }\n\n /**\n * Set defaults\n */\n pluginConfig.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.documentTenantField.name || defaults.tenantFieldName\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 adminUsersCollection.fields.push(userTenantsField(pluginConfig?.userTenantsField || {}))\n\n const globalCollectionSlugs = []\n\n /**\n * Modify collections\n */\n incomingConfig.collections.forEach((collection) => {\n if (collection.slug === tenantsCollectionSlug) {\n /**\n * Modify tenants collection\n */\n collection.access = Object.keys(collection.access || {}).reduce((acc, key) => {\n const accessFunction = collection.access[key]\n acc[key] = withTenantAccess({\n accessFunction,\n userHasAccessToAllTenants: pluginConfig.userHasAccessToAllTenants,\n })\n\n return acc\n }, {})\n } else if (pluginConfig.collections?.[collection.slug]) {\n if (!collection.admin) {\n collection.admin = {}\n }\n /**\n * Add tenant field to enabled collections\n */\n collection.fields.push(\n tenantField({\n ...pluginConfig.documentTenantField,\n name: tenantFieldName,\n debug: pluginConfig.debug,\n tenantsCollectionSlug,\n unique: Boolean(pluginConfig.collections[collection.slug].isGlobal),\n }),\n )\n\n if (pluginConfig.collections[collection.slug].useBaseListFilter !== false) {\n /**\n * Collection baseListFilter with selected tenant constraint (if selected)\n */\n collection.admin.baseListFilter = withTenantListFilter({\n baseListFilter: collection.admin?.baseListFilter,\n tenantFieldName,\n })\n }\n\n if (pluginConfig.collections[collection.slug].useTenantAccess !== false) {\n /**\n * Collection access functions with user assigned tenant constraints\n */\n collection.access = Object.keys(collection.access || {}).reduce((acc, key) => {\n const accessFunction = collection.access[key]\n acc[key] = withTenantAccess({\n accessFunction,\n userHasAccessToAllTenants: pluginConfig.userHasAccessToAllTenants,\n })\n\n return acc\n }, {})\n }\n\n if (pluginConfig.collections[collection.slug].isGlobal) {\n globalCollectionSlugs.push(collection.slug)\n }\n }\n })\n\n if (!incomingConfig.admin?.components) {\n incomingConfig.admin.components = {\n actions: [],\n beforeNavLinks: [],\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 globalSlugs: globalCollectionSlugs,\n },\n })\n }\n\n if (!incomingConfig.admin.components.beforeNavLinks) {\n incomingConfig.admin.components.beforeNavLinks = []\n }\n /**\n * Add tenant selector to admin UI\n */\n incomingConfig.admin.components.beforeNavLinks.push({\n clientProps: {\n tenantsCollectionSlug,\n },\n path: '@payloadcms/plugin-multi-tenant/rsc#TenantSelector',\n })\n\n return incomingConfig\n }\n"],"names":["tenantField","userTenantsField","withTenantAccess","withTenantListFilter","defaults","tenantCollectionSlug","tenantFieldName","userTenantsArrayFieldName","multiTenantPlugin","pluginConfig","incomingConfig","enabled","userHasAccessToAllTenants","tenantsCollectionSlug","tenantsSlug","documentTenantField","name","adminUsersCollection","collections","find","slug","auth","admin","user","fields","push","globalCollectionSlugs","forEach","collection","access","Object","keys","reduce","acc","key","accessFunction","debug","unique","Boolean","isGlobal","useBaseListFilter","baseListFilter","useTenantAccess","components","actions","beforeNavLinks","length","path","serverProps","globalSlugs","clientProps"],"mappings":"AAIA,SAASA,WAAW,QAAQ,gCAA+B;AAC3D,SAASC,gBAAgB,QAAQ,0CAAyC;AAC1E,SAASC,gBAAgB,QAAQ,kCAAiC;AAClE,SAASC,oBAAoB,QAAQ,sCAAqC;AAE1E,MAAMC,WAAW;IACfC,sBAAsB;IACtBC,iBAAiB;IACjBC,2BAA2B;AAC7B;AAEA,OAAO,MAAMC,oBACX,CAACC,eACD,CAACC;QACC,IAAID,aAAaE,OAAO,KAAK,OAAO;YAClC,OAAOD;QACT;QAEA;;KAEC,GACDD,aAAaG,yBAAyB,GACpC,OAAOH,aAAaG,yBAAyB,KAAK,aAC9CH,aAAaG,yBAAyB,GACtC,IAAM;QACZ,MAAMC,wBAAyBJ,aAAaK,WAAW,GACrDL,aAAaK,WAAW,IAAIV,SAASC,oBAAoB;QAC3D,MAAMC,kBAAkBG,aAAaM,mBAAmB,CAACC,IAAI,IAAIZ,SAASE,eAAe;QAEzF;;KAEC,GACD,MAAMW,uBAAuBP,eAAeQ,WAAW,CAACC,IAAI,CAAC,CAAC,EAAEC,IAAI,EAAEC,IAAI,EAAE;YAC1E,IAAIX,eAAeY,KAAK,EAAEC,MAAM;gBAC9B,OAAOH,SAASV,eAAeY,KAAK,CAACC,IAAI;YAC3C,OAAO,IAAIF,MAAM;gBACf,OAAO;YACT;QACF;QACAJ,qBAAqBO,MAAM,CAACC,IAAI,CAACxB,iBAAiBQ,cAAcR,oBAAoB,CAAC;QAErF,MAAMyB,wBAAwB,EAAE;QAEhC;;KAEC,GACDhB,eAAeQ,WAAW,CAACS,OAAO,CAAC,CAACC;YAClC,IAAIA,WAAWR,IAAI,KAAKP,uBAAuB;gBAC7C;;SAEC,GACDe,WAAWC,MAAM,GAAGC,OAAOC,IAAI,CAACH,WAAWC,MAAM,IAAI,CAAC,GAAGG,MAAM,CAAC,CAACC,KAAKC;oBACpE,MAAMC,iBAAiBP,WAAWC,MAAM,CAACK,IAAI;oBAC7CD,GAAG,CAACC,IAAI,GAAGhC,iBAAiB;wBAC1BiC;wBACAvB,2BAA2BH,aAAaG,yBAAyB;oBACnE;oBAEA,OAAOqB;gBACT,GAAG,CAAC;YACN,OAAO,IAAIxB,aAAaS,WAAW,EAAE,CAACU,WAAWR,IAAI,CAAC,EAAE;gBACtD,IAAI,CAACQ,WAAWN,KAAK,EAAE;oBACrBM,WAAWN,KAAK,GAAG,CAAC;gBACtB;gBACA;;SAEC,GACDM,WAAWJ,MAAM,CAACC,IAAI,CACpBzB,YAAY;oBACV,GAAGS,aAAaM,mBAAmB;oBACnCC,MAAMV;oBACN8B,OAAO3B,aAAa2B,KAAK;oBACzBvB;oBACAwB,QAAQC,QAAQ7B,aAAaS,WAAW,CAACU,WAAWR,IAAI,CAAC,CAACmB,QAAQ;gBACpE;gBAGF,IAAI9B,aAAaS,WAAW,CAACU,WAAWR,IAAI,CAAC,CAACoB,iBAAiB,KAAK,OAAO;oBACzE;;WAEC,GACDZ,WAAWN,KAAK,CAACmB,cAAc,GAAGtC,qBAAqB;wBACrDsC,gBAAgBb,WAAWN,KAAK,EAAEmB;wBAClCnC;oBACF;gBACF;gBAEA,IAAIG,aAAaS,WAAW,CAACU,WAAWR,IAAI,CAAC,CAACsB,eAAe,KAAK,OAAO;oBACvE;;WAEC,GACDd,WAAWC,MAAM,GAAGC,OAAOC,IAAI,CAACH,WAAWC,MAAM,IAAI,CAAC,GAAGG,MAAM,CAAC,CAACC,KAAKC;wBACpE,MAAMC,iBAAiBP,WAAWC,MAAM,CAACK,IAAI;wBAC7CD,GAAG,CAACC,IAAI,GAAGhC,iBAAiB;4BAC1BiC;4BACAvB,2BAA2BH,aAAaG,yBAAyB;wBACnE;wBAEA,OAAOqB;oBACT,GAAG,CAAC;gBACN;gBAEA,IAAIxB,aAAaS,WAAW,CAACU,WAAWR,IAAI,CAAC,CAACmB,QAAQ,EAAE;oBACtDb,sBAAsBD,IAAI,CAACG,WAAWR,IAAI;gBAC5C;YACF;QACF;QAEA,IAAI,CAACV,eAAeY,KAAK,EAAEqB,YAAY;YACrCjC,eAAeY,KAAK,CAACqB,UAAU,GAAG;gBAChCC,SAAS,EAAE;gBACXC,gBAAgB,EAAE;YACpB;QACF;QACA;;KAEC,GACD,IAAInB,sBAAsBoB,MAAM,EAAE;YAChCpC,eAAeY,KAAK,CAACqB,UAAU,CAACC,OAAO,CAACnB,IAAI,CAAC;gBAC3CsB,MAAM;gBACNC,aAAa;oBACXC,aAAavB;gBACf;YACF;QACF;QAEA,IAAI,CAAChB,eAAeY,KAAK,CAACqB,UAAU,CAACE,cAAc,EAAE;YACnDnC,eAAeY,KAAK,CAACqB,UAAU,CAACE,cAAc,GAAG,EAAE;QACrD;QACA;;KAEC,GACDnC,eAAeY,KAAK,CAACqB,UAAU,CAACE,cAAc,CAACpB,IAAI,CAAC;YAClDyB,aAAa;gBACXrC;YACF;YACAkC,MAAM;QACR;QAEA,OAAOrC;IACT,EAAC"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { CollectionConfig, Config } from 'payload'\n\nimport type { MultiTenantPluginConfig } from './types.js'\n\nimport { tenantField } from './fields/tenantField/index.js'\nimport { tenantsArrayField } from './fields/tenantsArrayField/index.js'\nimport { addTenantCleanup } from './hooks/afterTenantDelete.js'\nimport { addCollectionAccess } from './utilities/addCollectionAccess.js'\nimport { addFilterOptionsToFields } from './utilities/addFilterOptionsToFields.js'\nimport { withTenantListFilter } from './utilities/withTenantListFilter.js'\n\nconst defaults = {\n tenantCollectionSlug: 'tenants',\n tenantFieldName: 'tenant',\n userTenantsArrayFieldName: 'tenants',\n}\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\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 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(tenantsArrayField(pluginConfig?.tenantsArrayField || {}))\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 addCollectionAccess({\n collection,\n fieldName: 'id',\n userHasAccessToAllTenants,\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 usersSlug: adminUsersCollection.slug,\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 fields: collection.fields,\n tenantEnabledCollectionSlugs: collectionSlugs,\n tenantEnabledGlobalSlugs: globalCollectionSlugs,\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 * Collection baseListFilter with selected tenant constraint (if selected)\n */\n if (!collection.admin) {\n collection.admin = {}\n }\n collection.admin.baseListFilter = withTenantListFilter({\n baseListFilter: collection.admin?.baseListFilter,\n tenantFieldName,\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 collection,\n fieldName: tenantFieldName,\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 globalSlugs: globalCollectionSlugs,\n tenantFieldName,\n },\n })\n }\n\n /**\n * Add tenant selector to admin UI\n */\n incomingConfig.admin.components.beforeNavLinks.push({\n path: '@payloadcms/plugin-multi-tenant/client#TenantSelector',\n })\n\n return incomingConfig\n }\n"],"names":["tenantField","tenantsArrayField","addTenantCleanup","addCollectionAccess","addFilterOptionsToFields","withTenantListFilter","defaults","tenantCollectionSlug","tenantFieldName","userTenantsArrayFieldName","multiTenantPlugin","pluginConfig","incomingConfig","enabled","userHasAccessToAllTenants","tenantsCollectionSlug","tenantsSlug","name","admin","components","actions","beforeNavLinks","providers","collections","adminUsersCollection","find","slug","auth","user","Error","includeDefaultField","fields","push","tenantCollection","collectionSlugs","globalCollectionSlugs","Object","keys","reduce","acc","isGlobal","forEach","collection","fieldName","cleanupAfterTenantDelete","enabledSlugs","usersSlug","Boolean","disableDuplicate","tenantEnabledCollectionSlugs","tenantEnabledGlobalSlugs","splice","debug","unique","useBaseListFilter","baseListFilter","useTenantAccess","clientProps","useAsTitle","path","length","serverProps","globalSlugs"],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { OptionObject } from 'payload';
2
+ import React from 'react';
3
+ type ContextType = {
4
+ options: OptionObject[];
5
+ selectedTenantID: number | string | undefined;
6
+ setPreventRefreshOnChange: React.Dispatch<React.SetStateAction<boolean>>;
7
+ setTenant: (args: {
8
+ id: number | string | undefined;
9
+ refresh?: boolean;
10
+ }) => void;
11
+ };
12
+ export declare const TenantSelectionProviderClient: ({ children, initialValue, tenantOptions, }: {
13
+ children: React.ReactNode;
14
+ initialValue?: string;
15
+ tenantOptions: OptionObject[];
16
+ }) => React.JSX.Element;
17
+ export declare const useTenantSelection: () => ContextType;
18
+ export {};
19
+ //# sourceMappingURL=index.client.d.ts.map
@@ -0,0 +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;AAG3C,OAAO,KAAwB,MAAM,OAAO,CAAA;AAI5C,KAAK,WAAW,GAAG;IACjB,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB,gBAAgB,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;IAC7C,yBAAyB,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAA;IACxE,SAAS,EAAE,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAA;CAClF,CAAA;AASD,eAAO,MAAM,6BAA6B,+CAIvC;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,EAAE,YAAY,EAAE,CAAA;CAC9B,sBAuDA,CAAA;AAED,eAAO,MAAM,kBAAkB,mBAAkC,CAAA"}
@@ -0,0 +1,69 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { useRouter } from 'next/navigation.js';
4
+ import React, { createContext } from 'react';
5
+ import { SELECT_ALL } from '../../constants.js';
6
+ const Context = /*#__PURE__*/ createContext({
7
+ options: [],
8
+ selectedTenantID: undefined,
9
+ setPreventRefreshOnChange: ()=>null,
10
+ setTenant: ()=>null
11
+ });
12
+ export const TenantSelectionProviderClient = ({ children, initialValue, tenantOptions })=>{
13
+ const [selectedTenantID, setSelectedTenantID] = React.useState(initialValue || SELECT_ALL);
14
+ const [preventRefreshOnChange, setPreventRefreshOnChange] = React.useState(false);
15
+ const router = useRouter();
16
+ const setCookie = React.useCallback((value)=>{
17
+ const expires = '; expires=Fri, 31 Dec 9999 23:59:59 GMT';
18
+ document.cookie = 'payload-tenant=' + (value || '') + expires + '; path=/';
19
+ }, []);
20
+ const setTenant = React.useCallback(({ id, refresh })=>{
21
+ if (id === undefined) {
22
+ setSelectedTenantID(SELECT_ALL);
23
+ setCookie(SELECT_ALL);
24
+ } else {
25
+ setSelectedTenantID(id);
26
+ setCookie(String(id));
27
+ }
28
+ if (!preventRefreshOnChange && refresh) {
29
+ router.refresh();
30
+ }
31
+ }, [
32
+ setSelectedTenantID,
33
+ setCookie,
34
+ router,
35
+ preventRefreshOnChange
36
+ ]);
37
+ React.useEffect(()=>{
38
+ if (selectedTenantID && selectedTenantID !== SELECT_ALL && !tenantOptions.find((option)=>option.value === selectedTenantID)) {
39
+ if (tenantOptions?.[0]?.value) {
40
+ setTenant({
41
+ id: tenantOptions[0].value,
42
+ refresh: true
43
+ });
44
+ } else {
45
+ setTenant({
46
+ id: undefined,
47
+ refresh: true
48
+ });
49
+ }
50
+ }
51
+ }, [
52
+ initialValue,
53
+ setTenant,
54
+ selectedTenantID,
55
+ tenantOptions
56
+ ]);
57
+ return /*#__PURE__*/ _jsx(Context.Provider, {
58
+ value: {
59
+ options: tenantOptions,
60
+ selectedTenantID,
61
+ setPreventRefreshOnChange,
62
+ setTenant
63
+ },
64
+ children: children
65
+ });
66
+ };
67
+ export const useTenantSelection = ()=>React.useContext(Context);
68
+
69
+ //# sourceMappingURL=index.client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/providers/TenantSelectionProvider/index.client.tsx"],"sourcesContent":["'use client'\n\nimport type { OptionObject } from 'payload'\n\nimport { useRouter } from 'next/navigation.js'\nimport React, { createContext } from 'react'\n\nimport { SELECT_ALL } from '../../constants.js'\n\ntype ContextType = {\n options: OptionObject[]\n selectedTenantID: number | string | undefined\n setPreventRefreshOnChange: React.Dispatch<React.SetStateAction<boolean>>\n setTenant: (args: { id: number | string | undefined; refresh?: boolean }) => void\n}\n\nconst Context = createContext<ContextType>({\n options: [],\n selectedTenantID: undefined,\n setPreventRefreshOnChange: () => null,\n setTenant: () => null,\n})\n\nexport const TenantSelectionProviderClient = ({\n children,\n initialValue,\n tenantOptions,\n}: {\n children: React.ReactNode\n initialValue?: string\n tenantOptions: OptionObject[]\n}) => {\n const [selectedTenantID, setSelectedTenantID] = React.useState<number | string>(\n initialValue || SELECT_ALL,\n )\n const [preventRefreshOnChange, setPreventRefreshOnChange] = React.useState(false)\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 setTenant = React.useCallback<ContextType['setTenant']>(\n ({ id, refresh }) => {\n if (id === undefined) {\n setSelectedTenantID(SELECT_ALL)\n setCookie(SELECT_ALL)\n } else {\n setSelectedTenantID(id)\n setCookie(String(id))\n }\n if (!preventRefreshOnChange && refresh) {\n router.refresh()\n }\n },\n [setSelectedTenantID, setCookie, router, preventRefreshOnChange],\n )\n\n React.useEffect(() => {\n if (\n selectedTenantID &&\n selectedTenantID !== SELECT_ALL &&\n !tenantOptions.find((option) => option.value === selectedTenantID)\n ) {\n if (tenantOptions?.[0]?.value) {\n setTenant({ id: tenantOptions[0].value, refresh: true })\n } else {\n setTenant({ id: undefined, refresh: true })\n }\n }\n }, [initialValue, setTenant, selectedTenantID, tenantOptions])\n\n return (\n <Context.Provider\n value={{\n options: tenantOptions,\n selectedTenantID,\n setPreventRefreshOnChange,\n setTenant,\n }}\n >\n {children}\n </Context.Provider>\n )\n}\n\nexport const useTenantSelection = () => React.useContext(Context)\n"],"names":["useRouter","React","createContext","SELECT_ALL","Context","options","selectedTenantID","undefined","setPreventRefreshOnChange","setTenant","TenantSelectionProviderClient","children","initialValue","tenantOptions","setSelectedTenantID","useState","preventRefreshOnChange","router","setCookie","useCallback","value","expires","document","cookie","id","refresh","String","useEffect","find","option","Provider","useTenantSelection","useContext"],"mappings":"AAAA;;AAIA,SAASA,SAAS,QAAQ,qBAAoB;AAC9C,OAAOC,SAASC,aAAa,QAAQ,QAAO;AAE5C,SAASC,UAAU,QAAQ,qBAAoB;AAS/C,MAAMC,wBAAUF,cAA2B;IACzCG,SAAS,EAAE;IACXC,kBAAkBC;IAClBC,2BAA2B,IAAM;IACjCC,WAAW,IAAM;AACnB;AAEA,OAAO,MAAMC,gCAAgC,CAAC,EAC5CC,QAAQ,EACRC,YAAY,EACZC,aAAa,EAKd;IACC,MAAM,CAACP,kBAAkBQ,oBAAoB,GAAGb,MAAMc,QAAQ,CAC5DH,gBAAgBT;IAElB,MAAM,CAACa,wBAAwBR,0BAA0B,GAAGP,MAAMc,QAAQ,CAAC;IAE3E,MAAME,SAASjB;IAEf,MAAMkB,YAAYjB,MAAMkB,WAAW,CAAC,CAACC;QACnC,MAAMC,UAAU;QAChBC,SAASC,MAAM,GAAG,oBAAqBH,CAAAA,SAAS,EAAC,IAAKC,UAAU;IAClE,GAAG,EAAE;IAEL,MAAMZ,YAAYR,MAAMkB,WAAW,CACjC,CAAC,EAAEK,EAAE,EAAEC,OAAO,EAAE;QACd,IAAID,OAAOjB,WAAW;YACpBO,oBAAoBX;YACpBe,UAAUf;QACZ,OAAO;YACLW,oBAAoBU;YACpBN,UAAUQ,OAAOF;QACnB;QACA,IAAI,CAACR,0BAA0BS,SAAS;YACtCR,OAAOQ,OAAO;QAChB;IACF,GACA;QAACX;QAAqBI;QAAWD;QAAQD;KAAuB;IAGlEf,MAAM0B,SAAS,CAAC;QACd,IACErB,oBACAA,qBAAqBH,cACrB,CAACU,cAAce,IAAI,CAAC,CAACC,SAAWA,OAAOT,KAAK,KAAKd,mBACjD;YACA,IAAIO,eAAe,CAAC,EAAE,EAAEO,OAAO;gBAC7BX,UAAU;oBAAEe,IAAIX,aAAa,CAAC,EAAE,CAACO,KAAK;oBAAEK,SAAS;gBAAK;YACxD,OAAO;gBACLhB,UAAU;oBAAEe,IAAIjB;oBAAWkB,SAAS;gBAAK;YAC3C;QACF;IACF,GAAG;QAACb;QAAcH;QAAWH;QAAkBO;KAAc;IAE7D,qBACE,KAACT,QAAQ0B,QAAQ;QACfV,OAAO;YACLf,SAASQ;YACTP;YACAE;YACAC;QACF;kBAECE;;AAGP,EAAC;AAED,OAAO,MAAMoB,qBAAqB,IAAM9B,MAAM+B,UAAU,CAAC5B,SAAQ"}
@@ -0,0 +1,11 @@
1
+ import type { Payload, User } from 'payload';
2
+ type Args = {
3
+ children: React.ReactNode;
4
+ payload: Payload;
5
+ tenantsCollectionSlug: string;
6
+ useAsTitle: string;
7
+ user: User;
8
+ };
9
+ export declare const TenantSelectionProvider: ({ children, payload, tenantsCollectionSlug, useAsTitle, user, }: Args) => Promise<import("react").JSX.Element>;
10
+ export {};
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/TenantSelectionProvider/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgB,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAM1D,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,IAAI,CAAA;CACX,CAAA;AAED,eAAO,MAAM,uBAAuB,oEAMjC,IAAI,yCA0BN,CAAA"}