@bagelink/workspace
v1.10.17
Published
Monorepo workspace tooling for Bagel projects with proxy and config management
Readme
@bagelink/workspace
Workspace tooling for Bagel projects - works for both single projects and monorepos.
Features
- 🔧 Simple Configuration: One config file for all environments
- 🔀 Proxy Management: Vite dev proxy + Netlify production redirects
- 🏗️ Build Tooling: Auto-generate netlify.toml with environment injection
- 📦 Monorepo Support: Cascading config for multi-project setups
Installation
pnpm add @bagelink/workspaceQuick Start
Option 1: Run npx bgl init (Recommended)
npx bgl init
🔧 No bgl.config.ts found. Let's create one!
? What is your Bagel project ID? › my-project
? Use custom production host? › No / Yes
? Add/update dev scripts in package.json? › Yes
? Create/update vite.config.ts? › Yes
? Generate netlify.toml for deployment? › Yes
✅ Created bgl.config.ts
Production host: https://my-project.bagel.to
Local dev host: http://localhost:8000
✅ Updated package.json with dev scripts
✅ Created vite.config.ts
✅ Generated netlify.tomlThis will:
- Create
bgl.config.tswith your project configuration - Add/overwrite
devanddev:localscripts inpackage.json - Create
vite.config.tswith proxy configuration (if doesn't exist) - Generate
netlify.tomlwith production proxy configuration
Option 2: Automatic on first use
The first time you use @bagelink/workspace, it will automatically prompt you to create a config file if it doesn't exist.
Option 3: Create manually
Create bgl.config.ts:
import { defineWorkspace } from '@bagelink/workspace'
import type { WorkspaceConfig, WorkspaceEnvironment } from '@bagelink/workspace'
/**
* Define your workspace environments
* You can add as many custom environments as needed (e.g., 'staging', 'preview')
* Use --mode flag to switch: bgl dev --mode <env_name>
*/
const configs: Record<WorkspaceEnvironment, WorkspaceConfig> = {
localhost: {
host: 'http://localhost:8000',
proxy: '/api', // Optional: remove to skip proxy setup
openapi_url: 'http://localhost:8000/openapi.json',
},
development: {
host: 'https://project.bagel.to',
proxy: '/api',
openapi_url: 'https://project.bagel.to/openapi.json',
},
production: {
host: 'https://project.bagel.to',
proxy: '/api',
},
// Add your own custom environments
staging: {
host: 'https://staging.project.bagel.to',
proxy: '/api',
},
}
export default defineWorkspace(configs)Usage
1. Add Type Definitions
Add to your project's env.d.ts:
/// <reference types="@bagelink/workspace/env" />This provides TypeScript types for injected environment variables.
2. Configure Vite (vite.config.ts)
Recommended: Use the Vite plugin (keeps your config clean and standard)
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { bagelink } from '@bagelink/workspace/vite'
import workspace from './bgl.config'
export default defineConfig({
plugins: [
vue(),
bagelink({ workspace }),
],
})The plugin automatically:
- Configures proxy based on
bgl.config.ts - Sets up
@alias pointing to./src - Sets up
@sharedalias (in monorepos) - Keeps your vite.config.ts clean and extensible
Advanced: Custom options
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { bagelink } from '@bagelink/workspace/vite'
import { fileURLToPath } from 'node:url'
import workspace from './bgl.config'
export default defineConfig({
plugins: [
vue(),
bagelink({
workspace,
config: {
sharedPath: '../packages/shared',
additionalAliases: {
'@utils': fileURLToPath(new URL('./src/utils', import.meta.url))
}
}
}),
],
})Legacy: Manual proxy setup
import { defineConfig } from 'vite'
import { createViteProxy } from '@bagelink/workspace'
import workspace from './bgl.config'
export default defineConfig(({ mode }) => {
const config = workspace(mode as WorkspaceEnvironment)
return {
plugins: [vue()],
server: {
proxy: createViteProxy(config)
}
}
})3. Use Configuration in Your App
Access config at runtime with useWorkspace():
import { useWorkspace, getApiUrl } from '@bagelink/workspace'
// In your app setup
const { baseURL, proxy, host, mode } = useWorkspace()
const auth = createAuth({ baseURL }) // Uses proxy if available, otherwise host
// Or get full API URL
const apiUrl = getApiUrl() // 'https://project.bagel.to/api'Vue component example:
<script setup lang="ts">
import { useWorkspace } from '@bagelink/workspace'
import { createAuth } from '@bagelink/auth'
const { baseURL, proxy, host, mode } = useWorkspace()
const auth = createAuth({ baseURL }) // Uses proxy if available, otherwise host
console.log('API Host:', host)
console.log('Environment:', mode)
</script>Access raw environment variables:
// These are injected at build time by the bagelink plugin
const proxy = import.meta.env.VITE_BGL_PROXY // '/api'
const host = import.meta.env.VITE_BGL_HOST // 'https://project.bagel.to'
const openapi = import.meta.env.VITE_BGL_OPENAPI_URL // optional4. Add scripts to package.json
{
"scripts": {
"dev": "vite",
"dev:local": "vite --mode localhost",
"dev:staging": "vite --mode staging",
"build": "vite build",
"build:staging": "vite build --mode staging"
}
}5. Custom Environments
You can define as many custom environments as you need. The environment name is completely flexible:
const configs: Record<WorkspaceEnvironment, WorkspaceConfig> = {
localhost: {
host: 'http://localhost:8000',
proxy: '/api',
},
development: {
host: 'https://dev.project.bagel.to',
proxy: '/api',
},
staging: {
host: 'https://staging.project.bagel.to',
proxy: '/api',
},
preview: {
host: 'https://preview.project.bagel.to',
// No proxy - will use host directly
},
production: {
host: 'https://project.bagel.to',
proxy: '/api',
},
}Use the --mode flag to switch environments:
# Development
bgl dev --mode development
# Staging
bgl dev --mode staging
# Production build
bgl build --mode productionNote: The proxy field is optional. If omitted, no proxy will be configured for that environment, and baseURL from useWorkspace() will return the host value instead.
6. Generate Netlify Config
import { writeNetlifyConfig } from '@bagelink/workspace'
import workspace from './bgl.config'
const config = workspace('production')
writeNetlifyConfig(config, './netlify.toml')Monorepo Support
Root Config (/bgl.config.ts)
import { defineWorkspace } from '@bagelink/workspace'
export default defineWorkspace({
localhost: {
host: 'http://localhost:8000',
proxy: '/api',
},
development: {
host: 'https://shared.bagel.to',
proxy: '/api',
},
production: {
host: 'https://shared.bagel.to',
proxy: '/api',
},
})Project Override (/projects/admin/bgl.config.ts)
import { defineWorkspace } from '@bagelink/workspace'
import rootWorkspace from '../../bgl.config'
export default defineWorkspace({
localhost: rootWorkspace('localhost'),
development: rootWorkspace('development'),
production: {
...rootWorkspace('production'),
host: 'https://admin.bagel.to', // Override
},
})CLI
Single Project Setup
npx bgl init
Interactively generate project configuration files:
bgl.config.ts- Workspace configurationpackage.json- Add/update dev scripts (optional)vite.config.ts- Vite proxy configuration (optional)netlify.toml- Netlify deployment configuration (optional)
npx bgl initFeatures:
- Prompts for project ID and host configuration
- Adds/overwrites
devanddev:localscripts in package.json - Creates vite.config.ts with proxy setup (if doesn't exist)
- Generates netlify.toml with production proxy configuration
- Safe: prompts before each step
Workspace (Multi-Project) Setup
npx bgl init --workspace
Create a workspace with flat structure for multiple projects:
npx bgl init --workspace
? Workspace name: › my-workspace
? Bagel project ID: › my-project
? Create first project? › Yes
? First project name: › web
✅ Workspace created successfully!Creates structure:
my-workspace/
├── package.json # Workspace root
├── bgl.config.ts # Shared config
├── tsconfig.json
├── shared/ # Shared code
│ ├── package.json
│ ├── utils/
│ └── types/
└── web/ # First project
├── bgl.config.ts
├── package.json
├── vite.config.ts
└── src/bgl add <project-name>
Add a new project to workspace:
bgl add admin
bgl add customer
bgl add mobileEach project:
- Gets its own directory at root level
- Inherits shared config from workspace root
- Can import from
shared/utils,shared/types, etc. - Auto-configures with Vite proxy
bgl list
List all projects in workspace:
bgl list
Projects:
- web
- admin
- customerRunning Workspace Projects
# Run all projects concurrently
bun run dev
# Run specific project
bun run dev:admin
bun run dev:customer
# Build specific project
bun run build:admin
# Build all projects
bun run buildVite automatically assigns ports:
- First project:
http://localhost:5173 - Second project:
http://localhost:5174 - Third project:
http://localhost:5175 - etc.
Linting Setup
bgl lint init
Set up linting and formatting in your project:
bgl lint init
? Select configurations to set up:
✔ ESLint
✔ Prettier
✔ EditorConfig
○ Git Hooks
? Install dependencies? › Yes
✅ Created eslint.config.js
✅ Created .prettierrc
✅ Created .prettierignore
✅ Created .editorconfig
✅ Updated package.json with lint scriptsCreates:
eslint.config.js- ESLint configuration (Vue 3 + TypeScript).prettierrc- Prettier configuration.prettierignore- Prettier ignore patterns.editorconfig- Editor configuration.lintstagedrc- Lint-staged configuration (if git hooks selected)
Adds scripts:
bun run lint- Run linterbun run lint:fix- Fix linting issuesbun run format- Format codebun run format:check- Check formatting
Auto-detects workspace:
# In workspace root (auto-detected)
bgl lint init
✓ Detected workspace mode
# Sets up at workspace root
# In single project (auto-detected)
bgl lint init
# Sets up in current project
# Force modes:
bgl lint init --workspace # Force workspace mode
bgl lint init --project # Force single project modeWorkspace detection:
- Checks for
workspacesfield in package.json - Checks for multiple project directories
- Auto-applies best mode
SDK Generation
bgl sdk generate
Generate TypeScript SDK from OpenAPI specification:
bgl sdk generate
? OpenAPI spec URL: › http://localhost:8000/openapi.json
? Output directory: › ./src/api
? Split into organized files? › Yes
📡 Fetching OpenAPI spec from: http://localhost:8000/openapi.json
📁 Output directory: ./src/api
✅ Generated types.d.ts
✅ Generated api.ts
✅ Generated index.ts
🔀 Splitting into organized files...
✅ Files organized into directories
✅ SDK generated successfully!
Import it in your code:
import { api } from './api'Features:
- Auto-reads
openapi_urlfrombgl.config.ts - Generates TypeScript types from OpenAPI schema
- Creates type-safe API client
- Optional file organization (split by endpoints)
- Works with both local and remote OpenAPI specs
Auto-detects workspace:
# In workspace root (auto-detected)
bgl sdk generate
✓ Detected workspace mode - will generate for multiple projects
? Select projects to generate SDK for:
✔ admin
✔ customer
✔ mobile
# In single project (auto-detected)
bgl sdk generate
# Generates SDK for current project only
# Force modes:
bgl sdk generate --workspace # Force workspace mode
bgl sdk generate --project # Force single project modeSmart behavior:
- Auto-detects workspace structure
- Prompts for project selection in workspace mode
- Reads
openapi_urlfrom each project'sbgl.config.ts
Generated structure:
src/api/
├── index.ts # Main export
├── types.d.ts # TypeScript types
└── api.ts # API client
# Or with --split:
src/api/
├── endpoints/
│ ├── users.ts
│ ├── auth.ts
│ └── data.ts
├── types/
│ └── index.ts
└── index.tsnpx bgl --help
Show CLI help.
API
Runtime Functions
useWorkspace()
Get workspace configuration at runtime. Config is injected as environment variables during build.
import { useWorkspace } from '@bagelink/workspace'
const { baseURL, proxy, host, openapiUrl, mode } = useWorkspace()Returns:
interface RuntimeWorkspaceConfig {
baseURL: string // proxy if available, otherwise host
proxy?: string // '/api' (optional)
host: string // 'https://project.bagel.to'
openapiUrl?: string // optional
mode: string // current environment (e.g., 'localhost', 'development', 'staging')
}getApiUrl()
Get the full API URL by combining host and proxy.
import { getApiUrl } from '@bagelink/workspace'
const apiUrl = getApiUrl() // 'https://project.bagel.to/api'Configuration Functions
defineWorkspace(configs)
Define workspace configuration for all environments.
const workspace = defineWorkspace({
local: { host: 'http://localhost:8000', proxy: '/api' },
development: { host: 'https://project.bagel.to', proxy: '/api' },
production: { host: 'https://project.bagel.to', proxy: '/api' },
})generateWorkspaceConfig(root?, configFile?)
Interactively generate a bgl.config.ts file (called automatically when no config is found).
generateWorkspaceConfigSync(projectId, root?, configFile?, customHost?)
Generate a bgl.config.ts file programmatically.
import { generateWorkspaceConfigSync } from '@bagelink/workspace'
generateWorkspaceConfigSync('my-project')
// Creates bgl.config.ts with host: https://my-project.bagel.tocreateWorkspace(options?)
Create workspace instance with async config resolution (for advanced monorepo setups).
const workspace = createWorkspace({ root: process.cwd() })
const config = await workspace.getConfig('production')
const proxy = workspace.createProxy(config)
workspace.generateNetlify(config, './netlify.toml')Build-Time Functions
These are available from @bagelink/workspace/vite:
createViteProxy(config)
Generate Vite proxy configuration.
import { createViteProxy } from '@bagelink/workspace/vite'writeNetlifyConfig(config, outPath?, additionalConfig?)
Generate and write netlify.toml file.
import { writeNetlifyConfig } from '@bagelink/workspace/vite'setBuildEnvVars(config)
Set environment variables for build process:
BGL_PROXY_PATH- Proxy path (e.g.,/api)BGL_API_HOST- API host URLBGL_OPENAPI_URL- OpenAPI specification URL
import { setBuildEnvVars } from '@bagelink/workspace/vite'License
MIT © Bagel Studio
