@payloadcms/plugin-multi-tenant 4.0.0-internal.5b1e7cd → 4.0.0-internal.5e065b3
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/LICENSE.md +1 -1
- package/dist/components/AssignTenantFieldModal/index.client.d.ts +2 -3
- package/dist/components/AssignTenantFieldModal/index.client.d.ts.map +1 -1
- package/dist/components/AssignTenantFieldModal/index.client.js +26 -81
- package/dist/components/AssignTenantFieldModal/index.client.js.map +1 -1
- package/dist/components/GlobalViewRedirect/index.d.ts +1 -1
- package/dist/components/GlobalViewRedirect/index.d.ts.map +1 -1
- package/dist/components/GlobalViewRedirect/index.js +6 -4
- package/dist/components/GlobalViewRedirect/index.js.map +1 -1
- package/dist/components/TenantField/index.client.d.ts +1 -1
- package/dist/components/TenantField/index.client.d.ts.map +1 -1
- package/dist/components/TenantField/index.client.js +86 -76
- package/dist/components/TenantField/index.client.js.map +1 -1
- package/dist/components/TenantField/index.css +44 -0
- package/dist/components/TenantSelector/index.client.d.ts +2 -2
- package/dist/components/TenantSelector/index.client.d.ts.map +1 -1
- package/dist/components/TenantSelector/index.client.js +4 -2
- package/dist/components/TenantSelector/index.client.js.map +1 -1
- package/dist/components/TenantSelector/index.css +13 -0
- package/dist/defaults.d.ts.map +1 -1
- package/dist/endpoints/getTenantOptionsEndpoint.d.ts +2 -2
- package/dist/endpoints/getTenantOptionsEndpoint.d.ts.map +1 -1
- package/dist/endpoints/getTenantOptionsEndpoint.js.map +1 -1
- package/dist/fields/tenantField/index.d.ts +4 -2
- package/dist/fields/tenantField/index.d.ts.map +1 -1
- package/dist/fields/tenantField/index.js +41 -12
- package/dist/fields/tenantField/index.js.map +1 -1
- package/dist/filters/filterDocumentsByTenants.d.ts +3 -3
- package/dist/filters/filterDocumentsByTenants.d.ts.map +1 -1
- package/dist/filters/filterDocumentsByTenants.js.map +1 -1
- package/dist/hooks/afterTenantDelete.d.ts +1 -1
- package/dist/hooks/afterTenantDelete.d.ts.map +1 -1
- package/dist/hooks/afterTenantDelete.js +7 -1
- package/dist/hooks/afterTenantDelete.js.map +1 -1
- package/dist/hooks/enforceTenantMembership.d.ts +15 -0
- package/dist/hooks/enforceTenantMembership.d.ts.map +1 -0
- package/dist/hooks/enforceTenantMembership.js +39 -0
- package/dist/hooks/enforceTenantMembership.js.map +1 -0
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +36 -80
- package/dist/index.js.map +1 -1
- package/dist/providers/TenantSelectionProvider/index.client.d.ts.map +1 -1
- package/dist/providers/TenantSelectionProvider/index.client.js +44 -17
- package/dist/providers/TenantSelectionProvider/index.client.js.map +1 -1
- package/dist/providers/TenantSelectionProvider/index.d.ts +6 -5
- package/dist/providers/TenantSelectionProvider/index.d.ts.map +1 -1
- package/dist/providers/TenantSelectionProvider/index.js +5 -3
- package/dist/providers/TenantSelectionProvider/index.js.map +1 -1
- package/dist/translations/languages/en.d.ts.map +1 -1
- package/dist/types.d.ts +7 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utilities/addCollectionAccess.d.ts +8 -10
- package/dist/utilities/addCollectionAccess.d.ts.map +1 -1
- package/dist/utilities/addCollectionAccess.js +99 -21
- package/dist/utilities/addCollectionAccess.js.map +1 -1
- package/dist/utilities/addFilterOptionsToFields.d.ts +3 -3
- package/dist/utilities/addFilterOptionsToFields.d.ts.map +1 -1
- package/dist/utilities/addFilterOptionsToFields.js +6 -9
- package/dist/utilities/addFilterOptionsToFields.js.map +1 -1
- package/dist/utilities/generateCookie.d.ts.map +1 -1
- package/dist/utilities/getCollectionIDType.d.ts +1 -1
- package/dist/utilities/getGlobalViewRedirect.d.ts +5 -4
- package/dist/utilities/getGlobalViewRedirect.d.ts.map +1 -1
- package/dist/utilities/getGlobalViewRedirect.js +4 -3
- package/dist/utilities/getGlobalViewRedirect.js.map +1 -1
- package/dist/utilities/getTenantIDsFromValue.d.ts +2 -0
- package/dist/utilities/getTenantIDsFromValue.d.ts.map +1 -0
- package/dist/utilities/getTenantIDsFromValue.js +14 -0
- package/dist/utilities/getTenantIDsFromValue.js.map +1 -0
- package/dist/utilities/getTenantOptions.d.ts +3 -3
- package/dist/utilities/getTenantOptions.d.ts.map +1 -1
- package/dist/utilities/getTenantOptions.js.map +1 -1
- package/dist/utilities/getUserTenantIDs.d.ts.map +1 -1
- package/dist/utilities/getUserTenantIDs.js +5 -3
- package/dist/utilities/getUserTenantIDs.js.map +1 -1
- package/dist/utilities/isValidTenantAssignment.d.ts +13 -0
- package/dist/utilities/isValidTenantAssignment.d.ts.map +1 -0
- package/dist/utilities/isValidTenantAssignment.js +28 -0
- package/dist/utilities/isValidTenantAssignment.js.map +1 -0
- package/dist/utilities/miniChalk.d.ts.map +1 -1
- package/dist/utilities/shouldRefreshTenantSelection.d.ts +5 -0
- package/dist/utilities/shouldRefreshTenantSelection.d.ts.map +1 -0
- package/dist/utilities/shouldRefreshTenantSelection.js +3 -0
- package/dist/utilities/shouldRefreshTenantSelection.js.map +1 -0
- package/package.json +7 -8
- package/dist/components/AssignTenantFieldModal/index.scss +0 -78
- package/dist/components/TenantField/index.scss +0 -52
- package/dist/components/TenantSelector/index.scss +0 -4
- package/dist/utilities/combineWhereConstraints.d.ts +0 -3
- package/dist/utilities/combineWhereConstraints.d.ts.map +0 -1
- package/dist/utilities/combineWhereConstraints.js +0 -19
- package/dist/utilities/combineWhereConstraints.js.map +0 -1
- package/dist/utilities/withTenantAccess.d.ts +0 -16
- package/dist/utilities/withTenantAccess.d.ts.map +0 -1
- package/dist/utilities/withTenantAccess.js +0 -76
- package/dist/utilities/withTenantAccess.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { definePlugin } from 'payload';
|
|
1
2
|
import { hasAutosaveEnabled } from 'payload/shared';
|
|
2
3
|
import { defaults } from './defaults.js';
|
|
3
4
|
import { getTenantOptionsEndpoint } from './endpoints/getTenantOptionsEndpoint.js';
|
|
@@ -5,12 +6,15 @@ import { tenantField } from './fields/tenantField/index.js';
|
|
|
5
6
|
import { tenantsArrayField } from './fields/tenantsArrayField/index.js';
|
|
6
7
|
import { filterDocumentsByTenants } from './filters/filterDocumentsByTenants.js';
|
|
7
8
|
import { addTenantCleanup } from './hooks/afterTenantDelete.js';
|
|
9
|
+
import { enforceTenantMembership } from './hooks/enforceTenantMembership.js';
|
|
8
10
|
import { translations } from './translations/index.js';
|
|
9
11
|
import { addCollectionAccess } from './utilities/addCollectionAccess.js';
|
|
10
12
|
import { addFilterOptionsToFields } from './utilities/addFilterOptionsToFields.js';
|
|
11
13
|
import { combineFilters } from './utilities/combineFilters.js';
|
|
12
14
|
import { miniChalk } from './utilities/miniChalk.js';
|
|
13
|
-
export const multiTenantPlugin = (
|
|
15
|
+
export const multiTenantPlugin = definePlugin({
|
|
16
|
+
slug: '@payloadcms/plugin-multi-tenant',
|
|
17
|
+
plugin: ({ config: incomingConfig, options: pluginConfig })=>{
|
|
14
18
|
if (pluginConfig.enabled === false) {
|
|
15
19
|
return incomingConfig;
|
|
16
20
|
}
|
|
@@ -21,6 +25,7 @@ export const multiTenantPlugin = (pluginConfig)=>(incomingConfig)=>{
|
|
|
21
25
|
const tenantFieldName = pluginConfig?.tenantField?.name || defaults.tenantFieldName;
|
|
22
26
|
const tenantsArrayFieldName = pluginConfig?.tenantsArrayField?.arrayFieldName || defaults.tenantsArrayFieldName;
|
|
23
27
|
const tenantsArrayTenantFieldName = pluginConfig?.tenantsArrayField?.arrayTenantFieldName || defaults.tenantsArrayTenantFieldName;
|
|
28
|
+
const tenantAccessScopes = [];
|
|
24
29
|
/**
|
|
25
30
|
* Add defaults for admin properties
|
|
26
31
|
*/ if (!incomingConfig.admin) {
|
|
@@ -62,12 +67,17 @@ export const multiTenantPlugin = (pluginConfig)=>(incomingConfig)=>{
|
|
|
62
67
|
*/ if (pluginConfig?.tenantsArrayField?.includeDefaultField !== false) {
|
|
63
68
|
adminUsersCollection.fields.push(tenantsArrayField({
|
|
64
69
|
...pluginConfig?.tenantsArrayField || {},
|
|
70
|
+
arrayFieldAccess: {
|
|
71
|
+
create: ({ req })=>Boolean(req.user && userHasAccessToAllTenants(req.user)),
|
|
72
|
+
update: ({ req })=>Boolean(req.user && userHasAccessToAllTenants(req.user)),
|
|
73
|
+
...pluginConfig?.tenantsArrayField?.arrayFieldAccess || {}
|
|
74
|
+
},
|
|
65
75
|
tenantsArrayFieldName,
|
|
66
76
|
tenantsArrayTenantFieldName,
|
|
67
77
|
tenantsCollectionSlug
|
|
68
78
|
}));
|
|
69
79
|
}
|
|
70
|
-
|
|
80
|
+
tenantAccessScopes.push({
|
|
71
81
|
accessResultCallback: pluginConfig.usersAccessResultOverride,
|
|
72
82
|
adminUsersSlug: adminUsersCollection.slug,
|
|
73
83
|
collection: adminUsersCollection,
|
|
@@ -113,78 +123,6 @@ export const multiTenantPlugin = (pluginConfig)=>(incomingConfig)=>{
|
|
|
113
123
|
// used to validate enabled collection slugs
|
|
114
124
|
const multiTenantCollectionsFound = [];
|
|
115
125
|
/**
|
|
116
|
-
* The folders collection is added AFTER the plugin is initialized
|
|
117
|
-
* so if they added the folder slug to the plugin collections,
|
|
118
|
-
* we can assume that they have folders enabled
|
|
119
|
-
*/ const foldersSlug = incomingConfig.folders ? incomingConfig.folders.slug || 'payload-folders' : 'payload-folders';
|
|
120
|
-
if (collectionSlugs.includes(foldersSlug)) {
|
|
121
|
-
multiTenantCollectionsFound.push(foldersSlug);
|
|
122
|
-
incomingConfig.folders = incomingConfig.folders || {};
|
|
123
|
-
incomingConfig.folders.collectionOverrides = incomingConfig.folders.collectionOverrides || [];
|
|
124
|
-
incomingConfig.folders.collectionOverrides.push(({ collection })=>{
|
|
125
|
-
/**
|
|
126
|
-
* Add filter options to all relationship fields
|
|
127
|
-
*/ collection.fields = addFilterOptionsToFields({
|
|
128
|
-
blockReferencesWithFilters,
|
|
129
|
-
config: incomingConfig,
|
|
130
|
-
fields: collection.fields,
|
|
131
|
-
tenantEnabledCollectionSlugs: collectionSlugs,
|
|
132
|
-
tenantEnabledGlobalSlugs: globalCollectionSlugs,
|
|
133
|
-
tenantFieldName,
|
|
134
|
-
tenantsArrayFieldName,
|
|
135
|
-
tenantsArrayTenantFieldName,
|
|
136
|
-
tenantsCollectionSlug,
|
|
137
|
-
userHasAccessToAllTenants
|
|
138
|
-
});
|
|
139
|
-
if (pluginConfig.collections[foldersSlug]?.customTenantField !== true) {
|
|
140
|
-
/**
|
|
141
|
-
* Add tenant field to enabled collections
|
|
142
|
-
*/ collection.fields.unshift(tenantField({
|
|
143
|
-
name: tenantFieldName,
|
|
144
|
-
debug: pluginConfig.debug,
|
|
145
|
-
isAutosaveEnabled: hasAutosaveEnabled(collection),
|
|
146
|
-
overrides: pluginConfig.collections[collection.slug]?.tenantFieldOverrides ? pluginConfig.collections[collection.slug]?.tenantFieldOverrides : pluginConfig.tenantField || {},
|
|
147
|
-
tenantsArrayFieldName,
|
|
148
|
-
tenantsArrayTenantFieldName,
|
|
149
|
-
tenantsCollectionSlug,
|
|
150
|
-
unique: false
|
|
151
|
-
}));
|
|
152
|
-
}
|
|
153
|
-
const { useBaseFilter, useBaseListFilter } = pluginConfig.collections[collection.slug] || {};
|
|
154
|
-
if (useBaseFilter ?? useBaseListFilter ?? true) {
|
|
155
|
-
/**
|
|
156
|
-
* Add list filter to enabled collections
|
|
157
|
-
* - filters results by selected tenant
|
|
158
|
-
*/ collection.admin = collection.admin || {};
|
|
159
|
-
collection.admin.baseFilter = combineFilters({
|
|
160
|
-
baseFilter: collection.admin?.baseFilter ?? collection.admin?.baseListFilter,
|
|
161
|
-
customFilter: (args)=>filterDocumentsByTenants({
|
|
162
|
-
filterFieldName: tenantFieldName,
|
|
163
|
-
req: args.req,
|
|
164
|
-
tenantsArrayFieldName,
|
|
165
|
-
tenantsArrayTenantFieldName,
|
|
166
|
-
tenantsCollectionSlug,
|
|
167
|
-
userHasAccessToAllTenants
|
|
168
|
-
})
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
if (pluginConfig.collections[foldersSlug]?.useTenantAccess !== false) {
|
|
172
|
-
/**
|
|
173
|
-
* Add access control constraint to tenant enabled folders collection
|
|
174
|
-
*/ addCollectionAccess({
|
|
175
|
-
accessResultCallback: pluginConfig.collections[foldersSlug]?.accessResultOverride,
|
|
176
|
-
adminUsersSlug: adminUsersCollection.slug,
|
|
177
|
-
collection,
|
|
178
|
-
fieldName: tenantFieldName,
|
|
179
|
-
tenantsArrayFieldName,
|
|
180
|
-
tenantsArrayTenantFieldName,
|
|
181
|
-
userHasAccessToAllTenants
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
return collection;
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
/**
|
|
188
126
|
* Modify collections
|
|
189
127
|
*/ incomingConfig.collections.forEach((collection)=>{
|
|
190
128
|
/**
|
|
@@ -195,7 +133,7 @@ export const multiTenantPlugin = (pluginConfig)=>(incomingConfig)=>{
|
|
|
195
133
|
/**
|
|
196
134
|
* Add access control constraint to tenants collection
|
|
197
135
|
* - constrains access a users assigned tenants
|
|
198
|
-
*/
|
|
136
|
+
*/ tenantAccessScopes.push({
|
|
199
137
|
adminUsersSlug: adminUsersCollection.slug,
|
|
200
138
|
collection,
|
|
201
139
|
fieldName: 'id',
|
|
@@ -253,8 +191,10 @@ export const multiTenantPlugin = (pluginConfig)=>(incomingConfig)=>{
|
|
|
253
191
|
path: '@payloadcms/plugin-multi-tenant/client#WatchTenantCollection'
|
|
254
192
|
}
|
|
255
193
|
},
|
|
256
|
-
|
|
257
|
-
|
|
194
|
+
disabled: {
|
|
195
|
+
bulkEdit: true,
|
|
196
|
+
column: true
|
|
197
|
+
}
|
|
258
198
|
}
|
|
259
199
|
});
|
|
260
200
|
collection.endpoints = [
|
|
@@ -306,15 +246,26 @@ export const multiTenantPlugin = (pluginConfig)=>(incomingConfig)=>{
|
|
|
306
246
|
* Add tenant field to enabled collections
|
|
307
247
|
*/ collection.fields.unshift(tenantField({
|
|
308
248
|
name: tenantFieldName,
|
|
249
|
+
adminUsersSlug: adminUsersCollection.slug,
|
|
309
250
|
debug: pluginConfig.debug,
|
|
310
251
|
isAutosaveEnabled: hasAutosaveEnabled(collection),
|
|
311
252
|
overrides: pluginConfig.collections[collection.slug]?.tenantFieldOverrides ? pluginConfig.collections[collection.slug]?.tenantFieldOverrides : pluginConfig.tenantField || {},
|
|
312
253
|
tenantsArrayFieldName,
|
|
313
254
|
tenantsArrayTenantFieldName,
|
|
314
255
|
tenantsCollectionSlug,
|
|
315
|
-
unique: isGlobal
|
|
256
|
+
unique: isGlobal,
|
|
257
|
+
userHasAccessToAllTenants
|
|
316
258
|
}));
|
|
317
259
|
}
|
|
260
|
+
collection.hooks ??= {};
|
|
261
|
+
collection.hooks.beforeValidate ??= [];
|
|
262
|
+
collection.hooks.beforeValidate.push(enforceTenantMembership({
|
|
263
|
+
collectionSlug: collection.slug,
|
|
264
|
+
tenantFieldName,
|
|
265
|
+
tenantsArrayFieldName,
|
|
266
|
+
tenantsArrayTenantFieldName,
|
|
267
|
+
userHasAccessToAllTenants
|
|
268
|
+
}));
|
|
318
269
|
const { useBaseFilter, useBaseListFilter } = pluginConfig.collections[collection.slug] || {};
|
|
319
270
|
if (useBaseFilter ?? useBaseListFilter ?? true) {
|
|
320
271
|
/**
|
|
@@ -336,7 +287,7 @@ export const multiTenantPlugin = (pluginConfig)=>(incomingConfig)=>{
|
|
|
336
287
|
if (pluginConfig.collections[collection.slug]?.useTenantAccess !== false) {
|
|
337
288
|
/**
|
|
338
289
|
* Add access control constraint to tenant enabled collection
|
|
339
|
-
*/
|
|
290
|
+
*/ tenantAccessScopes.push({
|
|
340
291
|
accessResultCallback: pluginConfig.collections[collection.slug]?.accessResultOverride,
|
|
341
292
|
adminUsersSlug: adminUsersCollection.slug,
|
|
342
293
|
collection,
|
|
@@ -359,6 +310,10 @@ export const multiTenantPlugin = (pluginConfig)=>(incomingConfig)=>{
|
|
|
359
310
|
// eslint-disable-next-line no-console
|
|
360
311
|
console.error(miniChalk.yellowBold('WARNING (plugin-multi-tenant)'), 'missing collections', missingSlugs, 'try placing the multi-tenant plugin after other plugins.');
|
|
361
312
|
}
|
|
313
|
+
addCollectionAccess({
|
|
314
|
+
config: incomingConfig,
|
|
315
|
+
scopes: tenantAccessScopes
|
|
316
|
+
});
|
|
362
317
|
/**
|
|
363
318
|
* Add TenantSelectionProvider to admin providers
|
|
364
319
|
*/ incomingConfig.admin.components.providers.push({
|
|
@@ -425,6 +380,7 @@ export const multiTenantPlugin = (pluginConfig)=>(incomingConfig)=>{
|
|
|
425
380
|
};
|
|
426
381
|
});
|
|
427
382
|
return incomingConfig;
|
|
428
|
-
}
|
|
383
|
+
}
|
|
384
|
+
});
|
|
429
385
|
|
|
430
386
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { AcceptedLanguages } from '@payloadcms/translations'\nimport type { CollectionConfig, Config } from 'payload'\n\nimport chalk from 'chalk'\nimport { hasAutosaveEnabled } from 'payload/shared'\n\nimport type { PluginDefaultTranslationsObject } from './translations/types.js'\nimport type { MultiTenantPluginConfig } from './types.js'\n\nimport { defaults } from './defaults.js'\nimport { getTenantOptionsEndpoint } from './endpoints/getTenantOptionsEndpoint.js'\nimport { tenantField } from './fields/tenantField/index.js'\nimport { tenantsArrayField } from './fields/tenantsArrayField/index.js'\nimport { filterDocumentsByTenants } from './filters/filterDocumentsByTenants.js'\nimport { addTenantCleanup } from './hooks/afterTenantDelete.js'\nimport { translations } from './translations/index.js'\nimport { addCollectionAccess } from './utilities/addCollectionAccess.js'\nimport { addFilterOptionsToFields } from './utilities/addFilterOptionsToFields.js'\nimport { combineFilters } from './utilities/combineFilters.js'\nimport { miniChalk } from './utilities/miniChalk.js'\n\nexport const multiTenantPlugin =\n <ConfigType>(pluginConfig: MultiTenantPluginConfig<ConfigType>) =>\n (incomingConfig: Config): Config => {\n if (pluginConfig.enabled === false) {\n return incomingConfig\n }\n\n /**\n * Set defaults\n */\n const userHasAccessToAllTenants: Required<\n MultiTenantPluginConfig<ConfigType>\n >['userHasAccessToAllTenants'] =\n typeof pluginConfig.userHasAccessToAllTenants === 'function'\n ? pluginConfig.userHasAccessToAllTenants\n : () => false\n const tenantsCollectionSlug = (pluginConfig.tenantsSlug =\n pluginConfig.tenantsSlug || defaults.tenantCollectionSlug)\n const tenantFieldName = pluginConfig?.tenantField?.name || defaults.tenantFieldName\n const tenantsArrayFieldName =\n pluginConfig?.tenantsArrayField?.arrayFieldName || defaults.tenantsArrayFieldName\n const tenantsArrayTenantFieldName =\n pluginConfig?.tenantsArrayField?.arrayTenantFieldName || defaults.tenantsArrayTenantFieldName\n\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 beforeNav: [],\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?.beforeNav) {\n incomingConfig.admin.components.beforeNav = []\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(\n tenantsArrayField({\n ...(pluginConfig?.tenantsArrayField || {}),\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n }),\n )\n }\n\n addCollectionAccess({\n accessResultCallback: pluginConfig.usersAccessResultOverride,\n adminUsersSlug: adminUsersCollection.slug,\n collection: adminUsersCollection,\n fieldName: `${tenantsArrayFieldName}.${tenantsArrayTenantFieldName}`,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n })\n\n if (pluginConfig.useUsersTenantFilter !== false) {\n if (!adminUsersCollection.admin) {\n adminUsersCollection.admin = {}\n }\n\n const baseFilter =\n adminUsersCollection.admin?.baseFilter ?? adminUsersCollection.admin?.baseListFilter\n adminUsersCollection.admin.baseFilter = combineFilters({\n baseFilter,\n customFilter: (args) =>\n filterDocumentsByTenants<ConfigType>({\n filterFieldName: `${tenantsArrayFieldName}.${tenantsArrayTenantFieldName}`,\n req: args.req,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n userHasAccessToAllTenants,\n }),\n })\n }\n\n let tenantCollection: CollectionConfig | undefined\n\n const [collectionSlugs, globalCollectionSlugs] = Object.keys(pluginConfig.collections).reduce<\n [string[], string[]]\n >(\n (acc, slug) => {\n if (slug === adminUsersCollection.slug) {\n return acc\n }\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 // used to track and not duplicate filterOptions on referenced blocks\n const blockReferencesWithFilters: string[] = []\n\n // used to validate enabled collection slugs\n const multiTenantCollectionsFound: string[] = []\n\n /**\n * The folders collection is added AFTER the plugin is initialized\n * so if they added the folder slug to the plugin collections,\n * we can assume that they have folders enabled\n */\n const foldersSlug = incomingConfig.folders\n ? incomingConfig.folders.slug || 'payload-folders'\n : 'payload-folders'\n\n if (collectionSlugs.includes(foldersSlug)) {\n multiTenantCollectionsFound.push(foldersSlug)\n incomingConfig.folders = incomingConfig.folders || {}\n incomingConfig.folders.collectionOverrides = incomingConfig.folders.collectionOverrides || []\n incomingConfig.folders.collectionOverrides.push(({ collection }) => {\n /**\n * Add filter options to all relationship fields\n */\n collection.fields = addFilterOptionsToFields({\n blockReferencesWithFilters,\n config: incomingConfig,\n fields: collection.fields,\n tenantEnabledCollectionSlugs: collectionSlugs,\n tenantEnabledGlobalSlugs: globalCollectionSlugs,\n tenantFieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n userHasAccessToAllTenants,\n })\n\n if (pluginConfig.collections[foldersSlug]?.customTenantField !== true) {\n /**\n * Add tenant field to enabled collections\n */\n collection.fields.unshift(\n tenantField({\n name: tenantFieldName,\n debug: pluginConfig.debug,\n isAutosaveEnabled: hasAutosaveEnabled(collection),\n overrides: pluginConfig.collections[collection.slug]?.tenantFieldOverrides\n ? pluginConfig.collections[collection.slug]?.tenantFieldOverrides\n : pluginConfig.tenantField || {},\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n unique: false,\n }),\n )\n }\n\n const { useBaseFilter, useBaseListFilter } = pluginConfig.collections[collection.slug] || {}\n if (useBaseFilter ?? useBaseListFilter ?? true) {\n /**\n * Add list filter to enabled collections\n * - filters results by selected tenant\n */\n collection.admin = collection.admin || {}\n collection.admin.baseFilter = combineFilters({\n baseFilter: collection.admin?.baseFilter ?? collection.admin?.baseListFilter,\n customFilter: (args) =>\n filterDocumentsByTenants<ConfigType>({\n filterFieldName: tenantFieldName,\n req: args.req,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n userHasAccessToAllTenants,\n }),\n })\n }\n\n if (pluginConfig.collections[foldersSlug]?.useTenantAccess !== false) {\n /**\n * Add access control constraint to tenant enabled folders collection\n */\n addCollectionAccess({\n accessResultCallback: pluginConfig.collections[foldersSlug]?.accessResultOverride,\n adminUsersSlug: adminUsersCollection.slug,\n collection,\n fieldName: tenantFieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n })\n }\n\n return collection\n })\n }\n\n /**\n * Modify collections\n */\n incomingConfig.collections.forEach((collection) => {\n /**\n * Modify tenants collection\n */\n if (collection.slug === tenantsCollectionSlug) {\n tenantCollection = collection\n\n if (pluginConfig.useTenantsCollectionAccess !== false) {\n /**\n * Add access control constraint to tenants collection\n * - constrains access a users assigned tenants\n */\n addCollectionAccess({\n adminUsersSlug: adminUsersCollection.slug,\n collection,\n fieldName: 'id',\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n })\n }\n\n if (pluginConfig.useTenantsListFilter !== false) {\n /**\n * Add list filter to tenants collection\n * - filter by selected tenant\n */\n if (!collection.admin) {\n collection.admin = {}\n }\n\n const baseFilter = collection.admin?.baseFilter ?? collection.admin?.baseListFilter\n collection.admin.baseFilter = combineFilters({\n baseFilter,\n customFilter: (args) =>\n filterDocumentsByTenants({\n filterFieldName: 'id',\n req: args.req,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n userHasAccessToAllTenants,\n }),\n })\n }\n\n if (pluginConfig.cleanupAfterTenantDelete !== false) {\n /**\n * Add cleanup logic when tenant is deleted\n * - delete documents related to tenant\n * - remove tenant from users\n */\n addTenantCleanup({\n collection,\n enabledSlugs: [...collectionSlugs, ...globalCollectionSlugs],\n tenantFieldName,\n tenantsCollectionSlug,\n usersSlug: adminUsersCollection.slug,\n usersTenantsArrayFieldName: tenantsArrayFieldName,\n usersTenantsArrayTenantFieldName: tenantsArrayTenantFieldName,\n })\n }\n\n /**\n * Add custom tenant field that watches and dispatches updates to the selector\n */\n collection.fields.push({\n name: '_watchTenant',\n type: 'ui',\n admin: {\n components: {\n Field: {\n path: '@payloadcms/plugin-multi-tenant/client#WatchTenantCollection',\n },\n },\n disableBulkEdit: true,\n disableListColumn: true,\n },\n })\n\n collection.endpoints = [\n ...(collection.endpoints || []),\n getTenantOptionsEndpoint({\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n useAsTitle: tenantCollection.admin?.useAsTitle || 'id',\n userHasAccessToAllTenants,\n }),\n ]\n } else if (pluginConfig.collections?.[collection.slug]) {\n if (collection.slug === adminUsersCollection.slug) {\n // eslint-disable-next-line no-console\n console.warn(\n `[plugin-multi-tenant] The admin users collection \"${collection.slug}\" should not be listed in pluginConfig.collections — it is already handled by the plugin. Skipping tenant-field processing for this collection to avoid double access control and validation errors.`,\n )\n return\n }\n multiTenantCollectionsFound.push(collection.slug)\n const isGlobal = Boolean(pluginConfig.collections[collection.slug]?.isGlobal)\n\n if (isGlobal) {\n collection.disableDuplicate = true\n }\n\n if (!pluginConfig.debug && !isGlobal) {\n collection.admin ??= {}\n collection.admin.components ??= {}\n collection.admin.components.edit ??= {}\n collection.admin.components.edit.editMenuItems ??= []\n collection.admin.components.edit.editMenuItems.push({\n path: '@payloadcms/plugin-multi-tenant/client#AssignTenantFieldTrigger',\n })\n }\n\n /**\n * Add filter options to all relationship fields\n */\n collection.fields = addFilterOptionsToFields({\n blockReferencesWithFilters,\n config: incomingConfig,\n fields: collection.fields,\n tenantEnabledCollectionSlugs: collectionSlugs,\n tenantEnabledGlobalSlugs: globalCollectionSlugs,\n tenantFieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n userHasAccessToAllTenants,\n })\n\n if (pluginConfig.collections[collection.slug]?.customTenantField !== true) {\n /**\n * Add tenant field to enabled collections\n */\n collection.fields.unshift(\n tenantField({\n name: tenantFieldName,\n debug: pluginConfig.debug,\n isAutosaveEnabled: hasAutosaveEnabled(collection),\n overrides: pluginConfig.collections[collection.slug]?.tenantFieldOverrides\n ? pluginConfig.collections[collection.slug]?.tenantFieldOverrides\n : pluginConfig.tenantField || {},\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n unique: isGlobal,\n }),\n )\n }\n\n const { useBaseFilter, useBaseListFilter } = pluginConfig.collections[collection.slug] || {}\n if (useBaseFilter ?? useBaseListFilter ?? true) {\n /**\n * Add list filter to enabled collections\n * - filters results by selected tenant\n */\n collection.admin = collection.admin || {}\n collection.admin.baseFilter = combineFilters({\n baseFilter: collection.admin?.baseFilter ?? collection.admin?.baseListFilter,\n customFilter: (args) =>\n filterDocumentsByTenants({\n filterFieldName: tenantFieldName,\n req: args.req,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n userHasAccessToAllTenants,\n }),\n })\n }\n\n if (pluginConfig.collections[collection.slug]?.useTenantAccess !== false) {\n /**\n * Add access control constraint to tenant enabled collection\n */\n addCollectionAccess({\n accessResultCallback: pluginConfig.collections[collection.slug]?.accessResultOverride,\n adminUsersSlug: adminUsersCollection.slug,\n collection,\n fieldName: tenantFieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n })\n }\n }\n })\n\n if (!tenantCollection) {\n throw new Error(`Tenants collection not found with slug: ${tenantsCollectionSlug}`)\n }\n\n if (\n multiTenantCollectionsFound.length !==\n collectionSlugs.length + globalCollectionSlugs.length\n ) {\n const missingSlugs = [...collectionSlugs, ...globalCollectionSlugs].filter(\n (slug) => !multiTenantCollectionsFound.includes(slug),\n )\n // eslint-disable-next-line no-console\n console.error(\n miniChalk.yellowBold('WARNING (plugin-multi-tenant)'),\n 'missing collections',\n missingSlugs,\n 'try placing the multi-tenant plugin after other plugins.',\n )\n }\n\n /**\n * Add TenantSelectionProvider to admin providers\n */\n incomingConfig.admin.components.providers.push({\n clientProps: {\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug: tenantCollection.slug,\n useAsTitle: tenantCollection.admin?.useAsTitle || 'id',\n userHasAccessToAllTenants,\n },\n path: '@payloadcms/plugin-multi-tenant/rsc#TenantSelectionProvider',\n })\n\n /**\n * Add global redirect action\n */\n if (globalCollectionSlugs.length) {\n incomingConfig.admin.components.actions.push({\n path: '@payloadcms/plugin-multi-tenant/rsc#GlobalViewRedirect',\n serverProps: {\n globalSlugs: globalCollectionSlugs,\n tenantFieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n useAsTitle: tenantCollection.admin?.useAsTitle || 'id',\n userHasAccessToAllTenants,\n },\n })\n }\n\n /**\n * Add tenant selector to admin UI\n */\n incomingConfig.admin.components.beforeNav.push({\n clientProps: {\n enabledSlugs: [\n ...collectionSlugs,\n ...globalCollectionSlugs,\n adminUsersCollection.slug,\n tenantCollection.slug,\n ],\n label: pluginConfig.tenantSelectorLabel || undefined,\n },\n path: '@payloadcms/plugin-multi-tenant/rsc#TenantSelector',\n })\n\n /**\n * Merge plugin translations\n */\n if (!incomingConfig.i18n) {\n incomingConfig.i18n = {}\n }\n Object.entries(translations).forEach(([locale, pluginI18nObject]) => {\n const typedLocale = locale as AcceptedLanguages\n if (!incomingConfig.i18n!.translations) {\n incomingConfig.i18n!.translations = {}\n }\n if (!(typedLocale in incomingConfig.i18n!.translations)) {\n incomingConfig.i18n!.translations[typedLocale] = {}\n }\n if (!('plugin-multi-tenant' in incomingConfig.i18n!.translations[typedLocale]!)) {\n ;(incomingConfig.i18n!.translations[typedLocale] as PluginDefaultTranslationsObject)[\n 'plugin-multi-tenant'\n ] = {} as PluginDefaultTranslationsObject['plugin-multi-tenant']\n }\n\n ;(incomingConfig.i18n!.translations[typedLocale] as PluginDefaultTranslationsObject)[\n 'plugin-multi-tenant'\n ] = {\n ...pluginI18nObject.translations['plugin-multi-tenant'],\n ...(pluginConfig.i18n?.translations?.[typedLocale] || {}),\n }\n })\n\n return incomingConfig\n }\n"],"names":["hasAutosaveEnabled","defaults","getTenantOptionsEndpoint","tenantField","tenantsArrayField","filterDocumentsByTenants","addTenantCleanup","translations","addCollectionAccess","addFilterOptionsToFields","combineFilters","miniChalk","multiTenantPlugin","pluginConfig","incomingConfig","enabled","userHasAccessToAllTenants","tenantsCollectionSlug","tenantsSlug","tenantCollectionSlug","tenantFieldName","name","tenantsArrayFieldName","arrayFieldName","tenantsArrayTenantFieldName","arrayTenantFieldName","admin","components","actions","beforeNav","providers","collections","adminUsersCollection","find","slug","auth","user","Error","includeDefaultField","fields","push","accessResultCallback","usersAccessResultOverride","adminUsersSlug","collection","fieldName","useUsersTenantFilter","baseFilter","baseListFilter","customFilter","args","filterFieldName","req","tenantCollection","collectionSlugs","globalCollectionSlugs","Object","keys","reduce","acc","isGlobal","blockReferencesWithFilters","multiTenantCollectionsFound","foldersSlug","folders","includes","collectionOverrides","config","tenantEnabledCollectionSlugs","tenantEnabledGlobalSlugs","customTenantField","unshift","debug","isAutosaveEnabled","overrides","tenantFieldOverrides","unique","useBaseFilter","useBaseListFilter","useTenantAccess","accessResultOverride","forEach","useTenantsCollectionAccess","useTenantsListFilter","cleanupAfterTenantDelete","enabledSlugs","usersSlug","usersTenantsArrayFieldName","usersTenantsArrayTenantFieldName","type","Field","path","disableBulkEdit","disableListColumn","endpoints","useAsTitle","console","warn","Boolean","disableDuplicate","edit","editMenuItems","length","missingSlugs","filter","error","yellowBold","clientProps","serverProps","globalSlugs","label","tenantSelectorLabel","undefined","i18n","entries","locale","pluginI18nObject","typedLocale"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { AcceptedLanguages } from '@payloadcms/translations'\nimport type { CollectionConfig } from 'payload'\n\nimport { definePlugin } from 'payload'\nimport { hasAutosaveEnabled } from 'payload/shared'\n\nimport type { PluginDefaultTranslationsObject } from './translations/types.js'\nimport type { MultiTenantPluginConfig } from './types.js'\n\nimport { defaults } from './defaults.js'\nimport { getTenantOptionsEndpoint } from './endpoints/getTenantOptionsEndpoint.js'\nimport { tenantField } from './fields/tenantField/index.js'\nimport { tenantsArrayField } from './fields/tenantsArrayField/index.js'\nimport { filterDocumentsByTenants } from './filters/filterDocumentsByTenants.js'\nimport { addTenantCleanup } from './hooks/afterTenantDelete.js'\nimport { enforceTenantMembership } from './hooks/enforceTenantMembership.js'\nimport { translations } from './translations/index.js'\nimport { addCollectionAccess, type TenantAccessConfig } from './utilities/addCollectionAccess.js'\nimport { addFilterOptionsToFields } from './utilities/addFilterOptionsToFields.js'\nimport { combineFilters } from './utilities/combineFilters.js'\nimport { miniChalk } from './utilities/miniChalk.js'\n\nexport const multiTenantPlugin = definePlugin<MultiTenantPluginConfig>({\n slug: '@payloadcms/plugin-multi-tenant',\n plugin: ({ config: incomingConfig, options: pluginConfig }) => {\n if (pluginConfig.enabled === false) {\n return incomingConfig\n }\n\n /**\n * Set defaults\n */\n const userHasAccessToAllTenants: Required<MultiTenantPluginConfig>['userHasAccessToAllTenants'] =\n typeof pluginConfig.userHasAccessToAllTenants === 'function'\n ? pluginConfig.userHasAccessToAllTenants\n : () => false\n const tenantsCollectionSlug = (pluginConfig.tenantsSlug =\n pluginConfig.tenantsSlug || defaults.tenantCollectionSlug)\n const tenantFieldName = pluginConfig?.tenantField?.name || defaults.tenantFieldName\n const tenantsArrayFieldName =\n pluginConfig?.tenantsArrayField?.arrayFieldName || defaults.tenantsArrayFieldName\n const tenantsArrayTenantFieldName =\n pluginConfig?.tenantsArrayField?.arrayTenantFieldName || defaults.tenantsArrayTenantFieldName\n const tenantAccessScopes: TenantAccessConfig[] = []\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 beforeNav: [],\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?.beforeNav) {\n incomingConfig.admin.components.beforeNav = []\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(\n tenantsArrayField({\n ...(pluginConfig?.tenantsArrayField || {}),\n arrayFieldAccess: {\n create: ({ req }) => Boolean(req.user && userHasAccessToAllTenants(req.user)),\n update: ({ req }) => Boolean(req.user && userHasAccessToAllTenants(req.user)),\n ...(pluginConfig?.tenantsArrayField?.arrayFieldAccess || {}),\n },\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n }),\n )\n }\n\n tenantAccessScopes.push({\n accessResultCallback: pluginConfig.usersAccessResultOverride,\n adminUsersSlug: adminUsersCollection.slug,\n collection: adminUsersCollection,\n fieldName: `${tenantsArrayFieldName}.${tenantsArrayTenantFieldName}`,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n })\n\n if (pluginConfig.useUsersTenantFilter !== false) {\n if (!adminUsersCollection.admin) {\n adminUsersCollection.admin = {}\n }\n\n const baseFilter =\n adminUsersCollection.admin?.baseFilter ?? adminUsersCollection.admin?.baseListFilter\n adminUsersCollection.admin.baseFilter = combineFilters({\n baseFilter,\n customFilter: (args) =>\n filterDocumentsByTenants({\n filterFieldName: `${tenantsArrayFieldName}.${tenantsArrayTenantFieldName}`,\n req: args.req,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n userHasAccessToAllTenants,\n }),\n })\n }\n\n let tenantCollection: CollectionConfig | undefined\n\n const [collectionSlugs, globalCollectionSlugs] = Object.keys(pluginConfig.collections).reduce<\n [string[], string[]]\n >(\n (acc, slug) => {\n if (slug === adminUsersCollection.slug) {\n return acc\n }\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 // used to track and not duplicate filterOptions on referenced blocks\n const blockReferencesWithFilters: string[] = []\n\n // used to validate enabled collection slugs\n const multiTenantCollectionsFound: string[] = []\n\n /**\n * Modify collections\n */\n incomingConfig.collections.forEach((collection) => {\n /**\n * Modify tenants collection\n */\n if (collection.slug === tenantsCollectionSlug) {\n tenantCollection = collection\n\n if (pluginConfig.useTenantsCollectionAccess !== false) {\n /**\n * Add access control constraint to tenants collection\n * - constrains access a users assigned tenants\n */\n tenantAccessScopes.push({\n adminUsersSlug: adminUsersCollection.slug,\n collection,\n fieldName: 'id',\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n })\n }\n\n if (pluginConfig.useTenantsListFilter !== false) {\n /**\n * Add list filter to tenants collection\n * - filter by selected tenant\n */\n if (!collection.admin) {\n collection.admin = {}\n }\n\n const baseFilter = collection.admin?.baseFilter ?? collection.admin?.baseListFilter\n collection.admin.baseFilter = combineFilters({\n baseFilter,\n customFilter: (args) =>\n filterDocumentsByTenants({\n filterFieldName: 'id',\n req: args.req,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n userHasAccessToAllTenants,\n }),\n })\n }\n\n if (pluginConfig.cleanupAfterTenantDelete !== false) {\n /**\n * Add cleanup logic when tenant is deleted\n * - delete documents related to tenant\n * - remove tenant from users\n */\n addTenantCleanup({\n collection,\n enabledSlugs: [...collectionSlugs, ...globalCollectionSlugs],\n tenantFieldName,\n tenantsCollectionSlug,\n usersSlug: adminUsersCollection.slug,\n usersTenantsArrayFieldName: tenantsArrayFieldName,\n usersTenantsArrayTenantFieldName: tenantsArrayTenantFieldName,\n })\n }\n\n /**\n * Add custom tenant field that watches and dispatches updates to the selector\n */\n collection.fields.push({\n name: '_watchTenant',\n type: 'ui',\n admin: {\n components: {\n Field: {\n path: '@payloadcms/plugin-multi-tenant/client#WatchTenantCollection',\n },\n },\n disabled: { bulkEdit: true, column: true },\n },\n })\n\n collection.endpoints = [\n ...(collection.endpoints || []),\n getTenantOptionsEndpoint({\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n useAsTitle: tenantCollection.admin?.useAsTitle || 'id',\n userHasAccessToAllTenants,\n }),\n ]\n } else if (pluginConfig.collections?.[collection.slug]) {\n if (collection.slug === adminUsersCollection.slug) {\n // eslint-disable-next-line no-console\n console.warn(\n `[plugin-multi-tenant] The admin users collection \"${collection.slug}\" should not be listed in pluginConfig.collections — it is already handled by the plugin. Skipping tenant-field processing for this collection to avoid double access control and validation errors.`,\n )\n return\n }\n multiTenantCollectionsFound.push(collection.slug)\n const isGlobal = Boolean(pluginConfig.collections[collection.slug]?.isGlobal)\n\n if (isGlobal) {\n collection.disableDuplicate = true\n }\n\n if (!pluginConfig.debug && !isGlobal) {\n collection.admin ??= {}\n collection.admin.components ??= {}\n collection.admin.components.edit ??= {}\n collection.admin.components.edit.editMenuItems ??= []\n collection.admin.components.edit.editMenuItems.push({\n path: '@payloadcms/plugin-multi-tenant/client#AssignTenantFieldTrigger',\n })\n }\n\n /**\n * Add filter options to all relationship fields\n */\n collection.fields = addFilterOptionsToFields({\n blockReferencesWithFilters,\n config: incomingConfig,\n fields: collection.fields,\n tenantEnabledCollectionSlugs: collectionSlugs,\n tenantEnabledGlobalSlugs: globalCollectionSlugs,\n tenantFieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n userHasAccessToAllTenants,\n })\n\n if (pluginConfig.collections[collection.slug]?.customTenantField !== true) {\n /**\n * Add tenant field to enabled collections\n */\n collection.fields.unshift(\n tenantField({\n name: tenantFieldName,\n adminUsersSlug: adminUsersCollection.slug,\n debug: pluginConfig.debug,\n isAutosaveEnabled: hasAutosaveEnabled(collection),\n overrides: pluginConfig.collections[collection.slug]?.tenantFieldOverrides\n ? pluginConfig.collections[collection.slug]?.tenantFieldOverrides\n : pluginConfig.tenantField || {},\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n unique: isGlobal,\n userHasAccessToAllTenants,\n }),\n )\n }\n\n collection.hooks ??= {}\n collection.hooks.beforeValidate ??= []\n collection.hooks.beforeValidate.push(\n enforceTenantMembership({\n collectionSlug: collection.slug,\n tenantFieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n }),\n )\n\n const { useBaseFilter, useBaseListFilter } = pluginConfig.collections[collection.slug] || {}\n if (useBaseFilter ?? useBaseListFilter ?? true) {\n /**\n * Add list filter to enabled collections\n * - filters results by selected tenant\n */\n collection.admin = collection.admin || {}\n collection.admin.baseFilter = combineFilters({\n baseFilter: collection.admin?.baseFilter ?? collection.admin?.baseListFilter,\n customFilter: (args) =>\n filterDocumentsByTenants({\n filterFieldName: tenantFieldName,\n req: args.req,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n userHasAccessToAllTenants,\n }),\n })\n }\n\n if (pluginConfig.collections[collection.slug]?.useTenantAccess !== false) {\n /**\n * Add access control constraint to tenant enabled collection\n */\n tenantAccessScopes.push({\n accessResultCallback: pluginConfig.collections[collection.slug]?.accessResultOverride,\n adminUsersSlug: adminUsersCollection.slug,\n collection,\n fieldName: tenantFieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n userHasAccessToAllTenants,\n })\n }\n }\n })\n\n if (!tenantCollection) {\n throw new Error(`Tenants collection not found with slug: ${tenantsCollectionSlug}`)\n }\n\n if (\n multiTenantCollectionsFound.length !==\n collectionSlugs.length + globalCollectionSlugs.length\n ) {\n const missingSlugs = [...collectionSlugs, ...globalCollectionSlugs].filter(\n (slug) => !multiTenantCollectionsFound.includes(slug),\n )\n // eslint-disable-next-line no-console\n console.error(\n miniChalk.yellowBold('WARNING (plugin-multi-tenant)'),\n 'missing collections',\n missingSlugs,\n 'try placing the multi-tenant plugin after other plugins.',\n )\n }\n\n addCollectionAccess({ config: incomingConfig, scopes: tenantAccessScopes })\n\n /**\n * Add TenantSelectionProvider to admin providers\n */\n incomingConfig.admin.components.providers.push({\n clientProps: {\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug: tenantCollection.slug,\n useAsTitle: tenantCollection.admin?.useAsTitle || 'id',\n userHasAccessToAllTenants,\n },\n path: '@payloadcms/plugin-multi-tenant/rsc#TenantSelectionProvider',\n })\n\n /**\n * Add global redirect action\n */\n if (globalCollectionSlugs.length) {\n incomingConfig.admin.components.actions.push({\n path: '@payloadcms/plugin-multi-tenant/rsc#GlobalViewRedirect',\n serverProps: {\n globalSlugs: globalCollectionSlugs,\n tenantFieldName,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n useAsTitle: tenantCollection.admin?.useAsTitle || 'id',\n userHasAccessToAllTenants,\n },\n })\n }\n\n /**\n * Add tenant selector to admin UI\n */\n incomingConfig.admin.components.beforeNav.push({\n clientProps: {\n enabledSlugs: [\n ...collectionSlugs,\n ...globalCollectionSlugs,\n adminUsersCollection.slug,\n tenantCollection.slug,\n ],\n label: pluginConfig.tenantSelectorLabel || undefined,\n },\n path: '@payloadcms/plugin-multi-tenant/rsc#TenantSelector',\n })\n\n /**\n * Merge plugin translations\n */\n if (!incomingConfig.i18n) {\n incomingConfig.i18n = {}\n }\n Object.entries(translations).forEach(([locale, pluginI18nObject]) => {\n const typedLocale = locale as AcceptedLanguages\n if (!incomingConfig.i18n!.translations) {\n incomingConfig.i18n!.translations = {}\n }\n if (!(typedLocale in incomingConfig.i18n!.translations)) {\n incomingConfig.i18n!.translations[typedLocale] = {}\n }\n if (!('plugin-multi-tenant' in incomingConfig.i18n!.translations[typedLocale]!)) {\n ;(incomingConfig.i18n!.translations[typedLocale] as PluginDefaultTranslationsObject)[\n 'plugin-multi-tenant'\n ] = {} as PluginDefaultTranslationsObject['plugin-multi-tenant']\n }\n\n ;(incomingConfig.i18n!.translations[typedLocale] as PluginDefaultTranslationsObject)[\n 'plugin-multi-tenant'\n ] = {\n ...pluginI18nObject.translations['plugin-multi-tenant'],\n ...(pluginConfig.i18n?.translations?.[typedLocale] || {}),\n }\n })\n\n return incomingConfig\n },\n})\n"],"names":["definePlugin","hasAutosaveEnabled","defaults","getTenantOptionsEndpoint","tenantField","tenantsArrayField","filterDocumentsByTenants","addTenantCleanup","enforceTenantMembership","translations","addCollectionAccess","addFilterOptionsToFields","combineFilters","miniChalk","multiTenantPlugin","slug","plugin","config","incomingConfig","options","pluginConfig","enabled","userHasAccessToAllTenants","tenantsCollectionSlug","tenantsSlug","tenantCollectionSlug","tenantFieldName","name","tenantsArrayFieldName","arrayFieldName","tenantsArrayTenantFieldName","arrayTenantFieldName","tenantAccessScopes","admin","components","actions","beforeNav","providers","collections","adminUsersCollection","find","auth","user","Error","includeDefaultField","fields","push","arrayFieldAccess","create","req","Boolean","update","accessResultCallback","usersAccessResultOverride","adminUsersSlug","collection","fieldName","useUsersTenantFilter","baseFilter","baseListFilter","customFilter","args","filterFieldName","tenantCollection","collectionSlugs","globalCollectionSlugs","Object","keys","reduce","acc","isGlobal","blockReferencesWithFilters","multiTenantCollectionsFound","forEach","useTenantsCollectionAccess","useTenantsListFilter","cleanupAfterTenantDelete","enabledSlugs","usersSlug","usersTenantsArrayFieldName","usersTenantsArrayTenantFieldName","type","Field","path","disabled","bulkEdit","column","endpoints","useAsTitle","console","warn","disableDuplicate","debug","edit","editMenuItems","tenantEnabledCollectionSlugs","tenantEnabledGlobalSlugs","customTenantField","unshift","isAutosaveEnabled","overrides","tenantFieldOverrides","unique","hooks","beforeValidate","collectionSlug","useBaseFilter","useBaseListFilter","useTenantAccess","accessResultOverride","length","missingSlugs","filter","includes","error","yellowBold","scopes","clientProps","serverProps","globalSlugs","label","tenantSelectorLabel","undefined","i18n","entries","locale","pluginI18nObject","typedLocale"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.client.d.ts","sourceRoot":"","sources":["../../../src/providers/TenantSelectionProvider/index.client.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"index.client.d.ts","sourceRoot":"","sources":["../../../src/providers/TenantSelectionProvider/index.client.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAI3C,OAAO,KAAwB,MAAM,OAAO,CAAA;AAK5C,KAAK,WAAW,GAAG;IACjB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAA;IAClC;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;OAEG;IACH,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB;;OAEG;IACH,gBAAgB,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;IAC7C;;OAEG;IACH,aAAa,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAA;IACtF;;OAEG;IACH,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAA;IAC1D;;;;;OAKG;IACH,SAAS,EAAE,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAA;IACjF;;OAEG;IACH,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAChC;;OAEG;IACH,aAAa,EAAE,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAA;CACtE,CAAA;AA+CD,eAAO,MAAM,6BAA6B,6EAKvC;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,oBAAoB,EAAE,YAAY,EAAE,CAAA;IACpC,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAC9B,qBAAqB,EAAE,MAAM,CAAA;CAC9B,sBAkOA,CAAA;AAED,eAAO,MAAM,kBAAkB,mBAA2B,CAAA"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { toast, useAuth, useConfig } from '@payloadcms/ui';
|
|
4
|
-
import { useRouter } from 'next/navigation.js';
|
|
3
|
+
import { toast, useAuth, useConfig, useRouter } from '@payloadcms/ui';
|
|
5
4
|
import { formatAdminURL } from 'payload/shared';
|
|
6
5
|
import React, { createContext } from 'react';
|
|
7
6
|
import { generateCookie } from '../../utilities/generateCookie.js';
|
|
7
|
+
import { shouldRefreshTenantSelection } from '../../utilities/shouldRefreshTenantSelection.js';
|
|
8
8
|
const Context = /*#__PURE__*/ createContext({
|
|
9
9
|
entityType: undefined,
|
|
10
10
|
options: [],
|
|
@@ -177,17 +177,18 @@ export const TenantSelectionProviderClient = ({ children, initialTenantOptions,
|
|
|
177
177
|
initialTenantOptions
|
|
178
178
|
]);
|
|
179
179
|
React.useEffect(()=>{
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
180
|
+
const hasTenantSelectionMismatch = initialValue && String(initialValue) !== getTenantCookie();
|
|
181
|
+
if (userID && (userChanged || tenantOptions.length === 0 || hasTenantSelectionMismatch)) {
|
|
182
|
+
// Sync on login, and when the provider remounts after login without tenant options.
|
|
183
|
+
void syncTenants();
|
|
184
|
+
} else if (!userID && (userChanged || hasTenantSelectionMismatch)) {
|
|
185
|
+
// user logging out
|
|
186
|
+
setSelectedTenantID(undefined);
|
|
187
|
+
deleteTenantCookie();
|
|
188
|
+
setTenantOptions((prev)=>prev.length > 0 ? [] : prev);
|
|
189
|
+
router.refresh();
|
|
190
|
+
}
|
|
191
|
+
if (userChanged) {
|
|
191
192
|
prevUserID.current = userID;
|
|
192
193
|
}
|
|
193
194
|
}, [
|
|
@@ -195,13 +196,39 @@ export const TenantSelectionProviderClient = ({ children, initialTenantOptions,
|
|
|
195
196
|
userChanged,
|
|
196
197
|
syncTenants,
|
|
197
198
|
initialValue,
|
|
198
|
-
router
|
|
199
|
+
router,
|
|
200
|
+
tenantOptions.length
|
|
201
|
+
]);
|
|
202
|
+
/**
|
|
203
|
+
* Populate tenant options when the provider mounts already-authenticated but
|
|
204
|
+
* without server-provided options. This happens when a provider setup remounts
|
|
205
|
+
* this subtree on login (see `config.conditionalProvider`): the remounted
|
|
206
|
+
* instance initializes `prevUserID` to the current user, so `userChanged` above
|
|
207
|
+
* is `false` and never fires `syncTenants`, while the server still rendered the
|
|
208
|
+
* logged-out tree so `initialTenantOptions` is empty — leaving the selector
|
|
209
|
+
* unrendered. Unlike `router.refresh()`, `syncTenants()` is a plain client fetch
|
|
210
|
+
* that cannot trigger a remount loop, so this is safe on every framework adapter.
|
|
211
|
+
*/ const didInitialSync = React.useRef(false);
|
|
212
|
+
React.useEffect(()=>{
|
|
213
|
+
if (!didInitialSync.current && !userChanged && userID && tenantOptions.length === 0 && initialTenantOptions.length === 0) {
|
|
214
|
+
didInitialSync.current = true;
|
|
215
|
+
void syncTenants();
|
|
216
|
+
}
|
|
217
|
+
}, [
|
|
218
|
+
userChanged,
|
|
219
|
+
userID,
|
|
220
|
+
tenantOptions.length,
|
|
221
|
+
initialTenantOptions,
|
|
222
|
+
syncTenants
|
|
199
223
|
]);
|
|
200
224
|
/**
|
|
201
|
-
* If there is no initial value
|
|
202
|
-
*
|
|
225
|
+
* If there is no initial value and a stale tenant cookie exists, clear the
|
|
226
|
+
* tenant and refresh the router.
|
|
203
227
|
*/ React.useEffect(()=>{
|
|
204
|
-
if (
|
|
228
|
+
if (shouldRefreshTenantSelection({
|
|
229
|
+
initialValue,
|
|
230
|
+
tenantCookie: getTenantCookie()
|
|
231
|
+
})) {
|
|
205
232
|
setTenant({
|
|
206
233
|
id: undefined,
|
|
207
234
|
refresh: true
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/providers/TenantSelectionProvider/index.client.tsx"],"sourcesContent":["'use client'\n\nimport type { OptionObject } from 'payload'\n\nimport { toast, useAuth, useConfig } from '@payloadcms/ui'\nimport { useRouter } from 'next/navigation.js'\nimport { formatAdminURL } from 'payload/shared'\nimport React, { createContext } from 'react'\n\nimport { generateCookie } from '../../utilities/generateCookie.js'\n\ntype ContextType = {\n /**\n * What is the context of the selector? It is either 'document' | 'global' | undefined.\n *\n * - 'document' means you are viewing a document in the context of a tenant\n * - 'global' means you are viewing a \"global\" (globals are collection documents but prevent you from viewing the list view) document in the context of a tenant\n * - undefined means you are not viewing a document at all\n */\n entityType?: 'document' | 'global'\n /**\n * Hoists the forms modified state\n */\n modified?: boolean\n /**\n * Array of options to select from\n */\n options: OptionObject[]\n /**\n * The currently selected tenant ID\n */\n selectedTenantID: number | string | undefined\n /**\n * Sets the entityType when a document is loaded and sets it to undefined when the document unmounts.\n */\n setEntityType: React.Dispatch<React.SetStateAction<'document' | 'global' | undefined>>\n /**\n * Sets the modified state\n */\n setModified: React.Dispatch<React.SetStateAction<boolean>>\n /**\n * Sets the selected tenant ID\n *\n * @param args.id - The ID of the tenant to select\n * @param args.refresh - Whether to refresh the page after changing the tenant\n */\n setTenant: (args: { id: number | string | undefined; refresh?: boolean }) => void\n /**\n * Used to sync tenants displayed in the tenant selector when updates are made to the tenants collection.\n */\n syncTenants: () => Promise<void>\n /**\n *\n */\n updateTenants: (args: { id: number | string; label: string }) => void\n}\n\nconst Context = createContext<ContextType>({\n entityType: undefined,\n options: [],\n selectedTenantID: undefined,\n setEntityType: () => undefined,\n setModified: () => undefined,\n setTenant: () => null,\n syncTenants: () => Promise.resolve(),\n updateTenants: () => null,\n})\n\nconst DEFAULT_COOKIE_NAME = 'payload-tenant'\n\nconst setTenantCookie = (args: { cookieName?: string; value: string }) => {\n const { cookieName = DEFAULT_COOKIE_NAME, value } = args\n document.cookie = generateCookie<string>({\n name: cookieName,\n maxAge: 60 * 60 * 24 * 365, // 1 year in seconds\n path: '/',\n returnCookieAsObject: false,\n value: value || '',\n })\n}\n\nconst deleteTenantCookie = (args: { cookieName?: string } = {}) => {\n const { cookieName = DEFAULT_COOKIE_NAME } = args\n document.cookie = generateCookie<string>({\n name: cookieName,\n maxAge: -1,\n path: '/',\n returnCookieAsObject: false,\n value: '',\n })\n}\n\nconst getTenantCookie = (args: { cookieName?: string } = {}): string | undefined => {\n const { cookieName = DEFAULT_COOKIE_NAME } = args\n const value = `; ${document.cookie}`\n const parts = value.split(`; ${cookieName}=`)\n if (parts.length === 2) {\n return parts.pop()?.split(';').shift()\n }\n return undefined\n}\n\nexport const TenantSelectionProviderClient = ({\n children,\n initialTenantOptions,\n initialValue,\n tenantsCollectionSlug,\n}: {\n children: React.ReactNode\n initialTenantOptions: OptionObject[]\n initialValue?: number | string\n tenantsCollectionSlug: string\n}) => {\n const [selectedTenantID, setSelectedTenantID] = React.useState<number | string | undefined>(\n initialValue,\n )\n const [modified, setModified] = React.useState<boolean>(false)\n const [entityType, setEntityType] = React.useState<'document' | 'global' | undefined>(undefined)\n const { user } = useAuth()\n const { config } = useConfig()\n const router = useRouter()\n const userID = React.useMemo(() => user?.id, [user?.id])\n const prevUserID = React.useRef(userID)\n const userChanged = userID !== prevUserID.current\n const [tenantOptions, setTenantOptions] = React.useState<OptionObject[]>(\n () => initialTenantOptions,\n )\n const selectedTenantLabel = React.useMemo(\n () => tenantOptions.find((option) => option.value === selectedTenantID)?.label,\n [selectedTenantID, tenantOptions],\n )\n\n const setTenantAndCookie = React.useCallback(\n ({ id, refresh }: { id: number | string | undefined; refresh?: boolean }) => {\n setSelectedTenantID(id)\n if (id !== undefined) {\n setTenantCookie({ value: String(id) })\n } else {\n deleteTenantCookie()\n }\n if (refresh) {\n router.refresh()\n }\n },\n [router],\n )\n\n const setTenant = React.useCallback<ContextType['setTenant']>(\n ({ id, refresh }) => {\n if (id === undefined) {\n if (tenantOptions.length > 1 || tenantOptions.length === 0) {\n // users with multiple tenants can clear the tenant selection\n setTenantAndCookie({ id: undefined, refresh })\n } else if (tenantOptions[0]) {\n // if there is only one tenant, auto-select that tenant\n setTenantAndCookie({ id: tenantOptions[0].value, refresh: true })\n }\n } else if (!tenantOptions.find((option) => option.value === id)) {\n // if the tenant is invalid, set the first tenant as selected\n setTenantAndCookie({\n id: tenantOptions[0]?.value,\n refresh,\n })\n } else {\n // if the tenant is in the options, set it as selected\n setTenantAndCookie({ id, refresh })\n }\n },\n [tenantOptions, setTenantAndCookie],\n )\n\n const syncTenants = React.useCallback(async () => {\n try {\n const req = await fetch(\n formatAdminURL({\n apiRoute: config.routes.api,\n path: `/${tenantsCollectionSlug}/populate-tenant-options`,\n }),\n {\n credentials: 'include',\n method: 'GET',\n },\n )\n\n const result = await req.json()\n\n if (result.tenantOptions && userID) {\n setTenantOptions(result.tenantOptions)\n\n if (result.tenantOptions.length === 1) {\n setSelectedTenantID(result.tenantOptions[0].value)\n setTenantCookie({ value: String(result.tenantOptions[0].value) })\n }\n }\n } catch (e) {\n toast.error(`Error fetching tenants`)\n }\n }, [config.routes.api, tenantsCollectionSlug, userID])\n\n const updateTenants = React.useCallback<ContextType['updateTenants']>(\n ({ id, label }) => {\n setTenantOptions((prev) => {\n return prev.map((currentTenant) => {\n if (id === currentTenant.value) {\n return {\n label,\n value: id,\n }\n }\n return currentTenant\n })\n })\n\n void syncTenants()\n },\n [syncTenants],\n )\n\n /**\n * Sync server-provided tenant options into client state.\n * When the server component re-renders (e.g., after navigation post-login),\n * it provides updated initialTenantOptions. Since useState() ignores new\n * initial values on re-renders, and re-initializes with stale props on\n * remounts, we sync them explicitly via this effect.\n */\n React.useEffect(() => {\n if (initialTenantOptions.length > 0) {\n setTenantOptions((prev) => {\n if (\n prev.length === initialTenantOptions.length &&\n prev.every((opt, i) => opt.value === initialTenantOptions[i]?.value)\n ) {\n return prev\n }\n return initialTenantOptions\n })\n\n if (initialTenantOptions.length === 1 && initialTenantOptions[0]) {\n setSelectedTenantID(initialTenantOptions[0].value)\n setTenantCookie({ value: String(initialTenantOptions[0].value) })\n }\n }\n }, [initialTenantOptions])\n\n React.useEffect(() => {\n if (userChanged || (initialValue && String(initialValue) !== getTenantCookie())) {\n if (userID) {\n // user logging in\n void syncTenants()\n } else {\n // user logging out\n setSelectedTenantID(undefined)\n deleteTenantCookie()\n setTenantOptions((prev) => (prev.length > 0 ? [] : prev))\n router.refresh()\n }\n prevUserID.current = userID\n }\n }, [userID, userChanged, syncTenants, initialValue, router])\n\n /**\n * If there is no initial value, clear the tenant and refresh the router.\n * Needed for stale tenantIDs set as a cookie.\n */\n React.useEffect(() => {\n if (!initialValue) {\n setTenant({ id: undefined, refresh: true })\n }\n }, [initialValue, setTenant])\n\n /**\n * If there is no selected tenant ID and the entity type is 'global', set the first tenant as selected.\n * This ensures that the global tenant is always set when the component mounts.\n */\n React.useEffect(() => {\n if (!selectedTenantID && tenantOptions.length > 0 && entityType === 'global') {\n setTenant({\n id: tenantOptions[0]?.value,\n refresh: true,\n })\n }\n }, [selectedTenantID, tenantOptions, entityType, setTenant])\n\n return (\n <span\n data-selected-tenant-id={selectedTenantID}\n data-selected-tenant-title={selectedTenantLabel}\n >\n <Context\n value={{\n entityType,\n modified,\n options: tenantOptions,\n selectedTenantID,\n setEntityType,\n setModified,\n setTenant,\n syncTenants,\n updateTenants,\n }}\n >\n {children}\n </Context>\n </span>\n )\n}\n\nexport const useTenantSelection = () => React.use(Context)\n"],"names":["toast","useAuth","useConfig","useRouter","formatAdminURL","React","createContext","generateCookie","Context","entityType","undefined","options","selectedTenantID","setEntityType","setModified","setTenant","syncTenants","Promise","resolve","updateTenants","DEFAULT_COOKIE_NAME","setTenantCookie","args","cookieName","value","document","cookie","name","maxAge","path","returnCookieAsObject","deleteTenantCookie","getTenantCookie","parts","split","length","pop","shift","TenantSelectionProviderClient","children","initialTenantOptions","initialValue","tenantsCollectionSlug","setSelectedTenantID","useState","modified","user","config","router","userID","useMemo","id","prevUserID","useRef","userChanged","current","tenantOptions","setTenantOptions","selectedTenantLabel","find","option","label","setTenantAndCookie","useCallback","refresh","String","req","fetch","apiRoute","routes","api","credentials","method","result","json","e","error","prev","map","currentTenant","useEffect","every","opt","i","span","data-selected-tenant-id","data-selected-tenant-title","useTenantSelection","use"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/providers/TenantSelectionProvider/index.client.tsx"],"sourcesContent":["'use client'\n\nimport type { OptionObject } from 'payload'\n\nimport { toast, useAuth, useConfig, useRouter } from '@payloadcms/ui'\nimport { formatAdminURL } from 'payload/shared'\nimport React, { createContext } from 'react'\n\nimport { generateCookie } from '../../utilities/generateCookie.js'\nimport { shouldRefreshTenantSelection } from '../../utilities/shouldRefreshTenantSelection.js'\n\ntype ContextType = {\n /**\n * What is the context of the selector? It is either 'document' | 'global' | undefined.\n *\n * - 'document' means you are viewing a document in the context of a tenant\n * - 'global' means you are viewing a \"global\" (globals are collection documents but prevent you from viewing the list view) document in the context of a tenant\n * - undefined means you are not viewing a document at all\n */\n entityType?: 'document' | 'global'\n /**\n * Hoists the forms modified state\n */\n modified?: boolean\n /**\n * Array of options to select from\n */\n options: OptionObject[]\n /**\n * The currently selected tenant ID\n */\n selectedTenantID: number | string | undefined\n /**\n * Sets the entityType when a document is loaded and sets it to undefined when the document unmounts.\n */\n setEntityType: React.Dispatch<React.SetStateAction<'document' | 'global' | undefined>>\n /**\n * Sets the modified state\n */\n setModified: React.Dispatch<React.SetStateAction<boolean>>\n /**\n * Sets the selected tenant ID\n *\n * @param args.id - The ID of the tenant to select\n * @param args.refresh - Whether to refresh the page after changing the tenant\n */\n setTenant: (args: { id: number | string | undefined; refresh?: boolean }) => void\n /**\n * Used to sync tenants displayed in the tenant selector when updates are made to the tenants collection.\n */\n syncTenants: () => Promise<void>\n /**\n *\n */\n updateTenants: (args: { id: number | string; label: string }) => void\n}\n\nconst Context = createContext<ContextType>({\n entityType: undefined,\n options: [],\n selectedTenantID: undefined,\n setEntityType: () => undefined,\n setModified: () => undefined,\n setTenant: () => null,\n syncTenants: () => Promise.resolve(),\n updateTenants: () => null,\n})\n\nconst DEFAULT_COOKIE_NAME = 'payload-tenant'\n\nconst setTenantCookie = (args: { cookieName?: string; value: string }) => {\n const { cookieName = DEFAULT_COOKIE_NAME, value } = args\n document.cookie = generateCookie<string>({\n name: cookieName,\n maxAge: 60 * 60 * 24 * 365, // 1 year in seconds\n path: '/',\n returnCookieAsObject: false,\n value: value || '',\n })\n}\n\nconst deleteTenantCookie = (args: { cookieName?: string } = {}) => {\n const { cookieName = DEFAULT_COOKIE_NAME } = args\n document.cookie = generateCookie<string>({\n name: cookieName,\n maxAge: -1,\n path: '/',\n returnCookieAsObject: false,\n value: '',\n })\n}\n\nconst getTenantCookie = (args: { cookieName?: string } = {}): string | undefined => {\n const { cookieName = DEFAULT_COOKIE_NAME } = args\n const value = `; ${document.cookie}`\n const parts = value.split(`; ${cookieName}=`)\n if (parts.length === 2) {\n return parts.pop()?.split(';').shift()\n }\n return undefined\n}\n\nexport const TenantSelectionProviderClient = ({\n children,\n initialTenantOptions,\n initialValue,\n tenantsCollectionSlug,\n}: {\n children: React.ReactNode\n initialTenantOptions: OptionObject[]\n initialValue?: number | string\n tenantsCollectionSlug: string\n}) => {\n const [selectedTenantID, setSelectedTenantID] = React.useState<number | string | undefined>(\n initialValue,\n )\n const [modified, setModified] = React.useState<boolean>(false)\n const [entityType, setEntityType] = React.useState<'document' | 'global' | undefined>(undefined)\n const { user } = useAuth()\n const { config } = useConfig()\n const router = useRouter()\n const userID = React.useMemo(() => user?.id, [user?.id])\n const prevUserID = React.useRef(userID)\n const userChanged = userID !== prevUserID.current\n const [tenantOptions, setTenantOptions] = React.useState<OptionObject[]>(\n () => initialTenantOptions,\n )\n const selectedTenantLabel = React.useMemo(\n () => tenantOptions.find((option) => option.value === selectedTenantID)?.label,\n [selectedTenantID, tenantOptions],\n )\n\n const setTenantAndCookie = React.useCallback(\n ({ id, refresh }: { id: number | string | undefined; refresh?: boolean }) => {\n setSelectedTenantID(id)\n if (id !== undefined) {\n setTenantCookie({ value: String(id) })\n } else {\n deleteTenantCookie()\n }\n if (refresh) {\n router.refresh()\n }\n },\n [router],\n )\n\n const setTenant = React.useCallback<ContextType['setTenant']>(\n ({ id, refresh }) => {\n if (id === undefined) {\n if (tenantOptions.length > 1 || tenantOptions.length === 0) {\n // users with multiple tenants can clear the tenant selection\n setTenantAndCookie({ id: undefined, refresh })\n } else if (tenantOptions[0]) {\n // if there is only one tenant, auto-select that tenant\n setTenantAndCookie({ id: tenantOptions[0].value, refresh: true })\n }\n } else if (!tenantOptions.find((option) => option.value === id)) {\n // if the tenant is invalid, set the first tenant as selected\n setTenantAndCookie({\n id: tenantOptions[0]?.value,\n refresh,\n })\n } else {\n // if the tenant is in the options, set it as selected\n setTenantAndCookie({ id, refresh })\n }\n },\n [tenantOptions, setTenantAndCookie],\n )\n\n const syncTenants = React.useCallback(async () => {\n try {\n const req = await fetch(\n formatAdminURL({\n apiRoute: config.routes.api,\n path: `/${tenantsCollectionSlug}/populate-tenant-options`,\n }),\n {\n credentials: 'include',\n method: 'GET',\n },\n )\n\n const result = await req.json()\n\n if (result.tenantOptions && userID) {\n setTenantOptions(result.tenantOptions)\n\n if (result.tenantOptions.length === 1) {\n setSelectedTenantID(result.tenantOptions[0].value)\n setTenantCookie({ value: String(result.tenantOptions[0].value) })\n }\n }\n } catch (e) {\n toast.error(`Error fetching tenants`)\n }\n }, [config.routes.api, tenantsCollectionSlug, userID])\n\n const updateTenants = React.useCallback<ContextType['updateTenants']>(\n ({ id, label }) => {\n setTenantOptions((prev) => {\n return prev.map((currentTenant) => {\n if (id === currentTenant.value) {\n return {\n label,\n value: id,\n }\n }\n return currentTenant\n })\n })\n\n void syncTenants()\n },\n [syncTenants],\n )\n\n /**\n * Sync server-provided tenant options into client state.\n * When the server component re-renders (e.g., after navigation post-login),\n * it provides updated initialTenantOptions. Since useState() ignores new\n * initial values on re-renders, and re-initializes with stale props on\n * remounts, we sync them explicitly via this effect.\n */\n React.useEffect(() => {\n if (initialTenantOptions.length > 0) {\n setTenantOptions((prev) => {\n if (\n prev.length === initialTenantOptions.length &&\n prev.every((opt, i) => opt.value === initialTenantOptions[i]?.value)\n ) {\n return prev\n }\n return initialTenantOptions\n })\n\n if (initialTenantOptions.length === 1 && initialTenantOptions[0]) {\n setSelectedTenantID(initialTenantOptions[0].value)\n setTenantCookie({ value: String(initialTenantOptions[0].value) })\n }\n }\n }, [initialTenantOptions])\n\n React.useEffect(() => {\n const hasTenantSelectionMismatch =\n initialValue && String(initialValue) !== getTenantCookie()\n\n if (userID && (userChanged || tenantOptions.length === 0 || hasTenantSelectionMismatch)) {\n // Sync on login, and when the provider remounts after login without tenant options.\n void syncTenants()\n } else if (!userID && (userChanged || hasTenantSelectionMismatch)) {\n // user logging out\n setSelectedTenantID(undefined)\n deleteTenantCookie()\n setTenantOptions((prev) => (prev.length > 0 ? [] : prev))\n router.refresh()\n }\n\n if (userChanged) {\n prevUserID.current = userID\n }\n }, [userID, userChanged, syncTenants, initialValue, router, tenantOptions.length])\n\n /**\n * Populate tenant options when the provider mounts already-authenticated but\n * without server-provided options. This happens when a provider setup remounts\n * this subtree on login (see `config.conditionalProvider`): the remounted\n * instance initializes `prevUserID` to the current user, so `userChanged` above\n * is `false` and never fires `syncTenants`, while the server still rendered the\n * logged-out tree so `initialTenantOptions` is empty — leaving the selector\n * unrendered. Unlike `router.refresh()`, `syncTenants()` is a plain client fetch\n * that cannot trigger a remount loop, so this is safe on every framework adapter.\n */\n const didInitialSync = React.useRef(false)\n React.useEffect(() => {\n if (\n !didInitialSync.current &&\n !userChanged &&\n userID &&\n tenantOptions.length === 0 &&\n initialTenantOptions.length === 0\n ) {\n didInitialSync.current = true\n void syncTenants()\n }\n }, [userChanged, userID, tenantOptions.length, initialTenantOptions, syncTenants])\n\n /**\n * If there is no initial value and a stale tenant cookie exists, clear the\n * tenant and refresh the router.\n */\n React.useEffect(() => {\n if (\n shouldRefreshTenantSelection({\n initialValue,\n tenantCookie: getTenantCookie(),\n })\n ) {\n setTenant({ id: undefined, refresh: true })\n }\n }, [initialValue, setTenant])\n\n /**\n * If there is no selected tenant ID and the entity type is 'global', set the first tenant as selected.\n * This ensures that the global tenant is always set when the component mounts.\n */\n React.useEffect(() => {\n if (!selectedTenantID && tenantOptions.length > 0 && entityType === 'global') {\n setTenant({\n id: tenantOptions[0]?.value,\n refresh: true,\n })\n }\n }, [selectedTenantID, tenantOptions, entityType, setTenant])\n\n return (\n <span\n data-selected-tenant-id={selectedTenantID}\n data-selected-tenant-title={selectedTenantLabel}\n >\n <Context\n value={{\n entityType,\n modified,\n options: tenantOptions,\n selectedTenantID,\n setEntityType,\n setModified,\n setTenant,\n syncTenants,\n updateTenants,\n }}\n >\n {children}\n </Context>\n </span>\n )\n}\n\nexport const useTenantSelection = () => React.use(Context)\n"],"names":["toast","useAuth","useConfig","useRouter","formatAdminURL","React","createContext","generateCookie","shouldRefreshTenantSelection","Context","entityType","undefined","options","selectedTenantID","setEntityType","setModified","setTenant","syncTenants","Promise","resolve","updateTenants","DEFAULT_COOKIE_NAME","setTenantCookie","args","cookieName","value","document","cookie","name","maxAge","path","returnCookieAsObject","deleteTenantCookie","getTenantCookie","parts","split","length","pop","shift","TenantSelectionProviderClient","children","initialTenantOptions","initialValue","tenantsCollectionSlug","setSelectedTenantID","useState","modified","user","config","router","userID","useMemo","id","prevUserID","useRef","userChanged","current","tenantOptions","setTenantOptions","selectedTenantLabel","find","option","label","setTenantAndCookie","useCallback","refresh","String","req","fetch","apiRoute","routes","api","credentials","method","result","json","e","error","prev","map","currentTenant","useEffect","every","opt","i","hasTenantSelectionMismatch","didInitialSync","tenantCookie","span","data-selected-tenant-id","data-selected-tenant-title","useTenantSelection","use"],"mappings":"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"}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import type { Payload,
|
|
1
|
+
import type { Payload, ServerAdapter, User } from 'payload';
|
|
2
2
|
import type { MultiTenantPluginConfig } from '../../types.js';
|
|
3
|
-
type Args
|
|
3
|
+
type Args = {
|
|
4
4
|
children: React.ReactNode;
|
|
5
5
|
payload: Payload;
|
|
6
|
+
server?: ServerAdapter;
|
|
6
7
|
tenantsArrayFieldName: string;
|
|
7
8
|
tenantsArrayTenantFieldName: string;
|
|
8
9
|
tenantsCollectionSlug: string;
|
|
9
10
|
useAsTitle: string;
|
|
10
|
-
user:
|
|
11
|
-
userHasAccessToAllTenants: Required<MultiTenantPluginConfig
|
|
11
|
+
user: User;
|
|
12
|
+
userHasAccessToAllTenants: Required<MultiTenantPluginConfig>['userHasAccessToAllTenants'];
|
|
12
13
|
};
|
|
13
|
-
export declare const TenantSelectionProvider: ({ children, payload, tenantsArrayFieldName, tenantsArrayTenantFieldName, tenantsCollectionSlug, useAsTitle, user, userHasAccessToAllTenants, }: Args
|
|
14
|
+
export declare const TenantSelectionProvider: ({ children, payload, server, tenantsArrayFieldName, tenantsArrayTenantFieldName, tenantsCollectionSlug, useAsTitle, user, userHasAccessToAllTenants, }: Args) => Promise<import("react").JSX.Element>;
|
|
14
15
|
export {};
|
|
15
16
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/TenantSelectionProvider/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/TenantSelectionProvider/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAE3D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAA;AAK7D,KAAK,IAAI,GAAG;IACV,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,2BAA2B,EAAE,MAAM,CAAA;IACnC,qBAAqB,EAAE,MAAM,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,IAAI,CAAA;IACV,yBAAyB,EAAE,QAAQ,CAAC,uBAAuB,CAAC,CAAC,2BAA2B,CAAC,CAAA;CAC1F,CAAA;AAED,eAAO,MAAM,uBAAuB,2JAUjC,IAAI,yCA8CN,CAAA"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { cookies as getCookies } from 'next/headers.js';
|
|
3
2
|
import { getTenantOptions } from '../../utilities/getTenantOptions.js';
|
|
4
3
|
import { TenantSelectionProviderClient } from './index.client.js';
|
|
5
|
-
export const TenantSelectionProvider = async ({ children, payload, tenantsArrayFieldName, tenantsArrayTenantFieldName, tenantsCollectionSlug, useAsTitle, user, userHasAccessToAllTenants })=>{
|
|
4
|
+
export const TenantSelectionProvider = async ({ children, payload, server, tenantsArrayFieldName, tenantsArrayTenantFieldName, tenantsCollectionSlug, useAsTitle, user, userHasAccessToAllTenants })=>{
|
|
5
|
+
if (!server) {
|
|
6
|
+
throw new Error('TenantSelectionProvider requires `server` in ServerProps. Ensure your framework adapter (e.g. @payloadcms/next) populates ServerProps.server.');
|
|
7
|
+
}
|
|
6
8
|
const tenantOptions = await getTenantOptions({
|
|
7
9
|
payload,
|
|
8
10
|
tenantsArrayFieldName,
|
|
@@ -12,7 +14,7 @@ export const TenantSelectionProvider = async ({ children, payload, tenantsArrayF
|
|
|
12
14
|
user,
|
|
13
15
|
userHasAccessToAllTenants
|
|
14
16
|
});
|
|
15
|
-
const cookies = await getCookies();
|
|
17
|
+
const cookies = await server.getCookies();
|
|
16
18
|
const tenantCookie = cookies.get('payload-tenant')?.value;
|
|
17
19
|
let initialValue = undefined;
|
|
18
20
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/providers/TenantSelectionProvider/index.tsx"],"sourcesContent":["import type { Payload,
|
|
1
|
+
{"version":3,"sources":["../../../src/providers/TenantSelectionProvider/index.tsx"],"sourcesContent":["import type { Payload, ServerAdapter, User } from 'payload'\n\nimport type { MultiTenantPluginConfig } from '../../types.js'\n\nimport { getTenantOptions } from '../../utilities/getTenantOptions.js'\nimport { TenantSelectionProviderClient } from './index.client.js'\n\ntype Args = {\n children: React.ReactNode\n payload: Payload\n server?: ServerAdapter\n tenantsArrayFieldName: string\n tenantsArrayTenantFieldName: string\n tenantsCollectionSlug: string\n useAsTitle: string\n user: User\n userHasAccessToAllTenants: Required<MultiTenantPluginConfig>['userHasAccessToAllTenants']\n}\n\nexport const TenantSelectionProvider = async ({\n children,\n payload,\n server,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n useAsTitle,\n user,\n userHasAccessToAllTenants,\n}: Args) => {\n if (!server) {\n throw new Error(\n 'TenantSelectionProvider requires `server` in ServerProps. Ensure your framework adapter (e.g. @payloadcms/next) populates ServerProps.server.',\n )\n }\n const tenantOptions = await getTenantOptions({\n payload,\n tenantsArrayFieldName,\n tenantsArrayTenantFieldName,\n tenantsCollectionSlug,\n useAsTitle,\n user,\n userHasAccessToAllTenants,\n })\n\n const cookies = await server.getCookies()\n const tenantCookie = cookies.get('payload-tenant')?.value\n let initialValue = undefined\n\n /**\n * Ensure the cookie is a valid tenant\n */\n if (tenantCookie) {\n const matchingOption = tenantOptions.find((option) => String(option.value) === tenantCookie)\n if (matchingOption) {\n initialValue = matchingOption.value\n }\n }\n\n /**\n * If the there was no cookie or the cookie was an invalid tenantID set intialValue\n */\n if (!initialValue) {\n initialValue = tenantOptions.length > 1 ? undefined : tenantOptions[0]?.value\n }\n\n return (\n <TenantSelectionProviderClient\n initialTenantOptions={tenantOptions}\n initialValue={initialValue}\n tenantsCollectionSlug={tenantsCollectionSlug}\n >\n {children}\n </TenantSelectionProviderClient>\n )\n}\n"],"names":["getTenantOptions","TenantSelectionProviderClient","TenantSelectionProvider","children","payload","server","tenantsArrayFieldName","tenantsArrayTenantFieldName","tenantsCollectionSlug","useAsTitle","user","userHasAccessToAllTenants","Error","tenantOptions","cookies","getCookies","tenantCookie","get","value","initialValue","undefined","matchingOption","find","option","String","length","initialTenantOptions"],"mappings":";AAIA,SAASA,gBAAgB,QAAQ,sCAAqC;AACtE,SAASC,6BAA6B,QAAQ,oBAAmB;AAcjE,OAAO,MAAMC,0BAA0B,OAAO,EAC5CC,QAAQ,EACRC,OAAO,EACPC,MAAM,EACNC,qBAAqB,EACrBC,2BAA2B,EAC3BC,qBAAqB,EACrBC,UAAU,EACVC,IAAI,EACJC,yBAAyB,EACpB;IACL,IAAI,CAACN,QAAQ;QACX,MAAM,IAAIO,MACR;IAEJ;IACA,MAAMC,gBAAgB,MAAMb,iBAAiB;QAC3CI;QACAE;QACAC;QACAC;QACAC;QACAC;QACAC;IACF;IAEA,MAAMG,UAAU,MAAMT,OAAOU,UAAU;IACvC,MAAMC,eAAeF,QAAQG,GAAG,CAAC,mBAAmBC;IACpD,IAAIC,eAAeC;IAEnB;;GAEC,GACD,IAAIJ,cAAc;QAChB,MAAMK,iBAAiBR,cAAcS,IAAI,CAAC,CAACC,SAAWC,OAAOD,OAAOL,KAAK,MAAMF;QAC/E,IAAIK,gBAAgB;YAClBF,eAAeE,eAAeH,KAAK;QACrC;IACF;IAEA;;GAEC,GACD,IAAI,CAACC,cAAc;QACjBA,eAAeN,cAAcY,MAAM,GAAG,IAAIL,YAAYP,aAAa,CAAC,EAAE,EAAEK;IAC1E;IAEA,qBACE,KAACjB;QACCyB,sBAAsBb;QACtBM,cAAcA;QACdX,uBAAuBA;kBAEtBL;;AAGP,EAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../../src/translations/languages/en.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEjD,eAAO,MAAM,cAAc
|
|
1
|
+
{"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../../src/translations/languages/en.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEjD,eAAO,MAAM,cAAc;IACzB,qBAAqB;QACnB,4BAA4B;QAC5B,2BAA2B;QAC3B,4BAA4B;QAC5B,0BAA0B;;CAE7B,CAAA;AAED,eAAO,MAAM,EAAE,EAAE,cAGhB,CAAA"}
|