feat: add minLevel property to metadata.json files and update permission levels in levels.lua

This commit is contained in:
2025-12-30 00:13:12 +00:00
parent de20d96a82
commit b72763d9ff
38 changed files with 333 additions and 118 deletions

View File

@@ -15,7 +15,7 @@ export const useLuaDiagnostics = (monaco: Monaco | null) =>
endColumn: word.endColumn,
}
const suggestions: any[] = [
const suggestions: monaco.languages.CompletionItem[] = [
{
label: 'context.data',
kind: monaco.languages.CompletionItemKind.Property,

View File

@@ -1,4 +1,5 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import type { Comment } from '../../types/level-types'
const mockCreate = vi.fn()
const mockAdapter = { create: mockCreate }
@@ -14,7 +15,7 @@ describe('addComment', () => {
mockCreate.mockReset()
})
it.each([
const cases: Array<{ name: string; comment: Comment }> = [
{
name: 'basic comment',
comment: { id: 'c1', userId: 'u1', content: 'Hello', createdAt: 1000 },
@@ -23,10 +24,12 @@ describe('addComment', () => {
name: 'reply comment',
comment: { id: 'c2', userId: 'u1', content: 'Reply', createdAt: 2000, parentId: 'c1' },
},
])('should add $name', async ({ comment }) => {
]
it.each(cases)('should add $name', async ({ comment }) => {
mockCreate.mockResolvedValue(undefined)
await addComment(comment as any)
await addComment(comment)
expect(mockCreate).toHaveBeenCalledWith(
'Comment',

View File

@@ -1,13 +1,22 @@
import { getAdapter } from '../../core/dbal-client'
import type { Comment } from '../../types/level-types'
type DBALCommentRecord = {
id: string
userId: string
content: string
createdAt: number | string | Date
updatedAt?: number | string | Date | null
parentId?: string | null
}
/**
* Get all comments from database
*/
export async function getComments(): Promise<Comment[]> {
const adapter = getAdapter()
const result = await adapter.list('Comment')
return (result.data as any[]).map(c => ({
const result = (await adapter.list('Comment')) as { data: DBALCommentRecord[] }
return result.data.map(c => ({
id: c.id,
userId: c.userId,
content: c.content,

View File

@@ -1,4 +1,5 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import type { LuaScript } from '../../types/level-types'
const mockList = vi.fn()
const mockDelete = vi.fn()
@@ -23,7 +24,7 @@ describe('setLuaScripts', () => {
mockDelete.mockResolvedValue(undefined)
mockCreate.mockResolvedValue(undefined)
await setLuaScripts([
const scripts: LuaScript[] = [
{
id: 'new',
name: 'New',
@@ -32,7 +33,9 @@ describe('setLuaScripts', () => {
allowedGlobals: ['math'],
timeoutMs: 1500,
},
] as any)
]
await setLuaScripts(scripts)
expect(mockDelete).toHaveBeenCalledTimes(1)
expect(mockCreate).toHaveBeenCalledTimes(1)

View File

@@ -2,6 +2,10 @@ import type { LuaScript } from '../../types/level-types'
import { getAdapter } from '../core/dbal-client'
import { serializeLuaScript } from './serialization/serialize-lua-script'
type DBALLuaScriptRecord = {
id: string
}
/**
* Set all Lua scripts (replaces existing)
*/
@@ -9,8 +13,8 @@ export async function setLuaScripts(scripts: LuaScript[]): Promise<void> {
const adapter = getAdapter()
// Delete existing scripts
const existing = await adapter.list('LuaScript')
for (const s of existing.data as any[]) {
const existing = (await adapter.list('LuaScript')) as { data: DBALLuaScriptRecord[] }
for (const s of existing.data) {
await adapter.delete('LuaScript', s.id)
}

View File

@@ -1,13 +1,22 @@
import { getAdapter } from '../../core/dbal-client'
import type { Workflow } from '../../types/level-types'
type DBALWorkflowRecord = {
id: string
name: string
description?: string | null
nodes: string
edges: string
enabled: boolean
}
/**
* Get all workflows
*/
export async function getWorkflows(): Promise<Workflow[]> {
const adapter = getAdapter()
const result = await adapter.list('Workflow')
return (result.data as any[]).map(w => ({
const result = (await adapter.list('Workflow')) as { data: DBALWorkflowRecord[] }
return result.data.map(w => ({
id: w.id,
name: w.name,
description: w.description || undefined,

View File

@@ -1,4 +1,5 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import type { Workflow } from '../../types/level-types'
const mockList = vi.fn()
const mockDelete = vi.fn()
@@ -23,7 +24,11 @@ describe('setWorkflows', () => {
mockDelete.mockResolvedValue(undefined)
mockCreate.mockResolvedValue(undefined)
await setWorkflows([{ id: 'new', name: 'New', nodes: [], edges: [], enabled: true }] as any)
const workflows: Workflow[] = [
{ id: 'new', name: 'New', nodes: [], edges: [], enabled: true },
]
await setWorkflows(workflows)
expect(mockDelete).toHaveBeenCalledTimes(1)
expect(mockCreate).toHaveBeenCalledTimes(1)

View File

@@ -1,6 +1,10 @@
import { getAdapter } from '../../core/dbal-client'
import type { Workflow } from '../../types/level-types'
type DBALWorkflowRecord = {
id: string
}
/**
* Set all workflows (replaces existing)
*/
@@ -8,8 +12,8 @@ export async function setWorkflows(workflows: Workflow[]): Promise<void> {
const adapter = getAdapter()
// Delete existing workflows
const existing = await adapter.list('Workflow')
for (const w of existing.data as any[]) {
const existing = (await adapter.list('Workflow')) as { data: DBALWorkflowRecord[] }
for (const w of existing.data) {
await adapter.delete('Workflow', w.id)
}

View File

@@ -1,4 +1,5 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import type { Workflow } from '../../types/level-types'
const mockUpdate = vi.fn()
const mockAdapter = { update: mockUpdate }
@@ -20,7 +21,7 @@ describe('updateWorkflow', () => {
])('should update $id', async ({ id, updates }) => {
mockUpdate.mockResolvedValue(undefined)
await updateWorkflow(id, updates as any)
await updateWorkflow(id, updates as Partial<Workflow>)
expect(mockUpdate).toHaveBeenCalledWith('Workflow', id, expect.any(Object))
})

View File

@@ -9,5 +9,6 @@
"dependencies": [],
"exports": {
"components": []
}
},
"minLevel": 4
}

View File

@@ -9,5 +9,6 @@
"dependencies": [],
"exports": {
"components": []
}
}
},
"minLevel": 2
}

View File

@@ -8,7 +8,17 @@
"category": "editors",
"dependencies": [],
"exports": {
"scripts": ["json", "lua", "theme"],
"components": ["CodeEditor", "JsonEditor", "LuaEditor", "ThemeEditor"]
}
}
"scripts": [
"json",
"lua",
"theme"
],
"components": [
"CodeEditor",
"JsonEditor",
"LuaEditor",
"ThemeEditor"
]
},
"minLevel": 5
}

View File

@@ -9,5 +9,6 @@
"dependencies": [],
"exports": {
"components": []
}
}
},
"minLevel": 5
}

View File

@@ -8,7 +8,15 @@
"category": "ui",
"dependencies": [],
"exports": {
"components": ["StatCard", "DashboardGrid", "Widget"],
"scripts": ["stats", "layout"]
}
"components": [
"StatCard",
"DashboardGrid",
"Widget"
],
"scripts": [
"stats",
"layout"
]
},
"minLevel": 2
}

View File

@@ -9,5 +9,6 @@
"dependencies": [],
"exports": {
"components": []
}
},
"minLevel": 1
}

View File

@@ -8,7 +8,17 @@
"category": "ui",
"dependencies": [],
"exports": {
"components": ["FormField", "EmailField", "PasswordField", "NumberField", "SearchBar"],
"scripts": ["fields", "validate"]
}
"components": [
"FormField",
"EmailField",
"PasswordField",
"NumberField",
"SearchBar"
],
"scripts": [
"fields",
"validate"
]
},
"minLevel": 1
}

View File

@@ -9,5 +9,6 @@
"dependencies": [],
"exports": {
"components": []
}
}
},
"minLevel": 2
}

View File

@@ -6,9 +6,19 @@
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": ["ui_permissions"],
"dependencies": [
"ui_permissions"
],
"exports": {
"components": ["Sidebar", "NavigationMenu", "Breadcrumbs"],
"scripts": ["sidebar", "menu"]
}
"components": [
"Sidebar",
"NavigationMenu",
"Breadcrumbs"
],
"scripts": [
"sidebar",
"menu"
]
},
"minLevel": 2
}

View File

@@ -9,5 +9,6 @@
"dependencies": [],
"exports": {
"components": []
}
},
"minLevel": 1
}

View File

@@ -6,9 +6,20 @@
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "editors",
"dependencies": ["form_builder"],
"dependencies": [
"form_builder"
],
"exports": {
"scripts": ["fields", "tables", "relations"],
"components": ["SchemaEditor", "TableEditor", "FieldEditor"]
}
}
"scripts": [
"fields",
"tables",
"relations"
],
"components": [
"SchemaEditor",
"TableEditor",
"FieldEditor"
]
},
"minLevel": 5
}

View File

@@ -39,5 +39,6 @@
"social_hub_feed_post_2_body",
"social_hub_feed_post_2_badge"
]
}
}
},
"minLevel": 2
}

View File

@@ -9,5 +9,6 @@
"dependencies": [],
"exports": {
"components": []
}
}
},
"minLevel": 2
}

View File

@@ -6,9 +6,19 @@
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": ["ui_permissions"],
"dependencies": [
"ui_permissions"
],
"exports": {
"components": ["AccessDenied", "AuthGate", "PageLoader"],
"scripts": ["denied", "gate"]
}
}
"components": [
"AccessDenied",
"AuthGate",
"PageLoader"
],
"scripts": [
"denied",
"gate"
]
},
"minLevel": 2
}

View File

@@ -8,7 +8,15 @@
"category": "ui",
"dependencies": [],
"exports": {
"components": ["ConfirmDialog", "AlertDialog", "FormDialog"],
"scripts": ["confirm", "alert"]
}
}
"components": [
"ConfirmDialog",
"AlertDialog",
"FormDialog"
],
"scripts": [
"confirm",
"alert"
]
},
"minLevel": 1
}

View File

@@ -8,8 +8,13 @@
"category": "ui",
"dependencies": [],
"exports": {
"components": ["AppFooter"],
"scripts": ["footer"],
"components": [
"AppFooter"
],
"scripts": [
"footer"
],
"pages": []
}
}
},
"minLevel": 1
}

View File

@@ -6,10 +6,17 @@
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": ["ui_permissions"],
"dependencies": [
"ui_permissions"
],
"exports": {
"components": ["AppHeader"],
"scripts": ["header"],
"components": [
"AppHeader"
],
"scripts": [
"header"
],
"pages": []
}
}
},
"minLevel": 2
}

View File

@@ -6,10 +6,18 @@
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": ["ui_permissions"],
"dependencies": [
"ui_permissions"
],
"exports": {
"pages": ["level1"],
"scripts": ["home_ui", "navigate"],
"pages": [
"level1"
],
"scripts": [
"home_ui",
"navigate"
],
"components": []
}
}
},
"minLevel": 1
}

View File

@@ -8,8 +8,13 @@
"category": "ui",
"dependencies": [],
"exports": {
"components": ["IntroSection"],
"scripts": ["intro"],
"components": [
"IntroSection"
],
"scripts": [
"intro"
],
"pages": []
}
}
},
"minLevel": 1
}

View File

@@ -6,10 +6,21 @@
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": ["ui_permissions", "ui_header", "ui_intro"],
"dependencies": [
"ui_permissions",
"ui_header",
"ui_intro"
],
"exports": {
"pages": ["level2"],
"scripts": ["layout", "profile", "comments"],
"pages": [
"level2"
],
"scripts": [
"layout",
"profile",
"comments"
],
"components": []
}
}
},
"minLevel": 2
}

View File

@@ -6,10 +6,21 @@
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": ["ui_permissions", "ui_header", "ui_intro"],
"dependencies": [
"ui_permissions",
"ui_header",
"ui_intro"
],
"exports": {
"pages": ["level3"],
"scripts": ["layout", "users", "moderation"],
"pages": [
"level3"
],
"scripts": [
"layout",
"users",
"moderation"
],
"components": []
}
}
},
"minLevel": 3
}

View File

@@ -6,10 +6,21 @@
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": ["ui_permissions", "ui_header", "ui_intro"],
"dependencies": [
"ui_permissions",
"ui_header",
"ui_intro"
],
"exports": {
"pages": ["level4"],
"scripts": ["layout", "schemas", "workflows"],
"pages": [
"level4"
],
"scripts": [
"layout",
"schemas",
"workflows"
],
"components": []
}
}
},
"minLevel": 4
}

View File

@@ -6,10 +6,21 @@
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": ["ui_permissions", "ui_header", "ui_intro"],
"dependencies": [
"ui_permissions",
"ui_header",
"ui_intro"
],
"exports": {
"pages": ["level5"],
"scripts": ["layout", "tenants", "transfer"],
"pages": [
"level5"
],
"scripts": [
"layout",
"tenants",
"transfer"
],
"components": []
}
}
},
"minLevel": 5
}

View File

@@ -6,10 +6,18 @@
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "ui",
"dependencies": ["ui_permissions"],
"dependencies": [
"ui_permissions"
],
"exports": {
"pages": ["login"],
"scripts": ["login_ui", "login_actions"],
"pages": [
"login"
],
"scripts": [
"login_ui",
"login_actions"
],
"components": []
}
}
},
"minLevel": 1
}

View File

@@ -22,5 +22,6 @@
"pages": [],
"scripts": [],
"components": []
}
}
},
"minLevel": 1
}

View File

@@ -8,7 +8,10 @@
"category": "ui",
"dependencies": [],
"exports": {
"scripts": ["permissions"],
"scripts": [
"permissions"
],
"components": []
}
}
},
"minLevel": 1
}

View File

@@ -1,8 +1,9 @@
-- Permission level constants (5-level system)
-- Permission level constants (6-level system)
return {
PUBLIC = 1,
USER = 2,
ADMIN = 3,
GOD = 4,
SUPERGOD = 5
MODERATOR = 3,
ADMIN = 4,
GOD = 5,
SUPERGOD = 6
}

View File

@@ -6,9 +6,20 @@
"icon": "static_content/icon.svg",
"author": "MetaBuilder",
"category": "managers",
"dependencies": ["ui_permissions", "data_table"],
"dependencies": [
"ui_permissions",
"data_table"
],
"exports": {
"scripts": ["list", "actions"],
"components": ["UserManagement", "UserList", "UserActions"]
}
}
"scripts": [
"list",
"actions"
],
"components": [
"UserManagement",
"UserList",
"UserActions"
]
},
"minLevel": 4
}

View File

@@ -8,7 +8,16 @@
"category": "editors",
"dependencies": [],
"exports": {
"scripts": ["editor", "status", "run"],
"components": ["WorkflowEditor", "WorkflowRunCard", "WorkflowRunStatus"]
}
}
"scripts": [
"editor",
"status",
"run"
],
"components": [
"WorkflowEditor",
"WorkflowRunCard",
"WorkflowRunStatus"
]
},
"minLevel": 5
}