mirror of https://github.com/buster-so/buster.git
Merge pull request #475 from buster-so/nate/hot-fix-server-build
Server build update
This commit is contained in:
commit
252a892cae
|
@ -1,37 +0,0 @@
|
|||
# Custom Base Image - Published base with tools + dependencies
|
||||
# ================================================================
|
||||
# This image contains:
|
||||
# - Node 22 + npm
|
||||
# - pnpm + bun
|
||||
# - All workspace dependencies pre-installed
|
||||
#
|
||||
# Build and publish this multi-platform image:
|
||||
# docker buildx build --platform linux/amd64,linux/arm64 \
|
||||
# -f apps/server/Dockerfile.custom-base \
|
||||
# -t ghcr.io/buster-so/server-base:latest \
|
||||
# --push .
|
||||
|
||||
FROM node:22-alpine
|
||||
WORKDIR /app
|
||||
|
||||
# Install tools: pnpm + bun
|
||||
RUN echo "=== Installing build tools: $(date) ===" && \
|
||||
apk add --no-cache curl bash git && \
|
||||
npm install -g pnpm@9.15.0 turbo && \
|
||||
curl -fsSL https://bun.sh/install | bash && \
|
||||
echo "=== Tools installed: $(date) ==="
|
||||
|
||||
ENV PATH="/root/.bun/bin:$PATH"
|
||||
|
||||
# Copy package configuration files
|
||||
COPY package.json pnpm-lock.yaml* turbo.json* pnpm-workspace.yaml* ./
|
||||
COPY packages/ ./packages/
|
||||
COPY apps/server/package.json ./apps/server/
|
||||
|
||||
# Install ALL dependencies (this is the heavy lifting)
|
||||
RUN echo "=== Installing all dependencies: $(date) ===" && \
|
||||
time pnpm install --ignore-scripts && \
|
||||
echo "=== Dependencies installed: $(date) ===" && \
|
||||
echo "Base image ready with $(du -sh node_modules | cut -f1) of dependencies"
|
||||
|
||||
# This base image is now ready to be published and reused!
|
|
@ -1,51 +0,0 @@
|
|||
# Buster Server Docker Workflow
|
||||
Two-step build process for maximum efficiency
|
||||
|
||||
## 🔐 GitHub Container Registry Setup
|
||||
|
||||
First, authenticate with GitHub Container Registry:
|
||||
|
||||
- The password to login must be a github access token (made with token classic) with write and write package permissions
|
||||
|
||||
```bash
|
||||
docker login ghcr.io
|
||||
```
|
||||
|
||||
## 🏗️ Step 1: Build & Publish Base Image (Do this occasionally)
|
||||
|
||||
The base image contains all heavy dependencies and build tools.
|
||||
|
||||
```bash
|
||||
# Build the base image with all dependencies
|
||||
docker build -f apps/server/Dockerfile.custom-base -t ghcr.io/buster-so/server-base:latest .
|
||||
|
||||
# Publish to GitHub Container Registry
|
||||
docker push ghcr.io/buster-so/server-base:latest
|
||||
```
|
||||
|
||||
**When to rebuild the base:**
|
||||
- Major dependency updates
|
||||
- New packages added to workspace
|
||||
- Tool version updates (pnpm, bun)
|
||||
- Weekly/monthly maintenance
|
||||
|
||||
## ⚡ Step 2: Ultra-Fast App Builds (CI/CD)
|
||||
|
||||
Use the published base for lightning-fast builds:
|
||||
|
||||
```bash
|
||||
# Pull the latest base (in CI/CD)
|
||||
docker pull ghcr.io/buster-so/buster-server-base:latest
|
||||
|
||||
# Build your app (super fast!)
|
||||
docker build -f apps/server/Dockerfile.ultra-fast -t buster-server:latest .
|
||||
```
|
||||
|
||||
|
||||
### Update Base Image (periodically):
|
||||
```bash
|
||||
# Rebuild and push new base
|
||||
docker buildx build --platform linux/amd64,linux/arm64 \
|
||||
-f apps/server/Dockerfile.custom-base \
|
||||
-t ghcr.io/buster-so/server-base:latest \
|
||||
--push .
|
|
@ -7,11 +7,10 @@
|
|||
}
|
||||
},
|
||||
"scripts": {
|
||||
"prebuild": "bun run scripts/validate-env.js",
|
||||
"build": "bun build src/index.ts --outdir ./dist --target bun --external pino-pretty",
|
||||
"dev": "bun --max-old-space-size=512 run --hot src/index.ts",
|
||||
"prebuild": "bun run scripts/validate-env.js && pnpm run typecheck",
|
||||
"build": "tsup",
|
||||
"dev": "tsup --watch",
|
||||
"lint": "biome check",
|
||||
"prod": "pnpm run build:vercel && pnpm run start:vercel",
|
||||
"start": "bun dist/index.js",
|
||||
"test": "vitest run",
|
||||
"test:coverage": "vitest --coverage",
|
||||
|
@ -31,13 +30,10 @@
|
|||
"@trigger.dev/sdk": "catalog:",
|
||||
"drizzle-orm": "catalog:",
|
||||
"hono": "catalog:",
|
||||
"hono-pino": "^0.8.0",
|
||||
"hono-pino": "^0.9.1",
|
||||
"pino": "^9.7.0",
|
||||
"pino-pretty": "^13.0.0",
|
||||
"tsup": "catalog:",
|
||||
"zod": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vercel/node": "^5.3.3",
|
||||
"tsup": "^8.5.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,15 +16,10 @@ import type {
|
|||
ChatMessageResponseMessage,
|
||||
ChatWithMessages,
|
||||
} from '@buster/server-shared/chats';
|
||||
import {
|
||||
ChatError,
|
||||
ChatErrorCode,
|
||||
ReasoningMessageSchema,
|
||||
ResponseMessageSchema,
|
||||
} from '@buster/server-shared/chats';
|
||||
import { ChatError, ChatErrorCode } from '@buster/server-shared/chats';
|
||||
import { PostProcessingMessageSchema } from '@buster/server-shared/message';
|
||||
import { and, eq, gte, isNull } from 'drizzle-orm';
|
||||
import type { z } from 'zod/v4';
|
||||
import type { z } from 'zod';
|
||||
|
||||
/**
|
||||
* Validates a nullable JSONB field against a Zod schema
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
import { randomUUID } from 'node:crypto';
|
||||
import { db, organizations, users, usersToOrganizations } from '@buster/database';
|
||||
import type { Organization, User } from '@buster/database';
|
||||
import type { User } from '@buster/database';
|
||||
import type { UserOrganizationRole } from '@buster/server-shared/user';
|
||||
import type { InferInsertModel, InferSelectModel } from 'drizzle-orm';
|
||||
|
||||
type Organization = InferSelectModel<typeof organizations>;
|
||||
import { and, eq, isNull } from 'drizzle-orm';
|
||||
|
||||
export async function createTestUserInDb(userData: Partial<User> = {}): Promise<User> {
|
||||
|
@ -48,26 +52,28 @@ export async function createTestOrganizationInDb(
|
|||
const id = randomUUID();
|
||||
// Use a unique domain for each organization to avoid conflicts with the trigger
|
||||
const uniqueDomain = `test-${id.substring(0, 8)}.com`;
|
||||
const org = {
|
||||
const org: Organization = {
|
||||
id,
|
||||
name: `Test Organization ${id}`,
|
||||
domains: orgData.domains !== undefined ? orgData.domains : [uniqueDomain],
|
||||
restrictNewUserInvitations: false,
|
||||
defaultRole: 'restricted_querier',
|
||||
defaultRole: 'restricted_querier' as const,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
domain: null,
|
||||
paymentRequired: true,
|
||||
...orgData,
|
||||
};
|
||||
|
||||
await db.insert(organizations).values(org);
|
||||
return org as Organization;
|
||||
return org;
|
||||
}
|
||||
|
||||
export async function createTestOrgMemberInDb(
|
||||
userId: string,
|
||||
organizationId: string,
|
||||
role = 'querier'
|
||||
role: UserOrganizationRole = 'querier'
|
||||
): Promise<void> {
|
||||
// First check if there's already a membership
|
||||
const existing = await db
|
||||
|
@ -80,7 +86,7 @@ export async function createTestOrgMemberInDb(
|
|||
await db.delete(usersToOrganizations).where(eq(usersToOrganizations.userId, userId));
|
||||
}
|
||||
|
||||
const member = {
|
||||
const member: InferInsertModel<typeof usersToOrganizations> = {
|
||||
userId,
|
||||
organizationId,
|
||||
role,
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
import type { Organization, User } from '@buster/database';
|
||||
import type { User, organizations } from '@buster/database';
|
||||
import type { InferSelectModel } from 'drizzle-orm';
|
||||
|
||||
type Organization = InferSelectModel<typeof organizations>;
|
||||
|
||||
export function createTestUser(overrides?: Partial<User>): User {
|
||||
const id = `test-user-${Math.random().toString(36).substring(7)}`;
|
||||
|
|
|
@ -111,8 +111,8 @@ async function updateOrganizationSettings(
|
|||
restrictNewUserInvitations: updateData.restrictNewUserInvitations,
|
||||
}),
|
||||
...(updateData.defaultRole !== undefined &&
|
||||
updateData.defaultRole !== 'none' && {
|
||||
defaultRole: updateData.defaultRole as Exclude<OrganizationRole, 'none'>,
|
||||
updateData.defaultRole && {
|
||||
defaultRole: updateData.defaultRole,
|
||||
}),
|
||||
};
|
||||
|
||||
|
|
|
@ -130,10 +130,10 @@ export class SlackHandler {
|
|||
* Handle OAuth callback from Slack
|
||||
*/
|
||||
async handleOAuthCallback(c: Context): Promise<Response> {
|
||||
try {
|
||||
// Get base URL from environment
|
||||
const baseUrl = process.env.BUSTER_URL || '';
|
||||
// Get base URL from environment
|
||||
const baseUrl = process.env.BUSTER_URL || '';
|
||||
|
||||
try {
|
||||
// Get service instance (lazy initialization)
|
||||
const slackOAuthService = this.getSlackOAuthService();
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@ const SlackEnvSchema = z.object({
|
|||
SERVER_URL: z.string().url(),
|
||||
SLACK_INTEGRATION_ENABLED: z
|
||||
.string()
|
||||
.transform((val) => val === 'true')
|
||||
.default('false'),
|
||||
.default('false')
|
||||
.transform((val) => val === 'true'),
|
||||
});
|
||||
|
||||
// OAuth metadata schema
|
||||
|
|
|
@ -32,7 +32,13 @@ app.onError((err, c) => {
|
|||
}
|
||||
|
||||
if (err instanceof z.ZodError) {
|
||||
return c.text(err.errors.map((e) => e.message).join(', '), 400);
|
||||
return c.json(
|
||||
{
|
||||
error: 'Validation Error',
|
||||
message: err.issues.map((issue) => issue.message).join(', '),
|
||||
},
|
||||
400
|
||||
);
|
||||
}
|
||||
|
||||
return c.json(
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
import { defineConfig } from 'tsup';
|
||||
|
||||
export default defineConfig({
|
||||
entry: ['src/index.ts'],
|
||||
format: ['esm'],
|
||||
target: 'node22', // Bun is compatible with recent Node.js versions
|
||||
platform: 'node',
|
||||
outDir: 'dist',
|
||||
clean: true,
|
||||
dts: false, // Disable for now due to TypeScript file list errors
|
||||
sourcemap: true,
|
||||
minify: false, // Don't minify for bun runtime
|
||||
splitting: false,
|
||||
shims: false, // Bun doesn't need shims
|
||||
external: [
|
||||
// Mark all workspace packages as external to avoid bundling them
|
||||
'@buster/access-controls',
|
||||
'@buster/database',
|
||||
'@buster/server-shared',
|
||||
'@buster/slack',
|
||||
'@buster/test-utils',
|
||||
'@buster/typescript-config',
|
||||
'@buster/vitest-config',
|
||||
],
|
||||
noExternal: [
|
||||
// Bundle these specific packages if needed
|
||||
],
|
||||
esbuildOptions(options) {
|
||||
// Additional esbuild options for bun compatibility
|
||||
options.keepNames = true; // Preserve function names for better debugging
|
||||
},
|
||||
onSuccess: async () => {
|
||||
console.log('Build completed successfully!');
|
||||
},
|
||||
});
|
|
@ -27,13 +27,13 @@
|
|||
"@buster/typescript-config": "workspace:*",
|
||||
"@buster/vitest-config": "workspace:*",
|
||||
"@mastra/core": "catalog:",
|
||||
"@trigger.dev/sdk": "4.0.0-v4-beta.22",
|
||||
"@trigger.dev/sdk": "catalog:",
|
||||
"ai": "catalog:",
|
||||
"braintrust": "^0.0.206",
|
||||
"braintrust": "catalog:",
|
||||
"vitest": "catalog:",
|
||||
"zod": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@trigger.dev/build": "4.0.0-v4-beta.22"
|
||||
"@trigger.dev/build": "catalog:"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
"@mastra/core": "catalog:",
|
||||
"@mastra/loggers": "^0.10.3",
|
||||
"ai": "catalog:",
|
||||
"braintrust": "^0.0.206",
|
||||
"braintrust": "catalog:",
|
||||
"drizzle-orm": "catalog:",
|
||||
"glob": "^11.0.3",
|
||||
"minimatch": "^10.0.3",
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
"@buster/vitest-config": "workspace:*",
|
||||
"@buster/typescript-config": "workspace:*",
|
||||
"@buster/database": "workspace:*",
|
||||
"zod": "catalog:"
|
||||
"zod": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vitest": "catalog:"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
|
||||
/**
|
||||
* Error codes for chat operations
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
import { PostProcessingMessageSchema } from '../message';
|
||||
|
||||
// Message role for chat messages
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
import { ChatMessageSchema } from './chat-message.types';
|
||||
|
||||
const AssetType = z.enum(['metric_file', 'dashboard_file']);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const CurrencySchema = z.object({
|
||||
code: z.string(),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const AssumptionClassificationSchema = z.enum([
|
||||
'fieldMapping',
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
import { getDefaults } from '../defaultHelpers';
|
||||
|
||||
// Goal line is a line that is drawn on the chart to represent a goal.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const BarAndLineAxisSchema = z
|
||||
.object({
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
import { BarAndLineAxisSchema } from './axisInterfaces';
|
||||
import { BarSortBySchema } from './etcInterfaces';
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
import { getDefaults } from '../defaultHelpers';
|
||||
import { GoalLineSchema, TrendlineSchema } from './annotationInterfaces';
|
||||
import { BarChartPropsSchema } from './barChartProps';
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
import { getDefaults } from '../defaultHelpers';
|
||||
|
||||
export const LineColumnSettingsSchema = z.object({
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
import { getDefaults } from '../defaultHelpers';
|
||||
|
||||
export const ColumnLabelFormatSchema = z.object({
|
||||
|
@ -14,10 +14,8 @@ export const ColumnLabelFormatSchema = z.object({
|
|||
.optional(
|
||||
z
|
||||
.number()
|
||||
.check(
|
||||
z.gte(0, 'Minimum fraction digits must be at least 0'),
|
||||
z.lte(20, 'Minimum fraction digits must be at most 20')
|
||||
)
|
||||
.min(0, 'Minimum fraction digits must be at least 0')
|
||||
.max(20, 'Minimum fraction digits must be at most 20')
|
||||
)
|
||||
.default(0),
|
||||
// OPTIONAL: default is 2. This is essentially used to set a maximum number of decimal places. This will only apply if the format is set to 'number'.
|
||||
|
@ -25,10 +23,8 @@ export const ColumnLabelFormatSchema = z.object({
|
|||
.optional(
|
||||
z
|
||||
.number()
|
||||
.check(
|
||||
z.gte(0, 'Maximum fraction digits must be at least 0'),
|
||||
z.lte(20, 'Maximum fraction digits must be at most 20')
|
||||
)
|
||||
.min(0, 'Maximum fraction digits must be at least 0')
|
||||
.max(20, 'Maximum fraction digits must be at most 20')
|
||||
)
|
||||
.default(2),
|
||||
// OPTIONAL: default is 1. This will only apply if the format is set to 'number', 'currency', or 'percent'.
|
||||
|
@ -36,10 +32,8 @@ export const ColumnLabelFormatSchema = z.object({
|
|||
.optional(
|
||||
z
|
||||
.number()
|
||||
.check(
|
||||
z.gte(0.001, 'Multiplier must be at least 0.001'),
|
||||
z.lte(1000000, 'Multiplier must be at most 1,000,000')
|
||||
)
|
||||
.min(0.001, 'Multiplier must be at least 0.001')
|
||||
.max(1000000, 'Multiplier must be at most 1,000,000')
|
||||
)
|
||||
.default(1),
|
||||
// OPTIONAL: default is ''. This sets a prefix to go in front of each value found within the column. This will only apply if the format is set to 'number' or 'percent'.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
import { ComboChartAxisSchema } from './axisInterfaces';
|
||||
|
||||
export const ComboChartPropsSchema = z.object({
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const ChartTypeSchema = z
|
||||
.enum(['line', 'bar', 'scatter', 'pie', 'metric', 'table', 'combo'])
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
|
||||
// OPTIONAL: default is no sorting (none). The first item in the array will be the primary sort. The second item will be the secondary sort. This will only apply if the X axis type is not a date.
|
||||
export const BarSortBySchema = z.array(z.enum(['asc', 'desc', 'none'])).default([]);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const LineChartPropsSchema = z.object({
|
||||
// OPTIONAL: default is null. This will only apply if the columnVisualization is set to 'line'. If this is set to stack it will stack the lines on top of each other. The UI has this labeled as "Show as %"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const DerivedMetricTitleSchema = z.object({
|
||||
// which column to use.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
import { PieChartAxisSchema } from './axisInterfaces';
|
||||
import { PieSortBySchema } from './etcInterfaces';
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
import { ScatterAxisSchema } from './axisInterfaces';
|
||||
|
||||
export const ScatterChartPropsSchema = z.object({
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const TableChartPropsSchema = z.object({
|
||||
tableColumnOrder: z.nullable(z.array(z.string())).default(null),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
|
||||
/**
|
||||
* Configuration options for the Y-axis of a chart.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { describe, expect, it } from 'vitest';
|
||||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
import { getDefaults, getDefaultsPartial } from './defaultHelpers';
|
||||
|
||||
describe('getDefaults', () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import type { z } from 'zod/v4';
|
||||
import type { z } from 'zod';
|
||||
|
||||
/**
|
||||
* Extracts all default values from a Zod schema.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const ColumnMetaDataSchema = z.object({
|
||||
name: z.string(),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
import { ShareConfigSchema, VerificationStatusSchema } from '../share';
|
||||
import { ChartConfigPropsSchema } from './charts';
|
||||
import { DEFAULT_CHART_CONFIG } from './charts/chartConfigProps';
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
import { VerificationStatusSchema } from '../share';
|
||||
|
||||
export const MetricListItemSchema = z.object({
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
import { ShareRoleSchema, VerificationStatusSchema } from '../share';
|
||||
import { ChartConfigPropsSchema } from './charts';
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
import { DataMetadataSchema, DataResultSchema } from './metadata.type';
|
||||
import { MetricSchema } from './metric.types';
|
||||
import { MetricListItemSchema } from './metrics-list.types';
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
import { OrganizationRoleSchema } from './roles.types';
|
||||
|
||||
export const OrganizationSchema = z.object({
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import type { userOrganizationRoleEnum } from '@buster/database'; //we import as type to avoid postgres dependency in the frontend ☹️
|
||||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
|
||||
type OrganizationRoleBase = (typeof userOrganizationRoleEnum.enumValues)[number];
|
||||
|
||||
|
@ -14,6 +14,8 @@ export const OrganizationRoleEnum: Record<OrganizationRoleBase, OrganizationRole
|
|||
restricted_querier: 'restricted_querier',
|
||||
});
|
||||
|
||||
export const OrganizationRoleSchema = z.enum(Object.values(OrganizationRoleEnum));
|
||||
export const OrganizationRoleSchema = z.enum(
|
||||
Object.values(OrganizationRoleEnum) as [OrganizationRoleBase, ...OrganizationRoleBase[]]
|
||||
);
|
||||
|
||||
export type OrganizationRole = z.infer<typeof OrganizationRoleSchema>;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
import { OrganizationRoleSchema } from './roles.types';
|
||||
|
||||
export const LineageUserItemTypeSchema = z.enum(['user', 'datasets', 'permissionGroups']);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
import { OrganizationRoleSchema } from '../organization';
|
||||
|
||||
export const UpdateInviteLinkRequestSchema = z.object({
|
||||
|
@ -43,7 +43,7 @@ export const UpdateWorkspaceSettingsRequestSchema = z.object({
|
|||
restrict_new_user_invitations: z.boolean().optional(),
|
||||
default_role: OrganizationRoleSchema.optional(),
|
||||
// this can either be a uuid or "all"
|
||||
default_datasets_ids: z.array(z.union([z.uuid(), z.literal('all')])).optional(),
|
||||
default_datasets_ids: z.array(z.union([z.string(), z.literal('all')])).optional(),
|
||||
});
|
||||
|
||||
export type UpdateWorkspaceSettingsRequest = z.infer<typeof UpdateWorkspaceSettingsRequestSchema>;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
import { OrganizationRoleSchema } from '../organization';
|
||||
|
||||
export const GetInviteLinkResponseSchema = z.object({
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const ShareRoleSchema = z.enum([
|
||||
'owner', //owner of the asset
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const VerificationStatusSchema = z.enum([
|
||||
'notRequested',
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
|
||||
// POST /api/v2/slack/auth/init
|
||||
export const InitiateOAuthSchema = z
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const CreateTeamRequestSchema = z.object({
|
||||
name: z.string(),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
import { TeamSchema } from './teams.types';
|
||||
|
||||
export const TeamListResponseSchema = z.array(TeamSchema);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import type { teamRoleEnum } from '@buster/database'; //we import as type to avoid postgres dependency in the frontend ☹️
|
||||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
import { SharingSettingSchema } from '../user/sharing-setting.types';
|
||||
|
||||
type TeamRoleBase = (typeof teamRoleEnum.enumValues)[number] | 'none';
|
||||
|
@ -8,7 +8,9 @@ const TeamRoleEnums: Record<TeamRoleBase, TeamRoleBase> = Object.freeze({
|
|||
manager: 'manager',
|
||||
member: 'member',
|
||||
});
|
||||
export const TeamRoleSchema = z.enum(Object.values(TeamRoleEnums));
|
||||
export const TeamRoleSchema = z.enum(
|
||||
Object.values(TeamRoleEnums) as [TeamRoleBase, ...TeamRoleBase[]]
|
||||
);
|
||||
|
||||
export type TeamRole = z.infer<typeof TeamRoleSchema>;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
import { ShareAssetTypeSchema } from '../share';
|
||||
|
||||
export const UserFavoriteSchema = z.object({
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
import { OrganizationRoleSchema } from '../organization/roles.types';
|
||||
import { ShareAssetTypeSchema } from '../share';
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
import { OrganizationSchema } from '../organization/organization.types';
|
||||
import { OrganizationRoleSchema } from '../organization/roles.types';
|
||||
import { TeamSchema } from '../teams/teams.types';
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import type { userOrganizationRoleEnum } from '@buster/database'; //we import as type to avoid postgres dependency in the frontend ☹️
|
||||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
|
||||
type UserOrganizationRoleBase = (typeof userOrganizationRoleEnum.enumValues)[number] | 'none';
|
||||
type UserOrganizationRoleBase = (typeof userOrganizationRoleEnum.enumValues)[number];
|
||||
|
||||
const UserOrganizationRoleEnums: Record<UserOrganizationRoleBase, UserOrganizationRoleBase> =
|
||||
Object.freeze({
|
||||
none: 'none',
|
||||
viewer: 'viewer',
|
||||
workspace_admin: 'workspace_admin',
|
||||
data_admin: 'data_admin',
|
||||
|
@ -13,6 +12,11 @@ const UserOrganizationRoleEnums: Record<UserOrganizationRoleBase, UserOrganizati
|
|||
restricted_querier: 'restricted_querier',
|
||||
});
|
||||
|
||||
export const UserOrganizationRoleSchema = z.enum(Object.values(UserOrganizationRoleEnums));
|
||||
export const UserOrganizationRoleSchema = z.enum(
|
||||
Object.values(UserOrganizationRoleEnums) as [
|
||||
UserOrganizationRoleBase,
|
||||
...UserOrganizationRoleBase[],
|
||||
]
|
||||
);
|
||||
|
||||
export type UserOrganizationRole = z.infer<typeof UserOrganizationRoleSchema>;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import type { sharingSettingEnum } from '@buster/database'; //we import as type to avoid postgres dependency in the frontend ☹️
|
||||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
|
||||
type SharingSettingBase = (typeof sharingSettingEnum.enumValues)[number] | 'none';
|
||||
|
||||
|
@ -9,6 +9,9 @@ const SharingSettingEnums: Record<SharingSettingBase, SharingSettingBase> = Obje
|
|||
team: 'team',
|
||||
organization: 'organization',
|
||||
});
|
||||
export const SharingSettingSchema = z.enum(Object.values(SharingSettingEnums));
|
||||
|
||||
const test = Object.values(SharingSettingEnums) as [SharingSettingBase, ...SharingSettingBase[]];
|
||||
|
||||
export const SharingSettingSchema = z.enum(test);
|
||||
|
||||
export type SharingSetting = z.infer<typeof SharingSettingSchema>;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { z } from 'zod/v4';
|
||||
import { z } from 'zod';
|
||||
import type { UserFavorite } from './favorites.types';
|
||||
import type { UserOrganizationRole } from './roles.types';
|
||||
|
||||
|
|
|
@ -35,6 +35,6 @@
|
|||
"@buster/typescript-config": "workspace:*",
|
||||
"@buster/vitest-config": "workspace:*",
|
||||
"ai": "catalog:",
|
||||
"zod": "catalog:"
|
||||
"zod": "^3.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,21 +2,22 @@
|
|||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"compilerOptions": {
|
||||
"allowImportingTsExtensions": false,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"composite": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"incremental": true,
|
||||
"inlineSources": false,
|
||||
"isolatedModules": true,
|
||||
"lib": ["ESNext"],
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"noEmit": false,
|
||||
"preserveWatchOutput": true,
|
||||
"skipLibCheck": true,
|
||||
"target": "ES2022",
|
||||
"lib": ["ESNext"]
|
||||
"strict": true,
|
||||
"target": "ES2022"
|
||||
},
|
||||
"exclude": ["node_modules"],
|
||||
"extends": "./type-checking.json"
|
||||
|
|
931
pnpm-lock.yaml
931
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
|
@ -10,17 +10,19 @@ packages:
|
|||
- "apps/api"
|
||||
|
||||
catalog:
|
||||
"@mastra/core": "^0.10.8"
|
||||
"@supabase/supabase-js": "^2.50.0"
|
||||
"@trigger.dev/build": "^4.0.0-v4-beta.22"
|
||||
"@trigger.dev/sdk": "^4.0.0-v4-beta.22"
|
||||
ai: "^4.0.0"
|
||||
axios: "^1.10.0"
|
||||
"vite-tsconfig-paths": "^5.1.4"
|
||||
"braintrust": "^0.0.209"
|
||||
drizzle-orm: "^0.44.2"
|
||||
hono: "^4.8.0"
|
||||
"@mastra/core": "^0.10.8"
|
||||
pg: "^8.16.2"
|
||||
tsup: "^8.5.0"
|
||||
uuid: "^11.0.0"
|
||||
vitest: "3.2.4"
|
||||
vite: "6.3.5"
|
||||
zod: "^3.0.0"
|
||||
"vite-tsconfig-paths": "^5.1.4"
|
||||
vitest: "3.2.4"
|
||||
zod: "^3.25.0"
|
||||
|
|
Loading…
Reference in New Issue