@budibase/backend-core 3.2.4 → 3.2.6
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/dist/index.js.map +1 -1
- package/dist/index.js.meta.json +1 -1
- package/dist/package.json +11 -4
- package/dist/plugins.js.meta.json +1 -1
- package/package.json +11 -4
- package/src/accounts/accounts.ts +0 -82
- package/src/accounts/api.ts +0 -59
- package/src/accounts/index.ts +0 -1
- package/src/auth/auth.ts +0 -210
- package/src/auth/index.ts +0 -1
- package/src/auth/tests/auth.spec.ts +0 -14
- package/src/blacklist/blacklist.ts +0 -54
- package/src/blacklist/index.ts +0 -1
- package/src/blacklist/tests/blacklist.spec.ts +0 -46
- package/src/cache/appMetadata.ts +0 -88
- package/src/cache/base/index.ts +0 -150
- package/src/cache/docWritethrough.ts +0 -105
- package/src/cache/generic.ts +0 -33
- package/src/cache/index.ts +0 -8
- package/src/cache/invite.ts +0 -86
- package/src/cache/passwordReset.ts +0 -49
- package/src/cache/tests/docWritethrough.spec.ts +0 -296
- package/src/cache/tests/user.spec.ts +0 -145
- package/src/cache/tests/writethrough.spec.ts +0 -139
- package/src/cache/user.ts +0 -154
- package/src/cache/writethrough.ts +0 -133
- package/src/configs/configs.ts +0 -263
- package/src/configs/index.ts +0 -1
- package/src/configs/tests/configs.spec.ts +0 -184
- package/src/constants/db.ts +0 -75
- package/src/constants/index.ts +0 -2
- package/src/constants/misc.ts +0 -36
- package/src/context/Context.ts +0 -14
- package/src/context/identity.ts +0 -58
- package/src/context/index.ts +0 -3
- package/src/context/mainContext.ts +0 -422
- package/src/context/tests/index.spec.ts +0 -255
- package/src/context/types.ts +0 -26
- package/src/db/Replication.ts +0 -94
- package/src/db/couch/DatabaseImpl.ts +0 -511
- package/src/db/couch/connections.ts +0 -89
- package/src/db/couch/index.ts +0 -4
- package/src/db/couch/pouchDB.ts +0 -97
- package/src/db/couch/pouchDump.ts +0 -0
- package/src/db/couch/tests/DatabaseImpl.spec.ts +0 -118
- package/src/db/couch/utils.ts +0 -55
- package/src/db/db.ts +0 -34
- package/src/db/errors.ts +0 -14
- package/src/db/index.ts +0 -12
- package/src/db/instrumentation.ts +0 -199
- package/src/db/lucene.ts +0 -721
- package/src/db/searchIndexes/index.ts +0 -1
- package/src/db/searchIndexes/searchIndexes.ts +0 -62
- package/src/db/tests/DatabaseImpl.spec.ts +0 -55
- package/src/db/tests/connections.spec.ts +0 -22
- package/src/db/tests/index.spec.ts +0 -32
- package/src/db/tests/lucene.spec.ts +0 -400
- package/src/db/tests/pouch.spec.js +0 -62
- package/src/db/tests/utils.spec.ts +0 -63
- package/src/db/utils.ts +0 -208
- package/src/db/views.ts +0 -245
- package/src/docIds/conversions.ts +0 -60
- package/src/docIds/ids.ts +0 -126
- package/src/docIds/index.ts +0 -2
- package/src/docIds/newid.ts +0 -5
- package/src/docIds/params.ts +0 -189
- package/src/docUpdates/index.ts +0 -24
- package/src/environment.ts +0 -293
- package/src/errors/errors.ts +0 -119
- package/src/errors/index.ts +0 -1
- package/src/events/analytics.ts +0 -6
- package/src/events/asyncEvents/index.ts +0 -2
- package/src/events/asyncEvents/publisher.ts +0 -12
- package/src/events/asyncEvents/queue.ts +0 -22
- package/src/events/backfill.ts +0 -183
- package/src/events/documentId.ts +0 -56
- package/src/events/events.ts +0 -47
- package/src/events/identification.ts +0 -311
- package/src/events/index.ts +0 -15
- package/src/events/processors/AnalyticsProcessor.ts +0 -64
- package/src/events/processors/AuditLogsProcessor.ts +0 -92
- package/src/events/processors/LoggingProcessor.ts +0 -36
- package/src/events/processors/Processors.ts +0 -52
- package/src/events/processors/async/DocumentUpdateProcessor.ts +0 -38
- package/src/events/processors/index.ts +0 -19
- package/src/events/processors/posthog/PosthogProcessor.ts +0 -118
- package/src/events/processors/posthog/index.ts +0 -3
- package/src/events/processors/posthog/rateLimiting.ts +0 -106
- package/src/events/processors/posthog/tests/PosthogProcessor.spec.ts +0 -164
- package/src/events/processors/types.ts +0 -1
- package/src/events/publishers/account.ts +0 -41
- package/src/events/publishers/ai.ts +0 -21
- package/src/events/publishers/app.ts +0 -168
- package/src/events/publishers/auditLog.ts +0 -26
- package/src/events/publishers/auth.ts +0 -73
- package/src/events/publishers/automation.ts +0 -110
- package/src/events/publishers/backfill.ts +0 -74
- package/src/events/publishers/backup.ts +0 -42
- package/src/events/publishers/datasource.ts +0 -48
- package/src/events/publishers/email.ts +0 -17
- package/src/events/publishers/environmentVariable.ts +0 -38
- package/src/events/publishers/group.ts +0 -99
- package/src/events/publishers/index.ts +0 -25
- package/src/events/publishers/installation.ts +0 -38
- package/src/events/publishers/layout.ts +0 -26
- package/src/events/publishers/license.ts +0 -84
- package/src/events/publishers/org.ts +0 -37
- package/src/events/publishers/plugin.ts +0 -47
- package/src/events/publishers/query.ts +0 -89
- package/src/events/publishers/role.ts +0 -62
- package/src/events/publishers/rows.ts +0 -29
- package/src/events/publishers/screen.ts +0 -36
- package/src/events/publishers/serve.ts +0 -43
- package/src/events/publishers/table.ts +0 -70
- package/src/events/publishers/user.ts +0 -202
- package/src/events/publishers/view.ts +0 -107
- package/src/features/features.ts +0 -277
- package/src/features/index.ts +0 -2
- package/src/features/tests/features.spec.ts +0 -267
- package/src/features/tests/utils.ts +0 -64
- package/src/helpers.ts +0 -9
- package/src/index.ts +0 -59
- package/src/installation.ts +0 -115
- package/src/logging/alerts.ts +0 -26
- package/src/logging/correlation/correlation.ts +0 -15
- package/src/logging/correlation/index.ts +0 -1
- package/src/logging/correlation/middleware.ts +0 -18
- package/src/logging/index.ts +0 -4
- package/src/logging/pino/logger.ts +0 -239
- package/src/logging/pino/middleware.ts +0 -48
- package/src/logging/system.ts +0 -81
- package/src/logging/tests/system.spec.ts +0 -61
- package/src/middleware/adminOnly.ts +0 -9
- package/src/middleware/auditLog.ts +0 -6
- package/src/middleware/authenticated.ts +0 -247
- package/src/middleware/builderOnly.ts +0 -21
- package/src/middleware/builderOrAdmin.ts +0 -21
- package/src/middleware/contentSecurityPolicy.ts +0 -113
- package/src/middleware/csrf.ts +0 -81
- package/src/middleware/errorHandling.ts +0 -43
- package/src/middleware/index.ts +0 -24
- package/src/middleware/internalApi.ts +0 -23
- package/src/middleware/ip.ts +0 -12
- package/src/middleware/joi-validator.ts +0 -58
- package/src/middleware/matchers.ts +0 -39
- package/src/middleware/passport/datasource/google.ts +0 -102
- package/src/middleware/passport/local.ts +0 -54
- package/src/middleware/passport/sso/google.ts +0 -77
- package/src/middleware/passport/sso/oidc.ts +0 -152
- package/src/middleware/passport/sso/sso.ts +0 -138
- package/src/middleware/passport/sso/tests/google.spec.ts +0 -68
- package/src/middleware/passport/sso/tests/oidc.spec.ts +0 -144
- package/src/middleware/passport/sso/tests/sso.spec.ts +0 -197
- package/src/middleware/passport/utils.ts +0 -38
- package/src/middleware/querystringToBody.ts +0 -28
- package/src/middleware/tenancy.ts +0 -36
- package/src/middleware/tests/builder.spec.ts +0 -181
- package/src/middleware/tests/contentSecurityPolicy.spec.ts +0 -75
- package/src/middleware/tests/matchers.spec.ts +0 -100
- package/src/migrations/definitions.ts +0 -40
- package/src/migrations/index.ts +0 -2
- package/src/migrations/migrations.ts +0 -186
- package/src/migrations/tests/__snapshots__/migrations.spec.ts.snap +0 -11
- package/src/migrations/tests/migrations.spec.ts +0 -64
- package/src/objectStore/buckets/app.ts +0 -53
- package/src/objectStore/buckets/global.ts +0 -29
- package/src/objectStore/buckets/index.ts +0 -3
- package/src/objectStore/buckets/plugins.ts +0 -71
- package/src/objectStore/buckets/tests/app.spec.ts +0 -161
- package/src/objectStore/buckets/tests/global.spec.ts +0 -74
- package/src/objectStore/buckets/tests/plugins.spec.ts +0 -111
- package/src/objectStore/cloudfront.ts +0 -41
- package/src/objectStore/index.ts +0 -3
- package/src/objectStore/objectStore.ts +0 -585
- package/src/objectStore/utils.ts +0 -113
- package/src/platform/index.ts +0 -3
- package/src/platform/platformDb.ts +0 -6
- package/src/platform/tenants.ts +0 -101
- package/src/platform/tests/tenants.spec.ts +0 -26
- package/src/platform/users.ts +0 -129
- package/src/plugin/index.ts +0 -1
- package/src/plugin/tests/validation.spec.ts +0 -209
- package/src/plugin/utils.ts +0 -175
- package/src/queue/constants.ts +0 -8
- package/src/queue/inMemoryQueue.ts +0 -189
- package/src/queue/index.ts +0 -2
- package/src/queue/listeners.ts +0 -199
- package/src/queue/queue.ts +0 -84
- package/src/redis/index.ts +0 -6
- package/src/redis/init.ts +0 -118
- package/src/redis/redis.ts +0 -358
- package/src/redis/redlockImpl.ts +0 -155
- package/src/redis/tests/redis.spec.ts +0 -207
- package/src/redis/tests/redlockImpl.spec.ts +0 -105
- package/src/redis/utils.ts +0 -128
- package/src/security/auth.ts +0 -24
- package/src/security/encryption.ts +0 -185
- package/src/security/index.ts +0 -1
- package/src/security/permissions.ts +0 -166
- package/src/security/roles.ts +0 -655
- package/src/security/secrets.ts +0 -20
- package/src/security/sessions.ts +0 -123
- package/src/security/tests/auth.spec.ts +0 -45
- package/src/security/tests/encryption.spec.ts +0 -31
- package/src/security/tests/permissions.spec.ts +0 -146
- package/src/security/tests/secrets.spec.ts +0 -35
- package/src/security/tests/sessions.spec.ts +0 -12
- package/src/sql/designDoc.ts +0 -17
- package/src/sql/index.ts +0 -5
- package/src/sql/sql.ts +0 -1854
- package/src/sql/sqlTable.ts +0 -319
- package/src/sql/utils.ts +0 -193
- package/src/tenancy/db.ts +0 -6
- package/src/tenancy/index.ts +0 -2
- package/src/tenancy/tenancy.ts +0 -148
- package/src/tenancy/tests/tenancy.spec.ts +0 -184
- package/src/timers/index.ts +0 -1
- package/src/timers/timers.ts +0 -22
- package/src/users/db.ts +0 -582
- package/src/users/events.ts +0 -176
- package/src/users/index.ts +0 -4
- package/src/users/lookup.ts +0 -99
- package/src/users/test/db.spec.ts +0 -188
- package/src/users/test/utils.spec.ts +0 -67
- package/src/users/users.ts +0 -353
- package/src/users/utils.ts +0 -81
- package/src/utils/Duration.ts +0 -56
- package/src/utils/hashing.ts +0 -15
- package/src/utils/index.ts +0 -4
- package/src/utils/stringUtils.ts +0 -8
- package/src/utils/tests/Duration.spec.ts +0 -19
- package/src/utils/tests/utils.spec.ts +0 -204
- package/src/utils/utils.ts +0 -249
- package/tests/core/logging.ts +0 -34
- package/tests/core/users/users.spec.js +0 -53
- package/tests/core/utilities/index.ts +0 -7
- package/tests/core/utilities/jestUtils.ts +0 -33
- package/tests/core/utilities/mocks/alerts.ts +0 -4
- package/tests/core/utilities/mocks/date.ts +0 -3
- package/tests/core/utilities/mocks/events.ts +0 -132
- package/tests/core/utilities/mocks/index.ts +0 -9
- package/tests/core/utilities/mocks/licenses.ts +0 -119
- package/tests/core/utilities/queue.ts +0 -9
- package/tests/core/utilities/structures/Chance.ts +0 -20
- package/tests/core/utilities/structures/accounts.ts +0 -80
- package/tests/core/utilities/structures/apps.ts +0 -21
- package/tests/core/utilities/structures/common.ts +0 -7
- package/tests/core/utilities/structures/db.ts +0 -12
- package/tests/core/utilities/structures/documents/index.ts +0 -1
- package/tests/core/utilities/structures/documents/platform/index.ts +0 -1
- package/tests/core/utilities/structures/documents/platform/installation.ts +0 -12
- package/tests/core/utilities/structures/generator.ts +0 -3
- package/tests/core/utilities/structures/index.ts +0 -15
- package/tests/core/utilities/structures/koa.ts +0 -16
- package/tests/core/utilities/structures/licenses.ts +0 -190
- package/tests/core/utilities/structures/plugins.ts +0 -19
- package/tests/core/utilities/structures/quotas.ts +0 -72
- package/tests/core/utilities/structures/scim.ts +0 -80
- package/tests/core/utilities/structures/sso.ts +0 -118
- package/tests/core/utilities/structures/tenants.ts +0 -5
- package/tests/core/utilities/structures/userGroups.ts +0 -10
- package/tests/core/utilities/structures/users.ts +0 -89
- package/tests/core/utilities/testContainerUtils.ts +0 -165
- package/tests/core/utilities/utils/index.ts +0 -2
- package/tests/core/utilities/utils/queue.ts +0 -27
- package/tests/core/utilities/utils/time.ts +0 -3
- package/tests/extra/DBTestConfiguration.ts +0 -36
- package/tests/extra/index.ts +0 -2
- package/tests/extra/testEnv.ts +0 -95
- package/tests/index.ts +0 -2
- package/tests/jestEnv.ts +0 -10
- package/tests/jestSetup.ts +0 -36
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
import { DBTestConfiguration } from "../../../tests/extra"
|
|
2
|
-
import { structures } from "../../../tests"
|
|
3
|
-
import { Writethrough } from "../writethrough"
|
|
4
|
-
import { getDB } from "../../db"
|
|
5
|
-
import { Document } from "@budibase/types"
|
|
6
|
-
import tk from "timekeeper"
|
|
7
|
-
|
|
8
|
-
tk.freeze(Date.now())
|
|
9
|
-
|
|
10
|
-
interface ValueDoc extends Document {
|
|
11
|
-
value: any
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const DELAY = 5000
|
|
15
|
-
|
|
16
|
-
describe("writethrough", () => {
|
|
17
|
-
const config = new DBTestConfiguration()
|
|
18
|
-
|
|
19
|
-
const db = getDB(structures.db.id())
|
|
20
|
-
const db2 = getDB(structures.db.id())
|
|
21
|
-
|
|
22
|
-
const writethrough = new Writethrough(db, DELAY)
|
|
23
|
-
const writethrough2 = new Writethrough(db2, DELAY)
|
|
24
|
-
|
|
25
|
-
const docId = structures.uuid()
|
|
26
|
-
|
|
27
|
-
beforeEach(() => {
|
|
28
|
-
jest.clearAllMocks()
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
describe("put", () => {
|
|
32
|
-
let current: any
|
|
33
|
-
|
|
34
|
-
it("should be able to store, will go to DB", async () => {
|
|
35
|
-
await config.doInTenant(async () => {
|
|
36
|
-
const response = await writethrough.put({
|
|
37
|
-
_id: docId,
|
|
38
|
-
value: 1,
|
|
39
|
-
})
|
|
40
|
-
const output = await db.get<any>(response.id)
|
|
41
|
-
current = output
|
|
42
|
-
expect(output.value).toBe(1)
|
|
43
|
-
})
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
it("second put shouldn't update DB", async () => {
|
|
47
|
-
await config.doInTenant(async () => {
|
|
48
|
-
const response = await writethrough.put({ ...current, value: 2 })
|
|
49
|
-
const output = await db.get<any>(response.id)
|
|
50
|
-
expect(current._rev).toBe(output._rev)
|
|
51
|
-
expect(output.value).toBe(1)
|
|
52
|
-
})
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
it("should put it again after delay period", async () => {
|
|
56
|
-
await config.doInTenant(async () => {
|
|
57
|
-
tk.freeze(Date.now() + DELAY + 1)
|
|
58
|
-
const response = await writethrough.put({ ...current, value: 3 })
|
|
59
|
-
const output = await db.get<any>(response.id)
|
|
60
|
-
expect(response.rev).not.toBe(current._rev)
|
|
61
|
-
expect(output.value).toBe(3)
|
|
62
|
-
|
|
63
|
-
current = output
|
|
64
|
-
})
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
it("should handle parallel DB updates ignoring conflicts", async () => {
|
|
68
|
-
await config.doInTenant(async () => {
|
|
69
|
-
tk.freeze(Date.now() + DELAY + 1)
|
|
70
|
-
const responses = await Promise.all([
|
|
71
|
-
writethrough.put({ ...current, value: 4 }),
|
|
72
|
-
writethrough.put({ ...current, value: 4 }),
|
|
73
|
-
writethrough.put({ ...current, value: 4 }),
|
|
74
|
-
])
|
|
75
|
-
|
|
76
|
-
// with a lock, this will work
|
|
77
|
-
const newRev = responses.map(x => x.rev).find(x => x !== current._rev)
|
|
78
|
-
expect(newRev).toBeDefined()
|
|
79
|
-
expect(responses.map(x => x.rev)).toEqual(
|
|
80
|
-
expect.arrayContaining([current._rev, current._rev, newRev])
|
|
81
|
-
)
|
|
82
|
-
|
|
83
|
-
const output = await db.get<any>(current._id)
|
|
84
|
-
expect(output.value).toBe(4)
|
|
85
|
-
expect(output._rev).toBe(newRev)
|
|
86
|
-
|
|
87
|
-
current = output
|
|
88
|
-
})
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
it("should handle updates with documents falling behind", async () => {
|
|
92
|
-
await config.doInTenant(async () => {
|
|
93
|
-
tk.freeze(Date.now() + DELAY + 1)
|
|
94
|
-
|
|
95
|
-
const id = structures.uuid()
|
|
96
|
-
await writethrough.put({ _id: id, value: 1 })
|
|
97
|
-
const doc = await writethrough.get(id)
|
|
98
|
-
|
|
99
|
-
// Updating document
|
|
100
|
-
tk.freeze(Date.now() + DELAY + 1)
|
|
101
|
-
await writethrough.put({ ...doc, value: 2 })
|
|
102
|
-
|
|
103
|
-
// Update with the old rev value
|
|
104
|
-
tk.freeze(Date.now() + DELAY + 1)
|
|
105
|
-
const res = await writethrough.put({
|
|
106
|
-
...doc,
|
|
107
|
-
value: 3,
|
|
108
|
-
})
|
|
109
|
-
expect(res.ok).toBe(true)
|
|
110
|
-
|
|
111
|
-
const output = await db.get<any>(id)
|
|
112
|
-
expect(output.value).toBe(3)
|
|
113
|
-
expect(output._rev).toBe(res.rev)
|
|
114
|
-
})
|
|
115
|
-
})
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
describe("get", () => {
|
|
119
|
-
it("should be able to retrieve", async () => {
|
|
120
|
-
await config.doInTenant(async () => {
|
|
121
|
-
const response = await writethrough.get<ValueDoc>(docId)
|
|
122
|
-
expect(response.value).toBe(4)
|
|
123
|
-
})
|
|
124
|
-
})
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
describe("same doc, different databases (tenancy)", () => {
|
|
128
|
-
it("should be able to two different databases", async () => {
|
|
129
|
-
await config.doInTenant(async () => {
|
|
130
|
-
const resp1 = await writethrough.put({ _id: "db1", value: "first" })
|
|
131
|
-
const resp2 = await writethrough2.put({ _id: "db1", value: "second" })
|
|
132
|
-
expect(resp1.rev).toBeDefined()
|
|
133
|
-
expect(resp2.rev).toBeDefined()
|
|
134
|
-
expect((await db.get<any>("db1")).value).toBe("first")
|
|
135
|
-
expect((await db2.get<any>("db1")).value).toBe("second")
|
|
136
|
-
})
|
|
137
|
-
})
|
|
138
|
-
})
|
|
139
|
-
})
|
package/src/cache/user.ts
DELETED
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
import * as redis from "../redis/init"
|
|
2
|
-
import * as tenancy from "../tenancy"
|
|
3
|
-
import * as context from "../context"
|
|
4
|
-
import * as platform from "../platform"
|
|
5
|
-
import env from "../environment"
|
|
6
|
-
import * as accounts from "../accounts"
|
|
7
|
-
import { UserDB } from "../users"
|
|
8
|
-
import { sdk } from "@budibase/shared-core"
|
|
9
|
-
import { User, UserMetadata } from "@budibase/types"
|
|
10
|
-
|
|
11
|
-
const EXPIRY_SECONDS = 3600
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* The default populate user function
|
|
15
|
-
*/
|
|
16
|
-
async function populateFromDB(userId: string, tenantId: string) {
|
|
17
|
-
const db = tenancy.getTenantDB(tenantId)
|
|
18
|
-
const user = await db.get<UserMetadata>(userId)
|
|
19
|
-
user.budibaseAccess = true
|
|
20
|
-
if (!env.SELF_HOSTED && !env.DISABLE_ACCOUNT_PORTAL) {
|
|
21
|
-
const account = await accounts.getAccount(user.email)
|
|
22
|
-
if (account) {
|
|
23
|
-
user.account = account
|
|
24
|
-
user.accountPortalAccess = true
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return user
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async function populateUsersFromDB(
|
|
32
|
-
userIds: string[]
|
|
33
|
-
): Promise<{ users: User[]; notFoundIds?: string[] }> {
|
|
34
|
-
const getUsersResponse = await UserDB.bulkGet(userIds)
|
|
35
|
-
|
|
36
|
-
// Handle missed user ids
|
|
37
|
-
const notFoundIds = userIds.filter((uid, i) => !getUsersResponse[i])
|
|
38
|
-
|
|
39
|
-
const users = getUsersResponse.filter(x => x)
|
|
40
|
-
|
|
41
|
-
await Promise.all(
|
|
42
|
-
users.map(async (user: any) => {
|
|
43
|
-
user.budibaseAccess = true
|
|
44
|
-
if (!env.SELF_HOSTED && !env.DISABLE_ACCOUNT_PORTAL) {
|
|
45
|
-
const account = await accounts.getAccount(user.email)
|
|
46
|
-
if (account) {
|
|
47
|
-
user.account = account
|
|
48
|
-
user.accountPortalAccess = true
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
})
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
if (notFoundIds.length) {
|
|
55
|
-
return { users, notFoundIds }
|
|
56
|
-
}
|
|
57
|
-
return { users }
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Get the requested user by id.
|
|
62
|
-
* Use redis cache to first read the user.
|
|
63
|
-
* If not present fallback to loading the user directly and re-caching.
|
|
64
|
-
* @param userId the id of the user to get
|
|
65
|
-
* @param tenantId the tenant of the user to get
|
|
66
|
-
* @param email the email of the user to populate from account if needed
|
|
67
|
-
* @param populateUser function to provide the user for re-caching. default to couch db
|
|
68
|
-
* @returns
|
|
69
|
-
*/
|
|
70
|
-
export async function getUser({
|
|
71
|
-
userId,
|
|
72
|
-
tenantId,
|
|
73
|
-
email,
|
|
74
|
-
populateUser,
|
|
75
|
-
}: {
|
|
76
|
-
userId: string
|
|
77
|
-
email?: string
|
|
78
|
-
tenantId?: string
|
|
79
|
-
populateUser?: (
|
|
80
|
-
userId: string,
|
|
81
|
-
tenantId: string,
|
|
82
|
-
email?: string
|
|
83
|
-
) => Promise<User>
|
|
84
|
-
}) {
|
|
85
|
-
if (!populateUser) {
|
|
86
|
-
populateUser = populateFromDB
|
|
87
|
-
}
|
|
88
|
-
if (!tenantId) {
|
|
89
|
-
try {
|
|
90
|
-
tenantId = context.getTenantId()
|
|
91
|
-
} catch (err) {
|
|
92
|
-
tenantId = await platform.users.lookupTenantId(userId)
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
const client = await redis.getUserClient()
|
|
96
|
-
// try cache
|
|
97
|
-
let user: User = await client.get(userId)
|
|
98
|
-
if (!user) {
|
|
99
|
-
user = await populateUser(userId, tenantId, email)
|
|
100
|
-
await client.store(userId, user, EXPIRY_SECONDS)
|
|
101
|
-
}
|
|
102
|
-
if (user && !user.tenantId && tenantId) {
|
|
103
|
-
// make sure the tenant ID is always correct/set
|
|
104
|
-
user.tenantId = tenantId
|
|
105
|
-
}
|
|
106
|
-
// if has groups, could have builder permissions granted by a group
|
|
107
|
-
if (user.userGroups && !sdk.users.isGlobalBuilder(user)) {
|
|
108
|
-
await context.doInTenant(tenantId, async () => {
|
|
109
|
-
const appIds = await UserDB.getGroupBuilderAppIds(user)
|
|
110
|
-
if (appIds.length) {
|
|
111
|
-
const existing = user.builder?.apps || []
|
|
112
|
-
user.builder = {
|
|
113
|
-
apps: [...new Set(existing.concat(appIds))],
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
})
|
|
117
|
-
}
|
|
118
|
-
return user
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Get the requested users by id.
|
|
123
|
-
* Use redis cache to first read the users.
|
|
124
|
-
* If not present fallback to loading the users directly and re-caching.
|
|
125
|
-
* @param userIds the ids of the user to get
|
|
126
|
-
* @param tenantId the tenant of the users to get
|
|
127
|
-
* @returns
|
|
128
|
-
*/
|
|
129
|
-
export async function getUsers(
|
|
130
|
-
userIds: string[]
|
|
131
|
-
): Promise<{ users: User[]; notFoundIds?: string[] }> {
|
|
132
|
-
const client = await redis.getUserClient()
|
|
133
|
-
// try cache
|
|
134
|
-
let usersFromCache = await client.bulkGet<User>(userIds)
|
|
135
|
-
const missingUsersFromCache = userIds.filter(uid => !usersFromCache[uid])
|
|
136
|
-
const users = Object.values(usersFromCache)
|
|
137
|
-
let notFoundIds
|
|
138
|
-
|
|
139
|
-
if (missingUsersFromCache.length) {
|
|
140
|
-
const usersFromDb = await populateUsersFromDB(missingUsersFromCache)
|
|
141
|
-
|
|
142
|
-
notFoundIds = usersFromDb.notFoundIds
|
|
143
|
-
for (const userToCache of usersFromDb.users) {
|
|
144
|
-
await client.store(userToCache._id!, userToCache, EXPIRY_SECONDS)
|
|
145
|
-
}
|
|
146
|
-
users.push(...usersFromDb.users)
|
|
147
|
-
}
|
|
148
|
-
return { users, notFoundIds: notFoundIds }
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
export async function invalidateUser(userId: string) {
|
|
152
|
-
const client = await redis.getUserClient()
|
|
153
|
-
await client.delete(userId)
|
|
154
|
-
}
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import BaseCache from "./base"
|
|
2
|
-
import { getWritethroughClient } from "../redis/init"
|
|
3
|
-
import { logWarn } from "../logging"
|
|
4
|
-
import { Database, Document, LockName, LockType } from "@budibase/types"
|
|
5
|
-
import * as locks from "../redis/redlockImpl"
|
|
6
|
-
|
|
7
|
-
const DEFAULT_WRITE_RATE_MS = 10000
|
|
8
|
-
let CACHE: BaseCache | null = null
|
|
9
|
-
|
|
10
|
-
interface CacheItem<T extends Document> {
|
|
11
|
-
doc: T
|
|
12
|
-
lastWrite: number
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
async function getCache() {
|
|
16
|
-
if (!CACHE) {
|
|
17
|
-
const client = await getWritethroughClient()
|
|
18
|
-
CACHE = new BaseCache(client)
|
|
19
|
-
}
|
|
20
|
-
return CACHE
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function makeCacheKey(db: Database, key: string) {
|
|
24
|
-
return db.name + key
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function makeCacheItem<T extends Document>(
|
|
28
|
-
doc: T,
|
|
29
|
-
lastWrite: number | null = null
|
|
30
|
-
): CacheItem<T> {
|
|
31
|
-
return { doc, lastWrite: lastWrite || Date.now() }
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
async function put(
|
|
35
|
-
db: Database,
|
|
36
|
-
doc: Document,
|
|
37
|
-
writeRateMs: number = DEFAULT_WRITE_RATE_MS
|
|
38
|
-
) {
|
|
39
|
-
const cache = await getCache()
|
|
40
|
-
const key = doc._id
|
|
41
|
-
let cacheItem: CacheItem<any> | undefined
|
|
42
|
-
if (key) {
|
|
43
|
-
cacheItem = await cache.get(makeCacheKey(db, key))
|
|
44
|
-
}
|
|
45
|
-
const updateDb = !cacheItem || cacheItem.lastWrite < Date.now() - writeRateMs
|
|
46
|
-
let output = doc
|
|
47
|
-
if (updateDb) {
|
|
48
|
-
const lockResponse = await locks.doWithLock(
|
|
49
|
-
{
|
|
50
|
-
type: LockType.TRY_ONCE,
|
|
51
|
-
name: LockName.PERSIST_WRITETHROUGH,
|
|
52
|
-
resource: key,
|
|
53
|
-
ttl: 15000,
|
|
54
|
-
},
|
|
55
|
-
async () => {
|
|
56
|
-
const writeDb = async (toWrite: any) => {
|
|
57
|
-
// doc should contain the _id and _rev
|
|
58
|
-
const response = await db.put(toWrite, { force: true })
|
|
59
|
-
output._id = response.id
|
|
60
|
-
output._rev = response.rev
|
|
61
|
-
}
|
|
62
|
-
try {
|
|
63
|
-
await writeDb(doc)
|
|
64
|
-
} catch (err: any) {
|
|
65
|
-
if (err.status !== 409) {
|
|
66
|
-
throw err
|
|
67
|
-
} else {
|
|
68
|
-
// Swallow 409s but log them
|
|
69
|
-
logWarn(`Ignoring conflict in write-through cache`)
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
if (!lockResponse.executed) {
|
|
76
|
-
logWarn(`Ignoring redlock conflict in write-through cache`)
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
// if we are updating the DB then need to set the lastWrite to now
|
|
80
|
-
cacheItem = makeCacheItem(output, updateDb ? null : cacheItem?.lastWrite)
|
|
81
|
-
if (output._id) {
|
|
82
|
-
await cache.store(makeCacheKey(db, output._id), cacheItem)
|
|
83
|
-
}
|
|
84
|
-
return { ok: true, id: output._id, rev: output._rev }
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
async function get<T extends Document>(db: Database, id: string): Promise<T> {
|
|
88
|
-
const cache = await getCache()
|
|
89
|
-
const cacheKey = makeCacheKey(db, id)
|
|
90
|
-
let cacheItem: CacheItem<T> = await cache.get(cacheKey)
|
|
91
|
-
if (!cacheItem) {
|
|
92
|
-
const doc = await db.get<T>(id)
|
|
93
|
-
cacheItem = makeCacheItem(doc)
|
|
94
|
-
await cache.store(cacheKey, cacheItem)
|
|
95
|
-
}
|
|
96
|
-
return cacheItem.doc
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
async function remove(db: Database, docOrId: any, rev?: any): Promise<void> {
|
|
100
|
-
const cache = await getCache()
|
|
101
|
-
if (!docOrId) {
|
|
102
|
-
throw new Error("No ID/Rev provided.")
|
|
103
|
-
}
|
|
104
|
-
const id = typeof docOrId === "string" ? docOrId : docOrId._id
|
|
105
|
-
rev = typeof docOrId === "string" ? rev : docOrId._rev
|
|
106
|
-
try {
|
|
107
|
-
await cache.delete(makeCacheKey(db, id))
|
|
108
|
-
} finally {
|
|
109
|
-
await db.remove(id, rev)
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export class Writethrough {
|
|
114
|
-
db: Database
|
|
115
|
-
writeRateMs: number
|
|
116
|
-
|
|
117
|
-
constructor(db: Database, writeRateMs: number = DEFAULT_WRITE_RATE_MS) {
|
|
118
|
-
this.db = db
|
|
119
|
-
this.writeRateMs = writeRateMs
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
async put(doc: any, writeRateMs: number = this.writeRateMs) {
|
|
123
|
-
return put(this.db, doc, writeRateMs)
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
async get<T extends Document>(id: string) {
|
|
127
|
-
return get<T>(this.db, id)
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
async remove(docOrId: any, rev?: any) {
|
|
131
|
-
return remove(this.db, docOrId, rev)
|
|
132
|
-
}
|
|
133
|
-
}
|
package/src/configs/configs.ts
DELETED
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AIConfig,
|
|
3
|
-
Config,
|
|
4
|
-
ConfigType,
|
|
5
|
-
GoogleConfig,
|
|
6
|
-
GoogleInnerConfig,
|
|
7
|
-
OIDCConfig,
|
|
8
|
-
OIDCInnerConfig,
|
|
9
|
-
OIDCLogosConfig,
|
|
10
|
-
SCIMConfig,
|
|
11
|
-
SCIMInnerConfig,
|
|
12
|
-
SettingsConfig,
|
|
13
|
-
SettingsInnerConfig,
|
|
14
|
-
SMTPConfig,
|
|
15
|
-
SMTPInnerConfig,
|
|
16
|
-
} from "@budibase/types"
|
|
17
|
-
import { DocumentType, SEPARATOR } from "../constants"
|
|
18
|
-
import { CacheKey, TTL, withCache } from "../cache"
|
|
19
|
-
import * as context from "../context"
|
|
20
|
-
import env from "../environment"
|
|
21
|
-
|
|
22
|
-
// UTILS
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Generates a new configuration ID.
|
|
26
|
-
* @returns The new configuration ID which the config doc can be stored under.
|
|
27
|
-
*/
|
|
28
|
-
export function generateConfigID(type: ConfigType) {
|
|
29
|
-
return `${DocumentType.CONFIG}${SEPARATOR}${type}`
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export async function getConfig<T extends Config>(
|
|
33
|
-
type: ConfigType
|
|
34
|
-
): Promise<T | undefined> {
|
|
35
|
-
const db = context.getGlobalDB()
|
|
36
|
-
try {
|
|
37
|
-
// await to catch error
|
|
38
|
-
return (await db.get(generateConfigID(type))) as T
|
|
39
|
-
} catch (e: any) {
|
|
40
|
-
if (e.status === 404) {
|
|
41
|
-
return
|
|
42
|
-
}
|
|
43
|
-
throw e
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export async function save(
|
|
48
|
-
config: Config
|
|
49
|
-
): Promise<{ id: string; rev: string }> {
|
|
50
|
-
const db = context.getGlobalDB()
|
|
51
|
-
return db.put(config)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// SETTINGS
|
|
55
|
-
|
|
56
|
-
export async function getSettingsConfigDoc(): Promise<SettingsConfig> {
|
|
57
|
-
let config = await getConfig<SettingsConfig>(ConfigType.SETTINGS)
|
|
58
|
-
|
|
59
|
-
if (!config) {
|
|
60
|
-
config = {
|
|
61
|
-
_id: generateConfigID(ConfigType.SETTINGS),
|
|
62
|
-
type: ConfigType.SETTINGS,
|
|
63
|
-
config: {},
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// overridden fields
|
|
68
|
-
config.config.platformUrl = await getPlatformUrl({
|
|
69
|
-
tenantAware: true,
|
|
70
|
-
config: config.config,
|
|
71
|
-
})
|
|
72
|
-
config.config.analyticsEnabled = await analyticsEnabled({
|
|
73
|
-
config: config.config,
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
return config
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export async function getSettingsConfig(): Promise<SettingsInnerConfig> {
|
|
80
|
-
return (await getSettingsConfigDoc()).config
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export async function getPlatformUrl(
|
|
84
|
-
opts: { tenantAware: boolean; config?: SettingsInnerConfig } = {
|
|
85
|
-
tenantAware: true,
|
|
86
|
-
}
|
|
87
|
-
) {
|
|
88
|
-
let platformUrl = env.PLATFORM_URL || "http://localhost:10000"
|
|
89
|
-
|
|
90
|
-
if (!env.SELF_HOSTED && env.MULTI_TENANCY && opts.tenantAware) {
|
|
91
|
-
// cloud and multi tenant - add the tenant to the default platform url
|
|
92
|
-
const tenantId = context.getTenantId()
|
|
93
|
-
if (!platformUrl.includes("localhost:")) {
|
|
94
|
-
platformUrl = platformUrl.replace("://", `://${tenantId}.`)
|
|
95
|
-
}
|
|
96
|
-
} else if (env.SELF_HOSTED) {
|
|
97
|
-
const config = opts?.config
|
|
98
|
-
? opts.config
|
|
99
|
-
: // direct to db to prevent infinite loop
|
|
100
|
-
(await getConfig<SettingsConfig>(ConfigType.SETTINGS))?.config
|
|
101
|
-
if (config?.platformUrl) {
|
|
102
|
-
platformUrl = config.platformUrl
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return platformUrl
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export const analyticsEnabled = async (opts?: {
|
|
110
|
-
config?: SettingsInnerConfig
|
|
111
|
-
}) => {
|
|
112
|
-
// cloud - always use the environment variable
|
|
113
|
-
if (!env.SELF_HOSTED) {
|
|
114
|
-
return !!env.ENABLE_ANALYTICS
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// self host - prefer the settings doc
|
|
118
|
-
// use cache as events have high throughput
|
|
119
|
-
const enabledInDB = await withCache(
|
|
120
|
-
CacheKey.ANALYTICS_ENABLED,
|
|
121
|
-
TTL.ONE_DAY,
|
|
122
|
-
async () => {
|
|
123
|
-
const config = opts?.config
|
|
124
|
-
? opts.config
|
|
125
|
-
: // direct to db to prevent infinite loop
|
|
126
|
-
(await getConfig<SettingsConfig>(ConfigType.SETTINGS))?.config
|
|
127
|
-
|
|
128
|
-
// need to do explicit checks in case the field is not set
|
|
129
|
-
if (config?.analyticsEnabled === false) {
|
|
130
|
-
return false
|
|
131
|
-
} else if (config?.analyticsEnabled === true) {
|
|
132
|
-
return true
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
)
|
|
136
|
-
|
|
137
|
-
if (enabledInDB !== undefined) {
|
|
138
|
-
return enabledInDB
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// fallback to the environment variable
|
|
142
|
-
// explicitly check for 0 or false here, undefined or otherwise is treated as true
|
|
143
|
-
const envEnabled: any = env.ENABLE_ANALYTICS
|
|
144
|
-
if (envEnabled === 0 || envEnabled === false) {
|
|
145
|
-
return false
|
|
146
|
-
} else {
|
|
147
|
-
return true
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// GOOGLE
|
|
152
|
-
|
|
153
|
-
async function getGoogleConfigDoc(): Promise<GoogleConfig | undefined> {
|
|
154
|
-
return await getConfig<GoogleConfig>(ConfigType.GOOGLE)
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
export async function getGoogleConfig(): Promise<
|
|
158
|
-
GoogleInnerConfig | undefined
|
|
159
|
-
> {
|
|
160
|
-
const config = await getGoogleConfigDoc()
|
|
161
|
-
return config?.config
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
export async function getGoogleDatasourceConfig(): Promise<
|
|
165
|
-
GoogleInnerConfig | undefined
|
|
166
|
-
> {
|
|
167
|
-
if (!env.SELF_HOSTED) {
|
|
168
|
-
// always use the env vars in cloud
|
|
169
|
-
return getDefaultGoogleConfig()
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// prefer the config in self-host
|
|
173
|
-
let config = await getGoogleConfig()
|
|
174
|
-
|
|
175
|
-
// fallback to env vars
|
|
176
|
-
if (!config || !config.activated) {
|
|
177
|
-
config = getDefaultGoogleConfig()
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return config
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
export function getDefaultGoogleConfig(): GoogleInnerConfig | undefined {
|
|
184
|
-
if (env.GOOGLE_CLIENT_ID && env.GOOGLE_CLIENT_SECRET) {
|
|
185
|
-
return {
|
|
186
|
-
clientID: env.GOOGLE_CLIENT_ID!,
|
|
187
|
-
clientSecret: env.GOOGLE_CLIENT_SECRET!,
|
|
188
|
-
activated: true,
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// OIDC
|
|
194
|
-
|
|
195
|
-
export async function getOIDCLogosDoc(): Promise<OIDCLogosConfig | undefined> {
|
|
196
|
-
return getConfig<OIDCLogosConfig>(ConfigType.OIDC_LOGOS)
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
async function getOIDCConfigDoc(): Promise<OIDCConfig | undefined> {
|
|
200
|
-
return getConfig<OIDCConfig>(ConfigType.OIDC)
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
export async function getOIDCConfig(): Promise<OIDCInnerConfig | undefined> {
|
|
204
|
-
const config = (await getOIDCConfigDoc())?.config
|
|
205
|
-
// default to the 0th config
|
|
206
|
-
return config?.configs && config.configs[0]
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* @param configId The config id of the inner config to retrieve
|
|
211
|
-
*/
|
|
212
|
-
export async function getOIDCConfigById(
|
|
213
|
-
configId: string
|
|
214
|
-
): Promise<OIDCInnerConfig | undefined> {
|
|
215
|
-
const config = (await getConfig<OIDCConfig>(ConfigType.OIDC))?.config
|
|
216
|
-
return config && config.configs.filter((c: any) => c.uuid === configId)[0]
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// SMTP
|
|
220
|
-
|
|
221
|
-
export async function getSMTPConfigDoc(): Promise<SMTPConfig | undefined> {
|
|
222
|
-
return getConfig<SMTPConfig>(ConfigType.SMTP)
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
export async function getSMTPConfig(
|
|
226
|
-
isAutomation?: boolean
|
|
227
|
-
): Promise<SMTPInnerConfig | undefined> {
|
|
228
|
-
const config = await getSMTPConfigDoc()
|
|
229
|
-
if (config) {
|
|
230
|
-
return config.config
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// always allow fallback in self host
|
|
234
|
-
// in cloud don't allow for automations
|
|
235
|
-
const allowFallback = env.SELF_HOSTED || !isAutomation
|
|
236
|
-
|
|
237
|
-
// Use an SMTP fallback configuration from env variables
|
|
238
|
-
if (env.SMTP_FALLBACK_ENABLED && allowFallback) {
|
|
239
|
-
return {
|
|
240
|
-
port: env.SMTP_PORT,
|
|
241
|
-
host: env.SMTP_HOST!,
|
|
242
|
-
secure: false,
|
|
243
|
-
from: env.SMTP_FROM_ADDRESS!,
|
|
244
|
-
auth: {
|
|
245
|
-
user: env.SMTP_USER!,
|
|
246
|
-
pass: env.SMTP_PASSWORD!,
|
|
247
|
-
},
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
// SCIM
|
|
253
|
-
|
|
254
|
-
export async function getSCIMConfig(): Promise<SCIMInnerConfig | undefined> {
|
|
255
|
-
const config = await getConfig<SCIMConfig>(ConfigType.SCIM)
|
|
256
|
-
return config?.config
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// AI
|
|
260
|
-
|
|
261
|
-
export async function getAIConfig(): Promise<AIConfig | undefined> {
|
|
262
|
-
return getConfig<AIConfig>(ConfigType.AI)
|
|
263
|
-
}
|
package/src/configs/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./configs"
|