Skip to content

Commit 3845399

Browse files
committed
feat: simplify function pipeline by removing dynamic configuration and move sidebar items to shared utility.
1 parent f7bd84a commit 3845399

11 files changed

Lines changed: 43 additions & 122 deletions

File tree

api/lib/functions.ts

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import { batch } from '/api/lib/json_store.ts'
22
import { join } from '@std/path'
33
import { ensureDir } from '@std/fs'
4-
import { DeploymentFunction } from '/api/schema.ts'
54

65
// Define the function signatures
76
export type FunctionContext = {
87
deploymentUrl: string
98
projectId: string
10-
variables?: Record<string, unknown>
119
}
1210

1311
export type ReadTransformer<T = unknown> = (
@@ -27,7 +25,6 @@ export type ProjectFunctionModule = {
2725
write?: WriteTransformer
2826
config?: {
2927
targets?: string[]
30-
events?: string[]
3128
}
3229
}
3330

@@ -138,27 +135,20 @@ export async function applyReadTransformers<T>(
138135
deploymentUrl: string,
139136
tableName: string,
140137
projectFunctions?: LoadedFunction[],
141-
configMap?: Map<string, DeploymentFunction>,
142138
): Promise<T> {
143139
if (!projectFunctions || projectFunctions.length === 0) {
144140
return data
145141
}
146142
let currentData = data
147-
for (const { name, module } of projectFunctions) {
143+
for (const { module } of projectFunctions) {
148144
if (!module.read) continue
149-
const config = configMap?.get(name)
150-
if (!config) continue
151145
if (module.config?.targets && !module.config.targets.includes(tableName)) {
152146
continue
153147
}
154-
if (module.config?.events && !module.config.events.includes('read')) {
155-
continue
156-
}
157148

158149
const ctx: FunctionContext = {
159150
deploymentUrl,
160151
projectId,
161-
variables: config.variables || {},
162152
}
163153

164154
currentData = await module.read(currentData, ctx) as T
@@ -173,27 +163,20 @@ export async function applyWriteTransformers<T>(
173163
deploymentUrl: string,
174164
tableName: string,
175165
projectFunctions?: LoadedFunction[],
176-
configMap?: Map<string, DeploymentFunction>,
177166
): Promise<T> {
178167
if (!projectFunctions || projectFunctions.length === 0) {
179168
return data
180169
}
181170
let currentData = data
182-
for (const { name, module } of projectFunctions) {
171+
for (const { module } of projectFunctions) {
183172
if (!module.write) continue
184-
const config = configMap?.get(name)
185-
if (!config) continue
186173
if (module.config?.targets && !module.config.targets.includes(tableName)) {
187174
continue
188175
}
189-
if (module.config?.events && !module.config.events.includes('write')) {
190-
continue
191-
}
192176

193177
const ctx: FunctionContext = {
194178
deploymentUrl,
195179
projectId,
196-
variables: config.variables || {},
197180
}
198181

199182
currentData = await module.write(

api/lib/functions_test.ts

Lines changed: 6 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { assertEquals } from '@std/assert'
22
import * as functions from './functions.ts'
33
import { join } from '@std/path'
44
import { ensureDir } from '@std/fs'
5-
import { DeploymentFunctionsCollection } from '../schema.ts'
65

76
Deno.test('Functions Module - Pipeline & Config', async () => {
87
const testSlug = 'test-project-' + Date.now()
@@ -35,7 +34,7 @@ Deno.test('Functions Module - Pipeline & Config', async () => {
3534
const code1 = `
3635
export default {
3736
read: (row, ctx) => {
38-
return { ...row, step1: true, var1: ctx.variables.var1 }
37+
return { ...row, step1: true, var1: 'secret-value' }
3938
}
4039
}
4140
`
@@ -62,70 +61,34 @@ Deno.test('Functions Module - Pipeline & Config', async () => {
6261
// 3. Mock Deployment Config
6362
const deploymentUrl = 'test-pipeline-' + Date.now() + '.com'
6463

65-
// Config for 01-first.js (Enabled with variables)
66-
await DeploymentFunctionsCollection.insert({
67-
id: deploymentUrl + ':01-first.js',
68-
deploymentUrl,
69-
name: '01-first.js',
70-
enabled: true,
71-
variables: { var1: 'secret-value' },
72-
})
73-
74-
// Config for 02-second.js (Disabled)
75-
await DeploymentFunctionsCollection.insert({
76-
id: deploymentUrl + ':02-second.js',
77-
deploymentUrl,
78-
name: '02-second.js',
79-
enabled: false,
80-
variables: {},
81-
})
82-
8364
// 4. Simulate Pipeline Execution (Manually, echoing sql.ts logic)
8465
// We can't import sql.ts functions easily here without mocking runSQL,
8566
// so we re-implement the pipeline logic to verify the components work.
8667

8768
let row: TestRow = { id: 1 }
88-
const configs = DeploymentFunctionsCollection.filter((c) =>
89-
c.deploymentUrl === deploymentUrl && c.enabled
90-
)
91-
const configMap = new Map(configs.map((c) => [c.name, c]))
9269

93-
for (const { name, module } of loaded) {
94-
const config = configMap.get(name)
95-
if (!config || !module.read) continue
70+
for (const { module } of loaded) {
71+
if (!module.read) continue
9672

9773
const ctx = {
9874
deploymentUrl,
9975
projectId: testSlug,
100-
variables: config.variables || undefined,
10176
}
10277
row = await module.read(row, ctx) as TestRow
10378
}
10479

10580
const result = row
10681
assertEquals(result.step1, true)
10782
assertEquals(result.var1, 'secret-value')
108-
assertEquals(result.step2, undefined) // Should be skipped
109-
110-
// 5. Enable second function
111-
await DeploymentFunctionsCollection.update(deploymentUrl + ':02-second.js', {
112-
enabled: true,
113-
})
11483

11584
// Rerun pipeline
11685
row = { id: 1 }
117-
const configs2 = DeploymentFunctionsCollection.filter((c) =>
118-
c.deploymentUrl === deploymentUrl && c.enabled
119-
)
120-
const configMap2 = new Map(configs2.map((c) => [c.name, c]))
121-
122-
for (const { name, module } of loaded) {
123-
const config = configMap2.get(name)
124-
if (!config || !module.read) continue
86+
87+
for (const { module } of loaded) {
88+
if (!module.read) continue
12589
const ctx = {
12690
deploymentUrl,
12791
projectId: testSlug,
128-
variables: config.variables || undefined,
12992
}
13093
row = await module.read(row, ctx) as TestRow
13194
}

api/sql.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import {
22
DatabaseSchemasCollection,
33
Deployment,
4-
DeploymentFunctionsCollection,
54
DeploymentsCollection,
65
} from '/api/schema.ts'
76
import { DB_SCHEMA_REFRESH_MS } from '/api/lib/env.ts'
@@ -229,10 +228,6 @@ export const fetchTablesData = async (
229228
throw Error('Missing SQL endpoint or token')
230229
}
231230
const projectFunctions = getProjectFunctions(params.deployment.projectId)
232-
const configs = DeploymentFunctionsCollection.filter((c) =>
233-
c.deploymentUrl === params.deployment.url && c.enabled
234-
)
235-
const configMap = new Map(configs.map((c) => [c.name, c]))
236231

237232
const whereClause = constructWhereClause(params, columnsMap)
238233
const orderByClause = constructOrderByClause(params, columnsMap)
@@ -262,7 +257,6 @@ export const fetchTablesData = async (
262257
params.deployment.url,
263258
params.table,
264259
projectFunctions,
265-
configMap,
266260
)
267261

268262
return {

db/functions/tournament/01-hash-passwords.js

Lines changed: 0 additions & 33 deletions
This file was deleted.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { respond } from '@01edu/api/response'
2+
3+
export default {
4+
write: (_table, data, _query, _ctx) => {
5+
if (data && typeof data === 'object' && 'password' in data) {
6+
throw respond.forbidden({ message: 'Password update is not allowed.' })
7+
}
8+
return data
9+
},
10+
config: {
11+
targets: ['users'],
12+
events: ['write'],
13+
},
14+
}

db/functions/tournament/02-tactic-handler.js renamed to db/functions/tournament/1772019944781-tactic-handler.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ const decompress = (data) => new Uint8Array(brotliDecompressSync(data))
1111

1212
async function transformRowRead(row) {
1313
if (!row || typeof row !== 'object') return row
14-
const transformed = { ...row }
14+
const transformed = {}
1515

16-
for (const [key, value] of Object.entries(transformed)) {
16+
for (const [key, value] of Object.entries(row)) {
1717
if (value instanceof Uint8Array) {
1818
if (key === 'tacticContent') {
1919
try {
@@ -25,6 +25,8 @@ async function transformRowRead(row) {
2525
} else {
2626
transformed[key] = encodeBase64Url(value)
2727
}
28+
} else {
29+
transformed[key] = value
2830
}
2931
}
3032
return transformed

web/components/Dialog.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,10 @@ export const Dialog = ({
4444
)
4545
}
4646

47-
export const DialogModal = (
48-
{ children, boxClass, ...props }: DialogProps & { boxClass?: string },
49-
) => {
47+
export const DialogModal = ({ children, ...props }: DialogProps) => {
5048
return (
5149
<Dialog class='modal' {...props}>
52-
<div class={`modal-box ${boxClass || 'w-auto'}`}>
50+
<div class='modal-box w-auto'>
5351
<form method='dialog'>
5452
<button
5553
type='submit'

web/lib/navigation.tsx

Lines changed: 0 additions & 12 deletions
This file was deleted.

web/lib/shared.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
import { HardDrive, ListTodo } from 'lucide-preact'
12
import { api } from './api.ts'
3+
import { DeploymentPage } from '../pages/DeploymentPage.tsx'
4+
import { SidebarItem } from '../components/SideBar.tsx'
25
import { url } from '@01edu/signal-router'
36
import { Signal } from '@preact/signals'
47

@@ -10,6 +13,16 @@ export type QueryHistoryItem = {
1013
rows?: number
1114
}
1215

16+
// Sidebar items for project page
17+
export const sidebarItems: Record<string, SidebarItem> = {
18+
'deployment': {
19+
icon: HardDrive,
20+
label: 'Deployment',
21+
component: DeploymentPage,
22+
},
23+
'tasks': { icon: ListTodo, label: 'Tasks', component: DeploymentPage },
24+
} as const
25+
1326
// API signal for deployment queries
1427
export const querier = api['GET/api/deployment/query'].signal()
1528

web/pages/DeploymentPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ import {
3636
querier,
3737
queriesHistory,
3838
runQuery,
39+
sidebarItems,
3940
} from '../lib/shared.tsx'
40-
import { sidebarItems } from '../lib/navigation.tsx'
4141

4242
type AnyRecord = Record<string, unknown>
4343
// API signals for schema and table data

0 commit comments

Comments
 (0)