@fugood/bricks-project 2.21.0-beta.14.test5 → 2.21.0-beta.14.test7
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.
- package/api/instance.ts +115 -40
- package/compile/action-name-map.ts +502 -0
- package/compile/index.ts +39 -35
- package/compile/util.ts +2 -2
- package/index.ts +3 -8
- package/package.json +1 -1
- package/tools/deploy.ts +24 -0
- package/tools/postinstall.ts +12 -0
- package/tools/preview-main.mjs +7 -4
- package/tools/preview.ts +31 -14
- package/tools/pull.ts +51 -0
- package/types/common.ts +3 -3
- package/types/switch.ts +8 -5
- package/utils/calc.ts +118 -0
- package/utils/data.ts +397 -0
- package/{uuid.ts → utils/id.ts} +26 -10
package/index.ts
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
export type * from './types'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export {
|
|
6
|
-
|
|
7
|
-
export const linkData: ((dataGetter: () => Data) => DataLink) = (dataGetter) => ({
|
|
8
|
-
__typename: 'DataLink',
|
|
9
|
-
data: dataGetter,
|
|
10
|
-
})
|
|
3
|
+
export { makeId } from './utils/id'
|
|
4
|
+
export { generateDataCalculationMapEditorInfo } from './utils/calc'
|
|
5
|
+
export { linkData, useSystemData } from './utils/data'
|
package/package.json
CHANGED
package/tools/deploy.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { $ } from 'bun'
|
|
2
|
+
import { deployApp, deployModule } from '../api'
|
|
3
|
+
|
|
4
|
+
const cwd = process.cwd()
|
|
5
|
+
|
|
6
|
+
const unstagedChanges = await $`cd ${cwd} && git diff --name-only --diff-filter=ACMR`.text()
|
|
7
|
+
if (unstagedChanges) throw new Error('Unstaged changes found, please commit or stash your changes before deploying')
|
|
8
|
+
|
|
9
|
+
const commitId = (await $`cd ${cwd} && git rev-parse HEAD`.text()).trim()
|
|
10
|
+
const app = await Bun.file(`${cwd}/application.json`).json()
|
|
11
|
+
const stage = app.stage || 'production'
|
|
12
|
+
const config = await Bun.file(`${cwd}/.bricks/build/application-config.json`).json()
|
|
13
|
+
|
|
14
|
+
// ask for confirmation
|
|
15
|
+
const confirm = prompt('Are you sure you want to deploy? (y/n)')
|
|
16
|
+
if (confirm !== 'y') throw new Error('Deployment cancelled')
|
|
17
|
+
|
|
18
|
+
if (!app.type || app.type === 'application') {
|
|
19
|
+
await deployApp(stage, app.id, config, commitId)
|
|
20
|
+
console.log('App deployed')
|
|
21
|
+
} else if (app.type === 'module') {
|
|
22
|
+
await deployModule(stage, app.id, config, commitId)
|
|
23
|
+
console.log('Module deployed')
|
|
24
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { $ } from 'bun'
|
|
2
|
+
|
|
3
|
+
const cwd = process.cwd()
|
|
4
|
+
|
|
5
|
+
const libFiles = ['types', 'utils', 'index.ts']
|
|
6
|
+
|
|
7
|
+
await $`mkdir -p ${cwd}/project`
|
|
8
|
+
for (const file of libFiles) {
|
|
9
|
+
await $`cp -r ${__dirname}/../${file} ${cwd}/project`
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
console.log('Copied files to project/')
|
package/tools/preview-main.mjs
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
1
2
|
import { app, BrowserWindow } from 'electron'
|
|
2
3
|
import { readFile } from 'fs/promises'
|
|
3
4
|
import { watchFile } from 'fs'
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
const cwd = process.cwd()
|
|
7
|
+
|
|
8
|
+
let config = JSON.parse(await readFile(`${cwd}/.bricks/build/application-config.json`))
|
|
6
9
|
|
|
7
10
|
const stage = process.env.BRICKS_STAGE || 'production'
|
|
8
11
|
|
|
9
12
|
const previewUrlMap = {
|
|
10
13
|
production: 'https://control.bricks.tools/applicationPreview.html',
|
|
11
14
|
beta: 'https://control-beta.bricks.tools/applicationPreview.html',
|
|
12
|
-
|
|
15
|
+
development: 'http://localhost:3006/dev-applicationPreview.html',
|
|
13
16
|
}
|
|
14
17
|
|
|
15
18
|
const previewUrl = previewUrlMap[stage]
|
|
@@ -33,7 +36,7 @@ app.on('ready', () => {
|
|
|
33
36
|
mainWindow.webContents.once('dom-ready', sendConfig)
|
|
34
37
|
|
|
35
38
|
watchFile(
|
|
36
|
-
|
|
39
|
+
`${cwd}/.bricks/build/application-config.json`,
|
|
37
40
|
{
|
|
38
41
|
bigint: false,
|
|
39
42
|
persistent: true,
|
|
@@ -41,7 +44,7 @@ app.on('ready', () => {
|
|
|
41
44
|
},
|
|
42
45
|
async () => {
|
|
43
46
|
console.log('Detected config changed')
|
|
44
|
-
config = JSON.parse(await readFile(
|
|
47
|
+
config = JSON.parse(await readFile(`${cwd}/.bricks/build/application-config.json`))
|
|
45
48
|
sendConfig()
|
|
46
49
|
},
|
|
47
50
|
)
|
package/tools/preview.ts
CHANGED
|
@@ -1,20 +1,37 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { watch
|
|
1
|
+
import { $ } from 'bun'
|
|
2
|
+
import { watch } from 'fs'
|
|
3
|
+
import { parseArgs } from 'util'
|
|
3
4
|
import { debounce } from 'lodash'
|
|
4
5
|
|
|
5
|
-
const
|
|
6
|
+
const { values } = parseArgs({
|
|
7
|
+
args: Bun.argv,
|
|
8
|
+
options: {
|
|
9
|
+
'skip-typecheck': {
|
|
10
|
+
type: 'boolean',
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
strict: true,
|
|
14
|
+
allowPositionals: true,
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
const useTypecheck = !values['skip-typecheck']
|
|
6
18
|
|
|
7
|
-
const compile =
|
|
19
|
+
const compile = async () => {
|
|
20
|
+
if (useTypecheck) await $`bun typecheck`
|
|
8
21
|
await $`bun compile`
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
await compile()
|
|
25
|
+
|
|
26
|
+
const compileDebounced = debounce(compile, 500)
|
|
27
|
+
|
|
28
|
+
const cwd = process.cwd()
|
|
29
|
+
|
|
30
|
+
watch(`${cwd}/subspaces`, { recursive: true }, async (event, filename) => {
|
|
31
|
+
console.log(`Detected ${event} in ${filename}`)
|
|
32
|
+
compileDebounced()
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
const app = await Bun.file(`${cwd}/application.json`).json()
|
|
19
36
|
|
|
20
37
|
await $`BRICKS_STAGE=${app.stage || 'production'} bunx electron ${__dirname}/preview-main.mjs`
|
package/tools/pull.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { $ } from 'bun'
|
|
2
|
+
import { format } from 'prettier'
|
|
3
|
+
import { pullApplicationProject, pullModuleProject } from '../api'
|
|
4
|
+
|
|
5
|
+
const cwd = process.cwd()
|
|
6
|
+
|
|
7
|
+
const unstagedChanges = await $`cd ${cwd} && git diff --name-only --diff-filter=ACMR`.text()
|
|
8
|
+
if (unstagedChanges)
|
|
9
|
+
throw new Error('Unstaged changes found, please commit or stash your changes before deploying')
|
|
10
|
+
|
|
11
|
+
const app = await Bun.file(`${cwd}/application.json`).json()
|
|
12
|
+
const stage = app.stage || 'production'
|
|
13
|
+
const { files, lastCommitId } =
|
|
14
|
+
app.type === 'module'
|
|
15
|
+
? await pullModuleProject(stage, app.id)
|
|
16
|
+
: await pullApplicationProject(stage, app.id)
|
|
17
|
+
|
|
18
|
+
const found = (await $`cd ${cwd} && git rev-list -1 ${lastCommitId}`.nothrow().text())
|
|
19
|
+
.trim()
|
|
20
|
+
.match(/^[a-f0-9]{40}$/)
|
|
21
|
+
|
|
22
|
+
const commitId = (await $`cd ${cwd} && git rev-parse HEAD`.text()).trim()
|
|
23
|
+
|
|
24
|
+
if (commitId === lastCommitId) throw new Error('Commit not changed')
|
|
25
|
+
|
|
26
|
+
const branchName = 'BRICKS_PROJECT_try-pull-application'
|
|
27
|
+
|
|
28
|
+
await $`cd ${cwd} && git branch -D ${branchName}`.nothrow()
|
|
29
|
+
|
|
30
|
+
let useMain = false
|
|
31
|
+
if (found) {
|
|
32
|
+
await $`cd ${cwd} && git checkout -b ${branchName} ${lastCommitId}`.nothrow()
|
|
33
|
+
} else {
|
|
34
|
+
await $`cd ${cwd} && git checkout -b ${branchName}`
|
|
35
|
+
useMain = true
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
await Promise.all(
|
|
39
|
+
files.map(async (file) =>
|
|
40
|
+
Bun.write(
|
|
41
|
+
`${cwd}/${file.name}`,
|
|
42
|
+
file.formatable ? await format(file.input, { parser: 'typescript' }) : file.input,
|
|
43
|
+
),
|
|
44
|
+
),
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
await $`cd ${cwd} && git add .`
|
|
48
|
+
await $`cd ${cwd} && git commit -m 'Apply ${app.name} file changes'`
|
|
49
|
+
if (!useMain) {
|
|
50
|
+
await $`cd ${cwd} && git merge main`
|
|
51
|
+
}
|
package/types/common.ts
CHANGED
|
@@ -12,7 +12,7 @@ export interface Brick {
|
|
|
12
12
|
events: {}
|
|
13
13
|
outlets?: {}
|
|
14
14
|
animation?: {}
|
|
15
|
-
switches
|
|
15
|
+
switches?: Array<SwitchDef>
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export enum LocalSyncStrategy {
|
|
@@ -30,7 +30,7 @@ export interface Generator {
|
|
|
30
30
|
property?: {}
|
|
31
31
|
events: {}
|
|
32
32
|
outlets?: {}
|
|
33
|
-
switches
|
|
33
|
+
switches?: Array<SwitchDef>
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
export type SubspaceID = string
|
|
@@ -103,7 +103,7 @@ export type ApplicationSettings = {
|
|
|
103
103
|
borderBottomLeftRadius?: number
|
|
104
104
|
borderBottomRightRadius?: number
|
|
105
105
|
}
|
|
106
|
-
}
|
|
106
|
+
}
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
export type Application = {
|
package/types/switch.ts
CHANGED
|
@@ -36,10 +36,13 @@ export interface SwitchDef {
|
|
|
36
36
|
animation?: {}
|
|
37
37
|
conds?: Array<{
|
|
38
38
|
method: '==' | '!=' | '>' | '<' | '>=' | '<='
|
|
39
|
-
cond:
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
cond:
|
|
40
|
+
| SwitchCondInnerStateCurrentCanvas
|
|
41
|
+
| SwitchCondData
|
|
42
|
+
| {
|
|
43
|
+
__typename: 'SwitchCondInnerStateOutlet'
|
|
44
|
+
outlet: string
|
|
45
|
+
value: any
|
|
46
|
+
}
|
|
44
47
|
}>
|
|
45
48
|
}
|
package/utils/calc.ts
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import type { DataCalculationMap, DataCalculationData, DataCommand } from '../types/data-calc'
|
|
2
|
+
|
|
3
|
+
const GRID = {
|
|
4
|
+
WIDTH: 300, // Distance between columns
|
|
5
|
+
HEIGHT: 150, // Distance between rows
|
|
6
|
+
PADDING: 15, // Edge padding
|
|
7
|
+
COLUMNS: 4, // Max columns in grid
|
|
8
|
+
ROWS: 3, // Max rows in grid
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// TODO: Improve the algorithm to minimize crossing lines
|
|
12
|
+
|
|
13
|
+
// If we are too lazy to describe nodes in the editing interface,
|
|
14
|
+
// we can let it generate it automatically
|
|
15
|
+
export const generateDataCalculationMapEditorInfo = (
|
|
16
|
+
nodes: Array<DataCalculationData | DataCommand>,
|
|
17
|
+
) => {
|
|
18
|
+
const editorInfo: DataCalculationMap['editorInfo'] = []
|
|
19
|
+
|
|
20
|
+
// Track node relationships
|
|
21
|
+
const inputCounts = new Map<DataCalculationData | DataCommand, number>()
|
|
22
|
+
const outputCounts = new Map<DataCalculationData | DataCommand, number>()
|
|
23
|
+
const connectedTo = new Map<
|
|
24
|
+
DataCalculationData | DataCommand,
|
|
25
|
+
Set<DataCalculationData | DataCommand>
|
|
26
|
+
>()
|
|
27
|
+
|
|
28
|
+
// Analyze node connections
|
|
29
|
+
nodes.forEach((node) => {
|
|
30
|
+
// Count and track inputs
|
|
31
|
+
if ('inputs' in node) {
|
|
32
|
+
const inputs = node.inputs
|
|
33
|
+
.filter((input) => input !== null)
|
|
34
|
+
.map((input) => (Array.isArray(input) ? input.length : 1))
|
|
35
|
+
.reduce((sum, count) => sum + count, 0)
|
|
36
|
+
inputCounts.set(node, inputs)
|
|
37
|
+
|
|
38
|
+
// Track connections
|
|
39
|
+
node.inputs.forEach((input) => {
|
|
40
|
+
if (Array.isArray(input)) {
|
|
41
|
+
input.forEach((conn) => {
|
|
42
|
+
if (!connectedTo.has(node)) {
|
|
43
|
+
connectedTo.set(node, new Set())
|
|
44
|
+
}
|
|
45
|
+
const sourceNode = nodes.find((n) => 'id' in n && n.id === conn.id)
|
|
46
|
+
if (sourceNode) {
|
|
47
|
+
connectedTo.get(node)!.add(sourceNode)
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
} else {
|
|
53
|
+
inputCounts.set(node, 0)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Count outputs
|
|
57
|
+
if ('outputs' in node) {
|
|
58
|
+
const outputs = node.outputs
|
|
59
|
+
.filter((output) => output !== null)
|
|
60
|
+
.map((output) => (Array.isArray(output) ? output.length : 1))
|
|
61
|
+
.reduce((sum, count) => sum + count, 0)
|
|
62
|
+
outputCounts.set(node, outputs)
|
|
63
|
+
} else {
|
|
64
|
+
outputCounts.set(node, 0)
|
|
65
|
+
}
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
// Calculate layers
|
|
69
|
+
const layers: Array<Array<DataCalculationData | DataCommand>> = [[], [], [], []]
|
|
70
|
+
|
|
71
|
+
nodes.forEach((node) => {
|
|
72
|
+
const inputs = inputCounts.get(node) || 0
|
|
73
|
+
const outputs = outputCounts.get(node) || 0
|
|
74
|
+
const connections = connectedTo.get(node)?.size || 0
|
|
75
|
+
|
|
76
|
+
if (inputs === 0) {
|
|
77
|
+
// Input nodes (leftmost)
|
|
78
|
+
layers[0].push(node)
|
|
79
|
+
} else if (outputs === 0) {
|
|
80
|
+
// Output nodes (rightmost)
|
|
81
|
+
layers[3].push(node)
|
|
82
|
+
} else if (connections > 1) {
|
|
83
|
+
// Nodes with multiple connections (middle-right)
|
|
84
|
+
layers[2].push(node)
|
|
85
|
+
} else {
|
|
86
|
+
// Processing nodes (middle-left)
|
|
87
|
+
layers[1].push(node)
|
|
88
|
+
}
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
// Position nodes in each layer
|
|
92
|
+
layers.forEach((layerNodes, layerIndex) => {
|
|
93
|
+
// Sort nodes by their connections to try to minimize crossing lines
|
|
94
|
+
layerNodes.sort((a, b) => {
|
|
95
|
+
const aConns = connectedTo.get(a)?.size || 0
|
|
96
|
+
const bConns = connectedTo.get(b)?.size || 0
|
|
97
|
+
return bConns - aConns
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
// Position nodes in the layer
|
|
101
|
+
layerNodes.forEach((node, nodeIndex) => {
|
|
102
|
+
// Distribute nodes evenly within their layer
|
|
103
|
+
const row = nodeIndex % GRID.ROWS
|
|
104
|
+
const offset = Math.floor(nodeIndex / GRID.ROWS) * (GRID.HEIGHT / 2)
|
|
105
|
+
|
|
106
|
+
editorInfo.push({
|
|
107
|
+
node,
|
|
108
|
+
position: {
|
|
109
|
+
x: GRID.PADDING + layerIndex * GRID.WIDTH,
|
|
110
|
+
y: GRID.PADDING + row * GRID.HEIGHT + offset,
|
|
111
|
+
},
|
|
112
|
+
points: [],
|
|
113
|
+
})
|
|
114
|
+
})
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
return editorInfo
|
|
118
|
+
}
|