@fugood/bricks-project 2.23.0-beta.9 → 2.23.2

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.
Files changed (118) hide show
  1. package/api/instance.ts +37 -5
  2. package/compile/action-name-map.ts +107 -0
  3. package/compile/index.ts +172 -66
  4. package/compile/util.ts +13 -4
  5. package/package.json +9 -5
  6. package/skills/bricks-project/SKILL.md +32 -0
  7. package/skills/bricks-project/rules/animation.md +159 -0
  8. package/skills/bricks-project/rules/architecture-patterns.md +62 -0
  9. package/skills/bricks-project/rules/automations.md +221 -0
  10. package/skills/bricks-project/rules/buttress.md +153 -0
  11. package/skills/bricks-project/rules/data-calculation.md +208 -0
  12. package/skills/bricks-project/rules/local-sync.md +129 -0
  13. package/skills/bricks-project/rules/media-flow.md +158 -0
  14. package/skills/bricks-project/rules/remote-data-bank.md +196 -0
  15. package/skills/bricks-project/rules/standby-transition.md +124 -0
  16. package/skills/rive-marketplace/SKILL.md +99 -0
  17. package/tools/deploy.ts +74 -12
  18. package/tools/icons/.gitattributes +1 -0
  19. package/tools/icons/fa6pro-glyphmap.json +4686 -0
  20. package/tools/icons/fa6pro-meta.json +26127 -0
  21. package/tools/mcp-server.ts +818 -9
  22. package/tools/postinstall.ts +75 -13
  23. package/tools/preview-main.mjs +54 -4
  24. package/tools/preview.ts +54 -7
  25. package/tools/pull.ts +37 -16
  26. package/types/automation.ts +232 -0
  27. package/types/brick-base.ts +1 -0
  28. package/types/bricks/Camera.ts +26 -10
  29. package/types/bricks/Chart.ts +1 -0
  30. package/types/bricks/GenerativeMedia.ts +21 -3
  31. package/types/bricks/Icon.ts +1 -0
  32. package/types/bricks/Image.ts +6 -0
  33. package/types/bricks/Items.ts +1 -0
  34. package/types/bricks/Lottie.ts +1 -0
  35. package/types/bricks/Maps.ts +254 -0
  36. package/types/bricks/QrCode.ts +1 -0
  37. package/types/bricks/Rect.ts +1 -0
  38. package/types/bricks/RichText.ts +1 -0
  39. package/types/bricks/Rive.ts +1 -0
  40. package/types/bricks/Slideshow.ts +1 -0
  41. package/types/bricks/Svg.ts +1 -0
  42. package/types/bricks/Text.ts +1 -0
  43. package/types/bricks/TextInput.ts +1 -0
  44. package/types/bricks/Video.ts +1 -0
  45. package/types/bricks/VideoStreaming.ts +1 -0
  46. package/types/bricks/WebRtcStream.ts +1 -0
  47. package/types/bricks/WebView.ts +8 -1
  48. package/types/bricks/index.ts +2 -0
  49. package/types/canvas.ts +1 -0
  50. package/types/common.ts +2 -0
  51. package/types/data-calc-command.ts +7003 -0
  52. package/types/data-calc-script.ts +21 -0
  53. package/types/data-calc.ts +3 -6977
  54. package/types/data.ts +3 -0
  55. package/types/generators/AlarmClock.ts +2 -0
  56. package/types/generators/Assistant.ts +30 -6
  57. package/types/generators/BleCentral.ts +2 -0
  58. package/types/generators/BlePeripheral.ts +2 -0
  59. package/types/generators/CanvasMap.ts +2 -0
  60. package/types/generators/CastlesPay.ts +2 -0
  61. package/types/generators/DataBank.ts +2 -0
  62. package/types/generators/File.ts +2 -0
  63. package/types/generators/GraphQl.ts +2 -0
  64. package/types/generators/Http.ts +84 -2
  65. package/types/generators/HttpServer.ts +5 -1
  66. package/types/generators/Information.ts +2 -0
  67. package/types/generators/Intent.ts +51 -0
  68. package/types/generators/Iterator.ts +11 -2
  69. package/types/generators/Keyboard.ts +2 -0
  70. package/types/generators/LlmAnthropicCompat.ts +2 -0
  71. package/types/generators/LlmAppleBuiltin.ts +144 -0
  72. package/types/generators/LlmGgml.ts +28 -4
  73. package/types/generators/LlmOnnx.ts +2 -0
  74. package/types/generators/LlmOpenAiCompat.ts +2 -0
  75. package/types/generators/LlmQualcommAiEngine.ts +2 -0
  76. package/types/generators/Mcp.ts +6 -4
  77. package/types/generators/McpServer.ts +8 -6
  78. package/types/generators/MediaFlow.ts +2 -0
  79. package/types/generators/MqttBroker.ts +2 -0
  80. package/types/generators/MqttClient.ts +2 -0
  81. package/types/generators/Question.ts +9 -0
  82. package/types/generators/RealtimeTranscription.ts +18 -8
  83. package/types/generators/RerankerGgml.ts +23 -16
  84. package/types/generators/SerialPort.ts +2 -0
  85. package/types/generators/SoundPlayer.ts +2 -0
  86. package/types/generators/SoundRecorder.ts +2 -0
  87. package/types/generators/SpeechToTextGgml.ts +19 -4
  88. package/types/generators/SpeechToTextOnnx.ts +2 -0
  89. package/types/generators/SpeechToTextPlatform.ts +2 -0
  90. package/types/generators/SqLite.ts +32 -1
  91. package/types/generators/Step.ts +2 -0
  92. package/types/generators/SttAppleBuiltin.ts +117 -0
  93. package/types/generators/Tcp.ts +2 -0
  94. package/types/generators/TcpServer.ts +5 -1
  95. package/types/generators/TextToSpeechApple.ts +113 -0
  96. package/types/generators/TextToSpeechAppleBuiltin.ts +114 -0
  97. package/types/generators/TextToSpeechGgml.ts +24 -3
  98. package/types/generators/TextToSpeechOnnx.ts +2 -0
  99. package/types/generators/TextToSpeechOpenAiLike.ts +2 -0
  100. package/types/generators/ThermalPrinter.ts +2 -0
  101. package/types/generators/Tick.ts +5 -1
  102. package/types/generators/TtsAppleBuiltin.ts +105 -0
  103. package/types/generators/Udp.ts +2 -0
  104. package/types/generators/VadGgml.ts +4 -2
  105. package/types/generators/VadOnnx.ts +201 -0
  106. package/types/generators/VadTraditional.ts +123 -0
  107. package/types/generators/VectorStore.ts +15 -2
  108. package/types/generators/Watchdog.ts +2 -0
  109. package/types/generators/WebCrawler.ts +2 -0
  110. package/types/generators/WebRtc.ts +4 -2
  111. package/types/generators/WebSocket.ts +2 -0
  112. package/types/generators/index.ts +5 -0
  113. package/types/index.ts +3 -0
  114. package/types/system.ts +48 -6
  115. package/utils/calc.ts +15 -9
  116. package/utils/data.ts +1 -0
  117. package/utils/event-props.ts +112 -2
  118. package/utils/id.ts +3 -1
@@ -0,0 +1,196 @@
1
+ # Remote Data Bank
2
+
3
+ Cloud-synchronized Data Bank for real-time data sharing across devices and external API access.
4
+
5
+ ## Remote Update Types
6
+
7
+ The `remoteUpdate` field configures cloud synchronization:
8
+
9
+ ```typescript
10
+ remoteUpdate?:
11
+ | { type: 'auto' } // Sync across all devices
12
+ | { type: 'device-specific' } // Isolated per device
13
+ | { type: 'global-data', id: string } // Cross-application global data
14
+ ```
15
+
16
+ ### Auto Sync
17
+
18
+ Sync across all devices using the same application.
19
+
20
+ ```typescript
21
+ import { makeId } from 'bricks-project'
22
+
23
+ const data: Data = {
24
+ __typename: 'Data',
25
+ id: makeId('data'),
26
+ title: 'Announcement',
27
+ type: 'string',
28
+ value: '',
29
+ remoteUpdate: { type: 'auto' },
30
+ events: {},
31
+ }
32
+ ```
33
+
34
+ ### Global Data
35
+
36
+ Share data across different applications. Must create Global Data first on BANK page.
37
+
38
+ ```typescript
39
+ import { makeId } from 'bricks-project'
40
+
41
+ const data: Data = {
42
+ __typename: 'Data',
43
+ id: makeId('data'),
44
+ title: 'Global Config',
45
+ type: 'object',
46
+ value: {},
47
+ remoteUpdate: { type: 'global-data', id: 'workspace-global-config-id' },
48
+ events: {},
49
+ }
50
+ ```
51
+
52
+ ### Device Specific
53
+
54
+ Isolate data per device while still allowing web page control.
55
+
56
+ ```typescript
57
+ import { makeId } from 'bricks-project'
58
+
59
+ const data: Data = {
60
+ __typename: 'Data',
61
+ id: makeId('data'),
62
+ title: 'Device Message',
63
+ type: 'string',
64
+ value: '',
65
+ remoteUpdate: { type: 'device-specific' },
66
+ events: {},
67
+ }
68
+ ```
69
+
70
+ Use case: Control individual displays from a shared web interface without affecting other devices.
71
+
72
+ ## External Access
73
+
74
+ ### Web Update Page
75
+
76
+ Generate a web page for non-technical users to update data:
77
+
78
+ 1. Visit BANK page
79
+ 2. Click `Manage Keys`
80
+ 3. Select `Generate Key used by Update Page`
81
+ 4. Share the generated link
82
+
83
+ The page has independent permissions and can be shared with content managers.
84
+
85
+ ### API Access
86
+
87
+ Programmatic data updates via REST API.
88
+
89
+ **Setup:**
90
+ 1. Visit BANK page → Manage Keys
91
+ 2. Create API key with appropriate permissions
92
+ 3. Use key in API requests
93
+
94
+ **Example API Usage:**
95
+
96
+ ```bash
97
+ # Update a property
98
+ curl -X POST https://api.bricks.tools/v1/bank/update \
99
+ -H "Authorization: Bearer YOUR_API_KEY" \
100
+ -H "Content-Type: application/json" \
101
+ -d '{
102
+ "applicationId": "app-id",
103
+ "propertyId": "announcement",
104
+ "value": "New announcement text"
105
+ }'
106
+
107
+ # Get property value
108
+ curl https://api.bricks.tools/v1/bank/get \
109
+ -H "Authorization: Bearer YOUR_API_KEY" \
110
+ -G \
111
+ -d "applicationId=app-id" \
112
+ -d "propertyId=announcement"
113
+ ```
114
+
115
+ ## Data Routing
116
+
117
+ Cross-subspace data sharing with access control.
118
+
119
+ ```typescript
120
+ const routedData: Data = {
121
+ __typename: 'Data',
122
+ id: 'shared-state',
123
+ type: 'object',
124
+ routing: 'read-only', // 'read-only' | default (read-write)
125
+ // When read-only: only accepts changes from same subspace
126
+ // Default: accepts changes from any subspace
127
+ }
128
+ ```
129
+
130
+ ## Use Cases
131
+
132
+ ### Digital Signage Content Management
133
+
134
+ ```typescript
135
+ import { makeId } from 'bricks-project'
136
+
137
+ // Remote-updated announcement
138
+ const announcement: Data = {
139
+ __typename: 'Data',
140
+ id: makeId('data'),
141
+ title: 'Announcement',
142
+ type: 'object',
143
+ value: { title: '', body: '', enabled: false },
144
+ remoteUpdate: { type: 'auto' },
145
+ events: {},
146
+ }
147
+ ```
148
+
149
+ Operator updates content via web page → All displays update in real-time.
150
+
151
+ ### Multi-Location Coordination
152
+
153
+ ```typescript
154
+ import { makeId } from 'bricks-project'
155
+
156
+ // Global data shared across locations
157
+ const globalConfig: Data = {
158
+ __typename: 'Data',
159
+ id: makeId('data'),
160
+ title: 'Brand Config',
161
+ type: 'object',
162
+ value: {},
163
+ remoteUpdate: { type: 'global-data', id: 'brand-config-global' },
164
+ events: {},
165
+ }
166
+ ```
167
+
168
+ Update once → All locations receive update.
169
+
170
+ ### Per-Device Customization
171
+
172
+ ```typescript
173
+ import { makeId } from 'bricks-project'
174
+
175
+ // Device-specific greeting
176
+ const deviceGreeting: Data = {
177
+ __typename: 'Data',
178
+ id: makeId('data'),
179
+ title: 'Greeting',
180
+ type: 'string',
181
+ value: '',
182
+ remoteUpdate: { type: 'device-specific' },
183
+ events: {},
184
+ }
185
+ ```
186
+
187
+ Each display shows different greeting, controlled from single dashboard.
188
+
189
+ ## Best Practices
190
+
191
+ 1. **Minimize remote data**: Only enable for data that truly needs cloud sync
192
+ 2. **Use device-specific wisely**: Good for personalization, not for shared state
193
+ 3. **API key security**: Use scoped keys with minimal permissions
194
+ 4. **Offline resilience**: Design for temporary disconnection
195
+ 5. **Batch updates**: Group related changes to reduce API calls
196
+ 6. **Global data governance**: Establish clear ownership for global data keys
@@ -0,0 +1,124 @@
1
+ # Standby Transition
2
+
3
+ Easy-to-configure animation for Bricks based on Canvas render/change. Provides smooth enter animations when bricks appear and position transitions when canvas changes.
4
+
5
+ ## How It Works
6
+
7
+ Two transition cases:
8
+ 1. **First Render**: Run position transition based on `standbyMode` setting
9
+ 2. **Canvas Change**: Existing bricks animate to new positions instead of re-rendering
10
+
11
+ ## Configuration
12
+
13
+ Standby transition is configured in the **canvas item frame**, not the brick itself.
14
+
15
+ ### Standby Mode
16
+
17
+ | Mode | Description |
18
+ |------|-------------|
19
+ | `top` | Slide in from top |
20
+ | `bottom` | Slide in from bottom |
21
+ | `left` | Slide in from left |
22
+ | `right` | Slide in from right |
23
+ | `custom` | Use custom `standbyFrame` values |
24
+
25
+ ### Frame Options
26
+
27
+ | Option | Description |
28
+ |--------|-------------|
29
+ | `standbyMode` | Direction or `'custom'` |
30
+ | `standbyFrame` | Custom start frame `{ x?, y?, width?, height? }` |
31
+ | `standbyOpacity` | Start opacity (0.0 - 1.0) |
32
+ | `standbyDelay` | Delay before transition starts (ms) |
33
+ | `standbyDelayRandom` | Random delay variance (ms) |
34
+ | `standbyEasing` | Per-property easing config |
35
+
36
+ ### Easing Configuration
37
+
38
+ ```typescript
39
+ standbyEasing: {
40
+ default?: { method: Easing, duration: number },
41
+ x?: { method: Easing, duration: number },
42
+ y?: { method: Easing, duration: number },
43
+ width?: { method: Easing, duration: number },
44
+ height?: { method: Easing, duration: number },
45
+ opacity?: { method: Easing, duration: number },
46
+ }
47
+ ```
48
+
49
+ ## TypeScript Example
50
+
51
+ ```typescript
52
+ import { makeId } from 'bricks-project'
53
+
54
+ const canvas: Canvas = {
55
+ __typename: 'Canvas',
56
+ id: makeId('canvas'),
57
+ title: 'Home',
58
+ description: '',
59
+ property: {
60
+ backgroundColor: '#ffffff',
61
+ },
62
+ events: {},
63
+ switches: [],
64
+ items: [
65
+ {
66
+ item: () => heroCard,
67
+ frame: {
68
+ x: 100,
69
+ y: 50,
70
+ width: 400,
71
+ height: 300,
72
+ // Standby transition config
73
+ standbyMode: 'bottom',
74
+ standbyOpacity: 0,
75
+ standbyDelay: 100,
76
+ standbyEasing: {
77
+ default: { method: 'easeOutCubic', duration: 400 },
78
+ opacity: { method: 'easeOutQuad', duration: 300 },
79
+ },
80
+ },
81
+ },
82
+ ],
83
+ }
84
+ ```
85
+
86
+ ## Canvas Change Transition
87
+
88
+ When navigating between canvases, bricks with the same ID smoothly transition:
89
+ - Position interpolates from old to new location
90
+ - Size interpolates if dimensions change
91
+ - Opacity interpolates if visibility changes
92
+
93
+ This creates a "shared element transition" effect.
94
+
95
+ ## Related Events
96
+
97
+ - `standby`: Triggered when brick completes standby transition
98
+
99
+ ```typescript
100
+ // In brick definition
101
+ events: {
102
+ standby: [
103
+ {
104
+ handler: 'system',
105
+ action: {
106
+ __actionName: 'DYNAMIC_ANIMATION',
107
+ parent: 'System',
108
+ params: [
109
+ { input: 'brickId', value: () => heroCard },
110
+ { input: 'animationId', value: () => pulseAnimation },
111
+ ],
112
+ },
113
+ },
114
+ ],
115
+ }
116
+ ```
117
+
118
+ ## Best Practices
119
+
120
+ 1. **Stagger delays**: Use incremental delays for list items (e.g., 0, 50, 100ms)
121
+ 2. **Keep it short**: 200-400ms transitions feel responsive
122
+ 3. **Match content**: Use directional transitions that match scroll direction
123
+ 4. **Opacity for polish**: Combine position transition with opacity fade
124
+ 5. **Same-ID trick**: Reuse brick IDs across canvases for smooth transitions
@@ -0,0 +1,99 @@
1
+ ---
2
+ name: rive-marketplace
3
+ description: Search and download assets from Rive Marketplace. Use when searching for Rive animations, downloading .riv files, or exploring Rive community assets. Supports keyword search, tag browsing, and direct file downloads via public API. Requires browser tool for searching; API calls work without browser.
4
+ ---
5
+
6
+ # Rive Marketplace
7
+
8
+ Download animated assets (.riv files) from Rive's community marketplace.
9
+
10
+ ## URL Structure
11
+
12
+ - **Featured**: `https://rive.app/marketplace/featured/`
13
+ - **Latest**: `https://rive.app/marketplace/latest/`
14
+ - **Search**: `https://rive.app/marketplace/search/{query}/`
15
+ - **Tags**: `https://rive.app/marketplace/tag/{TagName}/`
16
+ - **Item**: `https://rive.app/marketplace/{post_id}-{revision_id}-{slug}/`
17
+
18
+ ## API (Public, No Auth)
19
+
20
+ ### Get Post Details
21
+ ```bash
22
+ curl -s "https://api.rive.app/api/community-posts/{post_id}" | jq '.'
23
+ ```
24
+
25
+ **Response contains:**
26
+ - `community_post_id` — Post ID
27
+ - `owner.username` — Creator name
28
+ - `community_revisions[0].title` — Asset title
29
+ - `community_revisions[0].description` — Description
30
+ - `community_revisions[0].tags` — Tags array
31
+ - `community_revisions[0].community_files[0].file_url` — **Download URL**
32
+
33
+ ### Download .riv File
34
+ ```bash
35
+ # Extract file_url from API response
36
+ curl -s "https://api.rive.app/api/community-posts/{post_id}" | jq -r '.community_revisions[0].community_files[0].file_url'
37
+
38
+ # Download directly
39
+ curl -O "https://public.rive.app/community/runtime-files/{post_id}-{revision_id}-{slug}.riv"
40
+ ```
41
+
42
+ ## Workflow: Search → Download
43
+
44
+ ### 1. Browse via Browser (profile=clawd)
45
+ ```
46
+ Open: https://rive.app/marketplace/search/{keyword}/
47
+ ```
48
+
49
+ ### 2. Get Post ID from URL
50
+ Item URL format: `/marketplace/{post_id}-{revision_id}-{slug}/`
51
+ Example: `/marketplace/1683-3324-like-button/` → post_id = **1683**
52
+
53
+ ### 3. Fetch Download URL via API
54
+ ```bash
55
+ curl -s "https://api.rive.app/api/community-posts/1683" | jq -r '.community_revisions[0].community_files[0].file_url'
56
+ # Output: https://public.rive.app/community/runtime-files/1683-3324-like-button.riv
57
+ ```
58
+
59
+ ### 4. Download File
60
+ ```bash
61
+ curl -O "https://public.rive.app/community/runtime-files/1683-3324-like-button.riv"
62
+ ```
63
+
64
+ ## Example: Full Flow
65
+
66
+ ```bash
67
+ # Search for "button" assets, pick one, get post_id from URL
68
+ POST_ID=1683
69
+
70
+ # Get file URL
71
+ FILE_URL=$(curl -s "https://api.rive.app/api/community-posts/$POST_ID" | jq -r '.community_revisions[0].community_files[0].file_url')
72
+
73
+ # Download
74
+ curl -o "my-button.riv" "$FILE_URL"
75
+ ```
76
+
77
+ ## Batch Download Script
78
+
79
+ ```bash
80
+ #!/bin/bash
81
+ # Download multiple Rive assets by post IDs
82
+ for POST_ID in 1683 3548 3703; do
83
+ FILE_URL=$(curl -s "https://api.rive.app/api/community-posts/$POST_ID" | jq -r '.community_revisions[0].community_files[0].file_url')
84
+ FILENAME=$(basename "$FILE_URL")
85
+ echo "Downloading $FILENAME..."
86
+ curl -sO "$FILE_URL"
87
+ done
88
+ ```
89
+
90
+ ## License
91
+
92
+ All Marketplace files are shared under **CC BY** (Creative Commons Attribution 4.0).
93
+ Attribution required when using assets.
94
+
95
+ ## Notes
96
+
97
+ - No official search API; browse via browser or scrape search results
98
+ - API is public but undocumented; may change without notice
99
+ - Remix/Like/Comment requires authentication
package/tools/deploy.ts CHANGED
@@ -1,8 +1,21 @@
1
1
  import { $ } from 'bun'
2
- import { deployApp, deployModule } from '../api'
2
+ import { parseArgs } from 'util'
3
3
 
4
4
  const cwd = process.cwd()
5
5
 
6
+ const {
7
+ values: { changelogs: changelogsArg, 'changelogs-file': changelogsFile, yes },
8
+ } = parseArgs({
9
+ args: Bun.argv.slice(2),
10
+ options: {
11
+ changelogs: { type: 'string' },
12
+ 'changelogs-file': { type: 'string' },
13
+ yes: { type: 'boolean', short: 'y' },
14
+ },
15
+ allowPositionals: true,
16
+ })
17
+
18
+ // Check git status
6
19
  const { exitCode } = await $`cd ${cwd} && git status`.nothrow()
7
20
  const isGitRepo = exitCode === 0
8
21
 
@@ -13,23 +26,72 @@ if (isGitRepo) {
13
26
  throw new Error('Unstaged changes found, please commit or stash your changes before deploying')
14
27
 
15
28
  commitId = (await $`cd ${cwd} && git rev-parse HEAD`.text()).trim()
16
- } else {
29
+ } else if (!yes) {
17
30
  const confirmContinue = prompt('No git repository found, continue? (y/n)')
18
31
  if (confirmContinue !== 'y') throw new Error('Deployment cancelled')
19
32
  }
20
33
 
34
+ // Read application.json
21
35
  const app = await Bun.file(`${cwd}/application.json`).json()
22
- const stage = app.stage || 'production'
23
36
  const config = await Bun.file(`${cwd}/.bricks/build/application-config.json`).json()
24
37
 
25
- // ask for confirmation
26
- const confirm = prompt('Are you sure you want to deploy? (y/n)')
27
- if (confirm !== 'y') throw new Error('Deployment cancelled')
38
+ // Get version from project's package.json
39
+ const pkgFile = Bun.file(`${cwd}/package.json`)
40
+ const version = (await pkgFile.exists()) ? (await pkgFile.json()).version : undefined
41
+
42
+ // Get changelog from flag or file
43
+ let changelogs = ''
44
+ if (changelogsArg) {
45
+ changelogs = changelogsArg
46
+ } else if (changelogsFile) {
47
+ const file = Bun.file(changelogsFile)
48
+ if (!(await file.exists())) {
49
+ throw new Error(`Changelogs file not found: ${changelogsFile}`)
50
+ }
51
+ changelogs = await file.text()
52
+ } else if (!yes) {
53
+ changelogs = prompt('Enter changelogs (optional, press Enter to skip):') || ''
54
+ }
55
+
56
+ // Ask for confirmation
57
+ if (!yes) {
58
+ const confirm = prompt('Are you sure you want to deploy? (y/n)')
59
+ if (confirm !== 'y') throw new Error('Deployment cancelled')
60
+ }
61
+
62
+ const isModule = app.type === 'module'
63
+ const command = isModule ? 'module' : 'app'
28
64
 
29
- if (!app.type || app.type === 'application') {
30
- await deployApp(stage, app.id, config, commitId)
31
- console.log('App deployed')
32
- } else if (app.type === 'module') {
33
- await deployModule(stage, app.id, config, commitId)
34
- console.log('Module deployed')
65
+ // Add project-specific fields to config and write to temp file
66
+ const releaseConfig = {
67
+ ...config,
68
+ title: version || config.title,
69
+ bricks_project_last_commit_id: commitId || undefined,
35
70
  }
71
+ const configPath = `${cwd}/.bricks/build/release-config.json`
72
+ await Bun.write(configPath, JSON.stringify(releaseConfig))
73
+
74
+ const args = ['bricks', command, 'release', app.id, '-c', configPath, '--json']
75
+
76
+ if (version) {
77
+ args.push('--version', version)
78
+ }
79
+
80
+ if (changelogs) {
81
+ args.push('--changelogs', changelogs)
82
+ }
83
+
84
+ const result = await $`${args}`.quiet().nothrow()
85
+
86
+ if (result.exitCode !== 0) {
87
+ const output = result.stderr.toString() || result.stdout.toString()
88
+ try {
89
+ const json = JSON.parse(output)
90
+ throw new Error(json.error || 'Release failed')
91
+ } catch {
92
+ throw new Error(output || 'Release failed')
93
+ }
94
+ }
95
+
96
+ const output = JSON.parse(result.stdout.toString())
97
+ console.log(`${isModule ? 'Module' : 'App'} deployed: ${output.name}`)
@@ -0,0 +1 @@
1
+ * text=auto eol=lf