@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.
- package/README.md +130 -95
- package/dist/components/GlobalViewRedirect/index.d.ts +3 -2
- package/dist/components/GlobalViewRedirect/index.d.ts.map +1 -1
- package/dist/components/GlobalViewRedirect/index.js +1 -0
- package/dist/components/GlobalViewRedirect/index.js.map +1 -1
- package/dist/components/TenantField/index.client.d.ts +3 -3
- package/dist/components/TenantField/index.client.d.ts.map +1 -1
- package/dist/components/TenantField/index.client.js +55 -17
- package/dist/components/TenantField/index.client.js.map +1 -1
- package/dist/components/TenantField/index.scss +14 -0
- package/dist/components/TenantSelector/index.d.ts +5 -8
- package/dist/components/TenantSelector/index.d.ts.map +1 -1
- package/dist/components/TenantSelector/index.js +35 -24
- package/dist/components/TenantSelector/index.js.map +1 -1
- package/dist/constants.d.ts +2 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +4 -0
- package/dist/constants.js.map +1 -0
- package/dist/exports/client.d.ts +3 -0
- package/dist/exports/client.d.ts.map +1 -0
- package/dist/exports/client.js +4 -0
- package/dist/exports/client.js.map +1 -0
- package/dist/exports/fields.d.ts +3 -0
- package/dist/exports/fields.d.ts.map +1 -0
- package/dist/exports/fields.js +4 -0
- package/dist/exports/fields.js.map +1 -0
- package/dist/exports/rsc.d.ts +1 -2
- package/dist/exports/rsc.d.ts.map +1 -1
- package/dist/exports/rsc.js +1 -2
- package/dist/exports/rsc.js.map +1 -1
- package/dist/fields/tenantField/index.d.ts +2 -3
- package/dist/fields/tenantField/index.d.ts.map +1 -1
- package/dist/fields/tenantField/index.js +8 -4
- package/dist/fields/tenantField/index.js.map +1 -1
- package/dist/fields/tenantsArrayField/index.d.ts +7 -0
- package/dist/fields/tenantsArrayField/index.d.ts.map +1 -0
- package/dist/fields/{userTenantsArrayField → tenantsArrayField}/index.js +3 -3
- package/dist/fields/tenantsArrayField/index.js.map +1 -0
- package/dist/hooks/afterTenantDelete.d.ts +16 -0
- package/dist/hooks/afterTenantDelete.d.ts.map +1 -0
- package/dist/hooks/afterTenantDelete.js +71 -0
- package/dist/hooks/afterTenantDelete.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +112 -49
- package/dist/index.js.map +1 -1
- package/dist/providers/TenantSelectionProvider/index.client.d.ts +19 -0
- package/dist/providers/TenantSelectionProvider/index.client.d.ts.map +1 -0
- package/dist/providers/TenantSelectionProvider/index.client.js +69 -0
- package/dist/providers/TenantSelectionProvider/index.client.js.map +1 -0
- package/dist/providers/TenantSelectionProvider/index.d.ts +11 -0
- package/dist/providers/TenantSelectionProvider/index.d.ts.map +1 -0
- package/dist/providers/TenantSelectionProvider/index.js +31 -0
- package/dist/providers/TenantSelectionProvider/index.js.map +1 -0
- package/dist/types.d.ts +54 -17
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utilities/addCollectionAccess.d.ts +13 -0
- package/dist/utilities/addCollectionAccess.d.ts.map +1 -0
- package/dist/utilities/addCollectionAccess.js +29 -0
- package/dist/utilities/addCollectionAccess.js.map +1 -0
- package/dist/utilities/addFilterOptionsToFields.d.ts +9 -0
- package/dist/utilities/addFilterOptionsToFields.d.ts.map +1 -0
- package/dist/utilities/addFilterOptionsToFields.js +107 -0
- package/dist/utilities/addFilterOptionsToFields.js.map +1 -0
- package/dist/utilities/combineWhereConstraints.js +2 -2
- package/dist/utilities/combineWhereConstraints.js.map +1 -1
- package/dist/utilities/getGlobalViewRedirect.d.ts +4 -3
- package/dist/utilities/getGlobalViewRedirect.d.ts.map +1 -1
- package/dist/utilities/getGlobalViewRedirect.js +6 -5
- package/dist/utilities/getGlobalViewRedirect.js.map +1 -1
- package/dist/utilities/getTenantAccess.d.ts +7 -3
- package/dist/utilities/getTenantAccess.d.ts.map +1 -1
- package/dist/utilities/getTenantAccess.js +6 -9
- package/dist/utilities/getTenantAccess.js.map +1 -1
- package/dist/utilities/getTenantFromCookie.d.ts +8 -1
- package/dist/utilities/getTenantFromCookie.d.ts.map +1 -1
- package/dist/utilities/getTenantFromCookie.js +7 -1
- package/dist/utilities/getTenantFromCookie.js.map +1 -1
- package/dist/utilities/getTenantListFilter.d.ts.map +1 -1
- package/dist/utilities/getTenantListFilter.js +8 -8
- package/dist/utilities/getTenantListFilter.js.map +1 -1
- package/dist/utilities/getUserTenantIDs.d.ts +1 -2
- package/dist/utilities/getUserTenantIDs.d.ts.map +1 -1
- package/dist/utilities/getUserTenantIDs.js +2 -6
- package/dist/utilities/getUserTenantIDs.js.map +1 -1
- package/dist/utilities/withTenantAccess.d.ts +4 -3
- package/dist/utilities/withTenantAccess.d.ts.map +1 -1
- package/dist/utilities/withTenantAccess.js +12 -16
- package/dist/utilities/withTenantAccess.js.map +1 -1
- package/dist/utilities/withTenantListFilter.js +1 -1
- package/dist/utilities/withTenantListFilter.js.map +1 -1
- package/package.json +20 -10
- package/dist/components/TenantField/index.d.ts +0 -3
- package/dist/components/TenantField/index.d.ts.map +0 -1
- package/dist/components/TenantField/index.js +0 -33
- package/dist/components/TenantField/index.js.map +0 -1
- package/dist/components/TenantSelector/index.client.d.ts +0 -11
- package/dist/components/TenantSelector/index.client.d.ts.map +0 -1
- package/dist/components/TenantSelector/index.client.js +0 -61
- package/dist/components/TenantSelector/index.client.js.map +0 -1
- package/dist/fields/userTenantsArrayField/index.d.ts +0 -4
- package/dist/fields/userTenantsArrayField/index.d.ts.map +0 -1
- package/dist/fields/userTenantsArrayField/index.js.map +0 -1
package/dist/exports/rsc.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/exports/rsc.ts"],"sourcesContent":["export { GlobalViewRedirect } from '../components/GlobalViewRedirect/index.js'\nexport {
|
|
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
|
|
3
|
+
access?: RelationshipField['access'];
|
|
5
4
|
debug?: boolean;
|
|
6
5
|
name: string;
|
|
7
|
-
tenantsCollectionSlug:
|
|
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;
|
|
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
|
-
|
|
14
|
+
unique
|
|
13
15
|
},
|
|
14
|
-
path: '@payloadcms/plugin-multi-tenant/
|
|
16
|
+
path: '@payloadcms/plugin-multi-tenant/client#TenantField'
|
|
15
17
|
}
|
|
16
18
|
},
|
|
17
|
-
|
|
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
|
|
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
|
|
1
|
+
export const tenantsArrayField = (args)=>({
|
|
2
2
|
name: 'tenants',
|
|
3
3
|
type: 'array',
|
|
4
|
-
access: args?.
|
|
4
|
+
access: args?.arrayFieldAccess,
|
|
5
5
|
fields: [
|
|
6
6
|
{
|
|
7
7
|
name: 'tenant',
|
|
8
8
|
type: 'relationship',
|
|
9
|
-
access: args.
|
|
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
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
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 {
|
|
3
|
-
import {
|
|
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
|
-
*/
|
|
18
|
+
*/ const userHasAccessToAllTenants = typeof pluginConfig.userHasAccessToAllTenants === 'function' ? pluginConfig.userHasAccessToAllTenants : ()=>false;
|
|
17
19
|
const tenantsCollectionSlug = pluginConfig.tenantsSlug = pluginConfig.tenantsSlug || defaults.tenantCollectionSlug;
|
|
18
|
-
const tenantFieldName = pluginConfig
|
|
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
|
|
29
|
-
|
|
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
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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
|
-
|
|
43
|
-
}, {});
|
|
100
|
+
}
|
|
44
101
|
} else if (pluginConfig.collections?.[collection.slug]) {
|
|
45
|
-
|
|
46
|
-
|
|
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.
|
|
51
|
-
...pluginConfig
|
|
115
|
+
*/ collection.fields.splice(0, 0, tenantField({
|
|
116
|
+
...pluginConfig?.tenantField || {},
|
|
52
117
|
name: tenantFieldName,
|
|
53
118
|
debug: pluginConfig.debug,
|
|
54
119
|
tenantsCollectionSlug,
|
|
55
|
-
unique:
|
|
120
|
+
unique: isGlobal
|
|
56
121
|
}));
|
|
57
|
-
if (pluginConfig.collections[collection.slug]
|
|
122
|
+
if (pluginConfig.collections[collection.slug]?.useBaseListFilter !== false) {
|
|
58
123
|
/**
|
|
59
124
|
* Collection baseListFilter with selected tenant constraint (if selected)
|
|
60
|
-
*/ collection.admin
|
|
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]
|
|
133
|
+
if (pluginConfig.collections[collection.slug]?.useTenantAccess !== false) {
|
|
66
134
|
/**
|
|
67
|
-
*
|
|
68
|
-
*/
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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 (!
|
|
83
|
-
|
|
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
|
-
|
|
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":"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"}
|
|
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":"AAIA,SAASA,WAAW,QAAQ,gCAA+B;AAC3D,SAASC,iBAAiB,QAAQ,sCAAqC;AACvE,SAASC,gBAAgB,QAAQ,+BAA8B;AAC/D,SAASC,mBAAmB,QAAQ,qCAAoC;AACxE,SAASC,wBAAwB,QAAQ,0CAAyC;AAClF,SAASC,oBAAoB,QAAQ,sCAAqC;AAE1E,MAAMC,WAAW;IACfC,sBAAsB;IACtBC,iBAAiB;IACjBC,2BAA2B;AAC7B;AAEA,OAAO,MAAMC,oBACX,CAAaC,eACb,CAACC;QACC,IAAID,aAAaE,OAAO,KAAK,OAAO;YAClC,OAAOD;QACT;QAEA;;KAEC,GACD,MAAME,4BAGJ,OAAOH,aAAaG,yBAAyB,KAAK,aAC9CH,aAAaG,yBAAyB,GACtC,IAAM;QACZ,MAAMC,wBAAyBJ,aAAaK,WAAW,GACrDL,aAAaK,WAAW,IAAIV,SAASC,oBAAoB;QAC3D,MAAMC,kBAAkBG,cAAcX,aAAaiB,QAAQX,SAASE,eAAe;QAEnF;;KAEC,GACD,IAAI,CAACI,eAAeM,KAAK,EAAE;YACzBN,eAAeM,KAAK,GAAG,CAAC;QAC1B;QACA,IAAI,CAACN,eAAeM,KAAK,EAAEC,YAAY;YACrCP,eAAeM,KAAK,CAACC,UAAU,GAAG;gBAChCC,SAAS,EAAE;gBACXC,gBAAgB,EAAE;gBAClBC,WAAW,EAAE;YACf;QACF;QACA,IAAI,CAACV,eAAeM,KAAK,CAACC,UAAU,EAAEG,WAAW;YAC/CV,eAAeM,KAAK,CAACC,UAAU,CAACG,SAAS,GAAG,EAAE;QAChD;QACA,IAAI,CAACV,eAAeM,KAAK,CAACC,UAAU,EAAEC,SAAS;YAC7CR,eAAeM,KAAK,CAACC,UAAU,CAACC,OAAO,GAAG,EAAE;QAC9C;QACA,IAAI,CAACR,eAAeM,KAAK,CAACC,UAAU,EAAEE,gBAAgB;YACpDT,eAAeM,KAAK,CAACC,UAAU,CAACE,cAAc,GAAG,EAAE;QACrD;QACA,IAAI,CAACT,eAAeW,WAAW,EAAE;YAC/BX,eAAeW,WAAW,GAAG,EAAE;QACjC;QAEA;;KAEC,GACD,MAAMC,uBAAuBZ,eAAeW,WAAW,CAACE,IAAI,CAAC,CAAC,EAAEC,IAAI,EAAEC,IAAI,EAAE;YAC1E,IAAIf,eAAeM,KAAK,EAAEU,MAAM;gBAC9B,OAAOF,SAASd,eAAeM,KAAK,CAACU,IAAI;YAC3C,OAAO,IAAID,MAAM;gBACf,OAAO;YACT;QACF;QAEA,IAAI,CAACH,sBAAsB;YACzB,MAAMK,MAAM;QACd;QAEA;;KAEC,GACD,IAAIlB,cAAcV,mBAAmB6B,wBAAwB,OAAO;YAClEN,qBAAqBO,MAAM,CAACC,IAAI,CAAC/B,kBAAkBU,cAAcV,qBAAqB,CAAC;QACzF;QAEA,IAAIgC;QAEJ,MAAM,CAACC,iBAAiBC,sBAAsB,GAAGC,OAAOC,IAAI,CAAC1B,aAAaY,WAAW,EAAEe,MAAM,CAG3F,CAACC,KAAKb;YACJ,IAAIf,cAAcY,aAAa,CAACG,KAAK,EAAEc,UAAU;gBAC/CD,GAAG,CAAC,EAAE,CAACP,IAAI,CAACN;YACd,OAAO;gBACLa,GAAG,CAAC,EAAE,CAACP,IAAI,CAACN;YACd;YAEA,OAAOa;QACT,GACA;YAAC,EAAE;YAAE,EAAE;SAAC;QAGV;;KAEC,GACD3B,eAAeW,WAAW,CAACkB,OAAO,CAAC,CAACC;YAClC;;OAEC,GACD,IAAIA,WAAWhB,IAAI,KAAKX,uBAAuB;gBAC7CkB,mBAAmBS;gBAEnBvC,oBAAoB;oBAClBuC;oBACAC,WAAW;oBACX7B;gBACF;gBAEA,IAAIH,aAAaiC,wBAAwB,KAAK,OAAO;oBACnD;;;;WAIC,GACD1C,iBAAiB;wBACfwC;wBACAG,cAAc;+BAAIX;+BAAoBC;yBAAsB;wBAC5D3B;wBACAsC,WAAWtB,qBAAqBE,IAAI;oBACtC;gBACF;YACF,OAAO,IAAIf,aAAaY,WAAW,EAAE,CAACmB,WAAWhB,IAAI,CAAC,EAAE;gBACtD,MAAMc,WAAWO,QAAQpC,aAAaY,WAAW,CAACmB,WAAWhB,IAAI,CAAC,EAAEc;gBAEpE,IAAIA,UAAU;oBACZE,WAAWM,gBAAgB,GAAG;gBAChC;gBAEA;;SAEC,GACD5C,yBAAyB;oBACvB2B,QAAQW,WAAWX,MAAM;oBACzBkB,8BAA8Bf;oBAC9BgB,0BAA0Bf;gBAC5B;gBAEA;;SAEC,GACDO,WAAWX,MAAM,CAACoB,MAAM,CACtB,GACA,GACAnD,YAAY;oBACV,GAAIW,cAAcX,eAAe,CAAC,CAAC;oBACnCiB,MAAMT;oBACN4C,OAAOzC,aAAayC,KAAK;oBACzBrC;oBACAsC,QAAQb;gBACV;gBAGF,IAAI7B,aAAaY,WAAW,CAACmB,WAAWhB,IAAI,CAAC,EAAE4B,sBAAsB,OAAO;oBAC1E;;WAEC,GACD,IAAI,CAACZ,WAAWxB,KAAK,EAAE;wBACrBwB,WAAWxB,KAAK,GAAG,CAAC;oBACtB;oBACAwB,WAAWxB,KAAK,CAACqC,cAAc,GAAGlD,qBAAqB;wBACrDkD,gBAAgBb,WAAWxB,KAAK,EAAEqC;wBAClC/C;oBACF;gBACF;gBAEA,IAAIG,aAAaY,WAAW,CAACmB,WAAWhB,IAAI,CAAC,EAAE8B,oBAAoB,OAAO;oBACxE;;WAEC,GACDrD,oBAAoB;wBAClBuC;wBACAC,WAAWnC;wBACXM;oBACF;gBACF;YACF;QACF;QAEA,IAAI,CAACmB,kBAAkB;YACrB,MAAM,IAAIJ,MAAM,CAAC,wCAAwC,EAAEd,uBAAuB;QACpF;QAEA;;KAEC,GACDH,eAAeM,KAAK,CAACC,UAAU,CAACG,SAAS,CAACU,IAAI,CAAC;YAC7CyB,aAAa;gBACX1C,uBAAuBkB,iBAAiBP,IAAI;gBAC5CgC,YAAYzB,iBAAiBf,KAAK,EAAEwC,cAAc;YACpD;YACAC,MAAM;QACR;QAEA;;KAEC,GACD,IAAIxB,sBAAsByB,MAAM,EAAE;YAChChD,eAAeM,KAAK,CAACC,UAAU,CAACC,OAAO,CAACY,IAAI,CAAC;gBAC3C2B,MAAM;gBACNE,aAAa;oBACXC,aAAa3B;oBACb3B;gBACF;YACF;QACF;QAEA;;KAEC,GACDI,eAAeM,KAAK,CAACC,UAAU,CAACE,cAAc,CAACW,IAAI,CAAC;YAClD2B,MAAM;QACR;QAEA,OAAO/C;IACT,EAAC"}
|
|
@@ -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"}
|