Merge pull request #16164 from Budibase/BUDI-9294/project-apps-to-workspace-apps

Rename project app to workspace app
This commit is contained in:
Adria Navarro 2025-05-19 09:53:18 +02:00 committed by GitHub
commit 0b6e78c006
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 250 additions and 246 deletions

View File

@ -214,9 +214,9 @@ export const getOAuth2ConfigParams = (
/** /**
* Gets parameters for retrieving project apps, this is a utility function for the getDocParams function. * Gets parameters for retrieving project apps, this is a utility function for the getDocParams function.
*/ */
export const getProjectAppParams = ( export const getWorkspaceAppParams = (
projectAppId?: string | null, workspaceAppId?: string | null,
otherProps: Partial<DatabaseQueryOpts> = {} otherProps: Partial<DatabaseQueryOpts> = {}
) => { ) => {
return getDocParams(DocumentType.PROJECT_APP, projectAppId, otherProps) return getDocParams(DocumentType.WORKSPACE_APP, workspaceAppId, otherProps)
} }

View File

@ -90,8 +90,8 @@ export class ScreenStore extends BudiStore<ScreenState> {
*/ */
syncAppScreens(pkg: FetchAppPackageResponse) { syncAppScreens(pkg: FetchAppPackageResponse) {
let screens = [...pkg.screens] let screens = [...pkg.screens]
if (featureFlag.isEnabled(FeatureFlag.PROJECT_APPS)) { if (featureFlag.isEnabled(FeatureFlag.WORKSPACE_APPS)) {
screens = [...pkg.projectApps.flatMap(p => p.screens)] screens = [...pkg.workspaceApps.flatMap(p => p.screens)]
} }
this.update(state => ({ this.update(state => ({
...state, ...state,

View File

@ -184,19 +184,19 @@ async function addSampleDataDocs() {
async function addSampleDataScreen() { async function addSampleDataScreen() {
const db = context.getAppDB() const db = context.getAppDB()
let projectAppId: string | undefined let workspaceAppId: string | undefined
if (await features.isEnabled(FeatureFlag.PROJECT_APPS)) { if (await features.isEnabled(FeatureFlag.WORKSPACE_APPS)) {
const appMetadata = await sdk.applications.metadata.get() const appMetadata = await sdk.applications.metadata.get()
const projectApp = await sdk.projectApps.create({ const workspaceApp = await sdk.workspaceApps.create({
name: appMetadata.name, name: appMetadata.name,
urlPrefix: "/", urlPrefix: "/",
icon: "Monitoring", icon: "Monitoring",
}) })
projectAppId = projectApp._id! workspaceAppId = workspaceApp._id!
} }
let screen = await createSampleDataTableScreen(projectAppId) let screen = await createSampleDataTableScreen(workspaceAppId)
screen._id = generateScreenID() screen._id = generateScreenID()
await db.put(screen) await db.put(screen)
} }
@ -282,10 +282,10 @@ export async function fetchAppPackage(
screens = await accessController.checkScreensAccess(screens, userRoleId) screens = await accessController.checkScreensAccess(screens, userRoleId)
} }
let projectApps: FetchAppPackageResponse["projectApps"] = [] let workspaceApps: FetchAppPackageResponse["workspaceApps"] = []
if (await features.flags.isEnabled(FeatureFlag.PROJECT_APPS)) { if (await features.flags.isEnabled(FeatureFlag.WORKSPACE_APPS)) {
projectApps = await extractScreensByProjectApp(screens) workspaceApps = await extractScreensByWorkspaceApp(screens)
screens = [] screens = []
} }
@ -297,7 +297,7 @@ export async function fetchAppPackage(
ctx.body = { ctx.body = {
application: { ...application, upgradableVersion: envCore.VERSION }, application: { ...application, upgradableVersion: envCore.VERSION },
licenseType: license?.plan.type || PlanType.FREE, licenseType: license?.plan.type || PlanType.FREE,
projectApps, workspaceApps,
screens, screens,
layouts, layouts,
clientLibPath, clientLibPath,
@ -305,20 +305,20 @@ export async function fetchAppPackage(
} }
} }
async function extractScreensByProjectApp( async function extractScreensByWorkspaceApp(
screens: Screen[] screens: Screen[]
): Promise<FetchAppPackageResponse["projectApps"]> { ): Promise<FetchAppPackageResponse["workspaceApps"]> {
const result: FetchAppPackageResponse["projectApps"] = [] const result: FetchAppPackageResponse["workspaceApps"] = []
const projectApps = await sdk.projectApps.fetch() const workspaceApps = await sdk.workspaceApps.fetch()
const screensByProjectApp = groupBy(s => s.projectAppId, screens) const screensByWorkspaceApp = groupBy(s => s.workspaceAppId, screens)
for (const projectAppId of Object.keys(screensByProjectApp)) { for (const workspaceAppId of Object.keys(screensByWorkspaceApp)) {
const projectApp = projectApps.find(p => p._id === projectAppId) const workspaceApp = workspaceApps.find(p => p._id === workspaceAppId)
result.push({ result.push({
...projectApp!, ...workspaceApp!,
screens: screensByProjectApp[projectAppId], screens: screensByWorkspaceApp[workspaceAppId],
}) })
} }

View File

@ -1,70 +0,0 @@
import {
Ctx,
InsertProjectAppRequest,
InsertProjectAppResponse,
ProjectApp,
ProjectAppResponse,
UpdateProjectAppRequest,
UpdateProjectAppResponse,
} from "@budibase/types"
import sdk from "../../sdk"
function toProjectAppResponse(projectApp: ProjectApp): ProjectAppResponse {
return {
_id: projectApp._id!,
_rev: projectApp._rev!,
name: projectApp.name,
urlPrefix: projectApp.urlPrefix,
icon: projectApp.icon,
iconColor: projectApp.iconColor,
}
}
export async function create(
ctx: Ctx<InsertProjectAppRequest, InsertProjectAppResponse>
) {
const { body } = ctx.request
const newProjectApp = {
name: body.name,
urlPrefix: body.urlPrefix,
icon: body.icon,
iconColor: body.iconColor,
}
const projectApp = await sdk.projectApps.create(newProjectApp)
ctx.status = 201
ctx.body = {
projectApp: toProjectAppResponse(projectApp),
}
}
export async function edit(
ctx: Ctx<UpdateProjectAppRequest, UpdateProjectAppResponse>
) {
const { body } = ctx.request
if (ctx.params.id !== body._id) {
ctx.throw("Path and body ids do not match", 400)
}
const toUpdate = {
_id: body._id,
_rev: body._rev,
name: body.name,
urlPrefix: body.urlPrefix,
icon: body.icon,
iconColor: body.iconColor,
}
const projectApp = await sdk.projectApps.update(toUpdate)
ctx.body = {
projectApp: toProjectAppResponse(projectApp),
}
}
export async function remove(ctx: Ctx<void, void>) {
const { id, rev } = ctx.params
await sdk.projectApps.remove(id, rev)
ctx.status = 204
}

View File

@ -0,0 +1,72 @@
import {
Ctx,
InsertWorkspaceAppRequest,
InsertWorkspaceAppResponse,
WorkspaceApp,
WorkspaceAppResponse,
UpdateWorkspaceAppRequest,
UpdateWorkspaceAppResponse,
} from "@budibase/types"
import sdk from "../../sdk"
function toWorkspaceAppResponse(
workspaceApp: WorkspaceApp
): WorkspaceAppResponse {
return {
_id: workspaceApp._id!,
_rev: workspaceApp._rev!,
name: workspaceApp.name,
urlPrefix: workspaceApp.urlPrefix,
icon: workspaceApp.icon,
iconColor: workspaceApp.iconColor,
}
}
export async function create(
ctx: Ctx<InsertWorkspaceAppRequest, InsertWorkspaceAppResponse>
) {
const { body } = ctx.request
const newWorkspaceApp = {
name: body.name,
urlPrefix: body.urlPrefix,
icon: body.icon,
iconColor: body.iconColor,
}
const workspaceApp = await sdk.workspaceApps.create(newWorkspaceApp)
ctx.status = 201
ctx.body = {
workspaceApp: toWorkspaceAppResponse(workspaceApp),
}
}
export async function edit(
ctx: Ctx<UpdateWorkspaceAppRequest, UpdateWorkspaceAppResponse>
) {
const { body } = ctx.request
if (ctx.params.id !== body._id) {
ctx.throw("Path and body ids do not match", 400)
}
const toUpdate = {
_id: body._id,
_rev: body._rev,
name: body.name,
urlPrefix: body.urlPrefix,
icon: body.icon,
iconColor: body.iconColor,
}
const workspaceApp = await sdk.workspaceApps.update(toUpdate)
ctx.body = {
workspaceApp: toWorkspaceAppResponse(workspaceApp),
}
}
export async function remove(ctx: Ctx<void, void>) {
const { id, rev } = ctx.params
await sdk.workspaceApps.remove(id, rev)
ctx.status = 204
}

View File

@ -32,7 +32,7 @@ import rowActionRoutes from "./rowAction"
import oauth2Routes from "./oauth2" import oauth2Routes from "./oauth2"
import featuresRoutes from "./features" import featuresRoutes from "./features"
import aiRoutes from "./ai" import aiRoutes from "./ai"
import projectApps from "./projectApp" import workspaceApps from "./workspaceApp"
export { default as staticRoutes } from "./static" export { default as staticRoutes } from "./static"
export { default as publicRoutes } from "./public" export { default as publicRoutes } from "./public"
@ -73,7 +73,7 @@ export const mainRoutes: Router[] = [
rowActionRoutes, rowActionRoutes,
oauth2Routes, oauth2Routes,
featuresRoutes, featuresRoutes,
projectApps, workspaceApps,
// these need to be handled last as they still use /api/:tableId // these need to be handled last as they still use /api/:tableId
// this could be breaking as koa may recognise other routes as this // this could be breaking as koa may recognise other routes as this
tableRoutes, tableRoutes,

View File

@ -3,7 +3,7 @@ import { PermissionType } from "@budibase/types"
import { middleware } from "@budibase/backend-core" import { middleware } from "@budibase/backend-core"
import authorized from "../../middleware/authorized" import authorized from "../../middleware/authorized"
import * as controller from "../controllers/projectApp" import * as controller from "../controllers/workspaceApp"
import Joi from "joi" import Joi from "joi"
const baseSchema = { const baseSchema = {
@ -23,7 +23,7 @@ const updateSchema = Joi.object({
...baseSchema, ...baseSchema,
}) })
function projectAppValidator( function workspaceAppValidator(
schema: typeof insertSchema | typeof updateSchema schema: typeof insertSchema | typeof updateSchema
) { ) {
return middleware.joiValidator.body(schema, { allowUnknown: false }) return middleware.joiValidator.body(schema, { allowUnknown: false })
@ -32,19 +32,19 @@ function projectAppValidator(
const router: Router = new Router() const router: Router = new Router()
router.post( router.post(
"/api/projectApp", "/api/workspaceApp",
authorized(PermissionType.BUILDER), authorized(PermissionType.BUILDER),
projectAppValidator(insertSchema), workspaceAppValidator(insertSchema),
controller.create controller.create
) )
router.put( router.put(
"/api/projectApp/:id", "/api/workspaceApp/:id",
authorized(PermissionType.BUILDER), authorized(PermissionType.BUILDER),
projectAppValidator(updateSchema), workspaceAppValidator(updateSchema),
controller.edit controller.edit
) )
router.delete( router.delete(
"/api/projectApp/:id/:rev", "/api/workspaceApp/:id/:rev",
authorized(PermissionType.BUILDER), authorized(PermissionType.BUILDER),
controller.remove controller.remove
) )

View File

@ -4,7 +4,7 @@ import { features } from "@budibase/backend-core"
import { AppMigration } from "." import { AppMigration } from "."
import m20240604153647_initial_sqs from "./migrations/20240604153647_initial_sqs" import m20240604153647_initial_sqs from "./migrations/20240604153647_initial_sqs"
import m20250514133719_project_apps from "./migrations/20250514133719_project_apps" import m20250514133719_workspace_apps from "./migrations/20250514133719_workspace_apps"
import { FeatureFlag } from "@budibase/types" import { FeatureFlag } from "@budibase/types"
export const MIGRATIONS: AppMigration[] = [ export const MIGRATIONS: AppMigration[] = [
@ -14,12 +14,12 @@ export const MIGRATIONS: AppMigration[] = [
func: m20240604153647_initial_sqs, func: m20240604153647_initial_sqs,
}, },
{ {
id: "20250514133719_project_apps", id: "m20250514133719_workspace_apps",
func: m20250514133719_project_apps, func: m20250514133719_workspace_apps,
// Disabling it, enabling it via env variables to enable development. // Disabling it, enabling it via env variables to enable development.
// Using the existing flag system would require async checks and we could run to race conditions, so this keeps is simple // Using the existing flag system would require async checks and we could run to race conditions, so this keeps is simple
disabled: !features disabled: !features
.getEnvFlags() .getEnvFlags()
.some(f => f.key === FeatureFlag.PROJECT_APPS && f.value === true), .some(f => f.key === FeatureFlag.WORKSPACE_APPS && f.value === true),
}, },
] ]

View File

@ -6,24 +6,26 @@ const migration = async () => {
const screens = await sdk.screens.fetch() const screens = await sdk.screens.fetch()
const application = await sdk.applications.metadata.get() const application = await sdk.applications.metadata.get()
const allProjectApps = await sdk.projectApps.fetch() const allWorkspaceApps = await sdk.workspaceApps.fetch()
let projectAppId = allProjectApps.find(p => p.name === application.name)?._id let workspaceAppId = allWorkspaceApps.find(
if (!projectAppId) { p => p.name === application.name
const projectApp = await sdk.projectApps.create({ )?._id
if (!workspaceAppId) {
const workspaceApp = await sdk.workspaceApps.create({
name: application.name, name: application.name,
urlPrefix: "/", urlPrefix: "/",
icon: "Monitoring", icon: "Monitoring",
}) })
projectAppId = projectApp._id workspaceAppId = workspaceApp._id
} }
const db = context.getAppDB() const db = context.getAppDB()
await db.bulkDocs( await db.bulkDocs(
screens screens
.filter(s => !s.projectAppId) .filter(s => !s.workspaceAppId)
.map<Screen>(s => ({ .map<Screen>(s => ({
...s, ...s,
projectAppId, workspaceAppId,
})) }))
) )
} }

View File

@ -3,14 +3,14 @@ import { Screen } from "@budibase/types"
export const SAMPLE_DATA_SCREEN_NAME = "sample-data-inventory-screen" export const SAMPLE_DATA_SCREEN_NAME = "sample-data-inventory-screen"
export function createSampleDataTableScreen( export function createSampleDataTableScreen(
projectAppId: string | undefined workspaceAppId: string | undefined
): Screen { ): Screen {
return { return {
showNavigation: true, showNavigation: true,
width: "Large", width: "Large",
routing: { route: "/inventory", roleId: "BASIC", homeScreen: false }, routing: { route: "/inventory", roleId: "BASIC", homeScreen: false },
name: SAMPLE_DATA_SCREEN_NAME, name: SAMPLE_DATA_SCREEN_NAME,
projectAppId, workspaceAppId,
props: { props: {
_id: "c38f2b9f250fb4c33965ce47e12c02a80", _id: "c38f2b9f250fb4c33965ce47e12c02a80",
_component: "@budibase/standard-components/container", _component: "@budibase/standard-components/container",

View File

@ -1,83 +0,0 @@
import { context, docIds, HTTPError, utils } from "@budibase/backend-core"
import {
DocumentType,
ProjectApp,
SEPARATOR,
WithoutDocMetadata,
} from "@budibase/types"
async function guardName(name: string, id?: string) {
const existingProjectApps = await fetch()
if (existingProjectApps.find(p => p.name === name && p._id !== id)) {
throw new HTTPError(`App with name '${name}' is already taken.`, 400)
}
}
export async function fetch(): Promise<ProjectApp[]> {
const db = context.getAppDB()
const docs = await db.allDocs<ProjectApp>(
docIds.getProjectAppParams(null, { include_docs: true })
)
const result = docs.rows.map(r => ({
...r.doc!,
_id: r.doc!._id!,
_rev: r.doc!._rev!,
}))
return result
}
export async function get(id: string): Promise<ProjectApp | undefined> {
const db = context.getAppDB()
const projectApp = await db.tryGet<ProjectApp>(id)
return projectApp
}
export async function create(projectApp: WithoutDocMetadata<ProjectApp>) {
const db = context.getAppDB()
await guardName(projectApp.name)
const response = await db.put({
_id: `${DocumentType.PROJECT_APP}${SEPARATOR}${utils.newid()}`,
...projectApp,
})
return {
_id: response.id!,
_rev: response.rev!,
...projectApp,
}
}
export async function update(
projectApp: Omit<ProjectApp, "createdAt" | "updatedAt">
) {
const db = context.getAppDB()
await guardName(projectApp.name, projectApp._id)
const response = await db.put(projectApp)
return {
_id: response.id!,
_rev: response.rev!,
...projectApp,
}
}
export async function remove(
projectAppId: string,
_rev: string
): Promise<void> {
const db = context.getAppDB()
try {
await db.remove(projectAppId, _rev)
} catch (e: any) {
if (e.status === 404) {
throw new HTTPError(
`Project app with id '${projectAppId}' not found.`,
404
)
}
throw e
}
}

View File

@ -0,0 +1,83 @@
import { context, docIds, HTTPError, utils } from "@budibase/backend-core"
import {
DocumentType,
WorkspaceApp,
SEPARATOR,
WithoutDocMetadata,
} from "@budibase/types"
async function guardName(name: string, id?: string) {
const existingWorkspaceApps = await fetch()
if (existingWorkspaceApps.find(p => p.name === name && p._id !== id)) {
throw new HTTPError(`App with name '${name}' is already taken.`, 400)
}
}
export async function fetch(): Promise<WorkspaceApp[]> {
const db = context.getAppDB()
const docs = await db.allDocs<WorkspaceApp>(
docIds.getWorkspaceAppParams(null, { include_docs: true })
)
const result = docs.rows.map(r => ({
...r.doc!,
_id: r.doc!._id!,
_rev: r.doc!._rev!,
}))
return result
}
export async function get(id: string): Promise<WorkspaceApp | undefined> {
const db = context.getAppDB()
const workspaceApp = await db.tryGet<WorkspaceApp>(id)
return workspaceApp
}
export async function create(workspaceApp: WithoutDocMetadata<WorkspaceApp>) {
const db = context.getAppDB()
await guardName(workspaceApp.name)
const response = await db.put({
_id: `${DocumentType.WORKSPACE_APP}${SEPARATOR}${utils.newid()}`,
...workspaceApp,
})
return {
_id: response.id!,
_rev: response.rev!,
...workspaceApp,
}
}
export async function update(
workspaceApp: Omit<WorkspaceApp, "createdAt" | "updatedAt">
) {
const db = context.getAppDB()
await guardName(workspaceApp.name, workspaceApp._id)
const response = await db.put(workspaceApp)
return {
_id: response.id!,
_rev: response.rev!,
...workspaceApp,
}
}
export async function remove(
workspaceAppId: string,
_rev: string
): Promise<void> {
const db = context.getAppDB()
try {
await db.remove(workspaceAppId, _rev)
} catch (e: any) {
if (e.status === 404) {
throw new HTTPError(
`Project app with id '${workspaceAppId}' not found.`,
404
)
}
throw e
}
}

View File

@ -15,7 +15,7 @@ import * as screens from "./app/screens"
import * as common from "./app/common" import * as common from "./app/common"
import * as oauth2 from "./app/oauth2" import * as oauth2 from "./app/oauth2"
import * as ai from "./app/ai" import * as ai from "./app/ai"
import * as projectApps from "./app/projectApps" import * as workspaceApps from "./app/workspaceApps"
const sdk = { const sdk = {
backups, backups,
@ -35,7 +35,7 @@ const sdk = {
common, common,
oauth2, oauth2,
ai, ai,
projectApps, workspaceApps,
} }
// default export for TS // default export for TS

View File

@ -587,7 +587,7 @@ function createHomeScreen(
roleId: config.roleId, roleId: config.roleId,
}, },
name: "home-screen", name: "home-screen",
projectAppId: "projectAppId", workspaceAppId: "workspaceAppId",
} }
} }

View File

@ -65,7 +65,7 @@ export function createTableScreen(
homeScreen: false, homeScreen: false,
}, },
name: "screen-id", name: "screen-id",
projectAppId: "projectAppId", workspaceAppId: "workspaceAppId",
} }
} }
@ -117,7 +117,7 @@ export function createViewScreen(view: ViewV2): Screen {
homeScreen: false, homeScreen: false,
}, },
name: "view-id", name: "view-id",
projectAppId: "projectAppId", workspaceAppId: "workspaceAppId",
} }
} }
@ -173,6 +173,6 @@ export function createQueryScreen(datasourceId: string, query: Query): Screen {
homeScreen: false, homeScreen: false,
}, },
name: "screen-id", name: "screen-id",
projectAppId: "projectAppId", workspaceAppId: "workspaceAppId",
} }
} }

View File

@ -1,5 +1,5 @@
import type { PlanType } from "../../../sdk" import type { PlanType } from "../../../sdk"
import type { Layout, App, Screen, ProjectApp } from "../../../documents" import type { Layout, App, Screen, WorkspaceApp } from "../../../documents"
import { ReadStream } from "fs" import { ReadStream } from "fs"
export interface SyncAppResponse { export interface SyncAppResponse {
@ -35,7 +35,7 @@ export interface FetchAppDefinitionResponse {
libraries: string[] libraries: string[]
} }
interface ProjectAppResponse extends ProjectApp { interface WorkspaceAppResponse extends WorkspaceApp {
screens: Screen[] screens: Screen[]
} }
@ -43,7 +43,7 @@ export interface FetchAppPackageResponse {
application: App application: App
licenseType: PlanType licenseType: PlanType
screens: Screen[] screens: Screen[]
projectApps: ProjectAppResponse[] workspaceApps: WorkspaceAppResponse[]
layouts: Layout[] layouts: Layout[]
clientLibPath: string clientLibPath: string
hasLock: boolean hasLock: boolean

View File

@ -11,7 +11,7 @@ export * from "./layout"
export * from "./metadata" export * from "./metadata"
export * from "./oauth2" export * from "./oauth2"
export * from "./permission" export * from "./permission"
export * from "./projectApp" export * from "./workspaceApp"
export * from "./query" export * from "./query"
export * from "./role" export * from "./role"
export * from "./rowAction" export * from "./rowAction"

View File

@ -1,32 +0,0 @@
export interface ProjectAppResponse {
_id: string
_rev: string
name: string
urlPrefix: string
icon: string
iconColor?: string
}
export interface InsertProjectAppRequest {
name: string
urlPrefix: string
icon: string
iconColor: string
}
export interface InsertProjectAppResponse {
projectApp: ProjectAppResponse
}
export interface UpdateProjectAppRequest {
_id: string
_rev: string
name: string
urlPrefix: string
icon: string
iconColor: string
}
export interface UpdateProjectAppResponse {
projectApp: ProjectAppResponse
}

View File

@ -0,0 +1,32 @@
export interface WorkspaceAppResponse {
_id: string
_rev: string
name: string
urlPrefix: string
icon: string
iconColor?: string
}
export interface InsertWorkspaceAppRequest {
name: string
urlPrefix: string
icon: string
iconColor: string
}
export interface InsertWorkspaceAppResponse {
workspaceApp: WorkspaceAppResponse
}
export interface UpdateWorkspaceAppRequest {
_id: string
_rev: string
name: string
urlPrefix: string
icon: string
iconColor: string
}
export interface UpdateWorkspaceAppResponse {
workspaceApp: WorkspaceAppResponse
}

View File

@ -9,7 +9,7 @@ export * from "./layout"
export * from "./links" export * from "./links"
export * from "./metadata" export * from "./metadata"
export * from "./oauth2" export * from "./oauth2"
export * from "./projectApp" export * from "./workspaceApp"
export * from "./query" export * from "./query"
export * from "./role" export * from "./role"
export * from "./row" export * from "./row"

View File

@ -29,7 +29,7 @@ export interface Screen extends Document {
pluginAdded?: boolean pluginAdded?: boolean
onLoad?: EventHandler[] onLoad?: EventHandler[]
variant?: ScreenVariant variant?: ScreenVariant
projectAppId?: string workspaceAppId?: string
} }
export interface ScreenRoutesViewOutput extends Document { export interface ScreenRoutesViewOutput extends Document {

View File

@ -1,6 +1,6 @@
import { Document } from "../document" import { Document } from "../document"
export interface ProjectApp extends Document { export interface WorkspaceApp extends Document {
name: string name: string
urlPrefix: string urlPrefix: string
icon: string icon: string

View File

@ -43,7 +43,7 @@ export enum DocumentType {
OAUTH2_CONFIG = "oauth2", OAUTH2_CONFIG = "oauth2",
OAUTH2_CONFIG_LOG = "oauth2log", OAUTH2_CONFIG_LOG = "oauth2log",
AGENT_CHAT = "agentchat", AGENT_CHAT = "agentchat",
PROJECT_APP = "project_app", WORKSPACE_APP = "workspace_app",
} }
// Because DocumentTypes can overlap, we need to make sure that we search // Because DocumentTypes can overlap, we need to make sure that we search

View File

@ -4,7 +4,7 @@ export enum FeatureFlag {
AI_JS_GENERATION = "AI_JS_GENERATION", AI_JS_GENERATION = "AI_JS_GENERATION",
AI_TABLE_GENERATION = "AI_TABLE_GENERATION", AI_TABLE_GENERATION = "AI_TABLE_GENERATION",
AI_AGENTS = "AI_AGENTS", AI_AGENTS = "AI_AGENTS",
PROJECT_APPS = "PROJECT_APPS", WORKSPACE_APPS = "WORKSPACE_APPS",
// Account-portal // Account-portal
DIRECT_LOGIN_TO_ACCOUNT_PORTAL = "DIRECT_LOGIN_TO_ACCOUNT_PORTAL", DIRECT_LOGIN_TO_ACCOUNT_PORTAL = "DIRECT_LOGIN_TO_ACCOUNT_PORTAL",
@ -15,7 +15,7 @@ export const FeatureFlagDefaults: Record<FeatureFlag, boolean> = {
[FeatureFlag.AI_JS_GENERATION]: false, [FeatureFlag.AI_JS_GENERATION]: false,
[FeatureFlag.AI_TABLE_GENERATION]: false, [FeatureFlag.AI_TABLE_GENERATION]: false,
[FeatureFlag.AI_AGENTS]: false, [FeatureFlag.AI_AGENTS]: false,
[FeatureFlag.PROJECT_APPS]: false, [FeatureFlag.WORKSPACE_APPS]: false,
// Account-portal // Account-portal
[FeatureFlag.DIRECT_LOGIN_TO_ACCOUNT_PORTAL]: false, [FeatureFlag.DIRECT_LOGIN_TO_ACCOUNT_PORTAL]: false,