From c6dd14b16bbf9530d1940518da0975bcf4313674 Mon Sep 17 00:00:00 2001 From: Jeroen van der Heijden Date: Thu, 11 Jun 2026 08:59:33 +0200 Subject: [PATCH 1/8] Improve text --- src/components/studio/QueryVarsDialog.tsx | 8 ++++---- src/components/studio/StudioTopBar.tsx | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/studio/QueryVarsDialog.tsx b/src/components/studio/QueryVarsDialog.tsx index 2584f76..9829f44 100644 --- a/src/components/studio/QueryVarsDialog.tsx +++ b/src/components/studio/QueryVarsDialog.tsx @@ -1,5 +1,5 @@ import { useState } from 'react'; -import { Dialog, Flex, Button, Box } from '@radix-ui/themes'; +import { Dialog, Flex, Button, Box, Code } from '@radix-ui/themes'; import Editor from '@monaco-editor/react'; import { useTheme } from '../../hooks'; @@ -41,9 +41,9 @@ export default function QueryVarsDialog({ return ( - Execution Configuration + Runtime Arguments - Provide runtime arguments as a valid JSON object. + Configure runtime arguments for this specific file. Provide a valid JSON object where keys map to variable names; for example, {'{"limit": 10}'}) registers 'limit' as an accessible variable inside your code. - Save Configuration + Save diff --git a/src/components/studio/StudioTopBar.tsx b/src/components/studio/StudioTopBar.tsx index 4a5b7e7..8c0a61f 100644 --- a/src/components/studio/StudioTopBar.tsx +++ b/src/components/studio/StudioTopBar.tsx @@ -156,7 +156,7 @@ export default function StudioTopBar() { size="2" disabled={!isTiCode || isRefreshing} onClick={() => setIsConfigOpen(true)} - title="Edit Execution Arguments (JSON)" + title="Edit Runtime Arguments" style={{ cursor: !isTiCode || isRefreshing ? 'not-allowed' : 'pointer' }} > From 5248005a1d70f5d8b58979a2b175ce6753c5e12f Mon Sep 17 00:00:00 2001 From: Jeroen van der Heijden Date: Thu, 11 Jun 2026 09:05:14 +0200 Subject: [PATCH 2/8] alpha, changed icon --- README.md | 26 +++++++++++++------------- app/version.go | 2 +- package-lock.json | 6 +++--- package.json | 2 +- src/components/AboutModal.tsx | 2 +- src/components/studio/StudioTopBar.tsx | 4 ++-- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 0ce3446..92d3d1f 100644 --- a/README.md +++ b/README.md @@ -10,17 +10,17 @@ ThingsCode (or **ticode** for short) is the interactive development studio built **1. Download the latest version:** -- [Linux (amd64)](https://github.com/thingsdb/ThingsCode/releases/download/v1.0.1/ticode-linux-amd64-1.0.1.tar.gz) -- [Linux (arm64)](https://github.com/thingsdb/ThingsCode/releases/download/v1.0.1/ticode-linux-arm64-1.0.1.tar.gz) -- [Darwin (amd64)](https://github.com/thingsdb/ThingsCode/releases/download/v1.0.1/ticode-darwin-amd64-1.0.1.tar.gz) -- [Darwin (arm64)](https://github.com/thingsdb/ThingsCode/releases/download/v1.0.1/ticode-darwin-arm64-1.0.1.tar.gz) -- [Windows (amd64)](https://github.com/thingsdb/ThingsCode/releases/download/v1.0.1/ticode-windows-amd64-1.0.1.tar.gz) -- [Windows (arm64)](https://github.com/thingsdb/ThingsCode/releases/download/v1.0.1/ticode-windows-arm64-1.0.1.tar.gz) +- [Linux (amd64)](https://github.com/thingsdb/ThingsCode/releases/download/v1.0.2-alpha0/ticode-linux-amd64-1.0.2-alpha0.tar.gz) +- [Linux (arm64)](https://github.com/thingsdb/ThingsCode/releases/download/v1.0.2-alpha0/ticode-linux-arm64-1.0.2-alpha0.tar.gz) +- [Darwin (amd64)](https://github.com/thingsdb/ThingsCode/releases/download/v1.0.2-alpha0/ticode-darwin-amd64-1.0.2-alpha0.tar.gz) +- [Darwin (arm64)](https://github.com/thingsdb/ThingsCode/releases/download/v1.0.2-alpha0/ticode-darwin-arm64-1.0.2-alpha0.tar.gz) +- [Windows (amd64)](https://github.com/thingsdb/ThingsCode/releases/download/v1.0.2-alpha0/ticode-windows-amd64-1.0.2-alpha0.tar.gz) +- [Windows (arm64)](https://github.com/thingsdb/ThingsCode/releases/download/v1.0.2-alpha0/ticode-windows-arm64-1.0.2-alpha0.tar.gz) **2. Extract the contents of the archive using a tool like `tar`. Here's an example for Linux (amd64):** ```bash -tar -xzvf ticode-linux-amd64-1.0.1.tar.gz +tar -xzvf ticode-linux-amd64-1.0.2-alpha0.tar.gz ``` **3. Install:** @@ -69,27 +69,27 @@ npm run build mkdir -p bin/darwin-amd64 GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 go build -trimpath -o bin/darwin-amd64/ticode -tar -zcf bin/ticode-darwin-amd64-1.0.1.tar.gz -C ./bin/darwin-amd64/ ticode +tar -zcf bin/ticode-darwin-amd64-1.0.2-alpha0.tar.gz -C ./bin/darwin-amd64/ ticode mkdir -p bin/darwin-arm64 GOOS=darwin GOARCH=arm64 CGO_ENABLED=0 go build -trimpath -o bin/darwin-arm64/ticode -tar -zcf bin/ticode-darwin-arm64-1.0.1.tar.gz -C ./bin/darwin-arm64/ ticode +tar -zcf bin/ticode-darwin-arm64-1.0.2-alpha0.tar.gz -C ./bin/darwin-arm64/ ticode mkdir -p bin/linux-amd64 GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -trimpath -o bin/linux-amd64/ticode -tar -zcf bin/ticode-linux-amd64-1.0.1.tar.gz -C ./bin/linux-amd64/ ticode +tar -zcf bin/ticode-linux-amd64-1.0.2-alpha0.tar.gz -C ./bin/linux-amd64/ ticode mkdir -p bin/linux-arm64 GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -trimpath -o bin/linux-arm64/ticode -tar -zcf bin/ticode-linux-arm64-1.0.1.tar.gz -C ./bin/linux-arm64/ ticode +tar -zcf bin/ticode-linux-arm64-1.0.2-alpha0.tar.gz -C ./bin/linux-arm64/ ticode mkdir -p bin/windows-amd64 GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -trimpath -o bin/windows-amd64/ticode.exe -tar -zcf bin/ticode-windows-amd64-1.0.1.tar.gz -C ./bin/windows-amd64/ ticode.exe +tar -zcf bin/ticode-windows-amd64-1.0.2-alpha0.tar.gz -C ./bin/windows-amd64/ ticode.exe mkdir -p bin/windows-arm64 GOOS=windows GOARCH=arm64 CGO_ENABLED=0 go build -trimpath -o bin/windows-arm64/ticode.exe -tar -zcf bin/ticode-windows-arm64-1.0.1.tar.gz -C ./bin/windows-arm64/ ticode.exe +tar -zcf bin/ticode-windows-arm64-1.0.2-alpha0.tar.gz -C ./bin/windows-arm64/ ticode.exe ``` ## Update diff --git a/app/version.go b/app/version.go index 7cb6714..3fca499 100644 --- a/app/version.go +++ b/app/version.go @@ -1,3 +1,3 @@ package app -const Version = "1.0.1" // And update package.json +const Version = "1.0.2-alpha0" // And update package.json diff --git a/package-lock.json b/package-lock.json index 501761c..3351844 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ticode", - "version": "1.0.1", + "version": "1.0.2-alpha0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ticode", - "version": "1.0.1", + "version": "1.0.2-alpha0", "dependencies": { "@monaco-editor/react": "^4.7.0", "@radix-ui/react-icons": "^1.3.2", @@ -4067,7 +4067,7 @@ }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.2-alpha0.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true, "license": "MIT" diff --git a/package.json b/package.json index ebd6153..8af1fb1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ticode", - "version": "1.0.1", + "version": "1.0.2-alpha0", "private": true, "type": "module", "scripts": { diff --git a/src/components/AboutModal.tsx b/src/components/AboutModal.tsx index 60974a5..f84b0b8 100644 --- a/src/components/AboutModal.tsx +++ b/src/components/AboutModal.tsx @@ -10,7 +10,7 @@ interface AboutModalProps { export default function AboutModal({ isOpen, onOpenChange }: AboutModalProps) { const { appearance } = useTheme(); - const appVersion = version || '1.0.1'; + const appVersion = version || '1.0.2-alpha0'; return ( diff --git a/src/components/studio/StudioTopBar.tsx b/src/components/studio/StudioTopBar.tsx index 8c0a61f..9425fe4 100644 --- a/src/components/studio/StudioTopBar.tsx +++ b/src/components/studio/StudioTopBar.tsx @@ -1,5 +1,5 @@ import { Flex, Text, Button, Tooltip, IconButton, Separator, Box, Badge } from '@radix-ui/themes'; -import { ExitIcon, GearIcon, MoonIcon, PlayIcon, SunIcon, UpdateIcon, GitHubLogoIcon, ReaderIcon, ExclamationTriangleIcon, MagnifyingGlassIcon, CubeIcon, PersonIcon } from '@radix-ui/react-icons'; +import { ExitIcon, GearIcon, MoonIcon, PlayIcon, SunIcon, UpdateIcon, GitHubLogoIcon, ReaderIcon, ExclamationTriangleIcon, MagnifyingGlassIcon, CubeIcon, PersonIcon, MixerHorizontalIcon } from '@radix-ui/react-icons'; import { useActiveWorkspace, useWebSocket } from '../../hooks'; import { useTheme } from '../../hooks'; import ScopeSelector from './ScopeSelector'; @@ -159,7 +159,7 @@ export default function StudioTopBar() { title="Edit Runtime Arguments" style={{ cursor: !isTiCode || isRefreshing ? 'not-allowed' : 'pointer' }} > - + From 10e9d30f777943a8c4515904c69a65bd3c953f23 Mon Sep 17 00:00:00 2001 From: Jeroen van der Heijden Date: Thu, 11 Jun 2026 09:17:21 +0200 Subject: [PATCH 3/8] render with links and use callout for task error --- src/components/studio/ProcedureModal.tsx | 4 ++-- src/components/studio/StudioResultView.tsx | 28 +--------------------- src/components/studio/TaskModal.tsx | 25 +++++-------------- src/utils/index.ts | 5 +++- src/utils/renderWithLinks.tsx | 26 ++++++++++++++++++++ 5 files changed, 39 insertions(+), 49 deletions(-) create mode 100644 src/utils/renderWithLinks.tsx diff --git a/src/components/studio/ProcedureModal.tsx b/src/components/studio/ProcedureModal.tsx index 352f91b..7bab5dd 100644 --- a/src/components/studio/ProcedureModal.tsx +++ b/src/components/studio/ProcedureModal.tsx @@ -5,7 +5,7 @@ import { InfoCircledIcon, ExclamationTriangleIcon, LightningBoltIcon, EyeOpenIco import { useTheme, useWebSocket, useActiveWorkspaceId } from '../../hooks'; import type { Procedure, Result } from '../../types'; import { parse } from 'lossless-json'; -import { errStr } from '../../utils'; +import { errStr, renderTextWithLinks } from '../../utils'; interface ProcedureModalProps { onClose: (open: boolean) => void; @@ -283,7 +283,7 @@ export default function ProcedureModal({ {executionResult.error && ( - {executionResult.error} + {renderTextWithLinks(executionResult.error)} )} diff --git a/src/components/studio/StudioResultView.tsx b/src/components/studio/StudioResultView.tsx index ae76d85..a227ef6 100644 --- a/src/components/studio/StudioResultView.tsx +++ b/src/components/studio/StudioResultView.tsx @@ -4,33 +4,7 @@ import Editor from '@monaco-editor/react'; import { useActiveWorkspace, useTheme } from '../../hooks'; import { useMemo, useState } from 'react'; import type { Result } from '../../types'; - -const renderTextWithLinks = (text: string) => { - const urlRegex = /(https?:\/\/[^\s]+)/g; - const parts = text.split(urlRegex); - - return parts.map((part, i) => { - if (part.match(urlRegex)) { - return ( - - {part} - - ); - } - return part; - }); -}; +import { renderTextWithLinks } from '../../utils'; export default function StudioResultView() { const { appearance } = useTheme(); diff --git a/src/components/studio/TaskModal.tsx b/src/components/studio/TaskModal.tsx index 6c15d05..85d1b64 100644 --- a/src/components/studio/TaskModal.tsx +++ b/src/components/studio/TaskModal.tsx @@ -1,9 +1,9 @@ import { useEffect, useState } from 'react'; -import { Dialog, Flex, Text, Badge, Box, Button, Spinner } from '@radix-ui/themes'; +import { Dialog, Flex, Text, Badge, Box, Button, Spinner, Callout } from '@radix-ui/themes'; import { ExclamationTriangleIcon, CalendarIcon, PersonIcon } from '@radix-ui/react-icons'; import Editor from '@monaco-editor/react'; import { useTheme, useWebSocket, useActiveWorkspaceId } from '../../hooks'; -import { errStr } from '../../utils'; +import { errStr, renderTextWithLinks } from '../../utils'; interface TaskDetail { id: number; @@ -96,23 +96,10 @@ export default function TaskModal({ taskId, scope, onClose }: TaskModalProps) { {task && !isLoading && ( {task.error ? ( - - - - - {task.error} - - - + + + {renderTextWithLinks(task.error)} + ) : ( diff --git a/src/utils/index.ts b/src/utils/index.ts index 3621060..812510d 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,3 +1,5 @@ +export { renderTextWithLinks } from './renderWithLinks'; + export const errStr = (err: unknown, fallback: string) => { const message = err instanceof Error ? err.message @@ -17,4 +19,5 @@ export function determineCardinality(thisDef: string, targetDef: string): Cardin if (thisIsMany && !targetIsMany) return 'N:1'; if (!thisIsMany && targetIsMany) return '1:N'; return '1:1'; -} \ No newline at end of file +} + diff --git a/src/utils/renderWithLinks.tsx b/src/utils/renderWithLinks.tsx new file mode 100644 index 0000000..9ab5423 --- /dev/null +++ b/src/utils/renderWithLinks.tsx @@ -0,0 +1,26 @@ +export const renderTextWithLinks = (text: string) => { + const urlRegex = /(https?:\/\/[^\s]+)/g; + const parts = text.split(urlRegex); + + return parts.map((part, i) => { + if (part.match(urlRegex)) { + return ( + + {part} + + ); + } + return part; + }); +}; \ No newline at end of file From e0f20f99d3fe92c8b071a0d265c3df470b2196a5 Mon Sep 17 00:00:00 2001 From: Jeroen van der Heijden Date: Thu, 11 Jun 2026 09:28:44 +0200 Subject: [PATCH 4/8] Use callout for history error --- src/components/studio/CommitModal.tsx | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/src/components/studio/CommitModal.tsx b/src/components/studio/CommitModal.tsx index 8213460..2e4f0f2 100644 --- a/src/components/studio/CommitModal.tsx +++ b/src/components/studio/CommitModal.tsx @@ -1,9 +1,9 @@ import { useEffect, useState } from 'react'; -import { Dialog, Flex, Text, Badge, Box, Button, Spinner } from '@radix-ui/themes'; +import { Dialog, Flex, Text, Badge, Box, Button, Spinner, Callout } from '@radix-ui/themes'; import { ExclamationTriangleIcon, CalendarIcon, PersonIcon } from '@radix-ui/react-icons'; import Editor from '@monaco-editor/react'; import { useTheme, useWebSocket, useActiveWorkspaceId } from '../../hooks'; -import { errStr } from '../../utils'; +import { errStr, renderTextWithLinks } from '../../utils'; import type { Commit } from '../../types'; @@ -90,23 +90,10 @@ export default function CommitModal({ commitId, scope, onClose }: CommitModalPro {commit && !isLoading && ( {commit.errMsg && ( - - - - - {commit.errMsg} - - - + + + {renderTextWithLinks(commit.errMsg)} + )} From d92554108a7bad9ade7aa5a758d44fdeb783ff18 Mon Sep 17 00:00:00 2001 From: Jeroen van der Heijden Date: Thu, 11 Jun 2026 09:56:31 +0200 Subject: [PATCH 5/8] no more gear icon --- src/components/studio/StudioTopBar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/studio/StudioTopBar.tsx b/src/components/studio/StudioTopBar.tsx index 9425fe4..b370534 100644 --- a/src/components/studio/StudioTopBar.tsx +++ b/src/components/studio/StudioTopBar.tsx @@ -1,5 +1,5 @@ import { Flex, Text, Button, Tooltip, IconButton, Separator, Box, Badge } from '@radix-ui/themes'; -import { ExitIcon, GearIcon, MoonIcon, PlayIcon, SunIcon, UpdateIcon, GitHubLogoIcon, ReaderIcon, ExclamationTriangleIcon, MagnifyingGlassIcon, CubeIcon, PersonIcon, MixerHorizontalIcon } from '@radix-ui/react-icons'; +import { ExitIcon, MoonIcon, PlayIcon, SunIcon, UpdateIcon, GitHubLogoIcon, ReaderIcon, ExclamationTriangleIcon, MagnifyingGlassIcon, CubeIcon, PersonIcon, MixerHorizontalIcon } from '@radix-ui/react-icons'; import { useActiveWorkspace, useWebSocket } from '../../hooks'; import { useTheme } from '../../hooks'; import ScopeSelector from './ScopeSelector'; From 75a4d670b3d4b8eb53545ed9dc8ed37165b0204c Mon Sep 17 00:00:00 2001 From: Jeroen van der Heijden Date: Thu, 11 Jun 2026 11:24:25 +0200 Subject: [PATCH 6/8] more tailwind, no appearance on workpace --- src/Root.tsx | 2 +- src/components/AboutModal.tsx | 2 +- src/components/ConfirmDialog.tsx | 4 +- src/components/NewWorkspaceModal.tsx | 4 +- src/components/QuickConnectModal.tsx | 4 +- src/components/ThingExplorerModal.tsx | 8 ++-- src/components/TreeNode.tsx | 2 +- src/components/WorkspaceLauncher.tsx | 2 +- src/components/WorkspaceModal.tsx | 4 +- src/components/studio/BackupModal.tsx | 6 +-- src/components/studio/CommitModal.tsx | 2 +- src/components/studio/CreateFileDialog.tsx | 2 +- src/components/studio/EnumModal.tsx | 8 ++-- src/components/studio/EventArgsModal.tsx | 2 +- src/components/studio/ModuleModal.tsx | 8 ++-- src/components/studio/ModulesPanel.tsx | 2 +- src/components/studio/NodeCountersPanel.tsx | 2 +- src/components/studio/NodeInfoPanel.tsx | 8 ++-- src/components/studio/NodeInspectModal.tsx | 2 +- src/components/studio/NodeLogLevelModal.tsx | 4 +- src/components/studio/NodeShutdownModal.tsx | 2 +- src/components/studio/ProcedureModal.tsx | 6 +-- src/components/studio/QueryVarsDialog.tsx | 2 +- src/components/studio/RenameFileDialog.tsx | 2 +- src/components/studio/RoomJoinModal.tsx | 2 +- src/components/studio/RoomsPanel.tsx | 2 +- src/components/studio/StudioConsoleHeader.tsx | 2 +- src/components/studio/StudioEventView.tsx | 4 +- src/components/studio/StudioLeftPanel.tsx | 4 +- src/components/studio/StudioLogView.tsx | 4 +- src/components/studio/StudioTopBar.tsx | 48 ++++++------------- src/components/studio/TaskModal.tsx | 2 +- src/components/studio/TypeModal.tsx | 8 ++-- src/components/studio/UserModal.tsx | 10 ++-- src/context/WorkspaceContext.tsx | 1 - src/providers/WorkspaceProvider.tsx | 4 +- 36 files changed, 79 insertions(+), 102 deletions(-) diff --git a/src/Root.tsx b/src/Root.tsx index 6bb1954..7dce5a8 100644 --- a/src/Root.tsx +++ b/src/Root.tsx @@ -43,7 +43,7 @@ function Root() { overflowX: 'hidden' }} > - + diff --git a/src/components/AboutModal.tsx b/src/components/AboutModal.tsx index f84b0b8..ba788d6 100644 --- a/src/components/AboutModal.tsx +++ b/src/components/AboutModal.tsx @@ -61,7 +61,7 @@ export default function AboutModal({ isOpen, onOpenChange }: AboutModalProps) { If you like using ThingsCode, please give us a star on our official GitHub organization page! - @@ -43,7 +43,7 @@ export default function ConfirmDialog({ variant="solid" color={colorVariant} onClick={onConfirm} - style={{ cursor: 'pointer' }} + className="cursor-pointer" > {confirmText} diff --git a/src/components/NewWorkspaceModal.tsx b/src/components/NewWorkspaceModal.tsx index 582d22b..85db027 100644 --- a/src/components/NewWorkspaceModal.tsx +++ b/src/components/NewWorkspaceModal.tsx @@ -218,7 +218,7 @@ export default function NewWorkspaceModal() { variant="ghost" color="gray" onClick={() => setShowToken(!showToken)} - style={{ cursor: 'pointer' }} + className="cursor-pointer" > {showToken ? : } @@ -244,7 +244,7 @@ export default function NewWorkspaceModal() { variant="ghost" color="gray" onClick={() => setShowPassword(!showPassword)} - style={{ cursor: 'pointer' }} + className="cursor-pointer" > {showPassword ? : } diff --git a/src/components/QuickConnectModal.tsx b/src/components/QuickConnectModal.tsx index 5260ca8..a20b72f 100644 --- a/src/components/QuickConnectModal.tsx +++ b/src/components/QuickConnectModal.tsx @@ -121,7 +121,7 @@ export default function QuickConnectModal() { ThingsDB Access Token setToken(e.target.value)} required> - setShowToken(!showToken)} style={{ cursor: 'pointer' }}> + setShowToken(!showToken)} className="cursor-pointer"> {showToken ? : } @@ -137,7 +137,7 @@ export default function QuickConnectModal() { Password setPassword(e.target.value)} required> - setShowPassword(!showPassword)} style={{ cursor: 'pointer' }}> + setShowPassword(!showPassword)} className="cursor-pointer"> {showPassword ? : } diff --git a/src/components/ThingExplorerModal.tsx b/src/components/ThingExplorerModal.tsx index 0675a1c..d2aea10 100644 --- a/src/components/ThingExplorerModal.tsx +++ b/src/components/ThingExplorerModal.tsx @@ -97,11 +97,11 @@ export default function ThingExplorerModal({ onClose, scope }: ThingExplorerModa - - @@ -119,11 +119,11 @@ export default function ThingExplorerModal({ onClose, scope }: ThingExplorerModa {/* FOOTER */} - - diff --git a/src/components/TreeNode.tsx b/src/components/TreeNode.tsx index 6ec081c..86884a7 100644 --- a/src/components/TreeNode.tsx +++ b/src/components/TreeNode.tsx @@ -111,7 +111,7 @@ export default function TreeNode({ {isThingReference && } diff --git a/src/components/WorkspaceLauncher.tsx b/src/components/WorkspaceLauncher.tsx index a696c6c..05c89bb 100644 --- a/src/components/WorkspaceLauncher.tsx +++ b/src/components/WorkspaceLauncher.tsx @@ -25,7 +25,7 @@ export default function WorkspaceLauncher() { variant="ghost" onClick={toggleAppearance} size="2" - style={{ cursor: 'pointer' }} + className="cursor-pointer" color="gray" > {appearance === 'dark' ? : } diff --git a/src/components/WorkspaceModal.tsx b/src/components/WorkspaceModal.tsx index ebf6107..5f65a35 100644 --- a/src/components/WorkspaceModal.tsx +++ b/src/components/WorkspaceModal.tsx @@ -173,7 +173,7 @@ export default function WorkspaceModal() { variant="ghost" color="gray" onClick={() => setShowToken(!showToken)} - style={{ cursor: 'pointer' }} + className="cursor-pointer" > {showToken ? : } @@ -202,7 +202,7 @@ export default function WorkspaceModal() { variant="ghost" color="gray" onClick={() => setShowPassword(!showPassword)} - style={{ cursor: 'pointer' }} + className="cursor-pointer" > {showPassword ? : } diff --git a/src/components/studio/BackupModal.tsx b/src/components/studio/BackupModal.tsx index a29734f..288a299 100644 --- a/src/components/studio/BackupModal.tsx +++ b/src/components/studio/BackupModal.tsx @@ -80,10 +80,10 @@ export default function BackupModal({ overflow: 'hidden' }}> - + General - + Files Generated ({backup.files?.length || 0}) @@ -220,7 +220,7 @@ export default function BackupModal({ {/* FOOTER */} - diff --git a/src/components/studio/CommitModal.tsx b/src/components/studio/CommitModal.tsx index 2e4f0f2..ca4525d 100644 --- a/src/components/studio/CommitModal.tsx +++ b/src/components/studio/CommitModal.tsx @@ -155,7 +155,7 @@ export default function CommitModal({ commitId, scope, onClose }: CommitModalPro - diff --git a/src/components/studio/CreateFileDialog.tsx b/src/components/studio/CreateFileDialog.tsx index 1380c05..03df7ab 100644 --- a/src/components/studio/CreateFileDialog.tsx +++ b/src/components/studio/CreateFileDialog.tsx @@ -93,7 +93,7 @@ export default function CreateFileDialog({ - diff --git a/src/components/studio/EnumModal.tsx b/src/components/studio/EnumModal.tsx index 93814fd..dbcc96e 100644 --- a/src/components/studio/EnumModal.tsx +++ b/src/components/studio/EnumModal.tsx @@ -73,11 +73,11 @@ export default function EnumModal({ onClose, enu, scope }: EnumModalProps) { overflow: 'hidden' }}> - General - + General + Members ({enu.members.length}) - + Methods ({Object.keys(enu.methods).length}) @@ -235,7 +235,7 @@ export default function EnumModal({ onClose, enu, scope }: EnumModalProps) { - + diff --git a/src/components/studio/EventArgsModal.tsx b/src/components/studio/EventArgsModal.tsx index e39de70..8bb5ebe 100644 --- a/src/components/studio/EventArgsModal.tsx +++ b/src/components/studio/EventArgsModal.tsx @@ -116,7 +116,7 @@ export default function EventArgsModal({ - diff --git a/src/components/studio/ModuleModal.tsx b/src/components/studio/ModuleModal.tsx index b892f28..9f7d6d2 100644 --- a/src/components/studio/ModuleModal.tsx +++ b/src/components/studio/ModuleModal.tsx @@ -79,13 +79,13 @@ export default function ModuleModal({ overflow: 'hidden' }}> - + General - + Configuration - + Exposes @@ -255,7 +255,7 @@ export default function ModuleModal({ {/* FOOTER */} - diff --git a/src/components/studio/ModulesPanel.tsx b/src/components/studio/ModulesPanel.tsx index 2112218..1023262 100644 --- a/src/components/studio/ModulesPanel.tsx +++ b/src/components/studio/ModulesPanel.tsx @@ -176,7 +176,7 @@ export default function ModulesPanel({ scope }: ModulesPanelProps) { variant="ghost" size="1" color="gray" - style={{ cursor: 'pointer' }} + className="cursor-pointer" asChild > fetchCounters()} - style={{ cursor: 'pointer' }} + className="cursor-pointer" > Refresh diff --git a/src/components/studio/NodeInfoPanel.tsx b/src/components/studio/NodeInfoPanel.tsx index 690da18..ed917bd 100644 --- a/src/components/studio/NodeInfoPanel.tsx +++ b/src/components/studio/NodeInfoPanel.tsx @@ -105,16 +105,16 @@ export default function NodeInfoPanel({ scope }: NodeInfoPanelProps) { - - - - diff --git a/src/components/studio/NodeInspectModal.tsx b/src/components/studio/NodeInspectModal.tsx index 8083973..f52da02 100644 --- a/src/components/studio/NodeInspectModal.tsx +++ b/src/components/studio/NodeInspectModal.tsx @@ -157,7 +157,7 @@ export default function NodeInspectModal({ isOpen, onOpenChange, nodeInfo, onRef - diff --git a/src/components/studio/NodeLogLevelModal.tsx b/src/components/studio/NodeLogLevelModal.tsx index 4a1eebe..0c2b969 100644 --- a/src/components/studio/NodeLogLevelModal.tsx +++ b/src/components/studio/NodeLogLevelModal.tsx @@ -64,7 +64,7 @@ export default function NodeLogLevelModal({ {LOG_LEVELS.map((level) => ( - + {level.name} ))} @@ -74,7 +74,7 @@ export default function NodeLogLevelModal({ - diff --git a/src/components/studio/NodeShutdownModal.tsx b/src/components/studio/NodeShutdownModal.tsx index c9c9eaf..5a59780 100644 --- a/src/components/studio/NodeShutdownModal.tsx +++ b/src/components/studio/NodeShutdownModal.tsx @@ -70,7 +70,7 @@ export default function NodeShutdownModal({ - diff --git a/src/components/studio/ProcedureModal.tsx b/src/components/studio/ProcedureModal.tsx index 7bab5dd..5c463ce 100644 --- a/src/components/studio/ProcedureModal.tsx +++ b/src/components/studio/ProcedureModal.tsx @@ -145,10 +145,10 @@ export default function ProcedureModal({ minHeight: 0 }}> - + Definition - + Execute @@ -329,7 +329,7 @@ export default function ProcedureModal({ - diff --git a/src/components/studio/QueryVarsDialog.tsx b/src/components/studio/QueryVarsDialog.tsx index 9829f44..37c77e0 100644 --- a/src/components/studio/QueryVarsDialog.tsx +++ b/src/components/studio/QueryVarsDialog.tsx @@ -75,7 +75,7 @@ export default function QueryVarsDialog({ - diff --git a/src/components/studio/RenameFileDialog.tsx b/src/components/studio/RenameFileDialog.tsx index f7353b7..e82d7a8 100644 --- a/src/components/studio/RenameFileDialog.tsx +++ b/src/components/studio/RenameFileDialog.tsx @@ -91,7 +91,7 @@ export default function RenameFileDialog({ - diff --git a/src/components/studio/RoomJoinModal.tsx b/src/components/studio/RoomJoinModal.tsx index cfd6f74..62f3235 100644 --- a/src/components/studio/RoomJoinModal.tsx +++ b/src/components/studio/RoomJoinModal.tsx @@ -232,7 +232,7 @@ export default function RoomJoinModal({ {/* FOOTER */} - diff --git a/src/components/studio/RoomsPanel.tsx b/src/components/studio/RoomsPanel.tsx index 802bef7..2ac1d8c 100644 --- a/src/components/studio/RoomsPanel.tsx +++ b/src/components/studio/RoomsPanel.tsx @@ -80,7 +80,7 @@ export default function RoomsPanel({ scope }: RoomsPanelProps) { variant="soft" color="iris" onClick={() => handleJoinRoomClick(null)} - style={{ cursor: 'pointer' }} + className="cursor-pointer" > diff --git a/src/components/studio/StudioConsoleHeader.tsx b/src/components/studio/StudioConsoleHeader.tsx index 6828da7..24c47e5 100644 --- a/src/components/studio/StudioConsoleHeader.tsx +++ b/src/components/studio/StudioConsoleHeader.tsx @@ -51,7 +51,7 @@ export default function StudioConsoleHeader({ size="1" value={consoleTab} onValueChange={(value) => setConsoleTab(value as StudioTab)} - style={{ cursor: 'pointer' }} + className="cursor-pointer" > Result diff --git a/src/components/studio/StudioEventView.tsx b/src/components/studio/StudioEventView.tsx index 70fb161..162157c 100644 --- a/src/components/studio/StudioEventView.tsx +++ b/src/components/studio/StudioEventView.tsx @@ -91,7 +91,7 @@ export default function StudioEventView() { variant="soft" color="gray" onClick={() => setSortNewestFirst((prev) => !prev)} - style={{ cursor: 'pointer' }} + className="cursor-pointer" > {sortNewestFirst ? ( <>Newest First @@ -105,7 +105,7 @@ export default function StudioEventView() { variant="soft" color="gray" onClick={clearEmitEvents} - style={{ cursor: 'pointer' }} + className="cursor-pointer" > diff --git a/src/components/studio/StudioLeftPanel.tsx b/src/components/studio/StudioLeftPanel.tsx index 63b4085..fa007e3 100644 --- a/src/components/studio/StudioLeftPanel.tsx +++ b/src/components/studio/StudioLeftPanel.tsx @@ -103,7 +103,7 @@ export default function StudioLeftPanel({ isCreateOpen, setIsCreateOpen }: Studi color="gray" disabled={loading || isRefreshing} onClick={handleRefreshClick} - style={{ cursor: 'pointer' }} + className="cursor-pointer" > @@ -115,7 +115,7 @@ export default function StudioLeftPanel({ isCreateOpen, setIsCreateOpen }: Studi color="iris" disabled={loading || isRefreshing} onClick={handleCreateClick} - style={{ cursor: 'pointer' }} + className="cursor-pointer" > diff --git a/src/components/studio/StudioLogView.tsx b/src/components/studio/StudioLogView.tsx index a70093a..9cbe17a 100644 --- a/src/components/studio/StudioLogView.tsx +++ b/src/components/studio/StudioLogView.tsx @@ -75,7 +75,7 @@ export default function StudioLogView() { variant="soft" color="gray" onClick={() => setSortNewestFirst((prev) => !prev)} - style={{ cursor: 'pointer' }} + className="cursor-pointer" > {sortNewestFirst ? ( <>Newest First @@ -89,7 +89,7 @@ export default function StudioLogView() { variant="soft" color="gray" onClick={clearWarnings} - style={{ cursor: 'pointer' }} + className="cursor-pointer" > diff --git a/src/components/studio/StudioTopBar.tsx b/src/components/studio/StudioTopBar.tsx index b370534..e5f5bd1 100644 --- a/src/components/studio/StudioTopBar.tsx +++ b/src/components/studio/StudioTopBar.tsx @@ -82,33 +82,19 @@ export default function StudioTopBar() { px="3" align="center" justify="between" - style={{ - height: 40, - borderBottom: '1px solid var(--gray-4)', - backgroundColor: 'var(--gray-2)', - position: 'relative', - zIndex: 2, - }} + className="h-10 border-b border-[var(--gray-4)] bg-[var(--gray-2)] relative z-10" > {/* Left side */} setIsAboutOpen(true)} - style={{ - cursor: 'pointer', - borderRadius: 'var(--radius-2)', - padding: '4px', - margin: '-4px', - display: 'inline-flex', - alignItems: 'center', - userSelect: 'none', - }} + className="cursor-pointer rounded-[var(--radius-2)] p-1 -m-1 inline-flex items-center select-none" title="About ThingsCode" > ThingsDB Logo @@ -125,13 +111,7 @@ export default function StudioTopBar() { @@ -143,7 +123,7 @@ export default function StudioTopBar() { loading={isExecuting || isRefreshing} disabled={!isTiCode} onClick={handleExecuteCode} - style={{ cursor: !isTiCode ? 'not-allowed' : 'pointer' }} + className={!isTiCode ? 'cursor-not-allowed' : 'cursor-pointer'} > @@ -157,7 +137,7 @@ export default function StudioTopBar() { disabled={!isTiCode || isRefreshing} onClick={() => setIsConfigOpen(true)} title="Edit Runtime Arguments" - style={{ cursor: !isTiCode || isRefreshing ? 'not-allowed' : 'pointer' }} + className={!isTiCode || isRefreshing ? 'cursor-not-allowed' : 'cursor-pointer'} > @@ -171,9 +151,9 @@ export default function StudioTopBar() { disabled={isRefreshing || loading} onClick={() => handleRefreshScopes()} title="Refresh Scopes" - style={{ cursor: isRefreshing || loading ? 'not-allowed' : 'pointer' }} + className={isRefreshing || loading ? 'cursor-not-allowed' : 'cursor-pointer'} > - + @@ -185,7 +165,7 @@ export default function StudioTopBar() { disabled={!isCollectionScope || isRefreshing || loading || isExplorerOpen} onClick={() => setIsExplorerOpen(true)} title="Open Thing Explorer" - style={{ cursor: !isCollectionScope || isRefreshing || loading || isExplorerOpen ? 'not-allowed' : 'pointer' }} + className={!isCollectionScope || isRefreshing || loading || isExplorerOpen ? 'cursor-not-allowed' : 'cursor-pointer'} > @@ -229,7 +209,7 @@ export default function StudioTopBar() { variant="ghost" size="2" color="gray" - style={{ cursor: 'pointer' }} + className="cursor-pointer" asChild > setIsSearchOpen(true)} disabled={isSearchOpen} size="2" - style={{ cursor: 'pointer' }} + className="cursor-pointer" color="gray" > @@ -283,7 +263,7 @@ export default function StudioTopBar() { variant="ghost" onClick={toggleAppearance} size="2" - style={{ cursor: 'pointer' }} + className="cursor-pointer" color="gray" > {appearance === 'dark' ? : } @@ -297,7 +277,7 @@ export default function StudioTopBar() { variant="ghost" onClick={() => setIsMyUserOpen(true)} size="2" - style={{ cursor: 'pointer' }} + className="cursor-pointer" color="gray" > diff --git a/src/components/studio/TaskModal.tsx b/src/components/studio/TaskModal.tsx index 85d1b64..68dc7ee 100644 --- a/src/components/studio/TaskModal.tsx +++ b/src/components/studio/TaskModal.tsx @@ -163,7 +163,7 @@ export default function TaskModal({ taskId, scope, onClose }: TaskModalProps) { - diff --git a/src/components/studio/TypeModal.tsx b/src/components/studio/TypeModal.tsx index 2702f38..5f8bab4 100644 --- a/src/components/studio/TypeModal.tsx +++ b/src/components/studio/TypeModal.tsx @@ -46,11 +46,11 @@ export default function TypeModal({ onClose, tp, onNavigateToType }: TypeModalPr overflow: 'hidden' }}> - General - + General + Fields ({tp.fields.length}) - + Methods ({Object.keys(tp.methods).length}) @@ -138,7 +138,7 @@ export default function TypeModal({ onClose, tp, onNavigateToType }: TypeModalPr - + diff --git a/src/components/studio/UserModal.tsx b/src/components/studio/UserModal.tsx index f81d6fa..93f09f6 100644 --- a/src/components/studio/UserModal.tsx +++ b/src/components/studio/UserModal.tsx @@ -92,14 +92,14 @@ export default function UserModal({ onClose, user }: UserModalProps) { overflow: 'hidden' }}> - General - + General + Scope Access ({user.access?.length || 0}) - + Tokens ({user.tokens?.length || 0}) - Whitelists + Whitelists @@ -293,7 +293,7 @@ export default function UserModal({ onClose, user }: UserModalProps) { {/* FOOTER */} - diff --git a/src/context/WorkspaceContext.tsx b/src/context/WorkspaceContext.tsx index e3db73a..469efdd 100644 --- a/src/context/WorkspaceContext.tsx +++ b/src/context/WorkspaceContext.tsx @@ -7,7 +7,6 @@ interface WorkspaceContextType { searchQuery: string; setSearchQuery: (query: string) => void; deleteWorkspace: (id: string) => void; - appearance: 'light' | 'dark'; editingWorkspace: Workspace | null; setEditingWorkspace: (ws: Workspace | null) => void; updateWorkspace: (updated: Workspace) => void; diff --git a/src/providers/WorkspaceProvider.tsx b/src/providers/WorkspaceProvider.tsx index 9a360b0..2cc6adb 100644 --- a/src/providers/WorkspaceProvider.tsx +++ b/src/providers/WorkspaceProvider.tsx @@ -7,10 +7,9 @@ import { errStr } from '../utils'; interface WorkspaceProviderProps { children: React.ReactNode; - appearance: 'light' | 'dark'; } -export function WorkspaceProvider({children, appearance}: WorkspaceProviderProps) { +export function WorkspaceProvider({children}: WorkspaceProviderProps) { const { status, emit } = useWebSocket(); const { setErrorMessage } = useError(); const [workspaces, setWorkspaces] = useState([]); @@ -119,7 +118,6 @@ export function WorkspaceProvider({children, appearance}: WorkspaceProviderProps searchQuery, setSearchQuery, deleteWorkspace, - appearance, editingWorkspace, setEditingWorkspace, updateWorkspace, From aa5efb97c8324de594417286ee21bf2939832491 Mon Sep 17 00:00:00 2001 From: Jeroen van der Heijden Date: Thu, 11 Jun 2026 11:27:02 +0200 Subject: [PATCH 7/8] update --- package-lock.json | 104 +++++++++++++++++++++++----------------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3351844..066d0be 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2426,13 +2426,13 @@ } }, "node_modules/@rsbuild/core": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@rsbuild/core/-/core-2.0.11.tgz", - "integrity": "sha512-Mpp/viUSkVdSWJkFipdZxM2nUztrBwSnMm6Q86bPzLHtHnXqQ3VFpSMlA4wWRyySNddP6s6efKiVpx0ZOCf7Gg==", + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@rsbuild/core/-/core-2.0.12.tgz", + "integrity": "sha512-6f0M9TO4pAeM/VAshg9PajYK4IbfUB21Xun2kT0q3/SbBQ607KzkQZ6fmReuKUKCLbo26tGnbgg5P77eDDcfaA==", "dev": true, "license": "MIT", "dependencies": { - "@rspack/core": "~2.0.6", + "@rspack/core": "~2.0.8", "@swc/helpers": "^0.5.23" }, "bin": { @@ -2493,28 +2493,28 @@ } }, "node_modules/@rspack/binding": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-2.0.7.tgz", - "integrity": "sha512-1LUIa0JeUSvuxf80+dIDLUbgnbYJk+44BmGDa8MMzQluC6AQczosAoXhz02oKMLJPMrr6p1DH0vjcafwor2IwA==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-2.0.8.tgz", + "integrity": "sha512-3uZ+y8aQxq33ty2srMxg2Nu0XuBI6vVrG50rkDaXqwWqOohfgGUSfFuQK7EnSUNy4aFUQlCG6NHialQHJov0wg==", "dev": true, "license": "MIT", "optionalDependencies": { - "@rspack/binding-darwin-arm64": "2.0.7", - "@rspack/binding-darwin-x64": "2.0.7", - "@rspack/binding-linux-arm64-gnu": "2.0.7", - "@rspack/binding-linux-arm64-musl": "2.0.7", - "@rspack/binding-linux-x64-gnu": "2.0.7", - "@rspack/binding-linux-x64-musl": "2.0.7", - "@rspack/binding-wasm32-wasi": "2.0.7", - "@rspack/binding-win32-arm64-msvc": "2.0.7", - "@rspack/binding-win32-ia32-msvc": "2.0.7", - "@rspack/binding-win32-x64-msvc": "2.0.7" + "@rspack/binding-darwin-arm64": "2.0.8", + "@rspack/binding-darwin-x64": "2.0.8", + "@rspack/binding-linux-arm64-gnu": "2.0.8", + "@rspack/binding-linux-arm64-musl": "2.0.8", + "@rspack/binding-linux-x64-gnu": "2.0.8", + "@rspack/binding-linux-x64-musl": "2.0.8", + "@rspack/binding-wasm32-wasi": "2.0.8", + "@rspack/binding-win32-arm64-msvc": "2.0.8", + "@rspack/binding-win32-ia32-msvc": "2.0.8", + "@rspack/binding-win32-x64-msvc": "2.0.8" } }, "node_modules/@rspack/binding-darwin-arm64": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-2.0.7.tgz", - "integrity": "sha512-P3PLEtJViDnjuKsgMgPPu8jAAybTHZSij8fFT7Oi5QwxcZD5Z8RvdxQE7Fjz47ng5RTSYSCaA0uIsiCl8TdEOQ==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-2.0.8.tgz", + "integrity": "sha512-vCgbgH7B7qom+uID+RCZsTCOYFb9wC4/4+1U6rMfytrXGVJ72eNQs2tbdjOl0lb18CT3N/n+VkWynUiLk84GwA==", "cpu": [ "arm64" ], @@ -2526,9 +2526,9 @@ ] }, "node_modules/@rspack/binding-darwin-x64": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-x64/-/binding-darwin-x64-2.0.7.tgz", - "integrity": "sha512-8mk94Cb1xlJ4m5ND/y84g8AA0nOG2/v7k58ElFG8ocTNqBnKYEgSgtNtDD5OxLcMvETOosE5oU+6SSuOqW6jCA==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-x64/-/binding-darwin-x64-2.0.8.tgz", + "integrity": "sha512-satPm2PD4B7jDTVlVAdvMVdUszwLvWUEnUDzLb77mvVkezKNDZmuhb+e8s+FfKs8hJpNbZ9VAejuA2rr8o985w==", "cpu": [ "x64" ], @@ -2540,9 +2540,9 @@ ] }, "node_modules/@rspack/binding-linux-arm64-gnu": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-2.0.7.tgz", - "integrity": "sha512-bBVJtZsh/eRF8Qt12JHjw46hvyJ3rT2pLmjS81qnA4gni0U7zD64QnR6C7Sg4++hhBgzYqbGeDkt5wcZa8qfMQ==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-2.0.8.tgz", + "integrity": "sha512-pSI+npPQE/uDtiboqvcOIRJbEV2+B+H1xffmko/gw50la92oTUW60kVULFwsb6L0+GVCzIcwX3yq60GtYIn+Ug==", "cpu": [ "arm64" ], @@ -2557,9 +2557,9 @@ ] }, "node_modules/@rspack/binding-linux-arm64-musl": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-2.0.7.tgz", - "integrity": "sha512-nrJXA3kFki/wZKmYqPo+hdtFmZ7q/HB2noP7oWcikUmCAzbJsXg4eNutjLW/Yj0DFm9TcFpRu/NWJ3L4fP86cQ==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-2.0.8.tgz", + "integrity": "sha512-igjJ43yxWQ72GZqjDDZSSHax9/Vg+6rLMmOvFglTJUkQpB4Tyvu/YjW+WRjYj2xRw6blOjLxUSJWASvuSqqlvg==", "cpu": [ "arm64" ], @@ -2574,9 +2574,9 @@ ] }, "node_modules/@rspack/binding-linux-x64-gnu": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-2.0.7.tgz", - "integrity": "sha512-rjIcfGfJ7/oVClJCmG6W54mIBgBBxsPodnIlrGz0bPKEZDP4NV2MCdSlujlDyeirMxvV9XL/WIuNSq9qAi2Syg==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-2.0.8.tgz", + "integrity": "sha512-zrkoEOnqj1hOEBO5T2I/2Ts2HSJsYFh1qXwMpK4dMJFGGNWDfNeUa6/LF5uq3VINF3JUl7RL47AgrucoSZJXPA==", "cpu": [ "x64" ], @@ -2591,9 +2591,9 @@ ] }, "node_modules/@rspack/binding-linux-x64-musl": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-2.0.7.tgz", - "integrity": "sha512-rSDC9+xCb3qgZg4iJbLn2I7bb37YnG+b4Vrb2Ems5FiP3s3KaBL+VGV98gOO4vtFJbML9oueMi16heoni7lMWw==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-2.0.8.tgz", + "integrity": "sha512-6CtDaGZjNDvJd9TBp7a9zABbrPORO21W96+3ZcGBn0YNUPUk4ARxIxrTTpeJ/1F41QDM8AYIkGDdqEYMqTYBsA==", "cpu": [ "x64" ], @@ -2608,9 +2608,9 @@ ] }, "node_modules/@rspack/binding-wasm32-wasi": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@rspack/binding-wasm32-wasi/-/binding-wasm32-wasi-2.0.7.tgz", - "integrity": "sha512-FyKTSsGpyB+HB9YFGcxd+SeMLpvecI6VbK0GFAYn+uIeDEWzG/t/rSXuXjXTUFJH6OLoMlr6IF0oh3hM1M1kgw==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@rspack/binding-wasm32-wasi/-/binding-wasm32-wasi-2.0.8.tgz", + "integrity": "sha512-Yf4SiqTUroT5Ju+te0YAY2xxKOb35tECsO21v7hYyGa705wrgoAK/MmF7enOvs9GR1iZIqgiLD/wxsIxl8GjJw==", "cpu": [ "wasm32" ], @@ -2624,9 +2624,9 @@ } }, "node_modules/@rspack/binding-win32-arm64-msvc": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-2.0.7.tgz", - "integrity": "sha512-JXs5GDk51Nv6n7/UpZPocyjshjYRSSaI1ih2Exrpb/QbePtQTXrRyiT5C8RHtZ89n6kGqybVZL96QrkVCTl8Gg==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-2.0.8.tgz", + "integrity": "sha512-8NCuiQsAhXrwRBy57QZoypqrws/zLBkaQVGiB8hksr6v++8hNigNjqpQARLbd0iyMuHsQQ++8+auGk6xlDXmzw==", "cpu": [ "arm64" ], @@ -2638,9 +2638,9 @@ ] }, "node_modules/@rspack/binding-win32-ia32-msvc": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-2.0.7.tgz", - "integrity": "sha512-kMjAWirDD+phbt3B0H1WRveYy86pekJyFxCJ21M/v0NQr/4Sa41nvduCHMWkpLVn0v47mjf1ehWGV6leO8gwDQ==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-2.0.8.tgz", + "integrity": "sha512-bxiekytbX7V9KFAra+HkwtNWC6pYfHEBBZFpiT0xUs3mCFOmAAFVBsBSQsoCP9AdCEXoMAvNdnrHNw3iov4OZw==", "cpu": [ "ia32" ], @@ -2652,9 +2652,9 @@ ] }, "node_modules/@rspack/binding-win32-x64-msvc": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-2.0.7.tgz", - "integrity": "sha512-auYSWDTRUxbjmUBbpF4ZWVD+gbuAm9STfsgaUI1Q5Zp13z8/9bWdGLVgaR4rzuyD/hUsRMGXFJz8BxMKT9oZBw==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-2.0.8.tgz", + "integrity": "sha512-7zPs8YCe/ZVJTwd+5lpB0CP0tkn2pONf/T1ycmVY76u21Nrwt8mXQGc/2yH2eWP4B7fikYBr3hGr7mpR2fajqQ==", "cpu": [ "x64" ], @@ -2666,13 +2666,13 @@ ] }, "node_modules/@rspack/core": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@rspack/core/-/core-2.0.7.tgz", - "integrity": "sha512-6L8f1Hzgimft/p5adFk1l0rHJlBygQ3Bosfi07807nZCIe2SdPt1bkymCd1oaFiMNkhgQ30XUBNEuemX9jmI3g==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@rspack/core/-/core-2.0.8.tgz", + "integrity": "sha512-+NLGJf8gZxihDmMFzjlly3toc2SMjeDmuvz0/Cai9AMdV4F+Pqcnt2BA9V4e3SY2jmhJQtPwgyyLtR1RiJO77g==", "dev": true, "license": "MIT", "dependencies": { - "@rspack/binding": "2.0.7" + "@rspack/binding": "2.0.8" }, "engines": { "node": "^20.19.0 || >=22.12.0" @@ -4067,7 +4067,7 @@ }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.2-alpha0.tgz", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true, "license": "MIT" From 2e9ba11a5bf62adc50f0bc3d2636ec5cb247967e Mon Sep 17 00:00:00 2001 From: Jeroen van der Heijden Date: Thu, 11 Jun 2026 12:12:12 +0200 Subject: [PATCH 8/8] Lint identation --- eslint.config.mjs | 3 +- src/components/ConnectionOverlay.tsx | 2 +- src/components/FieldsTab.tsx | 4 +- src/components/QuickConnectModal.tsx | 34 +- src/components/Search.tsx | 36 +- src/components/ThingExplorer.tsx | 18 +- src/components/WorkspaceLauncher.tsx | 38 +- src/components/WorkspaceModal.tsx | 24 +- src/components/studio/BackupModal.tsx | 24 +- .../studio/CollectionContextPanel.tsx | 14 +- src/components/studio/CommitModal.tsx | 16 +- src/components/studio/EnumModal.tsx | 2 +- src/components/studio/HistoryPanel.tsx | 22 +- src/components/studio/ModuleModal.tsx | 34 +- src/components/studio/NodeContextPanel.tsx | 8 +- src/components/studio/ProcedureModal.tsx | 6 +- src/components/studio/RoomJoinModal.tsx | 2 +- src/components/studio/ScopeSelector.tsx | 8 +- src/components/studio/StudioConsoleHeader.tsx | 8 +- src/components/studio/StudioEventView.tsx | 38 +- src/components/studio/StudioLeftPanel.tsx | 14 +- src/components/studio/TaskModal.tsx | 6 +- .../studio/ThingsDBContextPanel.tsx | 10 +- src/components/studio/TypeModal.tsx | 2 +- src/components/studio/UserModal.tsx | 20 +- src/components/studio/UserPanel.tsx | 14 +- src/providers/WebSocketProvider.tsx | 11 +- src/utils/index.ts | 12 +- src/utils/language.ts | 712 +++++++++--------- 29 files changed, 571 insertions(+), 571 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 5214e1a..6aa4007 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -19,7 +19,8 @@ export default defineConfig([ globals: globals.browser, }, rules: { - "semi": ["error", "always"] + "semi": ["error", "always"], + "indent": ["error", 2] } }, ]); diff --git a/src/components/ConnectionOverlay.tsx b/src/components/ConnectionOverlay.tsx index dd2cc24..4dffc8a 100644 --- a/src/components/ConnectionOverlay.tsx +++ b/src/components/ConnectionOverlay.tsx @@ -8,7 +8,7 @@ export default function ConnectionOverlay() { const [showOverlay, setShowOverlay] = useState(() => status !== 'connected'); const [prevStatus, setPrevStatus] = useState(status); -if (status !== prevStatus) { + if (status !== prevStatus) { setPrevStatus(status); if (status !== 'connected') { setShowOverlay(true); diff --git a/src/components/FieldsTab.tsx b/src/components/FieldsTab.tsx index 693a991..2258529 100644 --- a/src/components/FieldsTab.tsx +++ b/src/components/FieldsTab.tsx @@ -134,8 +134,8 @@ export default function FieldsTab({ tp, onNavigateToType }: FieldsTabProps) { const cardinalityColor = cardinality === '1:1' ? 'iris' : - cardinality === '1:N' ? 'orange' : - cardinality === 'N:1' ? 'yellow' : 'pink'; + cardinality === '1:N' ? 'orange' : + cardinality === 'N:1' ? 'yellow' : 'pink'; return ( diff --git a/src/components/QuickConnectModal.tsx b/src/components/QuickConnectModal.tsx index a20b72f..1e881a7 100644 --- a/src/components/QuickConnectModal.tsx +++ b/src/components/QuickConnectModal.tsx @@ -55,12 +55,12 @@ export default function QuickConnectModal() { }} > - + Quick Connect - + - Establish a temporary session link. This configuration won't be saved to your workspaces list. + Establish a temporary session link. This configuration won't be saved to your workspaces list.
@@ -117,33 +117,33 @@ export default function QuickConnectModal() { {/* Auth */} {authType === 'token' ? ( - ) : ( - + - Username - setUsername(e.target.value)} required /> + Username + setUsername(e.target.value)} required /> - Password - setPassword(e.target.value)} required> + Password + setPassword(e.target.value)} required> - setShowPassword(!showPassword)} className="cursor-pointer"> + setShowPassword(!showPassword)} className="cursor-pointer"> {showPassword ? : } - + - + - + )} diff --git a/src/components/Search.tsx b/src/components/Search.tsx index 839d184..34029a1 100644 --- a/src/components/Search.tsx +++ b/src/components/Search.tsx @@ -59,25 +59,25 @@ export default function TicodeSearch({ if (filteredResults.length === 0) return; switch (e.key) { - case 'ArrowDown': - e.preventDefault(); - setSelectedIndex((prev) => (prev + 1) % filteredResults.length); - break; - case 'ArrowUp': - e.preventDefault(); - setSelectedIndex((prev) => (prev - 1 + filteredResults.length) % filteredResults.length); - break; - case 'Enter': - e.preventDefault(); - if (filteredResults[selectedIndex]) { - onSelect(filteredResults[selectedIndex]); - onClose(); - } - break; - case 'Escape': - e.preventDefault(); + case 'ArrowDown': + e.preventDefault(); + setSelectedIndex((prev) => (prev + 1) % filteredResults.length); + break; + case 'ArrowUp': + e.preventDefault(); + setSelectedIndex((prev) => (prev - 1 + filteredResults.length) % filteredResults.length); + break; + case 'Enter': + e.preventDefault(); + if (filteredResults[selectedIndex]) { + onSelect(filteredResults[selectedIndex]); onClose(); - break; + } + break; + case 'Escape': + e.preventDefault(); + onClose(); + break; } }, [filteredResults, selectedIndex, onSelect, onClose] diff --git a/src/components/ThingExplorer.tsx b/src/components/ThingExplorer.tsx index 3823deb..c83d885 100644 --- a/src/components/ThingExplorer.tsx +++ b/src/components/ThingExplorer.tsx @@ -54,15 +54,15 @@ export default function ThingExplorer({ scope, startThingId }: ThingExplorerProp maxHeight: '100%' }} > - + ); } diff --git a/src/components/WorkspaceLauncher.tsx b/src/components/WorkspaceLauncher.tsx index 05c89bb..0110d2f 100644 --- a/src/components/WorkspaceLauncher.tsx +++ b/src/components/WorkspaceLauncher.tsx @@ -99,27 +99,27 @@ export default function WorkspaceLauncher() { > {ws.name} - - - {ws.host}:{ws.port} - - {ws.type === 'production' && ( - - PRD - - )} + + + {ws.host}:{ws.port} + + {ws.type === 'production' && ( + + PRD + + )} - {ws.type === 'staging' && ( - - STG - - )} + {ws.type === 'staging' && ( + + STG + + )} - {ws.type === 'development' && ( - - DEV - - )} + {ws.type === 'development' && ( + + DEV + + )} diff --git a/src/components/WorkspaceModal.tsx b/src/components/WorkspaceModal.tsx index 5f65a35..e7945a1 100644 --- a/src/components/WorkspaceModal.tsx +++ b/src/components/WorkspaceModal.tsx @@ -17,7 +17,7 @@ export default function WorkspaceModal() { if (editingWorkspace?.id !== prevId) { setPrevId(editingWorkspace?.id); - setForm({...editingWorkspace}); + setForm({ ...editingWorkspace }); } if (!editingWorkspace) return null; @@ -168,17 +168,17 @@ export default function WorkspaceModal() { onChange={e => setForm({ ...form, token: e.target.value })} > - setShowToken(!showToken)} - className="cursor-pointer" - > - {showToken ? : } - - - + setShowToken(!showToken)} + className="cursor-pointer" + > + {showToken ? : } + + + ) : ( diff --git a/src/components/studio/BackupModal.tsx b/src/components/studio/BackupModal.tsx index 288a299..90c8d4f 100644 --- a/src/components/studio/BackupModal.tsx +++ b/src/components/studio/BackupModal.tsx @@ -35,12 +35,12 @@ export default function BackupModal({ return ( {/* HEADER */} @@ -121,12 +121,12 @@ export default function BackupModal({ {backup.nextRun && ( Next Run - - - - {new Date(backup.nextRun).toLocaleString(undefined, {hour12: false})} - - + + + + {new Date(backup.nextRun).toLocaleString(undefined, { hour12: false })} + + )} diff --git a/src/components/studio/CollectionContextPanel.tsx b/src/components/studio/CollectionContextPanel.tsx index dd67699..6d8021c 100644 --- a/src/components/studio/CollectionContextPanel.tsx +++ b/src/components/studio/CollectionContextPanel.tsx @@ -51,7 +51,7 @@ export default function CollectionContextPanel({ scope, requireCommit }: Collect align="center" justify="between" py="1" - style={{ cursor: 'pointer', userSelect: 'none' }} + className="cursor-pointer select-none" onClick={() => toggleSection('rooms')} > Rooms @@ -66,7 +66,7 @@ export default function CollectionContextPanel({ scope, requireCommit }: Collect align="center" justify="between" py="1" - style={{ cursor: 'pointer', userSelect: 'none' }} + className="cursor-pointer select-none" onClick={() => toggleSection('tasks')} > Tasks @@ -81,7 +81,7 @@ export default function CollectionContextPanel({ scope, requireCommit }: Collect align="center" justify="between" py="1" - style={{ cursor: 'pointer', userSelect: 'none' }} + className="cursor-pointer select-none" onClick={() => toggleSection('procedures')} > Procedures @@ -96,7 +96,7 @@ export default function CollectionContextPanel({ scope, requireCommit }: Collect align="center" justify="between" py="1" - style={{ cursor: 'pointer', userSelect: 'none' }} + className="cursor-pointer select-none" onClick={() => toggleSection('enums')} > Enums @@ -111,7 +111,7 @@ export default function CollectionContextPanel({ scope, requireCommit }: Collect align="center" justify="between" py="1" - style={{ cursor: 'pointer', userSelect: 'none' }} + className="cursor-pointer select-none" onClick={() => toggleSection('types')} > Types @@ -126,7 +126,7 @@ export default function CollectionContextPanel({ scope, requireCommit }: Collect align="center" justify="between" py="1" - style={{ cursor: 'pointer', userSelect: 'none' }} + className="cursor-pointer select-none" onClick={() => toggleSection('explorer')} > Explorer @@ -142,7 +142,7 @@ export default function CollectionContextPanel({ scope, requireCommit }: Collect align="center" justify="between" py="1" - style={{ cursor: 'pointer', userSelect: 'none' }} + className="cursor-pointer select-none" onClick={() => toggleSection('history')} > History diff --git a/src/components/studio/CommitModal.tsx b/src/components/studio/CommitModal.tsx index ca4525d..0faf4c9 100644 --- a/src/components/studio/CommitModal.tsx +++ b/src/components/studio/CommitModal.tsx @@ -48,9 +48,9 @@ export default function CommitModal({ commitId, scope, onClose }: CommitModalPro return ( { if (!open) onClose(); }}> @@ -105,15 +105,15 @@ export default function CommitModal({ commitId, scope, onClose }: CommitModalPro gap="2" p="2" style={{ - backgroundColor: 'var(--gray-2)', - borderRadius: 'var(--radius-3)', - border: '1px solid var(--gray-4)', + backgroundColor: 'var(--gray-2)', + borderRadius: 'var(--radius-3)', + border: '1px solid var(--gray-4)', }} > - + - {new Date(commit.createdOn).toLocaleString(undefined, {hour12: false})} + {new Date(commit.createdOn).toLocaleString(undefined, { hour12: false })} diff --git a/src/components/studio/EnumModal.tsx b/src/components/studio/EnumModal.tsx index dbcc96e..714325b 100644 --- a/src/components/studio/EnumModal.tsx +++ b/src/components/studio/EnumModal.tsx @@ -71,7 +71,7 @@ export default function EnumModal({ onClose, enu, scope }: EnumModalProps) { flexDirection: 'column', minHeight: 0, overflow: 'hidden' - }}> + }}> General diff --git a/src/components/studio/HistoryPanel.tsx b/src/components/studio/HistoryPanel.tsx index a862744..5880980 100644 --- a/src/components/studio/HistoryPanel.tsx +++ b/src/components/studio/HistoryPanel.tsx @@ -38,18 +38,18 @@ export default function HistorysPanel({ scope }: HistorysPanelProps) { queueMicrotask(fetchHistory); }, [fetchHistory]); - const filtered = useMemo(() => { - const cleanedQuery = searchQuery.trim().toLowerCase(); - if (!cleanedQuery) { - return commits; - } + const filtered = useMemo(() => { + const cleanedQuery = searchQuery.trim().toLowerCase(); + if (!cleanedQuery) { + return commits; + } - return commits.filter((commit) => { - const messageMatch = commit.message?.toLowerCase().includes(cleanedQuery); + return commits.filter((commit) => { + const messageMatch = commit.message?.toLowerCase().includes(cleanedQuery); - return messageMatch; - }); - }, [commits, searchQuery]); + return messageMatch; + }); + }, [commits, searchQuery]); return ( @@ -152,7 +152,7 @@ export default function HistorysPanel({ scope }: HistorysPanelProps) { const hasError = !!commit.errMsg; let displayTime; try { - displayTime = new Date(commit.createdOn).toLocaleString(undefined, {hour12: false}); + displayTime = new Date(commit.createdOn).toLocaleString(undefined, { hour12: false }); } catch { displayTime = 'Invalid Date'; } diff --git a/src/components/studio/ModuleModal.tsx b/src/components/studio/ModuleModal.tsx index 9f7d6d2..ab47e3c 100644 --- a/src/components/studio/ModuleModal.tsx +++ b/src/components/studio/ModuleModal.tsx @@ -34,12 +34,12 @@ export default function ModuleModal({ return ( {/* HEADER */} @@ -108,7 +108,7 @@ export default function ModuleModal({ - {new Date(module.createdAt).toLocaleString(undefined, {hour12: false})} + {new Date(module.createdAt).toLocaleString(undefined, { hour12: false })} @@ -203,11 +203,11 @@ export default function ModuleModal({ /> ) : ( - - - No configuration for this module. - - + + + No configuration for this module. + + )} @@ -241,11 +241,11 @@ export default function ModuleModal({ /> ) : ( - - - No methods exposed on this module. - - + + + No methods exposed on this module. + + )} diff --git a/src/components/studio/NodeContextPanel.tsx b/src/components/studio/NodeContextPanel.tsx index f896b06..e6d80f3 100644 --- a/src/components/studio/NodeContextPanel.tsx +++ b/src/components/studio/NodeContextPanel.tsx @@ -47,7 +47,7 @@ export default function NodeContextPanel({ scope }: NodeContextPanelProps) { align="center" justify="between" py="1" - style={{ cursor: 'pointer', userSelect: 'none' }} + className="cursor-pointer select-none" onClick={() => toggleSection('node-info')} > Node Info @@ -64,7 +64,7 @@ export default function NodeContextPanel({ scope }: NodeContextPanelProps) { align="center" justify="between" py="1" - style={{ cursor: 'pointer', userSelect: 'none' }} + className="cursor-pointer select-none" onClick={() => toggleSection('counters')} > Counters @@ -81,7 +81,7 @@ export default function NodeContextPanel({ scope }: NodeContextPanelProps) { align="center" justify="between" py="1" - style={{ cursor: 'pointer', userSelect: 'none' }} + className="cursor-pointer select-none" onClick={() => toggleSection('backups')} > Backups @@ -96,7 +96,7 @@ export default function NodeContextPanel({ scope }: NodeContextPanelProps) { align="center" justify="between" py="1" - style={{ cursor: 'pointer', userSelect: 'none' }} + className="cursor-pointer select-none" onClick={() => toggleSection('modules')} > Modules diff --git a/src/components/studio/ProcedureModal.tsx b/src/components/studio/ProcedureModal.tsx index 5c463ce..5042614 100644 --- a/src/components/studio/ProcedureModal.tsx +++ b/src/components/studio/ProcedureModal.tsx @@ -100,9 +100,9 @@ export default function ProcedureModal({ return ( diff --git a/src/components/studio/RoomJoinModal.tsx b/src/components/studio/RoomJoinModal.tsx index 62f3235..84031be 100644 --- a/src/components/studio/RoomJoinModal.tsx +++ b/src/components/studio/RoomJoinModal.tsx @@ -40,7 +40,7 @@ export default function RoomJoinModal({ setName(room.name); setCode(room.code || ''); setValidationError(null); - }); + }); } else { queueMicrotask(() => { setName(''); diff --git a/src/components/studio/ScopeSelector.tsx b/src/components/studio/ScopeSelector.tsx index dc01624..8e3baef 100644 --- a/src/components/studio/ScopeSelector.tsx +++ b/src/components/studio/ScopeSelector.tsx @@ -2,10 +2,10 @@ import { Select, Flex } from '@radix-ui/themes'; import { useActiveWorkspace } from '../../hooks'; interface ScopeSelectorProps { - disabled: boolean; + disabled: boolean; } -export default function ScopeSelector({disabled} : ScopeSelectorProps) { +export default function ScopeSelector({ disabled }: ScopeSelectorProps) { const { loading, activeScope, setActiveScopeState, scopes } = useActiveWorkspace(); if (loading) return null; @@ -19,8 +19,8 @@ export default function ScopeSelector({disabled} : ScopeSelectorProps) { onValueChange={setActiveScopeState} > {scopes.map((scope) => ( diff --git a/src/components/studio/StudioConsoleHeader.tsx b/src/components/studio/StudioConsoleHeader.tsx index 24c47e5..949dcc8 100644 --- a/src/components/studio/StudioConsoleHeader.tsx +++ b/src/components/studio/StudioConsoleHeader.tsx @@ -23,9 +23,9 @@ export default function StudioConsoleHeader({ const { activeFile } = useActiveWorkspace(); const { emitEvents, warnings } = useEvent(); - const result = useMemo(() => { - return activeFile?.result || null; - }, [activeFile?.result]); + const result = useMemo(() => { + return activeFile?.result || null; + }, [activeFile?.result]); return ( setConsoleTab(value as StudioTab)} className="cursor-pointer" > - + Result diff --git a/src/components/studio/StudioEventView.tsx b/src/components/studio/StudioEventView.tsx index 162157c..ff042d7 100644 --- a/src/components/studio/StudioEventView.tsx +++ b/src/components/studio/StudioEventView.tsx @@ -48,12 +48,12 @@ export default function StudioEventView() { const query = searchQuery.trim().toLowerCase(); const filtered = query ? formatted.filter((item) => { - return ( - item.event.toLowerCase().includes(query) || - item.roomId.toString().includes(query) || - JSON.stringify(item.args).toLowerCase().includes(query) - ); - }) + return ( + item.event.toLowerCase().includes(query) || + item.roomId.toString().includes(query) || + JSON.stringify(item.args).toLowerCase().includes(query) + ); + }) : formatted; // Sort based on time @@ -122,19 +122,19 @@ export default function StudioEventView() { - {searchQuery && ( - - setSearchQuery('')} - style={{ cursor: 'pointer', height: '16px', width: '16px' }} - > - - - - )} + {searchQuery && ( + + setSearchQuery('')} + style={{ cursor: 'pointer', height: '16px', width: '16px' }} + > + + + + )} diff --git a/src/components/studio/StudioLeftPanel.tsx b/src/components/studio/StudioLeftPanel.tsx index fa007e3..1dca5f8 100644 --- a/src/components/studio/StudioLeftPanel.tsx +++ b/src/components/studio/StudioLeftPanel.tsx @@ -120,7 +120,7 @@ export default function StudioLeftPanel({ isCreateOpen, setIsCreateOpen }: Studi - + {/* Search */} @@ -265,12 +265,12 @@ export default function StudioLeftPanel({ isCreateOpen, setIsCreateOpen }: Studi /> )} file.filename)} - onRename={handleRenameConfirm} + key={`rename-${fileToRename}-${isRenameOpen}`} + isOpen={isRenameOpen} + onOpenChange={setIsRenameOpen} + filename={fileToRename} + existingFiles={files.map(file => file.filename)} + onRename={handleRenameConfirm} /> { if (!open) onClose(); }}> diff --git a/src/components/studio/ThingsDBContextPanel.tsx b/src/components/studio/ThingsDBContextPanel.tsx index 5bff893..deb4061 100644 --- a/src/components/studio/ThingsDBContextPanel.tsx +++ b/src/components/studio/ThingsDBContextPanel.tsx @@ -49,7 +49,7 @@ export default function ThingsDBContextPanel({ scope, requireCommit }: ThingsDBC align="center" justify="between" py="1" - style={{ cursor: 'pointer', userSelect: 'none' }} + className="cursor-pointer select-none" onClick={() => toggleSection('tasks')} > Tasks @@ -64,7 +64,7 @@ export default function ThingsDBContextPanel({ scope, requireCommit }: ThingsDBC align="center" justify="between" py="1" - style={{ cursor: 'pointer', userSelect: 'none' }} + className="cursor-pointer select-none" onClick={() => toggleSection('procedures')} > Procedures @@ -79,7 +79,7 @@ export default function ThingsDBContextPanel({ scope, requireCommit }: ThingsDBC align="center" justify="between" py="1" - style={{ cursor: 'pointer', userSelect: 'none' }} + className="cursor-pointer select-none" onClick={() => toggleSection('users')} > Users @@ -94,7 +94,7 @@ export default function ThingsDBContextPanel({ scope, requireCommit }: ThingsDBC align="center" justify="between" py="1" - style={{ cursor: 'pointer', userSelect: 'none' }} + className="cursor-pointer select-none" onClick={() => toggleSection('modules')} > Modules @@ -110,7 +110,7 @@ export default function ThingsDBContextPanel({ scope, requireCommit }: ThingsDBC align="center" justify="between" py="1" - style={{ cursor: 'pointer', userSelect: 'none' }} + className="cursor-pointer select-none" onClick={() => toggleSection('history')} > History diff --git a/src/components/studio/TypeModal.tsx b/src/components/studio/TypeModal.tsx index 5f8bab4..6919645 100644 --- a/src/components/studio/TypeModal.tsx +++ b/src/components/studio/TypeModal.tsx @@ -44,7 +44,7 @@ export default function TypeModal({ onClose, tp, onNavigateToType }: TypeModalPr flexDirection: 'column', minHeight: 0, overflow: 'hidden' - }}> + }}> General diff --git a/src/components/studio/UserModal.tsx b/src/components/studio/UserModal.tsx index 93f09f6..6f41572 100644 --- a/src/components/studio/UserModal.tsx +++ b/src/components/studio/UserModal.tsx @@ -38,11 +38,11 @@ export default function UserModal({ onClose, user }: UserModalProps) { let badgeColor: 'blue' | 'orange' | 'amber' | 'green' | 'purple' = 'blue'; switch (token.trim()) { - case 'CHANGE': badgeColor = 'orange'; break; - case 'GRANT': badgeColor = 'amber'; break; - case 'JOIN': badgeColor = 'purple'; break; - case 'RUN': badgeColor = 'green'; break; - case 'QUERY': badgeColor = 'blue'; break; + case 'CHANGE': badgeColor = 'orange'; break; + case 'GRANT': badgeColor = 'amber'; break; + case 'JOIN': badgeColor = 'purple'; break; + case 'RUN': badgeColor = 'green'; break; + case 'QUERY': badgeColor = 'blue'; break; } return ( @@ -116,9 +116,9 @@ export default function UserModal({ onClose, user }: UserModalProps) { Created Timestamp - + - {new Date(user.createdAt * 1000).toLocaleString(undefined, {hour12: false})} + {new Date(user.createdAt * 1000).toLocaleString(undefined, { hour12: false })} @@ -174,7 +174,7 @@ export default function UserModal({ onClose, user }: UserModalProps) { No access tokens. ) : ( - + @@ -222,13 +222,13 @@ export default function UserModal({ onClose, user }: UserModalProps) { )} - {new Date(token.createdOn).toLocaleString(undefined, {hour12: false})} + {new Date(token.createdOn).toLocaleString(undefined, { hour12: false })} {token.expirationTime === 'never' ? ( 'Never' ) : ( - new Date(token.expirationTime).toLocaleString(undefined, {hour12: false}) + new Date(token.expirationTime).toLocaleString(undefined, { hour12: false }) )} diff --git a/src/components/studio/UserPanel.tsx b/src/components/studio/UserPanel.tsx index cb8d1db..f432a2a 100644 --- a/src/components/studio/UserPanel.tsx +++ b/src/components/studio/UserPanel.tsx @@ -159,19 +159,19 @@ export default function UsersPanel() { > - + > {user.name} - + diff --git a/src/providers/WebSocketProvider.tsx b/src/providers/WebSocketProvider.tsx index 0433be0..a33a66a 100644 --- a/src/providers/WebSocketProvider.tsx +++ b/src/providers/WebSocketProvider.tsx @@ -37,8 +37,8 @@ export function WebSocketProvider({ children }: WebSocketProviderProps) { const connect = useCallback(function connect(): void { if (socketRef.current && ( - socketRef.current.readyState === WebSocket.CONNECTING || - socketRef.current.readyState === WebSocket.OPEN)) { + socketRef.current.readyState === WebSocket.CONNECTING || + socketRef.current.readyState === WebSocket.OPEN)) { return; } setStatus('connecting'); @@ -136,11 +136,10 @@ export function WebSocketProvider({ children }: WebSocketProviderProps) { return ( + status, + emit, + }}> {children} ); } - diff --git a/src/utils/index.ts b/src/utils/index.ts index 812510d..67243fd 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,12 +1,12 @@ export { renderTextWithLinks } from './renderWithLinks'; export const errStr = (err: unknown, fallback: string) => { - const message = err instanceof Error - ? err.message - : typeof err === 'string' - ? err - : fallback; - return message; + const message = err instanceof Error + ? err.message + : typeof err === 'string' + ? err + : fallback; + return message; }; type Cardinality = '1:1' | '1:N' | 'N:1' | 'N:N'; diff --git a/src/utils/language.ts b/src/utils/language.ts index 5420b43..a8d38bc 100644 --- a/src/utils/language.ts +++ b/src/utils/language.ts @@ -1,364 +1,364 @@ export const LanguageData = { - types: { - bytes: { - 'len': 'Returns the length of the bytes value.', - }, - closure: { - 'call': 'Call a closure.', - 'doc': 'Returns a doc string from a closure. An empty string ("") is returned if the closure has no doc string.' - }, - datetime: { - 'extract': 'Return a thing with second, minute, hour, day, month, year and gmt_offset as individual properties.', - 'format': 'Returns a string representation for a datetime object using a custom format.', - 'move': 'Return a new datetime (or timeval) object, which is shifted in time relative to the original date/time.', - 'replace': 'Return a new datetime (or timeval) object with altered properties. The new properties must be given by a thing.', - 'to': 'Return a new datetime (or timeval) object with new time zone information. Note that the proper time does not change, only the time zone will change.', - 'week': 'Return the week of the year as an integer between 0..53. Week 1 starts at the first Sunday in January.', - 'weekday':'Return the number of days (0..6) since the last Sunday.', - 'yday': 'Return the day in the year as an integer value between 0..365 where the first of January is day 0.', - 'zone': 'Return zone information as a string about the datetime (or timeval) object. If no zone information is available, nil will be returned.', - }, - enum: { - 'name': 'Return the name of the enum member.', - 'value': 'Return the value of the enum member.', - }, - error: { - 'code': 'Returns the error code of an error type.', - 'msg': 'Returns the error message of an error type.', - }, - future: { - 'then': 'Function then accepts a closure as argument which will be executed only when the future is successful. The code inside the closure will only generate a change then the closure code is executed. The return value of the closure will be used as the new future value.', - 'else': 'Function else accepts a closure as argument which will be executed only when the future is using a module which has failed with some error. The code inside the closure will only generate a change when the closure code is executed. The return value of the closure will be used as the new future value.', - }, - int: { - 'bit_count': 'Return the number of ones in the binary representation of the absolute value of the integer.', - }, - list: { - 'choice': 'This function returns a pseudo-random item from the list. The list must contain at least one item, otherwise a lookup_err() is raised.', - 'clear': 'Removes all items from a list.', - 'copy': 'Copy a list.', - 'count': 'Returns the number of times a value appears in a list. A closure might be given which can be used as a shortcut for .filter().len().', - 'each': 'Iterate over all the items in an list or tuple. Use this functions instead of map when you are not interested in the return value.', - 'every': 'This function tests whether all elements in the array pass a given test. It returns a boolean value.', - 'extend': 'Adds a list or tuple with items to the end of a list, and returns the new length.', - 'extend_unique': 'Adds a list or tuple with items to the end of a list, and returns the new length. Only items which do not have a duplicate in the list will be added.', - 'fill': 'Fills a list with a given value.', - 'filter': 'When this method is used on an list or tuple, a new list is returned with elements that pass the test.', - 'find': 'This function returns the value of the first element in the list or tuple that satisfies the callback function. Otherwise nil is returned unless an alternative return value is specified.', - 'find_index': 'This function returns the index of the first element in a list or tuple that satisfies the callback function. Otherwise nil is returned.', - 'first':'Returns the first item in the list. A lookup_err() is raised when this function is used on an empty list unless a default value is given, in which case the given value will be returned.', - 'flat': 'The function returns a new list with all tuple elements concatenated into it recursively up to a specified depth.', - 'has':'Return true if a given value is found in the list, or false if not found.', - 'index_of': 'Returns the first index at which a given value can be found in the list or tuple, or nil if it is not present. The index of an array starts at 0, so the first item has index 0 the second 1 and so on.', - 'is_unique': 'This function determines whether each item in a list is unique or not.', - 'join': 'This function returns a new string by concatenating all items in a list or tuple. All items in the list or tuple must be of type str, otherwise a type_err() is raised.', - 'last':'Returns the last item in the list. A lookup_err() is raised when this function is used on an empty list unless a default value is given, in which case the given value will be returned.', - 'len': 'Returns the length of a list or tuple.', - 'map': 'Iterate over items in an list or tuple.', - 'map_id': 'The function must be called on a list with things and returns a new list with the Ids of all the things.', - 'map_type': 'The function must be called on a list with Ids (integer values) or things and returns a new list with the Ids and things converted to corresponding typed things.', - 'map_wrap': 'The function must be called on a list with things and returns a new list with every thing wrapped according the given type.', - 'max': 'Returns the maximum value from a list or tuple.', - 'min': 'Returns the minimum value from a list or tuple.', - 'pop': 'Removes the last element from a list and returns that element. This method changes the length of the list. The pop() method works on a list type array, but not on a tuple since tuples are immutable.', - 'push': 'Adds new items to the end of an list, and returns the new length', - 'reduce': 'Executes a given reducer closure on each element of the list, resulting in a single output value.', - 'remove': 'This function removes and returns the value of the first element in the list that satisfies the callback function. Otherwise nil is returned unless an alternative return value is specified.', - 'reverse': 'Return a new list with the items in reverse order.', - 'shift': 'Remove the first item from a list and returns that item.', - 'some': 'This function tests whether at least one element in the array passes a given test. It returns a boolean value.', - 'sort': 'When this method is used on an list or tuple, a new sorted list is returned.', - 'splice': 'The splice() method changes the contents of an list by removing or replacing existing elements and/or adding new elements in place.', - 'sum': 'Returns the sum of each value in a list. A closure might be given which can be used as a shortcut for .map().sum().', - 'unique': 'This function returns a new list where each item in the list is unique. If duplicated items are found, the first item will be retained.', - 'unshift': 'Add new items to the start of a list and returns the new length.', - }, - mpdata: { - 'len': 'Returns the length of mpdata in bytes.', - 'load': 'Load mpdata into ThingsDB.' - }, - room: { - 'emit': 'Emit an event to all clients which have joined this room. The event is a string value which you are free to choose. It is possible, but not required, to send extra arguments with the event.', - 'id': 'Returns the id of a room or nil if the room is not stored.', - 'set_name': 'Set the name of a room.', - }, - regex: { - 'match': '', - 'test': 'Test if a string matches a given regular expression and return true or false.', - }, - set: { - 'add': 'Adds new thing to the set and returns the number of things which are actually added to the set. For example my_set.add(#42); will return 0 if my_set already contains thing #42.', - 'clear': 'Removes all things from a set.', - 'each': 'Iterate over items in an set.', - 'every': 'This function checks if all things in the set pass a given test. It returns a boolean value.', - 'filter': 'When this method is used on a set, then the return value will be a new set.', - 'find': 'This function returns the value of the first element in the set that satisfies the callback function. Otherwise nil is returned unless an alternative return value is specified.', - 'has': 'Determines if a set has a given thing.', - 'len': 'Returns the length of a set.', - 'map': 'Iterate over items in an set.', - 'map_id': 'The function returns a list with the Ids of all the things in the set.', - 'map_wrap': 'The function returns a list with every thing wrapped according the given type.', - 'one': 'This function returns a thing from a set. The set must contain at least one thing, otherwise a lookup_err() is raised.', - 'reduce': 'Executes a given reducer closure on every thing in the set, accumulating to a single return value.', - 'remove': 'This function can be used to remove things from a set. If a closure is used, then all things that satisfy the test are removed from the set and returned as list. The order of the removed things is not guaranteed since the set itself is unordered. It is also possible to specify things as arguments. In this case a list is returned with all the things which are removed from the set, in the order that the arguments are used. Things which are not found in the set are ignored.', - 'some': 'This function checks if at least one thing in the set passes a given test. It returns a boolean value.', - }, - string: { - 'contains': 'Determines if a given string is a substring of a string.', - 'ends_with': 'Determines if a string ends with characters given by another string.', - 'len': 'Returns the length of a string.', - 'lower': 'Return a new string in which all case-based characters are in lower case.', - 'replace': 'Returns a new string in witch occurrences of a given substring are replaced with another substring.', - 'split': 'Split a string into a new list with substrings.', - 'starts_with': 'Determines if a string starts with characters given by another string.', - 'trim': 'Returns a new string with whitespace characters removed from both the start and end of a string.', - 'trim_left': 'Returns a new string with whitespace characters removed from the start of a string.', - 'trim_right': 'Returns a new string with whitespace characters removed from the the end of a string.', - 'upper': 'Return a new string in which all case-based characters are in upper case.', - }, - task: { - 'again_at': 'Re-schedule a task at a specific date/time.', - 'again_in': 'Re-schedule a task relative to the original start time.', - 'args': 'Get a new list with then task arguments.', - 'at': 'Get the task scheduled date/time.', - 'cancel': 'Cancel a task.', - 'closure': 'Return the closure of the task.', - 'del': 'Delete a task.', - 'err': 'Get the task error (if any).', - 'id': 'Return id of the task or nil when the task is removed.', - 'owner': 'Return the owner name of the task.', - 'set_args': 'Set task arguments.', - 'set_closure': 'Set a new closure (code to execute) for an existing task.', - 'set_owner': 'Change the owner of a task.', - }, - thing: { - 'assign': 'Copies properties from a given thing. Existing properties will be overwritten and new properties will be added. If this function is used on an instance of a custom Type, all properties of the source must be valid according the type specification, otherwise an exception will be raised and no properties will be copied.', - 'clear': 'Removes all properties from a thing.', - 'copy': 'Copy a thing to a new thing. A Type is not preserved.', - 'del': 'Delete a property from a thing.', - 'dup': 'Duplicate a thing while preserving the Type.', - 'each': 'Iterate over all properties on a thing.', - 'equals': 'Determines if a thing is equal to another thing.', - 'filter': 'When this method is used on a thing, then a new thing will be returned with only the properties that pass the test.', - 'get': 'Return the value of a property on a thing by a given property name. If the property is not found then the return value will be nil, unless an alternative return value is given.', - 'has': 'Determines if a thing has a given property.', - 'id': 'Returns the id of a thing or nil if the thing is not stored.', - 'keys': 'Returns an list with all the property names of a thing. The same could be returned using map so the following statement is true: (.keys() == .map(|k| k))', - 'len': 'Returns the number of items in a thing.', - 'map': 'Iterate over all properties on a thing.', - 'remove': 'This function removes all properties from a thing that satisfies the callback function. The removed values will be returned in a new list. An empty list is returned if no values are removed.', - 'ren': 'Rename a property on a thing.', - 'restrict': 'Set or remove a value restriction on a thing. Function restriction() can be used to view the current restriction.', - 'restriction': 'Returns the value restriction of a thing as type str or nil when the thing is not value restricted.', - 'set': 'Creates a new property on a thing. If the property already existed then the old property will be overwritten. This function is equal to an assignment except that it can be used when the name of the property is dynamic.', - 'search': 'Find the parent(s) of a given thing.', - 'to_type': 'Converts a thing into an instance of a given Type.', - 'values': 'Returns an list with all the property values of a thing. The same could be returned using map so the following statement is true: (.values() == .map(|_, v| v))', - 'vmap': 'The function returns a new thing with equal keys but values computed as a result of a given closure callback.', - 'wrap': 'Wrap a thing with a Type.', - }, - typed: { - 'to_thing': 'Converts a typed thing into a thing.' - }, - type: { - 'copy': 'Copy a thing to a new thing. A Type is not preserved.', - 'dup': 'Duplicate a thing while preserving the Type.', - 'unwrap': 'Unwrap a wrapped thing.', - } + types: { + bytes: { + 'len': 'Returns the length of the bytes value.', }, - collection: { - 'alt_raise': 'This function will try a statement. If the statement is successful it will just return the result but in case of an error, it will re-raise the error using a given error code.', - 'ano': 'Creates an anomymous type.', - 'assert': 'Raises ASSERTION_ERROR if the specified statement evaluates to false.', - 'base64_decode': 'Decode a Base64 encoded string.', - 'base64_encode': 'Encode a str or bytes value using Base64.', - 'bool': 'Returns an bool from a specified value. If no value is given, false is returned.', - 'bytes': 'Convert a value to a byte sequence. If no value is given, an empty byte sequence is returned.', - 'commit': 'Saves a commit for the current query.', - 'datetime': 'Returns a datetime depending on some optional values.', - 'deep': 'Returns the current deep value. The deep value might change when a function with a return(..) is called which has changed the deep value for this query.', - 'del_enum': 'Delete an enumerator.', - 'del_type': 'Deletes an existing Type. It is not possible to delete a Type which is used by another type. You should first change or delete the other type before you are able to delete this type. See the example below.', - 'enum': 'Get an enum member by value', - 'enum_info': 'Return info about the enumerator type.', - 'enum_map': 'Returns a thing with key/value pairs for all the members of a given enum.', - 'enums_info': 'Return info about all the enumerator types in the current scope', - 'err': 'Returns an error.', - 'export': 'This function can be used to export the collection structure as a readable string with ThingsDB code. The function is also capable of exporting the full collection. This full collection export is returned as bytes which then can be imported in a new collection using the import(..) function.', - 'change_id': 'Returns the current change Id for the running query. The return value will be nil if the query does not require a change.', - 'float': 'Returns a float from a specified value. If no value is given, the default float 0.0 is returned. If the specified value is of type raw, then the initial characters of the string are converted until a non-digit character is found. Initial white space is ignored and the number may start with an optional + or - sign. Type bool values are converted to 1.0 for true and 0.0 for false.', - 'future': 'Returns a future. It is not possible to assign a future to a collection or add the future to a list. If you do, then nil will be assigned instead.', - 'has_enum': 'Determine if the current scope has a given enumerator type', - 'has_type': 'Determines if a Type exists in the current @collection scope.', - 'import': 'This function can be used to import a collection which was exported using the export(..) function with the option dump enabled.', - 'int': 'Returns an int from a specified value. If no value is given, the default integer 0 is returned. If the specified value was a float value, then the new integer value will be rounded towards zero. If the specified value is of type raw, then the initial characters of the string are converted until a non-digit character is found. Initial white space is ignored and the number may start with an optional + or - sign. Type bool values are converted to 1 for true and 0 for false.', - 'is_array': 'This function determines whether the value passed to this function is an array type or not. The functions is_lis_t and is_tuple can be used to check if the array is mutable.', - 'is_ascii': 'This function determines whether the value passed to this function is of type raw and contains only valid ascii characters.', - 'is_bool': 'This function determines whether the value passed to this function is a bool or not.', - 'is_bytes': 'This function determines whether the value passed to this function is of type bytes or not.', - 'is_closure': 'This function determines whether the provided value is a closure or not.', - 'is_datetime': 'This function determines whether the provided value is of type datetime.', - 'is_email': 'This function determines whether the provided value is of type str and contains an email address.', - 'is_enum': 'Test if a given value is a member of an enumerator type', - 'is_err': 'This function determines whether the value passed to this function is a error or not.', - 'is_float': 'This function determines whether the value passed to this function is a floating point value or not.', - 'is_future': 'This function determines whether the provided value is a future value or not.', - 'is_mpdata': 'This function determines whether the provided value is raw MessagePack data or not.', - 'is_inf': 'This function determines whether the provided value is a positive or negative infinity.', - 'is_int': 'This function determines whether the value passed to this function is an integer or not.', - 'is_list': 'This function determines whether the value passed to this function is a mutable array or not.', - 'is_module': 'This function determines whether the provided value is a module value or not.', - 'is_nan': 'This function determines whether the value passed to this function is a number. Returns true is the given value is not a number, else false.', - 'is_nil': 'This function determines whether the value passed to this function is nil.', - 'is_raw': 'This function determines whether the value passed to this function is of type raw.', - 'is_regex': 'This function determines whether the provided value is of type regex or not.', - 'is_room': 'This function determines whether the provided value is a room or not.', - 'is_set': 'This function determines whether the value passed to this function is a set or not.', - 'is_str': 'This function determines whether the value passed to this function is of type raw and contains valid utf8. Alias for is_utf8.', - 'is_task': 'This function determines whether the provided value is a task or not.', - 'is_tel': 'is function determines whether the provided value is of type str and contains a telephone number.', - 'is_thing': 'This function determines whether the value passed to this function is a thing or not.', - 'is_time_zone': 'This function determines whether the provided value is of type str and contains a valid time zone.', - 'is_timeval': 'This function determines whether the provided value is of type timeval.', - 'is_tuple': 'This function determines whether the value passed to this function is a immutable array or not. At least nested arrays are of kind tuple.', - 'is_url': 'This function determines whether the provided value is of type str and contains a URL. A valid URL must start with either http:/// , https:// or ftp://.', - 'is_utf8': 'This function determines whether the value passed to this function is of type raw and contains valid utf8.', - 'json_dump': 'Converts a ThingsDB value in to a JSON string.', - 'json_load': 'Converts a JSON string into a ThingsDB value.', - 'list': 'Returns a new empty list or returns a list for a given set.', - 'log': 'Might be used for debugging code. The message will be logged as a warning message on the console of the node which is processing the request. When you are connected using a socket stream, then a warning message with code 2 will be send to the client as well.', - 'mod_enum': 'Modify an existing enumerator type', - 'mod_type': 'This function is used to modify an existing Type. A number of actions can be performed with this function.', - 'new': 'Creates a new instance of a defined Type.', - 'new_type': 'Creates a new Type. This function only creates a new type and does not allow you to specify any fields. With the set_type() function you can define the fields for the new type.', - 'now': 'Return the time in seconds since the epoch as a floating point number. If you require the same time multiple times within a query, then call now() only once and save it to a variable, for example now = now();', - 'nse': 'This function promises ThingsDB that your code has no-side-effects and therefore does not require a change.', - 'raise': 'Raises an error.', - 'rand': 'Returns pseudo-random random number between 0.0 and 1.0.', - 'randint': 'Returns pseudo-random random integer number between a given range. The first argument specifies the start of the range and must have a value less than the second argument when specifies the end of the range. The start is inclusive and the end is exclusive, for example: randint(0, 2) will return either 0 or 1.', - 'randstr': 'Returns a string with random characters.', - 'range': 'This function returns a list of numbers, starting from 0 by default, and increments by 1 (by default), and ends at a specified number.', - 'refs': 'Returns the reference count of a value. The count returned is generally one higher than you might expect, because it includes the (temporary) reference.', - 'regex': 'This function can be used to create a regular expression from a given pattern with optional flags.', - 'rename_enum': 'Rename an enum type.', - 'rename_type': 'Rename a type.', - 'room': 'Returns a room from a specified value, that may be dynamic. If no value is given, a new room is returned.', - 'root': 'Returns the root for the current collection or nil when the current scope is not a collection scope.', - 'set': 'Returns a new empty set. If an array is given, then all elements in the given array must be or type thing and a new set is returned based on the given things. Instead of an array, it is also possible to provide things comma separated.', - 'set_enum': 'Create a new enumerator type', - 'set_type': 'Defines the properties of a Type. Function set_type works only on a new type. Use mod_type() if you want to change an existing type, see mod_type.', - 'str': 'Convert a value to a string. If no value is given, an empty string "" is returned. When bytes are converted to str then the data will be checked if it contains valid UTF-8 characters. If this is not the case, a VALUE_ERROR will be raised.', - 'task': 'Create a new task or get an existing task by Id.', - 'tasks': 'Return a list with all the tasks in the current scope.', - 'thing': 'Returns a thing from a specified value. If no value is given, a new thing is returned.', - 'time_zones_info': 'Returns all available time zones in ThingsDB.', - 'timeit': 'The timeit function can be used to check the duration of some code. It only measures the execution time of the code and does not include additional change creation and does not wait for futures to be completed.', - 'timeval': 'Returns a timeval depending on some optional values.', - 'try': 'Try a statement and if the statement fails with an error, then the error is returned. It is also possible to catch only specific errors.', - 'type': 'Returns the type name of a value.', - 'type_all': 'Returns a set with all instances of a given Type within a collection.', - 'type_assert': 'Raises a type_err() if the specified expression evaluates to false.', - 'type_count': 'Returns the number of instances of a given Type within a collection.', - 'type_info': 'Returns information about a given Type.', - 'types_info': 'Returns Type information about all the types within a collection.', - 'wse': 'Stored closures which can potentially make changes to ThingsDB are called closures with side effects and must be wrapped with the wse(..) function. This allows ThingsDB before running the query to make a change.', - 'abs': 'Return the absolute value of a given number.', - 'ceil': 'Return the ceiling of a given number. This is the smallest integer >= the given number.', - 'cos': 'Return the cosine of a given number. The value passed in this function should be in radians.', - 'exp': 'Returns e raised to the power of x.', - 'floor': 'Return the floor of a given number. This is the largest integer <= the given number.', - 'log10': 'Return the base 10 logarithm of a given number.', - 'log2': 'Return the base 2 logarithm of a given number.', - 'loge': 'Returns the natural logarithm (base e) of a given number.', - 'pow': 'Returns x to the power of y.', - 'round': 'Return a number that will be rounded to the decimal places which are given as input.', - 'sin': 'Return the sine of a given number. The value passed in this function should be in radians', - 'sqrt': 'Return the square root of a given number.', - 'tan': 'Return the tangent of a given number. The value passed in this function should be in radians.', + closure: { + 'call': 'Call a closure.', + 'doc': 'Returns a doc string from a closure. An empty string ("") is returned if the closure has no doc string.' }, - errors: { - 'assert_err': 'Returns an error when an assertion has failed.', - 'auth_err': 'Returns an error when authentication has failed.', - 'bad_data_err': 'Returns an error when a request is malformed.', - 'forbidden_err': 'Returns an error when the client or user is missing the required privileges.', - 'lookup_err': 'Returns an error when a requested resource is not found or when an index is out-of-range.', - 'max_quota_err': 'Returns an error when a quota limit is reached.', - 'node_err': 'Returns an error when a node was not able to handle the request.', - 'num_arguments_err': 'Returns an error when a wrong number of arguments is given.', - 'operation_err': 'Returns an error when an operation is not valid within the current context.', - 'overflow_err': 'Returns an error when an attempt is made to create an integer value out of the supported 64Bit (signed) range.', - 'syntax_err': 'Returns an error when the given ThingsDB code contains a syntax error.', - 'type_err': 'Returns an error when a given value is of the incorrect type.', - 'value_err': 'Returns an error when a given value has the correct type but contains invalid data.', - 'cancelled_err': 'Returns an error when an operation is cancelled before completion. Fox example by a time-out or stop of service.', - 'zero_div_err': 'Returns an error when an attempt is made to divide or take a modulo by zero.', + datetime: { + 'extract': 'Return a thing with second, minute, hour, day, month, year and gmt_offset as individual properties.', + 'format': 'Returns a string representation for a datetime object using a custom format.', + 'move': 'Return a new datetime (or timeval) object, which is shifted in time relative to the original date/time.', + 'replace': 'Return a new datetime (or timeval) object with altered properties. The new properties must be given by a thing.', + 'to': 'Return a new datetime (or timeval) object with new time zone information. Note that the proper time does not change, only the time zone will change.', + 'week': 'Return the week of the year as an integer between 0..53. Week 1 starts at the first Sunday in January.', + 'weekday': 'Return the number of days (0..6) since the last Sunday.', + 'yday': 'Return the day in the year as an integer value between 0..365 where the first of January is day 0.', + 'zone': 'Return zone information as a string about the datetime (or timeval) object. If no zone information is available, nil will be returned.', }, - node: { - 'backup_info': 'Returns information about a specific scheduled backup.', - 'backups_info': 'Returns backup schedule information for all backup schedules in the selected node scope.', - 'backups_ok': 'Returns false if at least one backup had failed (result code != 0). In all other cases this function returns true (also when no backups are available or not yet started).', - 'counters': 'Returns counters for the ThingsDB node you are connected too. Counters start all at zero when ThingsDB is started, or when the counters are reset by using reset_counters()’. Counters give information about things, queries and changes. If you suspect failed queries, then counters might provide you with more information.', - 'del_backup': 'Delete a scheduled backup. If the schedule was pending, the backup job will be cancelled.', - 'has_backup': 'Determines if a backup exists in ThingsDB.', - 'new_backup': 'Schedule a new backup. Backups are created using tar and gzip. Once a backup is made, the .tar.gz backup file can be used to recover ThingsDB, or can be used to load the ThingsDB into another node. The result value is a backup ID. This ID can be used by backup_info(..) for details about the backup schedule job, or can be used to delete the backup schedule.', - 'node_info': 'Returns information about the connected node.', - 'nodes_info': 'Returns information about all ThingsDB nodes.', - 'reset_counters': 'Resets the counters for the ThingsDB node you are connected too. Other nodes are not affected', - 'restart_module': 'Restarts a given module.', - 'set_log_level': 'Change the log level for the node in the selected scope. ThingsDB will then log all levels greater than or equal to the specified level. For example, a default log_level of warning will log warning, error and critical messages.', - 'shutdown':'Shutdown the node in the selected scope. This is a clean shutdown, allowing all other nodes (and clients) to disconnect.', + enum: { + 'name': 'Return the name of the enum member.', + 'value': 'Return the value of the enum member.', }, - thingsdb: { - 'collection_info': 'Returns information about a specific collection. This function requires QUERY privileges on the requested collection, or CHANGE privileges on the @thingsdb scope.', - 'collections_info': 'Returns collection information for all collections in ThingsDB.', - 'del_collection': 'Delete a collection.', - 'del_expired': 'Delete all expired tokens. Extends to all users.', - 'del_history': 'Delete commit records from history based on a given filter.', - 'del_module': 'Delete a module. A SIGTERM signal will be send to the process for the module which might cancel running futures.', - 'del_node': 'Delete a node from ThingsDB.', - 'del_token': 'Delete a token.', - 'del_user': 'Delete a user. It is not possible to delete your own user account and a BAD_REQUEST will be raised in case you try to. Any tokens associated with the user will also be deleted.', - 'deploy_module': 'Deploy a module on all nodes. The module must be configured first, using the new_module() function. This function is used to write the module data (or plain python code) to the module. After deploying the code, the module will be restarted on every node.', - 'grant': 'Grant collection or general privileges to a user. Access to a user is provided by setting a bit mask to either the .node scope, .thingsdb scope or a collection. Privileges to ThingsDB gives a user the ability to view counters, add, view remove users etc.', - 'has_collection': 'Determines if a collection exists in ThingsDB.', - 'has_module': 'Determines if a module exists in ThingsDB. The scope restriction of the module has no impact on the result of this function.', - 'has_node': 'Determines if a node exists in ThingsDB', - 'has_token': 'Determines if a token exists in ThingsDB.', - 'has_user': 'Determines if a user exists in ThingsDB.', - 'history': 'List commit records from history based on a given filter.', - 'module_info': 'Returns information about a specific module.', - 'modules_info': 'Returns module information about all modules in ThingsDB.', - 'new_collection': 'Create a new collection.', - 'new_module': 'Configures a new module for ThingsDB.', - 'new_node': 'Adds a new node to ThingsDB. Nodes are used for scaling and high availability.', - 'new_token': 'Adds a new token for a given user. An optional expiration time may be given after which the token cannot be used anymore. Use del_expired to cleanup expired tokens. The expiration time may be given as a UNIX time-stamp in seconds or a date/time string. It is also possible to set a description for the token which can be used to identify where token is used for. If you only want to set a description, but no expiration time, then you can use nil as second argument.', - 'new_user': 'Creates a new user to ThingsDB. The new user is created without a password, token and access privileges. You probably want to set a password or add a new token and assign some privileges using grant(…).', - 'refresh_module': 'Refresh module first stops the module (if running), next if will check for an update and performs the update if required. When finished, it will start the module again.', - 'rename_collection': 'Rename a collection.', - 'rename_module': 'Rename a module.', - 'rename_user': 'Rename a user.', - 'restore': 'Restore from a backup file created with the new_backup function.', - 'revoke': 'Revoke collection or general privileges from a user. See grant for more information on how access privileges can be set for a user.', - 'set_default_deep': 'The deep value determines how many levels of data are returned by a query. Only things count towards this value.', - 'set_history': 'Enables “commit history” for a given scope. Commit history can be enabled for collections scopes and the @thingsdb scope.', - 'set_module_conf': 'Change the module configuration. This will (re-send) the module configuration to the module. If the module was not started, ThingsDB will also auto-load the module and send the configuration. Any Value is accepted as config but value nil will not be considered as a configuration and thus will not be send to the module.', - 'set_module_scope': 'Modules can be restricted for usage in a single scope. This can be a @collection:.. scope, but also a @node or @thingsdb scope. This function can be used to change the module scope. When the scope is set to nil, the module can be used in any scope.', - 'set_password': 'Change a users password. This function can also be used to remove an existing password by using nil as the new password. Passwords must contain 1 to 128 printable characters.', - 'set_time_zone': 'By default each collection will be created with time zone UTC. This function can be used to change the time zone for a collection. If changed, the functions datetime(..) and timeval(..) will use the collections time zone unless specified otherwise.', - 'user_info': 'Returns information about a user. If no argument is given, this method will return information about the current logged in user.', - 'users_info': 'Returns user information for all users withing ThingsDB. This function requires GRANT privileges on the .thingsdb scope since it exposes user access and token information.', - 'whitelist_add': 'Add a new rule to the whitelist', - 'whitelist_del': 'Deletes an existing rule from a whitelist or removes all rules, effectively disabling the whitelist.', + error: { + 'code': 'Returns the error code of an error type.', + 'msg': 'Returns the error message of an error type.', }, - procedures: { - 'del_procedure': 'Delete a procedure.', - 'has_procedure': 'Determines if a procedure exists in the current scope.', - 'mod_procedure': 'Changes the closure for an existing procedure. This function also updates the created_at time as if it is a new procedure.', - 'new_procedure': 'Creates a new procedure to the @thingsdb or a @collection scope. The name of the procedure must be unique within the scope. The given closure will be copied to the procedure, so this is not a reference to a given closure.', - 'procedure_doc': 'Returns the doc string for a given procedure. An empty string is returned if the procedure has no doc string.', - 'procedure_info': 'Returns information about a procedure.', - 'procedures_info': 'Returns procedure information for all procedures in the scope.', - 'rename_procedure': 'Rename a procedure.', - 'run': 'Run a procedure.', + future: { + 'then': 'Function then accepts a closure as argument which will be executed only when the future is successful. The code inside the closure will only generate a change then the closure code is executed. The return value of the closure will be used as the new future value.', + 'else': 'Function else accepts a closure as argument which will be executed only when the future is using a module which has failed with some error. The code inside the closure will only generate a change when the closure code is executed. The return value of the closure will be used as the new future value.', }, + int: { + 'bit_count': 'Return the number of ones in the binary representation of the absolute value of the integer.', + }, + list: { + 'choice': 'This function returns a pseudo-random item from the list. The list must contain at least one item, otherwise a lookup_err() is raised.', + 'clear': 'Removes all items from a list.', + 'copy': 'Copy a list.', + 'count': 'Returns the number of times a value appears in a list. A closure might be given which can be used as a shortcut for .filter().len().', + 'each': 'Iterate over all the items in an list or tuple. Use this functions instead of map when you are not interested in the return value.', + 'every': 'This function tests whether all elements in the array pass a given test. It returns a boolean value.', + 'extend': 'Adds a list or tuple with items to the end of a list, and returns the new length.', + 'extend_unique': 'Adds a list or tuple with items to the end of a list, and returns the new length. Only items which do not have a duplicate in the list will be added.', + 'fill': 'Fills a list with a given value.', + 'filter': 'When this method is used on an list or tuple, a new list is returned with elements that pass the test.', + 'find': 'This function returns the value of the first element in the list or tuple that satisfies the callback function. Otherwise nil is returned unless an alternative return value is specified.', + 'find_index': 'This function returns the index of the first element in a list or tuple that satisfies the callback function. Otherwise nil is returned.', + 'first': 'Returns the first item in the list. A lookup_err() is raised when this function is used on an empty list unless a default value is given, in which case the given value will be returned.', + 'flat': 'The function returns a new list with all tuple elements concatenated into it recursively up to a specified depth.', + 'has': 'Return true if a given value is found in the list, or false if not found.', + 'index_of': 'Returns the first index at which a given value can be found in the list or tuple, or nil if it is not present. The index of an array starts at 0, so the first item has index 0 the second 1 and so on.', + 'is_unique': 'This function determines whether each item in a list is unique or not.', + 'join': 'This function returns a new string by concatenating all items in a list or tuple. All items in the list or tuple must be of type str, otherwise a type_err() is raised.', + 'last': 'Returns the last item in the list. A lookup_err() is raised when this function is used on an empty list unless a default value is given, in which case the given value will be returned.', + 'len': 'Returns the length of a list or tuple.', + 'map': 'Iterate over items in an list or tuple.', + 'map_id': 'The function must be called on a list with things and returns a new list with the Ids of all the things.', + 'map_type': 'The function must be called on a list with Ids (integer values) or things and returns a new list with the Ids and things converted to corresponding typed things.', + 'map_wrap': 'The function must be called on a list with things and returns a new list with every thing wrapped according the given type.', + 'max': 'Returns the maximum value from a list or tuple.', + 'min': 'Returns the minimum value from a list or tuple.', + 'pop': 'Removes the last element from a list and returns that element. This method changes the length of the list. The pop() method works on a list type array, but not on a tuple since tuples are immutable.', + 'push': 'Adds new items to the end of an list, and returns the new length', + 'reduce': 'Executes a given reducer closure on each element of the list, resulting in a single output value.', + 'remove': 'This function removes and returns the value of the first element in the list that satisfies the callback function. Otherwise nil is returned unless an alternative return value is specified.', + 'reverse': 'Return a new list with the items in reverse order.', + 'shift': 'Remove the first item from a list and returns that item.', + 'some': 'This function tests whether at least one element in the array passes a given test. It returns a boolean value.', + 'sort': 'When this method is used on an list or tuple, a new sorted list is returned.', + 'splice': 'The splice() method changes the contents of an list by removing or replacing existing elements and/or adding new elements in place.', + 'sum': 'Returns the sum of each value in a list. A closure might be given which can be used as a shortcut for .map().sum().', + 'unique': 'This function returns a new list where each item in the list is unique. If duplicated items are found, the first item will be retained.', + 'unshift': 'Add new items to the start of a list and returns the new length.', + }, + mpdata: { + 'len': 'Returns the length of mpdata in bytes.', + 'load': 'Load mpdata into ThingsDB.' + }, + room: { + 'emit': 'Emit an event to all clients which have joined this room. The event is a string value which you are free to choose. It is possible, but not required, to send extra arguments with the event.', + 'id': 'Returns the id of a room or nil if the room is not stored.', + 'set_name': 'Set the name of a room.', + }, + regex: { + 'match': '', + 'test': 'Test if a string matches a given regular expression and return true or false.', + }, + set: { + 'add': 'Adds new thing to the set and returns the number of things which are actually added to the set. For example my_set.add(#42); will return 0 if my_set already contains thing #42.', + 'clear': 'Removes all things from a set.', + 'each': 'Iterate over items in an set.', + 'every': 'This function checks if all things in the set pass a given test. It returns a boolean value.', + 'filter': 'When this method is used on a set, then the return value will be a new set.', + 'find': 'This function returns the value of the first element in the set that satisfies the callback function. Otherwise nil is returned unless an alternative return value is specified.', + 'has': 'Determines if a set has a given thing.', + 'len': 'Returns the length of a set.', + 'map': 'Iterate over items in an set.', + 'map_id': 'The function returns a list with the Ids of all the things in the set.', + 'map_wrap': 'The function returns a list with every thing wrapped according the given type.', + 'one': 'This function returns a thing from a set. The set must contain at least one thing, otherwise a lookup_err() is raised.', + 'reduce': 'Executes a given reducer closure on every thing in the set, accumulating to a single return value.', + 'remove': 'This function can be used to remove things from a set. If a closure is used, then all things that satisfy the test are removed from the set and returned as list. The order of the removed things is not guaranteed since the set itself is unordered. It is also possible to specify things as arguments. In this case a list is returned with all the things which are removed from the set, in the order that the arguments are used. Things which are not found in the set are ignored.', + 'some': 'This function checks if at least one thing in the set passes a given test. It returns a boolean value.', + }, + string: { + 'contains': 'Determines if a given string is a substring of a string.', + 'ends_with': 'Determines if a string ends with characters given by another string.', + 'len': 'Returns the length of a string.', + 'lower': 'Return a new string in which all case-based characters are in lower case.', + 'replace': 'Returns a new string in witch occurrences of a given substring are replaced with another substring.', + 'split': 'Split a string into a new list with substrings.', + 'starts_with': 'Determines if a string starts with characters given by another string.', + 'trim': 'Returns a new string with whitespace characters removed from both the start and end of a string.', + 'trim_left': 'Returns a new string with whitespace characters removed from the start of a string.', + 'trim_right': 'Returns a new string with whitespace characters removed from the the end of a string.', + 'upper': 'Return a new string in which all case-based characters are in upper case.', + }, + task: { + 'again_at': 'Re-schedule a task at a specific date/time.', + 'again_in': 'Re-schedule a task relative to the original start time.', + 'args': 'Get a new list with then task arguments.', + 'at': 'Get the task scheduled date/time.', + 'cancel': 'Cancel a task.', + 'closure': 'Return the closure of the task.', + 'del': 'Delete a task.', + 'err': 'Get the task error (if any).', + 'id': 'Return id of the task or nil when the task is removed.', + 'owner': 'Return the owner name of the task.', + 'set_args': 'Set task arguments.', + 'set_closure': 'Set a new closure (code to execute) for an existing task.', + 'set_owner': 'Change the owner of a task.', + }, + thing: { + 'assign': 'Copies properties from a given thing. Existing properties will be overwritten and new properties will be added. If this function is used on an instance of a custom Type, all properties of the source must be valid according the type specification, otherwise an exception will be raised and no properties will be copied.', + 'clear': 'Removes all properties from a thing.', + 'copy': 'Copy a thing to a new thing. A Type is not preserved.', + 'del': 'Delete a property from a thing.', + 'dup': 'Duplicate a thing while preserving the Type.', + 'each': 'Iterate over all properties on a thing.', + 'equals': 'Determines if a thing is equal to another thing.', + 'filter': 'When this method is used on a thing, then a new thing will be returned with only the properties that pass the test.', + 'get': 'Return the value of a property on a thing by a given property name. If the property is not found then the return value will be nil, unless an alternative return value is given.', + 'has': 'Determines if a thing has a given property.', + 'id': 'Returns the id of a thing or nil if the thing is not stored.', + 'keys': 'Returns an list with all the property names of a thing. The same could be returned using map so the following statement is true: (.keys() == .map(|k| k))', + 'len': 'Returns the number of items in a thing.', + 'map': 'Iterate over all properties on a thing.', + 'remove': 'This function removes all properties from a thing that satisfies the callback function. The removed values will be returned in a new list. An empty list is returned if no values are removed.', + 'ren': 'Rename a property on a thing.', + 'restrict': 'Set or remove a value restriction on a thing. Function restriction() can be used to view the current restriction.', + 'restriction': 'Returns the value restriction of a thing as type str or nil when the thing is not value restricted.', + 'set': 'Creates a new property on a thing. If the property already existed then the old property will be overwritten. This function is equal to an assignment except that it can be used when the name of the property is dynamic.', + 'search': 'Find the parent(s) of a given thing.', + 'to_type': 'Converts a thing into an instance of a given Type.', + 'values': 'Returns an list with all the property values of a thing. The same could be returned using map so the following statement is true: (.values() == .map(|_, v| v))', + 'vmap': 'The function returns a new thing with equal keys but values computed as a result of a given closure callback.', + 'wrap': 'Wrap a thing with a Type.', + }, + typed: { + 'to_thing': 'Converts a typed thing into a thing.' + }, + type: { + 'copy': 'Copy a thing to a new thing. A Type is not preserved.', + 'dup': 'Duplicate a thing while preserving the Type.', + 'unwrap': 'Unwrap a wrapped thing.', + } + }, + collection: { + 'alt_raise': 'This function will try a statement. If the statement is successful it will just return the result but in case of an error, it will re-raise the error using a given error code.', + 'ano': 'Creates an anomymous type.', + 'assert': 'Raises ASSERTION_ERROR if the specified statement evaluates to false.', + 'base64_decode': 'Decode a Base64 encoded string.', + 'base64_encode': 'Encode a str or bytes value using Base64.', + 'bool': 'Returns an bool from a specified value. If no value is given, false is returned.', + 'bytes': 'Convert a value to a byte sequence. If no value is given, an empty byte sequence is returned.', + 'commit': 'Saves a commit for the current query.', + 'datetime': 'Returns a datetime depending on some optional values.', + 'deep': 'Returns the current deep value. The deep value might change when a function with a return(..) is called which has changed the deep value for this query.', + 'del_enum': 'Delete an enumerator.', + 'del_type': 'Deletes an existing Type. It is not possible to delete a Type which is used by another type. You should first change or delete the other type before you are able to delete this type. See the example below.', + 'enum': 'Get an enum member by value', + 'enum_info': 'Return info about the enumerator type.', + 'enum_map': 'Returns a thing with key/value pairs for all the members of a given enum.', + 'enums_info': 'Return info about all the enumerator types in the current scope', + 'err': 'Returns an error.', + 'export': 'This function can be used to export the collection structure as a readable string with ThingsDB code. The function is also capable of exporting the full collection. This full collection export is returned as bytes which then can be imported in a new collection using the import(..) function.', + 'change_id': 'Returns the current change Id for the running query. The return value will be nil if the query does not require a change.', + 'float': 'Returns a float from a specified value. If no value is given, the default float 0.0 is returned. If the specified value is of type raw, then the initial characters of the string are converted until a non-digit character is found. Initial white space is ignored and the number may start with an optional + or - sign. Type bool values are converted to 1.0 for true and 0.0 for false.', + 'future': 'Returns a future. It is not possible to assign a future to a collection or add the future to a list. If you do, then nil will be assigned instead.', + 'has_enum': 'Determine if the current scope has a given enumerator type', + 'has_type': 'Determines if a Type exists in the current @collection scope.', + 'import': 'This function can be used to import a collection which was exported using the export(..) function with the option dump enabled.', + 'int': 'Returns an int from a specified value. If no value is given, the default integer 0 is returned. If the specified value was a float value, then the new integer value will be rounded towards zero. If the specified value is of type raw, then the initial characters of the string are converted until a non-digit character is found. Initial white space is ignored and the number may start with an optional + or - sign. Type bool values are converted to 1 for true and 0 for false.', + 'is_array': 'This function determines whether the value passed to this function is an array type or not. The functions is_lis_t and is_tuple can be used to check if the array is mutable.', + 'is_ascii': 'This function determines whether the value passed to this function is of type raw and contains only valid ascii characters.', + 'is_bool': 'This function determines whether the value passed to this function is a bool or not.', + 'is_bytes': 'This function determines whether the value passed to this function is of type bytes or not.', + 'is_closure': 'This function determines whether the provided value is a closure or not.', + 'is_datetime': 'This function determines whether the provided value is of type datetime.', + 'is_email': 'This function determines whether the provided value is of type str and contains an email address.', + 'is_enum': 'Test if a given value is a member of an enumerator type', + 'is_err': 'This function determines whether the value passed to this function is a error or not.', + 'is_float': 'This function determines whether the value passed to this function is a floating point value or not.', + 'is_future': 'This function determines whether the provided value is a future value or not.', + 'is_mpdata': 'This function determines whether the provided value is raw MessagePack data or not.', + 'is_inf': 'This function determines whether the provided value is a positive or negative infinity.', + 'is_int': 'This function determines whether the value passed to this function is an integer or not.', + 'is_list': 'This function determines whether the value passed to this function is a mutable array or not.', + 'is_module': 'This function determines whether the provided value is a module value or not.', + 'is_nan': 'This function determines whether the value passed to this function is a number. Returns true is the given value is not a number, else false.', + 'is_nil': 'This function determines whether the value passed to this function is nil.', + 'is_raw': 'This function determines whether the value passed to this function is of type raw.', + 'is_regex': 'This function determines whether the provided value is of type regex or not.', + 'is_room': 'This function determines whether the provided value is a room or not.', + 'is_set': 'This function determines whether the value passed to this function is a set or not.', + 'is_str': 'This function determines whether the value passed to this function is of type raw and contains valid utf8. Alias for is_utf8.', + 'is_task': 'This function determines whether the provided value is a task or not.', + 'is_tel': 'is function determines whether the provided value is of type str and contains a telephone number.', + 'is_thing': 'This function determines whether the value passed to this function is a thing or not.', + 'is_time_zone': 'This function determines whether the provided value is of type str and contains a valid time zone.', + 'is_timeval': 'This function determines whether the provided value is of type timeval.', + 'is_tuple': 'This function determines whether the value passed to this function is a immutable array or not. At least nested arrays are of kind tuple.', + 'is_url': 'This function determines whether the provided value is of type str and contains a URL. A valid URL must start with either http:/// , https:// or ftp://.', + 'is_utf8': 'This function determines whether the value passed to this function is of type raw and contains valid utf8.', + 'json_dump': 'Converts a ThingsDB value in to a JSON string.', + 'json_load': 'Converts a JSON string into a ThingsDB value.', + 'list': 'Returns a new empty list or returns a list for a given set.', + 'log': 'Might be used for debugging code. The message will be logged as a warning message on the console of the node which is processing the request. When you are connected using a socket stream, then a warning message with code 2 will be send to the client as well.', + 'mod_enum': 'Modify an existing enumerator type', + 'mod_type': 'This function is used to modify an existing Type. A number of actions can be performed with this function.', + 'new': 'Creates a new instance of a defined Type.', + 'new_type': 'Creates a new Type. This function only creates a new type and does not allow you to specify any fields. With the set_type() function you can define the fields for the new type.', + 'now': 'Return the time in seconds since the epoch as a floating point number. If you require the same time multiple times within a query, then call now() only once and save it to a variable, for example now = now();', + 'nse': 'This function promises ThingsDB that your code has no-side-effects and therefore does not require a change.', + 'raise': 'Raises an error.', + 'rand': 'Returns pseudo-random random number between 0.0 and 1.0.', + 'randint': 'Returns pseudo-random random integer number between a given range. The first argument specifies the start of the range and must have a value less than the second argument when specifies the end of the range. The start is inclusive and the end is exclusive, for example: randint(0, 2) will return either 0 or 1.', + 'randstr': 'Returns a string with random characters.', + 'range': 'This function returns a list of numbers, starting from 0 by default, and increments by 1 (by default), and ends at a specified number.', + 'refs': 'Returns the reference count of a value. The count returned is generally one higher than you might expect, because it includes the (temporary) reference.', + 'regex': 'This function can be used to create a regular expression from a given pattern with optional flags.', + 'rename_enum': 'Rename an enum type.', + 'rename_type': 'Rename a type.', + 'room': 'Returns a room from a specified value, that may be dynamic. If no value is given, a new room is returned.', + 'root': 'Returns the root for the current collection or nil when the current scope is not a collection scope.', + 'set': 'Returns a new empty set. If an array is given, then all elements in the given array must be or type thing and a new set is returned based on the given things. Instead of an array, it is also possible to provide things comma separated.', + 'set_enum': 'Create a new enumerator type', + 'set_type': 'Defines the properties of a Type. Function set_type works only on a new type. Use mod_type() if you want to change an existing type, see mod_type.', + 'str': 'Convert a value to a string. If no value is given, an empty string "" is returned. When bytes are converted to str then the data will be checked if it contains valid UTF-8 characters. If this is not the case, a VALUE_ERROR will be raised.', + 'task': 'Create a new task or get an existing task by Id.', + 'tasks': 'Return a list with all the tasks in the current scope.', + 'thing': 'Returns a thing from a specified value. If no value is given, a new thing is returned.', + 'time_zones_info': 'Returns all available time zones in ThingsDB.', + 'timeit': 'The timeit function can be used to check the duration of some code. It only measures the execution time of the code and does not include additional change creation and does not wait for futures to be completed.', + 'timeval': 'Returns a timeval depending on some optional values.', + 'try': 'Try a statement and if the statement fails with an error, then the error is returned. It is also possible to catch only specific errors.', + 'type': 'Returns the type name of a value.', + 'type_all': 'Returns a set with all instances of a given Type within a collection.', + 'type_assert': 'Raises a type_err() if the specified expression evaluates to false.', + 'type_count': 'Returns the number of instances of a given Type within a collection.', + 'type_info': 'Returns information about a given Type.', + 'types_info': 'Returns Type information about all the types within a collection.', + 'wse': 'Stored closures which can potentially make changes to ThingsDB are called closures with side effects and must be wrapped with the wse(..) function. This allows ThingsDB before running the query to make a change.', + 'abs': 'Return the absolute value of a given number.', + 'ceil': 'Return the ceiling of a given number. This is the smallest integer >= the given number.', + 'cos': 'Return the cosine of a given number. The value passed in this function should be in radians.', + 'exp': 'Returns e raised to the power of x.', + 'floor': 'Return the floor of a given number. This is the largest integer <= the given number.', + 'log10': 'Return the base 10 logarithm of a given number.', + 'log2': 'Return the base 2 logarithm of a given number.', + 'loge': 'Returns the natural logarithm (base e) of a given number.', + 'pow': 'Returns x to the power of y.', + 'round': 'Return a number that will be rounded to the decimal places which are given as input.', + 'sin': 'Return the sine of a given number. The value passed in this function should be in radians', + 'sqrt': 'Return the square root of a given number.', + 'tan': 'Return the tangent of a given number. The value passed in this function should be in radians.', + }, + errors: { + 'assert_err': 'Returns an error when an assertion has failed.', + 'auth_err': 'Returns an error when authentication has failed.', + 'bad_data_err': 'Returns an error when a request is malformed.', + 'forbidden_err': 'Returns an error when the client or user is missing the required privileges.', + 'lookup_err': 'Returns an error when a requested resource is not found or when an index is out-of-range.', + 'max_quota_err': 'Returns an error when a quota limit is reached.', + 'node_err': 'Returns an error when a node was not able to handle the request.', + 'num_arguments_err': 'Returns an error when a wrong number of arguments is given.', + 'operation_err': 'Returns an error when an operation is not valid within the current context.', + 'overflow_err': 'Returns an error when an attempt is made to create an integer value out of the supported 64Bit (signed) range.', + 'syntax_err': 'Returns an error when the given ThingsDB code contains a syntax error.', + 'type_err': 'Returns an error when a given value is of the incorrect type.', + 'value_err': 'Returns an error when a given value has the correct type but contains invalid data.', + 'cancelled_err': 'Returns an error when an operation is cancelled before completion. Fox example by a time-out or stop of service.', + 'zero_div_err': 'Returns an error when an attempt is made to divide or take a modulo by zero.', + }, + node: { + 'backup_info': 'Returns information about a specific scheduled backup.', + 'backups_info': 'Returns backup schedule information for all backup schedules in the selected node scope.', + 'backups_ok': 'Returns false if at least one backup had failed (result code != 0). In all other cases this function returns true (also when no backups are available or not yet started).', + 'counters': 'Returns counters for the ThingsDB node you are connected too. Counters start all at zero when ThingsDB is started, or when the counters are reset by using reset_counters()’. Counters give information about things, queries and changes. If you suspect failed queries, then counters might provide you with more information.', + 'del_backup': 'Delete a scheduled backup. If the schedule was pending, the backup job will be cancelled.', + 'has_backup': 'Determines if a backup exists in ThingsDB.', + 'new_backup': 'Schedule a new backup. Backups are created using tar and gzip. Once a backup is made, the .tar.gz backup file can be used to recover ThingsDB, or can be used to load the ThingsDB into another node. The result value is a backup ID. This ID can be used by backup_info(..) for details about the backup schedule job, or can be used to delete the backup schedule.', + 'node_info': 'Returns information about the connected node.', + 'nodes_info': 'Returns information about all ThingsDB nodes.', + 'reset_counters': 'Resets the counters for the ThingsDB node you are connected too. Other nodes are not affected', + 'restart_module': 'Restarts a given module.', + 'set_log_level': 'Change the log level for the node in the selected scope. ThingsDB will then log all levels greater than or equal to the specified level. For example, a default log_level of warning will log warning, error and critical messages.', + 'shutdown': 'Shutdown the node in the selected scope. This is a clean shutdown, allowing all other nodes (and clients) to disconnect.', + }, + thingsdb: { + 'collection_info': 'Returns information about a specific collection. This function requires QUERY privileges on the requested collection, or CHANGE privileges on the @thingsdb scope.', + 'collections_info': 'Returns collection information for all collections in ThingsDB.', + 'del_collection': 'Delete a collection.', + 'del_expired': 'Delete all expired tokens. Extends to all users.', + 'del_history': 'Delete commit records from history based on a given filter.', + 'del_module': 'Delete a module. A SIGTERM signal will be send to the process for the module which might cancel running futures.', + 'del_node': 'Delete a node from ThingsDB.', + 'del_token': 'Delete a token.', + 'del_user': 'Delete a user. It is not possible to delete your own user account and a BAD_REQUEST will be raised in case you try to. Any tokens associated with the user will also be deleted.', + 'deploy_module': 'Deploy a module on all nodes. The module must be configured first, using the new_module() function. This function is used to write the module data (or plain python code) to the module. After deploying the code, the module will be restarted on every node.', + 'grant': 'Grant collection or general privileges to a user. Access to a user is provided by setting a bit mask to either the .node scope, .thingsdb scope or a collection. Privileges to ThingsDB gives a user the ability to view counters, add, view remove users etc.', + 'has_collection': 'Determines if a collection exists in ThingsDB.', + 'has_module': 'Determines if a module exists in ThingsDB. The scope restriction of the module has no impact on the result of this function.', + 'has_node': 'Determines if a node exists in ThingsDB', + 'has_token': 'Determines if a token exists in ThingsDB.', + 'has_user': 'Determines if a user exists in ThingsDB.', + 'history': 'List commit records from history based on a given filter.', + 'module_info': 'Returns information about a specific module.', + 'modules_info': 'Returns module information about all modules in ThingsDB.', + 'new_collection': 'Create a new collection.', + 'new_module': 'Configures a new module for ThingsDB.', + 'new_node': 'Adds a new node to ThingsDB. Nodes are used for scaling and high availability.', + 'new_token': 'Adds a new token for a given user. An optional expiration time may be given after which the token cannot be used anymore. Use del_expired to cleanup expired tokens. The expiration time may be given as a UNIX time-stamp in seconds or a date/time string. It is also possible to set a description for the token which can be used to identify where token is used for. If you only want to set a description, but no expiration time, then you can use nil as second argument.', + 'new_user': 'Creates a new user to ThingsDB. The new user is created without a password, token and access privileges. You probably want to set a password or add a new token and assign some privileges using grant(…).', + 'refresh_module': 'Refresh module first stops the module (if running), next if will check for an update and performs the update if required. When finished, it will start the module again.', + 'rename_collection': 'Rename a collection.', + 'rename_module': 'Rename a module.', + 'rename_user': 'Rename a user.', + 'restore': 'Restore from a backup file created with the new_backup function.', + 'revoke': 'Revoke collection or general privileges from a user. See grant for more information on how access privileges can be set for a user.', + 'set_default_deep': 'The deep value determines how many levels of data are returned by a query. Only things count towards this value.', + 'set_history': 'Enables “commit history” for a given scope. Commit history can be enabled for collections scopes and the @thingsdb scope.', + 'set_module_conf': 'Change the module configuration. This will (re-send) the module configuration to the module. If the module was not started, ThingsDB will also auto-load the module and send the configuration. Any Value is accepted as config but value nil will not be considered as a configuration and thus will not be send to the module.', + 'set_module_scope': 'Modules can be restricted for usage in a single scope. This can be a @collection:.. scope, but also a @node or @thingsdb scope. This function can be used to change the module scope. When the scope is set to nil, the module can be used in any scope.', + 'set_password': 'Change a users password. This function can also be used to remove an existing password by using nil as the new password. Passwords must contain 1 to 128 printable characters.', + 'set_time_zone': 'By default each collection will be created with time zone UTC. This function can be used to change the time zone for a collection. If changed, the functions datetime(..) and timeval(..) will use the collections time zone unless specified otherwise.', + 'user_info': 'Returns information about a user. If no argument is given, this method will return information about the current logged in user.', + 'users_info': 'Returns user information for all users withing ThingsDB. This function requires GRANT privileges on the .thingsdb scope since it exposes user access and token information.', + 'whitelist_add': 'Add a new rule to the whitelist', + 'whitelist_del': 'Deletes an existing rule from a whitelist or removes all rules, effectively disabling the whitelist.', + }, + procedures: { + 'del_procedure': 'Delete a procedure.', + 'has_procedure': 'Determines if a procedure exists in the current scope.', + 'mod_procedure': 'Changes the closure for an existing procedure. This function also updates the created_at time as if it is a new procedure.', + 'new_procedure': 'Creates a new procedure to the @thingsdb or a @collection scope. The name of the procedure must be unique within the scope. The given closure will be copied to the procedure, so this is not a reference to a given closure.', + 'procedure_doc': 'Returns the doc string for a given procedure. An empty string is returned if the procedure has no doc string.', + 'procedure_info': 'Returns information about a procedure.', + 'procedures_info': 'Returns procedure information for all procedures in the scope.', + 'rename_procedure': 'Rename a procedure.', + 'run': 'Run a procedure.', + }, };