@bagelink/workspace 1.7.33 → 1.7.35

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.
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Runtime workspace configuration
3
+ * Provides access to workspace config injected at build time
4
+ */
5
+ export interface RuntimeWorkspaceConfig {
6
+ /** API proxy path (e.g., '/api') */
7
+ proxy: string
8
+ /** API host URL (e.g., 'https://project.bagel.to') */
9
+ host: string
10
+ /** OpenAPI specification URL (if configured) */
11
+ openapiUrl?: string
12
+ /** Current environment mode */
13
+ mode: 'localhost' | 'development' | 'production'
14
+ }
15
+
16
+ /**
17
+ * Get workspace configuration at runtime
18
+ * Config is injected as environment variables during build
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * import { useWorkspace } from '@bagelink/workspace'
23
+ *
24
+ * const { proxy, host } = useWorkspace()
25
+ * const auth = initAuth({ baseURL: proxy })
26
+ * ```
27
+ *
28
+ * @example In Vue component
29
+ * ```vue
30
+ * <script setup>
31
+ * import { useWorkspace } from '@bagelink/workspace'
32
+ *
33
+ * const { proxy, host, mode } = useWorkspace()
34
+ * </script>
35
+ * ```
36
+ */
37
+ export function useWorkspace(): RuntimeWorkspaceConfig {
38
+ // Access env variables injected by the Vite plugin
39
+ const proxy = import.meta.env.VITE_BGL_PROXY || '/api'
40
+ const host = import.meta.env.VITE_BGL_HOST || ''
41
+ const openapiUrl = import.meta.env.VITE_BGL_OPENAPI_URL
42
+ const mode = (import.meta.env.MODE as RuntimeWorkspaceConfig['mode']) || 'development'
43
+
44
+ return {
45
+ proxy,
46
+ host,
47
+ openapiUrl,
48
+ mode,
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Get the full API URL by combining host and proxy
54
+ *
55
+ * @example
56
+ * ```ts
57
+ * import { getApiUrl } from '@bagelink/workspace'
58
+ *
59
+ * const apiUrl = getApiUrl() // 'https://project.bagel.to/api'
60
+ * ```
61
+ */
62
+ export function getApiUrl(): string {
63
+ const { host, proxy } = useWorkspace()
64
+ return `${host}${proxy}`
65
+ }
package/src/index.ts CHANGED
@@ -34,10 +34,14 @@ export {
34
34
  writeNetlifyConfig,
35
35
  }
36
36
 
37
+ export { getApiUrl, useWorkspace } from './composable'
38
+ export type { RuntimeWorkspaceConfig } from './composable'
37
39
  export { getWorkspaceInfo, isWorkspace } from './detect'
38
40
  export { runDev } from './dev'
39
41
  export { setupLint } from './lint'
40
42
  export { generateSDK, generateSDKForWorkspace } from './sdk'
43
+ export { bagelink } from './vite'
44
+ export type { BagelinkPluginOptions } from './vite'
41
45
  export { addProject, initWorkspace, listProjects } from './workspace'
42
46
 
43
47
  /**
package/src/init.ts CHANGED
@@ -233,25 +233,31 @@ function updateViteConfig(root: string): void {
233
233
  }
234
234
 
235
235
  // Ask to overwrite
236
- console.log('⚠️ vite.config.ts exists. Please manually add the workspace configuration.')
237
- console.log(' See: https://github.com/bageldb/bagelink/tree/master/packages/workspace#readme')
236
+ console.log('⚠️ vite.config.ts exists. Please manually add the bagelink plugin:')
237
+ console.log('')
238
+ console.log(' import { bagelink } from \'@bagelink/workspace/vite\'')
239
+ console.log(' import workspace from \'./bgl.config\'')
240
+ console.log('')
241
+ console.log(' plugins: [')
242
+ console.log(' vue(),')
243
+ console.log(' bagelink({ workspace }),')
244
+ console.log(' ]')
245
+ console.log('')
238
246
  return
239
247
  }
240
248
 
241
- // Create new vite.config.ts
249
+ // Create new vite.config.ts with plugin
242
250
  const viteConfigContent = `import { defineConfig } from 'vite'
243
- import { createViteProxy } from '@bagelink/workspace'
251
+ import vue from '@vitejs/plugin-vue'
252
+ import { bagelink } from '@bagelink/workspace/vite'
244
253
  import workspace from './bgl.config'
245
254
 
246
255
  // https://vitejs.dev/config/
247
- export default defineConfig(({ mode }) => {
248
- const config = workspace(mode as 'localhost' | 'development' | 'production')
249
-
250
- return {
251
- server: {
252
- proxy: createViteProxy(config),
253
- },
254
- }
256
+ export default defineConfig({
257
+ plugins: [
258
+ vue(),
259
+ bagelink({ workspace }),
260
+ ],
255
261
  })
256
262
  `
257
263
 
package/src/netlify.ts CHANGED
@@ -5,9 +5,13 @@ import process from 'node:process'
5
5
 
6
6
  /**
7
7
  * Generate netlify.toml redirect configuration
8
+ * Uses environment variables for flexibility across environments
8
9
  */
9
10
  export function generateNetlifyRedirect(config: WorkspaceConfig): string {
10
- const redirect = `[[redirects]]
11
+ const redirect = `# API Proxy Configuration
12
+ # Environment variables are set in Netlify UI or netlify.toml [build.environment] section
13
+
14
+ [[redirects]]
11
15
  from = "${config.proxy}/*"
12
16
  to = "${config.host}/:splat"
13
17
  status = 200
@@ -18,13 +22,49 @@ export function generateNetlifyRedirect(config: WorkspaceConfig): string {
18
22
  return redirect
19
23
  }
20
24
 
25
+ /**
26
+ * Generate netlify.toml with environment variable template
27
+ * Provides a standard config that can be reused across projects
28
+ */
29
+ export function generateNetlifyConfigTemplate(): string {
30
+ return `# Standard Netlify configuration for Bagelink projects
31
+ # Uses environment variables for proxy configuration
32
+
33
+ [build.environment]
34
+ # Set these in Netlify UI or override here
35
+ # BGL_PROXY_PATH = "/api"
36
+ # BGL_API_HOST = "https://your-project.bagel.to"
37
+
38
+ [[redirects]]
39
+ # Proxy API requests to backend
40
+ # Uses BGL_PROXY_PATH and BGL_API_HOST from environment
41
+ from = "/api/*"
42
+ to = "https://your-project.bagel.to/:splat"
43
+ status = 200
44
+ force = true
45
+ headers = {X-From = "Netlify"}
46
+
47
+ # Example: Multiple API backends
48
+ # [[redirects]]
49
+ # from = "/api/v2/*"
50
+ # to = "https://api-v2.example.com/:splat"
51
+ # status = 200
52
+ # force = true
53
+ `
54
+ }
55
+
21
56
  /**
22
57
  * Generate complete netlify.toml file
23
58
  */
24
59
  export function generateNetlifyConfig(
25
60
  config: WorkspaceConfig,
26
61
  additionalConfig?: string,
62
+ useTemplate: boolean = false,
27
63
  ): string {
64
+ if (useTemplate) {
65
+ return generateNetlifyConfigTemplate()
66
+ }
67
+
28
68
  const redirect = generateNetlifyRedirect(config)
29
69
 
30
70
  if (additionalConfig !== undefined && additionalConfig !== '') {
@@ -40,13 +80,24 @@ export function generateNetlifyConfig(
40
80
  export function writeNetlifyConfig(
41
81
  config: WorkspaceConfig,
42
82
  outPath: string = './netlify.toml',
43
- additionalConfig?: string
83
+ additionalConfig?: string,
84
+ useTemplate: boolean = false,
44
85
  ): void {
45
- const content = generateNetlifyConfig(config, additionalConfig)
86
+ const content = generateNetlifyConfig(config, additionalConfig, useTemplate)
46
87
  const resolvedPath = resolve(outPath)
47
88
 
48
89
  writeFileSync(resolvedPath, content, 'utf-8')
49
90
  console.log(`✓ Generated netlify.toml at ${resolvedPath}`)
91
+
92
+ if (!useTemplate) {
93
+ console.log('\n💡 Tip: For environment-based config, set these in Netlify UI:')
94
+ console.log(` BGL_PROXY_PATH = "${config.proxy}"`)
95
+ console.log(` BGL_API_HOST = "${config.host}"`)
96
+ if (config.openapi_url) {
97
+ console.log(` BGL_OPENAPI_URL = "${config.openapi_url}"`)
98
+ }
99
+ console.log('')
100
+ }
50
101
  }
51
102
 
52
103
  /**
package/src/vite.ts ADDED
@@ -0,0 +1,135 @@
1
+ import type { Plugin, ResolvedConfig } from 'vite'
2
+ import type { WorkspaceConfig, WorkspaceEnvironment } from './types'
3
+ import process from 'node:process'
4
+ import { fileURLToPath } from 'node:url'
5
+ import { createViteProxy } from './proxy'
6
+
7
+ export interface BagelinkPluginOptions {
8
+ /**
9
+ * Path to shared package relative to project
10
+ * @default '../shared'
11
+ */
12
+ sharedPath?: string
13
+
14
+ /**
15
+ * Whether to include @shared alias
16
+ * @default true
17
+ */
18
+ includeSharedAlias?: boolean
19
+
20
+ /**
21
+ * Additional path aliases beyond @ and @shared
22
+ */
23
+ additionalAliases?: Record<string, string>
24
+
25
+ /**
26
+ * Whether to auto-configure proxy
27
+ * @default true
28
+ */
29
+ configureProxy?: boolean
30
+ }
31
+
32
+ /**
33
+ * Vite plugin for Bagelink workspace integration
34
+ * Automatically configures proxy and path aliases based on bgl.config.ts
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * import { defineConfig } from 'vite'
39
+ * import vue from '@vitejs/plugin-vue'
40
+ * import { bagelink } from '@bagelink/workspace/vite'
41
+ * import workspace from './bgl.config'
42
+ *
43
+ * export default defineConfig({
44
+ * plugins: [
45
+ * vue(),
46
+ * bagelink({ workspace })
47
+ * ]
48
+ * })
49
+ * ```
50
+ *
51
+ * @example With custom options
52
+ * ```ts
53
+ * import { defineConfig } from 'vite'
54
+ * import vue from '@vitejs/plugin-vue'
55
+ * import { bagelink } from '@bagelink/workspace/vite'
56
+ * import workspace from './bgl.config'
57
+ *
58
+ * export default defineConfig({
59
+ * plugins: [
60
+ * vue(),
61
+ * bagelink({
62
+ * workspace,
63
+ * sharedPath: '../packages/shared',
64
+ * additionalAliases: {
65
+ * '@utils': fileURLToPath(new URL('./src/utils', import.meta.url))
66
+ * }
67
+ * })
68
+ * ]
69
+ * })
70
+ * ```
71
+ */
72
+ export function bagelink(options: {
73
+ workspace: (mode: WorkspaceEnvironment) => WorkspaceConfig
74
+ config?: BagelinkPluginOptions
75
+ }): Plugin {
76
+ const { workspace, config = {} } = options
77
+ let resolvedConfig: ResolvedConfig
78
+ let workspaceConfig: WorkspaceConfig
79
+
80
+ return {
81
+ name: 'vite-plugin-bagelink',
82
+ enforce: 'pre',
83
+
84
+ configResolved(resolved) {
85
+ resolvedConfig = resolved
86
+ workspaceConfig = workspace(resolved.mode as WorkspaceEnvironment)
87
+ },
88
+
89
+ config(userConfig, { mode }) {
90
+ workspaceConfig = workspace(mode as WorkspaceEnvironment)
91
+
92
+ // Build alias configuration
93
+ const alias: Record<string, string> = {}
94
+
95
+ // Add @shared alias if enabled
96
+ if (config.includeSharedAlias !== false) {
97
+ const sharedPath = config.sharedPath ?? '../shared'
98
+ // Resolve relative to the project root
99
+ alias['@shared'] = fileURLToPath(new URL(sharedPath, `file://${process.cwd()}/`))
100
+ }
101
+
102
+ // Add @ alias pointing to src
103
+ alias['@'] = fileURLToPath(new URL('./src', `file://${process.cwd()}/`))
104
+
105
+ // Add any additional aliases
106
+ if (config.additionalAliases) {
107
+ Object.assign(alias, config.additionalAliases)
108
+ }
109
+
110
+ // Build server config with proxy
111
+ const server = config.configureProxy !== false
112
+ ? {
113
+ proxy: createViteProxy(workspaceConfig),
114
+ }
115
+ : undefined
116
+
117
+ // Inject workspace config as environment variables
118
+ const define = {
119
+ 'import.meta.env.VITE_BGL_PROXY': JSON.stringify(workspaceConfig.proxy),
120
+ 'import.meta.env.VITE_BGL_HOST': JSON.stringify(workspaceConfig.host),
121
+ ...(workspaceConfig.openapi_url && {
122
+ 'import.meta.env.VITE_BGL_OPENAPI_URL': JSON.stringify(workspaceConfig.openapi_url),
123
+ }),
124
+ }
125
+
126
+ return {
127
+ resolve: {
128
+ alias,
129
+ },
130
+ define,
131
+ ...(server && { server }),
132
+ }
133
+ },
134
+ }
135
+ }
package/src/workspace.ts CHANGED
@@ -87,13 +87,27 @@ function createWorkspaceRoot(root: string, name: string, projectId: string): voi
87
87
  private: true,
88
88
  workspaces: ['*', '!node_modules'],
89
89
  scripts: {
90
- dev: 'bun scripts/dev.ts',
90
+ 'dev': 'bgl dev',
91
+ 'dev:local': 'bgl dev --mode localhost',
91
92
  'dev:verbose': 'bun run --filter \'./[!shared]*\' dev',
92
- build: 'bun run --filter \'./[!shared]*\' build',
93
- typecheck: 'tsc --noEmit',
93
+ 'build': 'bun run --filter \'./[!shared]*\' build',
94
+ 'typecheck': 'tsc --noEmit',
95
+ 'lint': 'eslint . --cache',
96
+ 'lint:fix': 'eslint . --cache --fix',
97
+ },
98
+ dependencies: {
99
+ '@bagelink/auth': 'latest',
100
+ '@bagelink/sdk': 'latest',
101
+ '@bagelink/vue': 'latest',
102
+ 'pinia': 'latest',
103
+ 'vue': 'latest',
104
+ 'vue-router': 'latest',
94
105
  },
95
106
  devDependencies: {
107
+ '@bagelink/lint-config': 'latest',
96
108
  '@bagelink/workspace': 'latest',
109
+ '@vitejs/plugin-vue': 'latest',
110
+ 'eslint': 'latest',
97
111
  'typescript': '^5.0.0',
98
112
  'vite': 'latest',
99
113
  },
@@ -372,18 +386,14 @@ export default defineWorkspace({
372
386
  // vite.config.ts
373
387
  const viteConfig = `import { defineConfig } from 'vite'
374
388
  import vue from '@vitejs/plugin-vue'
375
- import { createViteProxy } from '@bagelink/workspace'
389
+ import { bagelink } from '@bagelink/workspace/vite'
376
390
  import workspace from './bgl.config'
377
391
 
378
- export default defineConfig(({ mode }) => {
379
- const config = workspace(mode as 'localhost' | 'development' | 'production')
380
-
381
- return {
382
- plugins: [vue()],
383
- server: {
384
- proxy: createViteProxy(config),
385
- },
386
- }
392
+ export default defineConfig({
393
+ plugins: [
394
+ vue(),
395
+ bagelink({ workspace }),
396
+ ],
387
397
  })
388
398
  `
389
399