@everysk/apps-sdk 0.2.0 → 0.3.0-beta-20261019175049
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +342 -12
- package/dist/EveryskApp.d.ts +34 -2
- package/dist/EveryskApp.d.ts.map +1 -1
- package/dist/EveryskApp.js +35 -2
- package/dist/EveryskApp.js.map +1 -1
- package/dist/agGrid/handleRowsScrollEnd.d.ts +53 -0
- package/dist/agGrid/handleRowsScrollEnd.d.ts.map +1 -0
- package/dist/agGrid/handleRowsScrollEnd.js +47 -0
- package/dist/agGrid/handleRowsScrollEnd.js.map +1 -0
- package/dist/agGrid/index.d.ts +2 -0
- package/dist/agGrid/index.d.ts.map +1 -1
- package/dist/agGrid/index.js +2 -1
- package/dist/api/datastore.d.ts +10 -8
- package/dist/api/datastore.d.ts.map +1 -1
- package/dist/api/datastore.js +24 -55
- package/dist/api/datastore.js.map +1 -1
- package/dist/api/entityQuery.d.ts +46 -41
- package/dist/api/entityQuery.d.ts.map +1 -1
- package/dist/api/entityQuery.js +55 -14
- package/dist/api/entityQuery.js.map +1 -1
- package/dist/api/file.d.ts +26 -9
- package/dist/api/file.d.ts.map +1 -1
- package/dist/api/file.js +45 -55
- package/dist/api/file.js.map +1 -1
- package/dist/api/portfolio.d.ts +11 -8
- package/dist/api/portfolio.d.ts.map +1 -1
- package/dist/api/portfolio.js +24 -55
- package/dist/api/portfolio.js.map +1 -1
- package/dist/api/profile.d.ts +3 -2
- package/dist/api/profile.d.ts.map +1 -1
- package/dist/api/profile.js +4 -9
- package/dist/api/profile.js.map +1 -1
- package/dist/api/request.d.ts +106 -0
- package/dist/api/request.d.ts.map +1 -0
- package/dist/api/request.js +132 -0
- package/dist/api/request.js.map +1 -0
- package/dist/api/websocketsConfig.d.ts +7 -2
- package/dist/api/websocketsConfig.d.ts.map +1 -1
- package/dist/api/websocketsConfig.js +2 -10
- package/dist/api/websocketsConfig.js.map +1 -1
- package/dist/api/workflow.d.ts +84 -89
- package/dist/api/workflow.d.ts.map +1 -1
- package/dist/api/workflow.js +121 -208
- package/dist/api/workflow.js.map +1 -1
- package/dist/api/workspace.d.ts +18 -8
- package/dist/api/workspace.d.ts.map +1 -1
- package/dist/api/workspace.js +21 -26
- package/dist/api/workspace.js.map +1 -1
- package/dist/components/ui/Footer/index.d.ts.map +1 -1
- package/dist/components/ui/Footer/index.js.map +1 -1
- package/dist/components/ui/GlobalLoading/index.d.ts.map +1 -1
- package/dist/components/ui/GlobalLoading/index.js.map +1 -1
- package/dist/components/ui/PageContainer/index.d.ts +1 -1
- package/dist/components/ui/PageContainer/index.d.ts.map +1 -1
- package/dist/components/ui/PageContainer/index.js.map +1 -1
- package/dist/components/ui/Toolbar/index.d.ts +40 -3
- package/dist/components/ui/Toolbar/index.d.ts.map +1 -1
- package/dist/components/ui/Toolbar/index.js +42 -15
- package/dist/components/ui/Toolbar/index.js.map +1 -1
- package/dist/contexts/appAlertContext/provider.js.map +1 -1
- package/dist/contexts/appAlertContext/types.d.ts.map +1 -1
- package/dist/contexts/appConfigContext/index.d.ts.map +1 -1
- package/dist/contexts/appConfigContext/index.js.map +1 -1
- package/dist/contexts/appConfigContext/provider.d.ts.map +1 -1
- package/dist/contexts/appConfigContext/provider.js.map +1 -1
- package/dist/contexts/webSocketContext/handler.d.ts +3 -2
- package/dist/contexts/webSocketContext/handler.d.ts.map +1 -1
- package/dist/contexts/webSocketContext/handler.js.map +1 -1
- package/dist/contexts/webSocketContext/hooks/useWebSocket/index.d.ts +1 -1
- package/dist/contexts/webSocketContext/hooks/useWebSocket/index.js +1 -1
- package/dist/contexts/webSocketContext/hooks/useWebSocket/index.js.map +1 -1
- package/dist/contexts/webSocketContext/provider.d.ts +6 -3
- package/dist/contexts/webSocketContext/provider.d.ts.map +1 -1
- package/dist/contexts/webSocketContext/provider.js +42 -7
- package/dist/contexts/webSocketContext/provider.js.map +1 -1
- package/dist/contexts/webSocketContext/types.d.ts +7 -5
- package/dist/contexts/webSocketContext/types.d.ts.map +1 -1
- package/dist/file/index.d.ts +2 -0
- package/dist/file/index.d.ts.map +1 -1
- package/dist/hooks/datastore/useDatastoreMutations.d.ts +4 -4
- package/dist/hooks/datastore/useDatastoreMutations.d.ts.map +1 -1
- package/dist/hooks/datastore/useDatastoreMutations.js +17 -55
- package/dist/hooks/datastore/useDatastoreMutations.js.map +1 -1
- package/dist/hooks/datastore/useFetchDatastore.d.ts +30 -41
- package/dist/hooks/datastore/useFetchDatastore.d.ts.map +1 -1
- package/dist/hooks/datastore/useFetchDatastore.js +25 -59
- package/dist/hooks/datastore/useFetchDatastore.js.map +1 -1
- package/dist/hooks/datastore/useFetchDatastores.d.ts +47 -52
- package/dist/hooks/datastore/useFetchDatastores.d.ts.map +1 -1
- package/dist/hooks/datastore/useFetchDatastores.js +55 -70
- package/dist/hooks/datastore/useFetchDatastores.js.map +1 -1
- package/dist/hooks/file/fileData.d.ts +17 -0
- package/dist/hooks/file/fileData.d.ts.map +1 -0
- package/dist/hooks/file/fileData.js +10 -0
- package/dist/hooks/file/fileData.js.map +1 -0
- package/dist/hooks/file/useFetchFile.d.ts +38 -58
- package/dist/hooks/file/useFetchFile.d.ts.map +1 -1
- package/dist/hooks/file/useFetchFile.js +26 -66
- package/dist/hooks/file/useFetchFile.js.map +1 -1
- package/dist/hooks/file/useFetchFiles.d.ts +18 -52
- package/dist/hooks/file/useFetchFiles.d.ts.map +1 -1
- package/dist/hooks/file/useFetchFiles.js +53 -69
- package/dist/hooks/file/useFetchFiles.js.map +1 -1
- package/dist/hooks/file/useFileMutations.d.ts +9 -8
- package/dist/hooks/file/useFileMutations.d.ts.map +1 -1
- package/dist/hooks/file/useFileMutations.js +23 -60
- package/dist/hooks/file/useFileMutations.js.map +1 -1
- package/dist/hooks/portfolio/useFetchPortfolio.d.ts +16 -50
- package/dist/hooks/portfolio/useFetchPortfolio.d.ts.map +1 -1
- package/dist/hooks/portfolio/useFetchPortfolio.js +15 -63
- package/dist/hooks/portfolio/useFetchPortfolio.js.map +1 -1
- package/dist/hooks/portfolio/useFetchPortfolios.d.ts +13 -52
- package/dist/hooks/portfolio/useFetchPortfolios.d.ts.map +1 -1
- package/dist/hooks/portfolio/useFetchPortfolios.js +29 -71
- package/dist/hooks/portfolio/useFetchPortfolios.js.map +1 -1
- package/dist/hooks/portfolio/usePortfolioMutations.d.ts +8 -8
- package/dist/hooks/portfolio/usePortfolioMutations.d.ts.map +1 -1
- package/dist/hooks/portfolio/usePortfolioMutations.js +20 -58
- package/dist/hooks/portfolio/usePortfolioMutations.js.map +1 -1
- package/dist/hooks/profile/useFetchProfile.d.ts +18 -44
- package/dist/hooks/profile/useFetchProfile.d.ts.map +1 -1
- package/dist/hooks/profile/useFetchProfile.js +16 -48
- package/dist/hooks/profile/useFetchProfile.js.map +1 -1
- package/dist/hooks/useAxios.js.map +1 -1
- package/dist/hooks/useEntityInfiniteQuery.d.ts +88 -0
- package/dist/hooks/useEntityInfiniteQuery.d.ts.map +1 -0
- package/dist/hooks/useEntityInfiniteQuery.js +111 -0
- package/dist/hooks/useEntityInfiniteQuery.js.map +1 -0
- package/dist/hooks/useEntityMutation.d.ts +47 -0
- package/dist/hooks/useEntityMutation.d.ts.map +1 -0
- package/dist/hooks/useEntityMutation.js +58 -0
- package/dist/hooks/useEntityMutation.js.map +1 -0
- package/dist/hooks/useEntityQuery.d.ts +68 -0
- package/dist/hooks/useEntityQuery.d.ts.map +1 -0
- package/dist/hooks/useEntityQuery.js +75 -0
- package/dist/hooks/useEntityQuery.js.map +1 -0
- package/dist/hooks/workflow/useFetchWorkerExecution.d.ts +17 -34
- package/dist/hooks/workflow/useFetchWorkerExecution.d.ts.map +1 -1
- package/dist/hooks/workflow/useFetchWorkerExecution.js +16 -46
- package/dist/hooks/workflow/useFetchWorkerExecution.js.map +1 -1
- package/dist/hooks/workflow/useFetchWorkerExecutions.d.ts +179 -41
- package/dist/hooks/workflow/useFetchWorkerExecutions.d.ts.map +1 -1
- package/dist/hooks/workflow/useFetchWorkerExecutions.js +29 -62
- package/dist/hooks/workflow/useFetchWorkerExecutions.js.map +1 -1
- package/dist/hooks/workflow/useFetchWorkflow.d.ts +16 -35
- package/dist/hooks/workflow/useFetchWorkflow.d.ts.map +1 -1
- package/dist/hooks/workflow/useFetchWorkflow.js +15 -48
- package/dist/hooks/workflow/useFetchWorkflow.js.map +1 -1
- package/dist/hooks/workflow/useFetchWorkflowExecution.d.ts +17 -34
- package/dist/hooks/workflow/useFetchWorkflowExecution.d.ts.map +1 -1
- package/dist/hooks/workflow/useFetchWorkflowExecution.js +16 -46
- package/dist/hooks/workflow/useFetchWorkflowExecution.js.map +1 -1
- package/dist/hooks/workflow/useFetchWorkflowExecutions.d.ts +22 -36
- package/dist/hooks/workflow/useFetchWorkflowExecutions.d.ts.map +1 -1
- package/dist/hooks/workflow/useFetchWorkflowExecutions.js +43 -56
- package/dist/hooks/workflow/useFetchWorkflowExecutions.js.map +1 -1
- package/dist/hooks/workflow/useFetchWorkflows.d.ts +20 -37
- package/dist/hooks/workflow/useFetchWorkflows.d.ts.map +1 -1
- package/dist/hooks/workflow/useFetchWorkflows.js +32 -47
- package/dist/hooks/workflow/useFetchWorkflows.js.map +1 -1
- package/dist/hooks/workflow/useRunWorkflow.d.ts +21 -16
- package/dist/hooks/workflow/useRunWorkflow.d.ts.map +1 -1
- package/dist/hooks/workflow/useRunWorkflow.js +66 -29
- package/dist/hooks/workflow/useRunWorkflow.js.map +1 -1
- package/dist/hooks/workflow/useTriggerWorkflow.d.ts +20 -0
- package/dist/hooks/workflow/useTriggerWorkflow.d.ts.map +1 -0
- package/dist/hooks/workflow/useTriggerWorkflow.js +32 -0
- package/dist/hooks/workflow/useTriggerWorkflow.js.map +1 -0
- package/dist/hooks/workspace/useFetchWorkspace.d.ts +19 -34
- package/dist/hooks/workspace/useFetchWorkspace.d.ts.map +1 -1
- package/dist/hooks/workspace/useFetchWorkspace.js +16 -46
- package/dist/hooks/workspace/useFetchWorkspace.js.map +1 -1
- package/dist/hooks/workspace/useFetchWorkspaces.d.ts +17 -37
- package/dist/hooks/workspace/useFetchWorkspaces.d.ts.map +1 -1
- package/dist/hooks/workspace/useFetchWorkspaces.js +25 -47
- package/dist/hooks/workspace/useFetchWorkspaces.js.map +1 -1
- package/dist/index.d.ts +13 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -11
- package/dist/lib/abort.d.ts +58 -0
- package/dist/lib/abort.d.ts.map +1 -0
- package/dist/lib/abort.js +112 -0
- package/dist/lib/abort.js.map +1 -0
- package/dist/lib/datastoreTable.d.ts +59 -54
- package/dist/lib/datastoreTable.d.ts.map +1 -1
- package/dist/lib/datastoreTable.js +58 -62
- package/dist/lib/datastoreTable.js.map +1 -1
- package/dist/lib/file.d.ts +34 -0
- package/dist/lib/file.d.ts.map +1 -0
- package/dist/lib/file.js +63 -0
- package/dist/lib/file.js.map +1 -0
- package/dist/lib/queryClient.d.ts.map +1 -1
- package/dist/lib/queryClient.js.map +1 -1
- package/dist/lib/workflowRun.d.ts +91 -0
- package/dist/lib/workflowRun.d.ts.map +1 -0
- package/dist/lib/workflowRun.js +224 -0
- package/dist/lib/workflowRun.js.map +1 -0
- package/dist/socket/index.d.ts +1 -3
- package/dist/socket/index.d.ts.map +1 -1
- package/dist/socket/index.js +3 -5
- package/dist/test/mocks/index.d.ts +1 -1
- package/dist/test/mocks/index.d.ts.map +1 -1
- package/dist/test/msw/fakeApi.d.ts +43 -0
- package/dist/test/msw/fakeApi.d.ts.map +1 -0
- package/dist/test/msw/fakeApi.js +74 -0
- package/dist/test/msw/fakeApi.js.map +1 -0
- package/dist/test/msw/handlers.d.ts +20 -0
- package/dist/test/msw/handlers.d.ts.map +1 -0
- package/dist/test/msw/handlers.js +279 -0
- package/dist/test/msw/handlers.js.map +1 -0
- package/dist/test/msw/index.d.ts +5 -0
- package/dist/test/msw/index.d.ts.map +1 -0
- package/dist/test/msw/index.js +2 -0
- package/dist/test/msw/query.d.ts +34 -0
- package/dist/test/msw/query.d.ts.map +1 -0
- package/dist/test/msw/query.js +96 -0
- package/dist/test/msw/query.js.map +1 -0
- package/dist/test/msw/recorder.d.ts +30 -0
- package/dist/test/msw/recorder.d.ts.map +1 -0
- package/dist/test/msw/recorder.js +65 -0
- package/dist/test/msw/recorder.js.map +1 -0
- package/dist/test/msw/store.d.ts +57 -0
- package/dist/test/msw/store.d.ts.map +1 -0
- package/dist/test/msw/store.js +145 -0
- package/dist/test/msw/store.js.map +1 -0
- package/dist/test/renderWithProviders.d.ts +2 -2
- package/dist/test/renderWithProviders.d.ts.map +1 -1
- package/dist/test/renderWithProviders.js.map +1 -1
- package/dist/test/setup.js.map +1 -1
- package/dist/theme/index.d.ts +1 -1
- package/dist/theme/index.d.ts.map +1 -1
- package/dist/theme/overrides/index.d.ts +4 -2
- package/dist/theme/overrides/index.d.ts.map +1 -1
- package/dist/theme/overrides/index.js +5 -3
- package/dist/theme/overrides/index.js.map +1 -1
- package/dist/theme/overrides/muiButton.d.ts +2 -2
- package/dist/theme/overrides/muiButton.js.map +1 -1
- package/dist/theme/overrides/muiCssBaseline.d.ts.map +1 -1
- package/dist/theme/overrides/muiCssBaseline.js.map +1 -1
- package/dist/theme/overrides/muiDatePicker.js.map +1 -1
- package/dist/theme/overrides/muiFormControl.js.map +1 -1
- package/dist/theme/overrides/muiIconButton.d.ts +2 -2
- package/dist/theme/overrides/muiIconButton.js.map +1 -1
- package/dist/theme/overrides/muiSelect.d.ts.map +1 -1
- package/dist/theme/overrides/muiSelect.js.map +1 -1
- package/dist/theme/overrides/muiSvgIcon.d.ts.map +1 -1
- package/dist/theme/overrides/muiSvgIcon.js.map +1 -1
- package/dist/theme/overrides/muiTextField.js.map +1 -1
- package/dist/theme/overrides/muiToggleButton.d.ts +2 -2
- package/dist/theme/overrides/muiToggleButton.js.map +1 -1
- package/dist/theme/overrides/muiToggleButtonGroup.d.ts +2 -2
- package/dist/theme/overrides/muiToggleButtonGroup.js.map +1 -1
- package/dist/theme/themes/DefaultDark.js +2 -2
- package/dist/theme/themes/DefaultDark.js.map +1 -1
- package/dist/theme/themes/DefaultLight.js +2 -2
- package/dist/theme/themes/DefaultLight.js.map +1 -1
- package/dist/theme/themes/EveryskDark.js +2 -2
- package/dist/theme/themes/EveryskDark.js.map +1 -1
- package/dist/theme/themes/EveryskLight.js +2 -2
- package/dist/theme/themes/EveryskLight.js.map +1 -1
- package/dist/theme/themes/MidnightEmber.js +2 -2
- package/dist/theme/themes/MidnightEmber.js.map +1 -1
- package/dist/types/anyRecord.d.ts.map +1 -1
- package/dist/types/datastore.d.ts +35 -5
- package/dist/types/datastore.d.ts.map +1 -1
- package/dist/types/datastoreDataFormat.d.ts +13 -0
- package/dist/types/datastoreDataFormat.d.ts.map +1 -0
- package/dist/types/entityQuery.d.ts +86 -16
- package/dist/types/entityQuery.d.ts.map +1 -1
- package/dist/types/file.d.ts +7 -3
- package/dist/types/file.d.ts.map +1 -1
- package/dist/types/portfolio.d.ts +1 -3
- package/dist/types/portfolio.d.ts.map +1 -1
- package/dist/types/profile.d.ts +0 -10
- package/dist/types/profile.d.ts.map +1 -1
- package/dist/types/workflow.d.ts +35 -6
- package/dist/types/workflow.d.ts.map +1 -1
- package/dist/types/workspace.d.ts +1 -2
- package/dist/types/workspace.d.ts.map +1 -1
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/workflow/index.d.ts +2 -0
- package/dist/workflow/index.d.ts.map +1 -1
- package/package.json +10 -1
- package/src/EveryskApp.tsx +53 -2
- package/src/agGrid/handleRowsScrollEnd.ts +71 -0
- package/src/agGrid/index.ts +5 -1
- package/src/api/datastore.ts +79 -107
- package/src/api/entityQuery.ts +86 -17
- package/src/api/file.ts +110 -103
- package/src/api/portfolio.ts +82 -125
- package/src/api/profile.ts +25 -18
- package/src/api/request.ts +168 -0
- package/src/api/websocketsConfig.ts +11 -19
- package/src/api/workflow.ts +232 -334
- package/src/api/workspace.ts +43 -43
- package/src/components/ui/Footer/index.tsx +8 -7
- package/src/components/ui/GlobalLoading/index.tsx +13 -3
- package/src/components/ui/PageContainer/index.tsx +9 -2
- package/src/components/ui/Toolbar/index.tsx +105 -30
- package/src/contexts/appAlertContext/provider.tsx +1 -1
- package/src/contexts/appAlertContext/types.ts +3 -3
- package/src/contexts/appConfigContext/index.tsx +1 -1
- package/src/contexts/appConfigContext/provider.tsx +1 -5
- package/src/contexts/webSocketContext/handler.ts +8 -2
- package/src/contexts/webSocketContext/hooks/useWebSocket/index.ts +1 -1
- package/src/contexts/webSocketContext/provider.tsx +64 -14
- package/src/contexts/webSocketContext/types.ts +7 -6
- package/src/file/index.ts +2 -0
- package/src/hooks/datastore/useDatastoreMutations.ts +19 -60
- package/src/hooks/datastore/useFetchDatastore.ts +45 -73
- package/src/hooks/datastore/useFetchDatastores.ts +106 -131
- package/src/hooks/file/fileData.ts +19 -0
- package/src/hooks/file/useFetchFile.ts +41 -76
- package/src/hooks/file/useFetchFiles.ts +92 -87
- package/src/hooks/file/useFileMutations.ts +23 -73
- package/src/hooks/portfolio/useFetchPortfolio.ts +26 -78
- package/src/hooks/portfolio/useFetchPortfolios.ts +50 -93
- package/src/hooks/portfolio/usePortfolioMutations.ts +22 -72
- package/src/hooks/profile/useFetchProfile.ts +24 -65
- package/src/hooks/useAxios.ts +5 -5
- package/src/hooks/useEntityInfiniteQuery.ts +193 -0
- package/src/hooks/useEntityMutation.ts +70 -0
- package/src/hooks/useEntityQuery.ts +117 -0
- package/src/hooks/workflow/useFetchWorkerExecution.ts +27 -56
- package/src/hooks/workflow/useFetchWorkerExecutions.ts +54 -79
- package/src/hooks/workflow/useFetchWorkflow.ts +24 -58
- package/src/hooks/workflow/useFetchWorkflowExecution.ts +27 -57
- package/src/hooks/workflow/useFetchWorkflowExecutions.ts +64 -73
- package/src/hooks/workflow/useFetchWorkflows.ts +48 -64
- package/src/hooks/workflow/useRunWorkflow.ts +82 -36
- package/src/hooks/workflow/useTriggerWorkflow.ts +36 -0
- package/src/hooks/workspace/useFetchWorkspace.ts +25 -58
- package/src/hooks/workspace/useFetchWorkspaces.ts +38 -69
- package/src/index.ts +34 -19
- package/src/lib/abort.ts +131 -0
- package/src/lib/datastoreTable.ts +127 -74
- package/src/lib/file.ts +67 -0
- package/src/lib/queryClient.ts +11 -13
- package/src/lib/workflowRun.ts +329 -0
- package/src/socket/index.ts +1 -3
- package/src/test/mocks/index.ts +1 -5
- package/src/test/msw/fakeApi.ts +83 -0
- package/src/test/msw/handlers.ts +350 -0
- package/src/test/msw/index.ts +9 -0
- package/src/test/msw/query.ts +134 -0
- package/src/test/msw/recorder.ts +88 -0
- package/src/test/msw/store.ts +182 -0
- package/src/test/renderWithProviders.tsx +8 -3
- package/src/test/setup.ts +16 -16
- package/src/theme/index.ts +1 -1
- package/src/theme/overrides/index.ts +5 -3
- package/src/theme/overrides/muiButton.ts +3 -3
- package/src/theme/overrides/muiCssBaseline.ts +11 -12
- package/src/theme/overrides/muiDatePicker.ts +2 -2
- package/src/theme/overrides/muiFormControl.ts +2 -2
- package/src/theme/overrides/muiIconButton.ts +3 -3
- package/src/theme/overrides/muiSelect.ts +2 -2
- package/src/theme/overrides/muiSvgIcon.ts +2 -2
- package/src/theme/overrides/muiTextField.ts +1 -1
- package/src/theme/overrides/muiToggleButton.ts +4 -4
- package/src/theme/overrides/muiToggleButtonGroup.ts +4 -4
- package/src/theme/themes/DefaultDark.ts +2 -2
- package/src/theme/themes/DefaultLight.ts +2 -2
- package/src/theme/themes/EveryskDark.ts +2 -2
- package/src/theme/themes/EveryskLight.ts +2 -2
- package/src/theme/themes/MidnightEmber.ts +15 -15
- package/src/types/anyRecord.ts +2 -2
- package/src/types/datastore.ts +56 -22
- package/src/types/datastoreDataFormat.ts +12 -0
- package/src/types/entityQuery.ts +122 -38
- package/src/types/file.ts +8 -6
- package/src/types/portfolio.ts +70 -74
- package/src/types/profile.ts +0 -11
- package/src/types/workflow.ts +38 -9
- package/src/types/workspace.ts +2 -4
- package/src/ui/index.ts +1 -1
- package/src/workflow/index.ts +5 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { Datastore } from "../types/datastore.d.ts";
|
|
1
|
+
import type { Datastore, ParsedDatastore } from "../types/datastore.d.ts";
|
|
2
|
+
import type { DatastoreDataFormat } from "../types/datastoreDataFormat.d.ts";
|
|
2
3
|
import type { AnyRecord } from "../types/anyRecord.d.ts";
|
|
3
4
|
type Cell = string | number | null;
|
|
4
5
|
type DatastoreData = Cell[][];
|
|
@@ -32,13 +33,49 @@ type DatastoreData = Cell[][];
|
|
|
32
33
|
* ["Alice", 30],
|
|
33
34
|
* ["Bob", null],
|
|
34
35
|
* ];
|
|
35
|
-
* const rows =
|
|
36
|
+
* const rows = matrixToObjects("ds_123", headers, data);
|
|
36
37
|
* // [
|
|
37
38
|
* // { datastoreId: "ds_123", name: "Alice", age: 30 },
|
|
38
39
|
* // { datastoreId: "ds_123", name: "Bob", age: null }
|
|
39
40
|
* // ]
|
|
40
41
|
*/
|
|
41
|
-
export declare const
|
|
42
|
+
export declare const matrixToObjects: <T extends Record<string, Cell>>(datastoreId: string, headers: string[], data: DatastoreData) => T[];
|
|
43
|
+
/**
|
|
44
|
+
* Converts a datastore as the API returns it into the shape the datastore hooks return.
|
|
45
|
+
*
|
|
46
|
+
* A datastore is tabular or JSON, and the API does not say which. `data` is a matrix, an object,
|
|
47
|
+
* or an array of objects, so only an array whose every element is an array is read as a table.
|
|
48
|
+
* "Any array" is not enough: the API has returned `[{ … }]` for a JSON datastore, which read as a
|
|
49
|
+
* matrix lost its content with one element and threw with two. A table's matrix becomes row
|
|
50
|
+
* objects, with the header row kept as `fields` so that saving back can restore the column
|
|
51
|
+
* order. JSON passes through untouched.
|
|
52
|
+
*
|
|
53
|
+
* A read without its data (`projection: "-data"`) carries nothing to tell the kinds apart and
|
|
54
|
+
* comes back as an empty table.
|
|
55
|
+
*
|
|
56
|
+
* The hooks convert in the request rather than in `select`, so the cache holds objects and an
|
|
57
|
+
* app patches a row as `{ ...row, ...patch }` rather than by column index. It is exported for an
|
|
58
|
+
* app that seeds that cache itself.
|
|
59
|
+
*
|
|
60
|
+
* With `dataFormat: "matrix"` a table keeps its matrix unconverted, header row included, and still
|
|
61
|
+
* gets `fields`. JSON is untouched either way.
|
|
62
|
+
*
|
|
63
|
+
* @param datastore The datastore as the API returned it.
|
|
64
|
+
* @param dataFormat `"object"` (default) or `"matrix"`.
|
|
65
|
+
* @returns A tabular or a `JsonDatastore`, told apart by `format`.
|
|
66
|
+
*/
|
|
67
|
+
export declare function parseDatastore(datastore: Datastore): ParsedDatastore;
|
|
68
|
+
export declare function parseDatastore<F extends DatastoreDataFormat>(datastore: Datastore, dataFormat: F): ParsedDatastore<F>;
|
|
69
|
+
/**
|
|
70
|
+
* Narrows a datastore to a tabular one, whose `data` is rows. For a `select` over a list that
|
|
71
|
+
* may mix kinds: `datastores.filter(isTableDatastore).flatMap((d) => d.data)`.
|
|
72
|
+
*
|
|
73
|
+
* @param datastore A datastore as the hooks return it.
|
|
74
|
+
* @returns True for a tabular datastore.
|
|
75
|
+
*/
|
|
76
|
+
export declare const isTableDatastore: <D extends ParsedDatastore<DatastoreDataFormat>>(datastore: D) => datastore is Extract<D, {
|
|
77
|
+
format: "table";
|
|
78
|
+
}>;
|
|
42
79
|
/**
|
|
43
80
|
* Converts an array of objects into a datastore table (2D array).
|
|
44
81
|
*
|
|
@@ -47,7 +84,8 @@ export declare const tableToObjects: <T extends Record<string, Cell>>(datastoreI
|
|
|
47
84
|
* - For each object in `data`, creates a row by mapping `headers` to values in the object.
|
|
48
85
|
* - If a header is missing in an object, the corresponding cell is set to `null`.
|
|
49
86
|
*
|
|
50
|
-
*
|
|
87
|
+
* Takes rows as the datastore hooks hand them over (`AnyRecord`): a value that is not a cell is
|
|
88
|
+
* written as it is, since the row came from a matrix in the first place.
|
|
51
89
|
*
|
|
52
90
|
* @param headers Column names (and output table header row).
|
|
53
91
|
* @param data Array of objects to convert into rows.
|
|
@@ -58,7 +96,7 @@ export declare const tableToObjects: <T extends Record<string, Cell>>(datastoreI
|
|
|
58
96
|
*
|
|
59
97
|
* @example
|
|
60
98
|
* const headers = ["name", "age"];
|
|
61
|
-
* const rows =
|
|
99
|
+
* const rows = objectsToMatrix(headers, [
|
|
62
100
|
* { name: "Alice", age: 30 },
|
|
63
101
|
* { name: "Bob" }, // age missing -> null
|
|
64
102
|
* ]);
|
|
@@ -68,59 +106,26 @@ export declare const tableToObjects: <T extends Record<string, Cell>>(datastoreI
|
|
|
68
106
|
* // ["Bob", null]
|
|
69
107
|
* // ]
|
|
70
108
|
*/
|
|
71
|
-
export declare const
|
|
109
|
+
export declare const objectsToMatrix: <T extends AnyRecord = AnyRecord>(headers: string[], data: T[]) => DatastoreData;
|
|
72
110
|
/**
|
|
73
|
-
*
|
|
111
|
+
* The matrix of a tabular datastore, however the hook read it. Code that saves or exports a
|
|
112
|
+
* datastore calls this without knowing the `dataFormat` it was read with: a matrix read is
|
|
113
|
+
* copied, an object read is rebuilt in the datastore's own column order (`fields`), without the
|
|
114
|
+
* `datastoreId` the SDK adds to each row, and with any patch applied to the rows.
|
|
74
115
|
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
116
|
+
* Either way the result is a new matrix the caller owns and may edit before saving. A matrix
|
|
117
|
+
* read's `data` is the matrix in the query cache, and handing that back made an edit change what
|
|
118
|
+
* every screen reading the entry sees.
|
|
77
119
|
*
|
|
78
|
-
*
|
|
120
|
+
* Do not save the result of a read that projected `data` away (`projection: "-data"`): it comes
|
|
121
|
+
* back as an empty table, indistinguishable from a real one, and saving it would empty the
|
|
122
|
+
* datastore.
|
|
79
123
|
*
|
|
80
|
-
* @
|
|
81
|
-
*
|
|
82
|
-
* @example
|
|
83
|
-
* const merged = mergeDatastores([
|
|
84
|
-
* [{ datastoreId: "a", x: 1 }],
|
|
85
|
-
* [{ datastoreId: "b", x: 2 }, { datastoreId: "b", x: 3 }],
|
|
86
|
-
* ]);
|
|
87
|
-
* // [{...}, {...}, {...}]
|
|
88
|
-
*/
|
|
89
|
-
export declare const mergeDatastores: (datastores: AnyRecord[][]) => AnyRecord[];
|
|
90
|
-
/**
|
|
91
|
-
* buildDatastoreProps
|
|
92
|
-
*
|
|
93
|
-
* Extracts and maps the metadata properties of a `Datastore` into a plain object
|
|
94
|
-
* for UI usage, discarding raw data rows.
|
|
95
|
-
*
|
|
96
|
-
* - `header` is derived from `datastore.data?.[0]` (the first row of the data matrix),
|
|
97
|
-
* which is expected to contain the column names. Falls back to `[]` if not present.
|
|
98
|
-
*
|
|
99
|
-
* @param {Datastore} datastore - The source datastore object.
|
|
100
|
-
* @returns Metadata object with the datastore's descriptive properties and header.
|
|
101
|
-
*
|
|
102
|
-
* @example
|
|
103
|
-
* const meta = buildDatastoreProps(datastore);
|
|
104
|
-
* // {
|
|
105
|
-
* // name: "my-datastore",
|
|
106
|
-
* // workspace: "ws-1",
|
|
107
|
-
* // header: ["col1", "col2"],
|
|
108
|
-
* // ...
|
|
109
|
-
* // }
|
|
124
|
+
* @param datastore A tabular datastore as the hooks return it (narrow with `isTableDatastore`).
|
|
125
|
+
* @returns The matrix, header row first.
|
|
110
126
|
*/
|
|
111
|
-
export declare const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
version: string | undefined;
|
|
115
|
-
description: string | undefined;
|
|
116
|
-
tags: string[] | undefined;
|
|
117
|
-
link_uid: string | undefined;
|
|
118
|
-
workspace: string;
|
|
119
|
-
date_time: string;
|
|
120
|
-
created: number | undefined;
|
|
121
|
-
updated: number | undefined;
|
|
122
|
-
level: string | undefined;
|
|
123
|
-
header: import("../types/datastore.d.ts").DatastoreRow[];
|
|
124
|
-
};
|
|
127
|
+
export declare const toDatastoreMatrix: (datastore: Extract<ParsedDatastore<DatastoreDataFormat>, {
|
|
128
|
+
format: "table";
|
|
129
|
+
}>) => DatastoreData;
|
|
125
130
|
export {};
|
|
126
131
|
//# sourceMappingURL=datastoreTable.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"datastoreTable.d.ts","sourceRoot":"","sources":["../../src/lib/datastoreTable.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"datastoreTable.d.ts","sourceRoot":"","sources":["../../src/lib/datastoreTable.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAiB,MAAM,mBAAmB,CAAC;AACnF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,KAAK,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;AACnC,KAAK,aAAa,GAAG,IAAI,EAAE,EAAE,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,EAC1D,aAAa,MAAM,EACnB,SAAS,MAAM,EAAE,EACjB,MAAM,aAAa,KACpB,CAAC,EAgBH,CAAC;AAMF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,SAAS,GAAG,eAAe,CAAC;AACtE,wBAAgB,cAAc,CAAC,CAAC,SAAS,mBAAmB,EACxD,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,CAAC,GACd,eAAe,CAAC,CAAC,CAAC,CAAC;AA0BtB;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,GAAI,CAAC,SAAS,eAAe,CAAC,mBAAmB,CAAC,EAC3E,WAAW,CAAC,KACb,SAAS,IAAI,OAAO,CAAC,CAAC,EAAE;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,CAAiC,CAAC;AAEhF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS,SAAS,GAAG,SAAS,EAC3D,SAAS,MAAM,EAAE,EACjB,MAAM,CAAC,EAAE,KACV,aAUF,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,iBAAiB,GAC1B,WAAW,OAAO,CAAC,eAAe,CAAC,mBAAmB,CAAC,EAAE;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,CAAC,KAC9E,aAaF,CAAC"}
|
|
@@ -29,13 +29,13 @@
|
|
|
29
29
|
* ["Alice", 30],
|
|
30
30
|
* ["Bob", null],
|
|
31
31
|
* ];
|
|
32
|
-
* const rows =
|
|
32
|
+
* const rows = matrixToObjects("ds_123", headers, data);
|
|
33
33
|
* // [
|
|
34
34
|
* // { datastoreId: "ds_123", name: "Alice", age: 30 },
|
|
35
35
|
* // { datastoreId: "ds_123", name: "Bob", age: null }
|
|
36
36
|
* // ]
|
|
37
37
|
*/
|
|
38
|
-
var
|
|
38
|
+
var matrixToObjects = (datastoreId, headers, data) => {
|
|
39
39
|
const result = [];
|
|
40
40
|
for (let i = 1; i < data?.length; i++) {
|
|
41
41
|
const item = {};
|
|
@@ -47,6 +47,38 @@ var tableToObjects = (datastoreId, headers, data) => {
|
|
|
47
47
|
}
|
|
48
48
|
return result;
|
|
49
49
|
};
|
|
50
|
+
/** A tabular datastore's `data`: an array of rows. An empty array counts, as an empty table. */
|
|
51
|
+
var isMatrix = (data) => Array.isArray(data) && data.every(Array.isArray);
|
|
52
|
+
function parseDatastore(datastore, dataFormat = "object") {
|
|
53
|
+
const { data } = datastore;
|
|
54
|
+
if (data && !isMatrix(data)) return {
|
|
55
|
+
...datastore,
|
|
56
|
+
format: "json",
|
|
57
|
+
data
|
|
58
|
+
};
|
|
59
|
+
const matrix = data ?? [];
|
|
60
|
+
const fields = matrix[0] ?? [];
|
|
61
|
+
if (dataFormat === "matrix") return {
|
|
62
|
+
...datastore,
|
|
63
|
+
format: "table",
|
|
64
|
+
fields,
|
|
65
|
+
data: matrix
|
|
66
|
+
};
|
|
67
|
+
return {
|
|
68
|
+
...datastore,
|
|
69
|
+
format: "table",
|
|
70
|
+
fields,
|
|
71
|
+
data: matrixToObjects(datastore.id, fields, matrix)
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Narrows a datastore to a tabular one, whose `data` is rows. For a `select` over a list that
|
|
76
|
+
* may mix kinds: `datastores.filter(isTableDatastore).flatMap((d) => d.data)`.
|
|
77
|
+
*
|
|
78
|
+
* @param datastore A datastore as the hooks return it.
|
|
79
|
+
* @returns True for a tabular datastore.
|
|
80
|
+
*/
|
|
81
|
+
var isTableDatastore = (datastore) => datastore.format === "table";
|
|
50
82
|
/**
|
|
51
83
|
* Converts an array of objects into a datastore table (2D array).
|
|
52
84
|
*
|
|
@@ -55,7 +87,8 @@ var tableToObjects = (datastoreId, headers, data) => {
|
|
|
55
87
|
* - For each object in `data`, creates a row by mapping `headers` to values in the object.
|
|
56
88
|
* - If a header is missing in an object, the corresponding cell is set to `null`.
|
|
57
89
|
*
|
|
58
|
-
*
|
|
90
|
+
* Takes rows as the datastore hooks hand them over (`AnyRecord`): a value that is not a cell is
|
|
91
|
+
* written as it is, since the row came from a matrix in the first place.
|
|
59
92
|
*
|
|
60
93
|
* @param headers Column names (and output table header row).
|
|
61
94
|
* @param data Array of objects to convert into rows.
|
|
@@ -66,7 +99,7 @@ var tableToObjects = (datastoreId, headers, data) => {
|
|
|
66
99
|
*
|
|
67
100
|
* @example
|
|
68
101
|
* const headers = ["name", "age"];
|
|
69
|
-
* const rows =
|
|
102
|
+
* const rows = objectsToMatrix(headers, [
|
|
70
103
|
* { name: "Alice", age: 30 },
|
|
71
104
|
* { name: "Bob" }, // age missing -> null
|
|
72
105
|
* ]);
|
|
@@ -76,71 +109,34 @@ var tableToObjects = (datastoreId, headers, data) => {
|
|
|
76
109
|
* // ["Bob", null]
|
|
77
110
|
* // ]
|
|
78
111
|
*/
|
|
79
|
-
var
|
|
80
|
-
|
|
112
|
+
var objectsToMatrix = (headers, data) => {
|
|
113
|
+
const matrix = [headers.slice()];
|
|
114
|
+
for (const row of data) matrix.push(headers.map((header) => row[header] ?? null));
|
|
115
|
+
return matrix;
|
|
81
116
|
};
|
|
82
117
|
/**
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
118
|
+
* The matrix of a tabular datastore, however the hook read it. Code that saves or exports a
|
|
119
|
+
* datastore calls this without knowing the `dataFormat` it was read with: a matrix read is
|
|
120
|
+
* copied, an object read is rebuilt in the datastore's own column order (`fields`), without the
|
|
121
|
+
* `datastoreId` the SDK adds to each row, and with any patch applied to the rows.
|
|
87
122
|
*
|
|
88
|
-
*
|
|
123
|
+
* Either way the result is a new matrix the caller owns and may edit before saving. A matrix
|
|
124
|
+
* read's `data` is the matrix in the query cache, and handing that back made an edit change what
|
|
125
|
+
* every screen reading the entry sees.
|
|
89
126
|
*
|
|
90
|
-
*
|
|
127
|
+
* Do not save the result of a read that projected `data` away (`projection: "-data"`): it comes
|
|
128
|
+
* back as an empty table, indistinguishable from a real one, and saving it would empty the
|
|
129
|
+
* datastore.
|
|
91
130
|
*
|
|
92
|
-
* @
|
|
93
|
-
*
|
|
94
|
-
* [{ datastoreId: "a", x: 1 }],
|
|
95
|
-
* [{ datastoreId: "b", x: 2 }, { datastoreId: "b", x: 3 }],
|
|
96
|
-
* ]);
|
|
97
|
-
* // [{...}, {...}, {...}]
|
|
131
|
+
* @param datastore A tabular datastore as the hooks return it (narrow with `isTableDatastore`).
|
|
132
|
+
* @returns The matrix, header row first.
|
|
98
133
|
*/
|
|
99
|
-
var
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
});
|
|
104
|
-
return result;
|
|
105
|
-
};
|
|
106
|
-
/**
|
|
107
|
-
* buildDatastoreProps
|
|
108
|
-
*
|
|
109
|
-
* Extracts and maps the metadata properties of a `Datastore` into a plain object
|
|
110
|
-
* for UI usage, discarding raw data rows.
|
|
111
|
-
*
|
|
112
|
-
* - `header` is derived from `datastore.data?.[0]` (the first row of the data matrix),
|
|
113
|
-
* which is expected to contain the column names. Falls back to `[]` if not present.
|
|
114
|
-
*
|
|
115
|
-
* @param {Datastore} datastore - The source datastore object.
|
|
116
|
-
* @returns Metadata object with the datastore's descriptive properties and header.
|
|
117
|
-
*
|
|
118
|
-
* @example
|
|
119
|
-
* const meta = buildDatastoreProps(datastore);
|
|
120
|
-
* // {
|
|
121
|
-
* // name: "my-datastore",
|
|
122
|
-
* // workspace: "ws-1",
|
|
123
|
-
* // header: ["col1", "col2"],
|
|
124
|
-
* // ...
|
|
125
|
-
* // }
|
|
126
|
-
*/
|
|
127
|
-
var buildDatastoreProps = (datastore) => {
|
|
128
|
-
return {
|
|
129
|
-
name: datastore.name,
|
|
130
|
-
date: datastore.date,
|
|
131
|
-
version: datastore.version,
|
|
132
|
-
description: datastore.description,
|
|
133
|
-
tags: datastore.tags,
|
|
134
|
-
link_uid: datastore.link_uid,
|
|
135
|
-
workspace: datastore.workspace,
|
|
136
|
-
date_time: datastore.date_time,
|
|
137
|
-
created: datastore.created,
|
|
138
|
-
updated: datastore.updated,
|
|
139
|
-
level: datastore.level,
|
|
140
|
-
header: datastore.data?.[0] || []
|
|
141
|
-
};
|
|
134
|
+
var toDatastoreMatrix = (datastore) => {
|
|
135
|
+
const { data, fields } = datastore;
|
|
136
|
+
if (data.length === 0) return fields.length > 0 ? [fields.slice()] : [];
|
|
137
|
+
return Array.isArray(data[0]) ? data.map((row) => row.slice()) : objectsToMatrix(fields, data);
|
|
142
138
|
};
|
|
143
139
|
//#endregion
|
|
144
|
-
export {
|
|
140
|
+
export { isTableDatastore, matrixToObjects, objectsToMatrix, parseDatastore, toDatastoreMatrix };
|
|
145
141
|
|
|
146
142
|
//# sourceMappingURL=datastoreTable.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"datastoreTable.js","names":[],"sources":["../../src/lib/datastoreTable.ts"],"sourcesContent":["import type { Datastore } from \"@/types/datastore\";\nimport type { AnyRecord } from \"@/types/anyRecord\";\n\ntype Cell = string | number | null;\ntype DatastoreData = Cell[][];\n\n/**\n * Converts a datastore table (2D array) into an array of objects.\n *\n * The input `data` is expected to be a 2D array where:\n * - Row 0 typically contains the headers (but headers are provided explicitly via `headers`)\n * - Rows 1..N contain the data values\n *\n * Key behaviors:\n * - Skips the first row of `data` (starts at index 1), assuming it is the header row.\n * - Adds a `datastoreId` field to every generated object so each record can be traced\n * back to its source datastore.\n * - Maps each header to the corresponding cell value by column index.\n *\n * @template T A record type whose values are compatible with `Cell` (string | number | null).\n *\n * @param datastoreId The id of the datastore to attach to each row as `datastoreId`.\n * @param headers The column names used as object keys (positionally aligned with row cells).\n * @param data The datastore matrix (rows x columns). Row 0 is assumed to be headers.\n *\n * @returns An array of objects (one per data row), each containing:\n * - `datastoreId`\n * - one property per header (with the corresponding cell value)\n *\n * @example\n * const headers = [\"name\", \"age\"];\n * const data = [\n * [\"name\", \"age\"],\n * [\"Alice\", 30],\n * [\"Bob\", null],\n * ];\n * const rows = tableToObjects(\"ds_123\", headers, data);\n * // [\n * // { datastoreId: \"ds_123\", name: \"Alice\", age: 30 },\n * // { datastoreId: \"ds_123\", name: \"Bob\", age: null }\n * // ]\n */\nexport const tableToObjects = <T extends Record<string, Cell>>(datastoreId: string, headers: string[], data: DatastoreData): T[] => {\n const result: T[] = [];\n\n for (let i = 1; i < data?.length; i++) {\n const item: Record<string, Cell> = {};\n\n item.datastoreId = datastoreId;\n\n headers.forEach((header: string, index: number) => {\n item[header] = data[i][index];\n });\n\n result.push(item as T);\n }\n\n return result;\n};\n\n/**\n * Converts an array of objects into a datastore table (2D array).\n *\n * Key behaviors:\n * - Produces a 2D array where the first row is the provided `headers`.\n * - For each object in `data`, creates a row by mapping `headers` to values in the object.\n * - If a header is missing in an object, the corresponding cell is set to `null`.\n *\n * @template T A record type whose values are compatible with `Cell` (string | number | null).\n *\n * @param headers Column names (and output table header row).\n * @param data Array of objects to convert into rows.\n *\n * @returns A datastore matrix where:\n * - Row 0 is `headers`\n * - Rows 1..N contain cell values aligned with `headers`\n *\n * @example\n * const headers = [\"name\", \"age\"];\n * const rows = objectsToTable(headers, [\n * { name: \"Alice\", age: 30 },\n * { name: \"Bob\" }, // age missing -> null\n * ]);\n * // [\n * // [\"name\", \"age\"],\n * // [\"Alice\", 30],\n * // [\"Bob\", null]\n * // ]\n */\nexport const objectsToTable = <T extends Record<string, Cell>>(headers: string[] ,data: T[]): DatastoreData => {\n const rows: DatastoreData = data.map((d) => headers.map<Cell>((h) => d[h as string] ?? null));\n\n return [headers, ...rows];\n};\n\n/**\n * Flattens multiple datastore row arrays into a single array.\n *\n * This is typically used after fetching multiple datastores, where each datastore is\n * represented as `AnyRecord[]` (i.e., an array of row objects).\n *\n * @param datastores A list of datastores, each represented as an array of row objects.\n *\n * @returns A single array containing all rows from all datastores, in the same order.\n *\n * @example\n * const merged = mergeDatastores([\n * [{ datastoreId: \"a\", x: 1 }],\n * [{ datastoreId: \"b\", x: 2 }, { datastoreId: \"b\", x: 3 }],\n * ]);\n * // [{...}, {...}, {...}]\n */\nexport const mergeDatastores = (datastores: AnyRecord[][]): AnyRecord[] => {\n const result: AnyRecord[] = [];\n\n datastores.forEach((datastore: AnyRecord[]) => {\n result.push(...datastore);\n });\n\n return result;\n};\n\n/**\n * buildDatastoreProps\n *\n * Extracts and maps the metadata properties of a `Datastore` into a plain object\n * for UI usage, discarding raw data rows.\n *\n * - `header` is derived from `datastore.data?.[0]` (the first row of the data matrix),\n * which is expected to contain the column names. Falls back to `[]` if not present.\n *\n * @param {Datastore} datastore - The source datastore object.\n * @returns Metadata object with the datastore's descriptive properties and header.\n *\n * @example\n * const meta = buildDatastoreProps(datastore);\n * // {\n * // name: \"my-datastore\",\n * // workspace: \"ws-1\",\n * // header: [\"col1\", \"col2\"],\n * // ...\n * // }\n */\nexport const buildDatastoreProps = (datastore: Datastore) => {\n return {\n name: datastore.name,\n date: datastore.date,\n version: datastore.version,\n description: datastore.description,\n tags: datastore.tags,\n link_uid: datastore.link_uid,\n workspace: datastore.workspace,\n date_time: datastore.date_time,\n created: datastore.created,\n updated: datastore.updated,\n level: datastore.level,\n header: datastore.data?.[0] || [],\n };\n};"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CA,IAAa,kBAAkD,aAAqB,SAAmB,SAA6B;CAClI,MAAM,SAAc,CAAC;CAErB,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;EACrC,MAAM,OAA6B,CAAC;EAEpC,KAAK,cAAc;EAEnB,QAAQ,SAAS,QAAgB,UAAkB;GACjD,KAAK,UAAU,KAAK,EAAE,CAAC;EACzB,CAAC;EAED,OAAO,KAAK,IAAS;CACvB;CAEA,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,IAAa,kBAAkD,SAAmB,SAA6B;CAG7G,OAAO,CAAC,SAAS,GAFW,KAAK,KAAK,MAAM,QAAQ,KAAW,MAAM,EAAE,MAAgB,IAAI,CAEvE,CAAI;AAC1B;;;;;;;;;;;;;;;;;;AAmBA,IAAa,mBAAmB,eAA2C;CACzE,MAAM,SAAsB,CAAC;CAE7B,WAAW,SAAS,cAA2B;EAC7C,OAAO,KAAK,GAAG,SAAS;CAC1B,CAAC;CAED,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;AAuBA,IAAa,uBAAuB,cAAyB;CACzD,OAAO;EACH,MAAM,UAAU;EAChB,MAAM,UAAU;EAChB,SAAS,UAAU;EACnB,aAAa,UAAU;EACvB,MAAM,UAAU;EAChB,UAAU,UAAU;EACpB,WAAW,UAAU;EACrB,WAAW,UAAU;EACrB,SAAS,UAAU;EACnB,SAAS,UAAU;EACnB,OAAO,UAAU;EACjB,QAAQ,UAAU,OAAO,MAAM,CAAC;CACpC;AACJ"}
|
|
1
|
+
{"version":3,"file":"datastoreTable.js","names":[],"sources":["../../src/lib/datastoreTable.ts"],"sourcesContent":["import type { Datastore, ParsedDatastore, JsonDatastore } from \"@/types/datastore\";\nimport type { DatastoreDataFormat } from \"@/types/datastoreDataFormat\";\nimport type { AnyRecord } from \"@/types/anyRecord\";\n\ntype Cell = string | number | null;\ntype DatastoreData = Cell[][];\n\n/**\n * Converts a datastore table (2D array) into an array of objects.\n *\n * The input `data` is expected to be a 2D array where:\n * - Row 0 typically contains the headers (but headers are provided explicitly via `headers`)\n * - Rows 1..N contain the data values\n *\n * Key behaviors:\n * - Skips the first row of `data` (starts at index 1), assuming it is the header row.\n * - Adds a `datastoreId` field to every generated object so each record can be traced\n * back to its source datastore.\n * - Maps each header to the corresponding cell value by column index.\n *\n * @template T A record type whose values are compatible with `Cell` (string | number | null).\n *\n * @param datastoreId The id of the datastore to attach to each row as `datastoreId`.\n * @param headers The column names used as object keys (positionally aligned with row cells).\n * @param data The datastore matrix (rows x columns). Row 0 is assumed to be headers.\n *\n * @returns An array of objects (one per data row), each containing:\n * - `datastoreId`\n * - one property per header (with the corresponding cell value)\n *\n * @example\n * const headers = [\"name\", \"age\"];\n * const data = [\n * [\"name\", \"age\"],\n * [\"Alice\", 30],\n * [\"Bob\", null],\n * ];\n * const rows = matrixToObjects(\"ds_123\", headers, data);\n * // [\n * // { datastoreId: \"ds_123\", name: \"Alice\", age: 30 },\n * // { datastoreId: \"ds_123\", name: \"Bob\", age: null }\n * // ]\n */\nexport const matrixToObjects = <T extends Record<string, Cell>>(\n datastoreId: string,\n headers: string[],\n data: DatastoreData,\n): T[] => {\n const result: T[] = [];\n\n for (let i = 1; i < data?.length; i++) {\n const item: Record<string, Cell> = {};\n\n item.datastoreId = datastoreId;\n\n headers.forEach((header: string, index: number) => {\n item[header] = data[i][index];\n });\n\n result.push(item as T);\n }\n\n return result;\n};\n\n/** A tabular datastore's `data`: an array of rows. An empty array counts, as an empty table. */\nconst isMatrix = (data: unknown): data is DatastoreData =>\n Array.isArray(data) && data.every(Array.isArray);\n\n/**\n * Converts a datastore as the API returns it into the shape the datastore hooks return.\n *\n * A datastore is tabular or JSON, and the API does not say which. `data` is a matrix, an object,\n * or an array of objects, so only an array whose every element is an array is read as a table.\n * \"Any array\" is not enough: the API has returned `[{ … }]` for a JSON datastore, which read as a\n * matrix lost its content with one element and threw with two. A table's matrix becomes row\n * objects, with the header row kept as `fields` so that saving back can restore the column\n * order. JSON passes through untouched.\n *\n * A read without its data (`projection: \"-data\"`) carries nothing to tell the kinds apart and\n * comes back as an empty table.\n *\n * The hooks convert in the request rather than in `select`, so the cache holds objects and an\n * app patches a row as `{ ...row, ...patch }` rather than by column index. It is exported for an\n * app that seeds that cache itself.\n *\n * With `dataFormat: \"matrix\"` a table keeps its matrix unconverted, header row included, and still\n * gets `fields`. JSON is untouched either way.\n *\n * @param datastore The datastore as the API returned it.\n * @param dataFormat `\"object\"` (default) or `\"matrix\"`.\n * @returns A tabular or a `JsonDatastore`, told apart by `format`.\n */\nexport function parseDatastore(datastore: Datastore): ParsedDatastore;\nexport function parseDatastore<F extends DatastoreDataFormat>(\n datastore: Datastore,\n dataFormat: F,\n): ParsedDatastore<F>;\nexport function parseDatastore(\n datastore: Datastore,\n dataFormat: DatastoreDataFormat = \"object\",\n): ParsedDatastore<DatastoreDataFormat> {\n const { data } = datastore;\n\n if (data && !isMatrix(data)) {\n return { ...datastore, format: \"json\", data: data as JsonDatastore[\"data\"] };\n }\n\n const matrix = (data ?? []) as DatastoreData;\n const fields = (matrix[0] ?? []) as string[];\n\n if (dataFormat === \"matrix\") {\n return { ...datastore, format: \"table\", fields, data: matrix };\n }\n\n return {\n ...datastore,\n format: \"table\",\n fields,\n data: matrixToObjects(datastore.id, fields, matrix),\n };\n}\n\n/**\n * Narrows a datastore to a tabular one, whose `data` is rows. For a `select` over a list that\n * may mix kinds: `datastores.filter(isTableDatastore).flatMap((d) => d.data)`.\n *\n * @param datastore A datastore as the hooks return it.\n * @returns True for a tabular datastore.\n */\nexport const isTableDatastore = <D extends ParsedDatastore<DatastoreDataFormat>>(\n datastore: D,\n): datastore is Extract<D, { format: \"table\" }> => datastore.format === \"table\";\n\n/**\n * Converts an array of objects into a datastore table (2D array).\n *\n * Key behaviors:\n * - Produces a 2D array where the first row is the provided `headers`.\n * - For each object in `data`, creates a row by mapping `headers` to values in the object.\n * - If a header is missing in an object, the corresponding cell is set to `null`.\n *\n * Takes rows as the datastore hooks hand them over (`AnyRecord`): a value that is not a cell is\n * written as it is, since the row came from a matrix in the first place.\n *\n * @param headers Column names (and output table header row).\n * @param data Array of objects to convert into rows.\n *\n * @returns A datastore matrix where:\n * - Row 0 is `headers`\n * - Rows 1..N contain cell values aligned with `headers`\n *\n * @example\n * const headers = [\"name\", \"age\"];\n * const rows = objectsToMatrix(headers, [\n * { name: \"Alice\", age: 30 },\n * { name: \"Bob\" }, // age missing -> null\n * ]);\n * // [\n * // [\"name\", \"age\"],\n * // [\"Alice\", 30],\n * // [\"Bob\", null]\n * // ]\n */\nexport const objectsToMatrix = <T extends AnyRecord = AnyRecord>(\n headers: string[],\n data: T[],\n): DatastoreData => {\n // Built into one array: mapping the rows and then spreading them after the header copied the\n // whole list a second time. The header is copied: a caller's `headers` is often a datastore's\n // `fields`, held in the query cache, and renaming a column in the matrix renamed it there too.\n const matrix: DatastoreData = [headers.slice()];\n\n for (const row of data)\n matrix.push(headers.map<Cell>((header) => (row[header] ?? null) as Cell));\n\n return matrix;\n};\n\n/**\n * The matrix of a tabular datastore, however the hook read it. Code that saves or exports a\n * datastore calls this without knowing the `dataFormat` it was read with: a matrix read is\n * copied, an object read is rebuilt in the datastore's own column order (`fields`), without the\n * `datastoreId` the SDK adds to each row, and with any patch applied to the rows.\n *\n * Either way the result is a new matrix the caller owns and may edit before saving. A matrix\n * read's `data` is the matrix in the query cache, and handing that back made an edit change what\n * every screen reading the entry sees.\n *\n * Do not save the result of a read that projected `data` away (`projection: \"-data\"`): it comes\n * back as an empty table, indistinguishable from a real one, and saving it would empty the\n * datastore.\n *\n * @param datastore A tabular datastore as the hooks return it (narrow with `isTableDatastore`).\n * @returns The matrix, header row first.\n */\nexport const toDatastoreMatrix = (\n datastore: Extract<ParsedDatastore<DatastoreDataFormat>, { format: \"table\" }>,\n): DatastoreData => {\n const { data, fields } = datastore;\n\n if (data.length === 0) return fields.length > 0 ? [fields.slice()] : [];\n\n // The first row is enough: the SDK built this `data`, so it is all rows or all objects. The\n // full `isMatrix` scan guards the API's data, and here it would only walk every row for nothing.\n // A row-by-row copy is a full copy: a matrix is two levels deep and its cells are primitives.\n // `structuredClone` would do the same about 8 times slower (147 ms against 18 ms for 100,000\n // rows of 10 cells), paying for cycles and special types a datastore matrix never holds.\n return Array.isArray(data[0])\n ? (data as DatastoreData).map((row) => row.slice())\n : objectsToMatrix(fields, data as AnyRecord[]);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2CA,IAAa,mBACT,aACA,SACA,SACM;CACN,MAAM,SAAc,CAAC;CAErB,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;EACnC,MAAM,OAA6B,CAAC;EAEpC,KAAK,cAAc;EAEnB,QAAQ,SAAS,QAAgB,UAAkB;GAC/C,KAAK,UAAU,KAAK,EAAE,CAAC;EAC3B,CAAC;EAED,OAAO,KAAK,IAAS;CACzB;CAEA,OAAO;AACX;;AAGA,IAAM,YAAY,SACd,MAAM,QAAQ,IAAI,KAAK,KAAK,MAAM,MAAM,OAAO;AA+BnD,SAAgB,eACZ,WACA,aAAkC,UACE;CACpC,MAAM,EAAE,SAAS;CAEjB,IAAI,QAAQ,CAAC,SAAS,IAAI,GACtB,OAAO;EAAE,GAAG;EAAW,QAAQ;EAAc;CAA8B;CAG/E,MAAM,SAAU,QAAQ,CAAC;CACzB,MAAM,SAAU,OAAO,MAAM,CAAC;CAE9B,IAAI,eAAe,UACf,OAAO;EAAE,GAAG;EAAW,QAAQ;EAAS;EAAQ,MAAM;CAAO;CAGjE,OAAO;EACH,GAAG;EACH,QAAQ;EACR;EACA,MAAM,gBAAgB,UAAU,IAAI,QAAQ,MAAM;CACtD;AACJ;;;;;;;;AASA,IAAa,oBACT,cAC+C,UAAU,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCxE,IAAa,mBACT,SACA,SACgB;CAIhB,MAAM,SAAwB,CAAC,QAAQ,MAAM,CAAC;CAE9C,KAAK,MAAM,OAAO,MACd,OAAO,KAAK,QAAQ,KAAW,WAAY,IAAI,WAAW,IAAa,CAAC;CAE5E,OAAO;AACX;;;;;;;;;;;;;;;;;;AAmBA,IAAa,qBACT,cACgB;CAChB,MAAM,EAAE,MAAM,WAAW;CAEzB,IAAI,KAAK,WAAW,GAAG,OAAO,OAAO,SAAS,IAAI,CAAC,OAAO,MAAM,CAAC,IAAI,CAAC;CAOtE,OAAO,MAAM,QAAQ,KAAK,EAAE,IACrB,KAAuB,KAAK,QAAQ,IAAI,MAAM,CAAC,IAChD,gBAAgB,QAAQ,IAAmB;AACrD"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fileToBase64
|
|
3
|
+
*
|
|
4
|
+
* The raw base64 `createFile` and `updateFile` take as `data`, from a `File` an `<input
|
|
5
|
+
* type="file">` gives or any `Blob`. The API stores `data` as given, so the `data:<type>;base64,`
|
|
6
|
+
* prefix `FileReader` puts in front would be stored as part of the content.
|
|
7
|
+
*
|
|
8
|
+
* Read through `FileReader` rather than by encoding the bytes in a loop: the browser encodes
|
|
9
|
+
* natively, with no binary string built byte by byte for `btoa`. An empty file reads as `data:`
|
|
10
|
+
* with no comma in Chromium, so a missing comma is empty content — for an empty file only, as
|
|
11
|
+
* a file with content read that way would otherwise be uploaded empty.
|
|
12
|
+
*
|
|
13
|
+
* @param blob - The file.
|
|
14
|
+
* @returns The content as base64, without a prefix.
|
|
15
|
+
*/
|
|
16
|
+
export declare const fileToBase64: (blob: Blob) => Promise<string>;
|
|
17
|
+
/**
|
|
18
|
+
* base64ToBlob
|
|
19
|
+
*
|
|
20
|
+
* A file's content, as the API returns it in `data`, decoded into a `Blob` byte for byte: to work
|
|
21
|
+
* on the bytes in code, such as parsing a CSV or unzipping. Not to show the file — the app page's
|
|
22
|
+
* CSP blocks a `blob:` frame, image or media; use the file's own `url` — and it decodes
|
|
23
|
+
* synchronously, a byte at a time, so a file of several megabytes is better read through it.
|
|
24
|
+
*
|
|
25
|
+
* Without content — a file read without `withData: true` — it warns and gives an empty blob:
|
|
26
|
+
* `atob(null)` decodes the text "null", three bytes of garbage that would pass for the file.
|
|
27
|
+
*
|
|
28
|
+
* @param data - The content as base64, as the hooks return it with `withData: true`.
|
|
29
|
+
* @param contentType - The file's `content_type`, which becomes the blob's `type`.
|
|
30
|
+
* @returns The content.
|
|
31
|
+
* @throws {Error} If `data` is not raw base64.
|
|
32
|
+
*/
|
|
33
|
+
export declare const base64ToBlob: (data: string | null | undefined, contentType: string) => Blob;
|
|
34
|
+
//# sourceMappingURL=file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../src/lib/file.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,YAAY,GAAI,MAAM,IAAI,KAAG,OAAO,CAAC,MAAM,CAgBlD,CAAC;AAEP;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,YAAY,GAAI,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,aAAa,MAAM,KAAG,IAiBnF,CAAC"}
|
package/dist/lib/file.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
//#region src/lib/file.ts
|
|
2
|
+
/**
|
|
3
|
+
* fileToBase64
|
|
4
|
+
*
|
|
5
|
+
* The raw base64 `createFile` and `updateFile` take as `data`, from a `File` an `<input
|
|
6
|
+
* type="file">` gives or any `Blob`. The API stores `data` as given, so the `data:<type>;base64,`
|
|
7
|
+
* prefix `FileReader` puts in front would be stored as part of the content.
|
|
8
|
+
*
|
|
9
|
+
* Read through `FileReader` rather than by encoding the bytes in a loop: the browser encodes
|
|
10
|
+
* natively, with no binary string built byte by byte for `btoa`. An empty file reads as `data:`
|
|
11
|
+
* with no comma in Chromium, so a missing comma is empty content — for an empty file only, as
|
|
12
|
+
* a file with content read that way would otherwise be uploaded empty.
|
|
13
|
+
*
|
|
14
|
+
* @param blob - The file.
|
|
15
|
+
* @returns The content as base64, without a prefix.
|
|
16
|
+
*/
|
|
17
|
+
var fileToBase64 = (blob) => new Promise((resolve, reject) => {
|
|
18
|
+
const reader = new FileReader();
|
|
19
|
+
reader.onload = () => {
|
|
20
|
+
const dataUrl = String(reader.result);
|
|
21
|
+
const comma = dataUrl.indexOf(",");
|
|
22
|
+
if (comma !== -1) resolve(dataUrl.slice(comma + 1));
|
|
23
|
+
else if (blob.size === 0) resolve("");
|
|
24
|
+
else reject(/* @__PURE__ */ new Error("Unable to read the file: it read as a data URL with no content"));
|
|
25
|
+
};
|
|
26
|
+
reader.onerror = () => reject(reader.error ?? /* @__PURE__ */ new Error("Unable to read the file"));
|
|
27
|
+
reader.readAsDataURL(blob);
|
|
28
|
+
});
|
|
29
|
+
/**
|
|
30
|
+
* base64ToBlob
|
|
31
|
+
*
|
|
32
|
+
* A file's content, as the API returns it in `data`, decoded into a `Blob` byte for byte: to work
|
|
33
|
+
* on the bytes in code, such as parsing a CSV or unzipping. Not to show the file — the app page's
|
|
34
|
+
* CSP blocks a `blob:` frame, image or media; use the file's own `url` — and it decodes
|
|
35
|
+
* synchronously, a byte at a time, so a file of several megabytes is better read through it.
|
|
36
|
+
*
|
|
37
|
+
* Without content — a file read without `withData: true` — it warns and gives an empty blob:
|
|
38
|
+
* `atob(null)` decodes the text "null", three bytes of garbage that would pass for the file.
|
|
39
|
+
*
|
|
40
|
+
* @param data - The content as base64, as the hooks return it with `withData: true`.
|
|
41
|
+
* @param contentType - The file's `content_type`, which becomes the blob's `type`.
|
|
42
|
+
* @returns The content.
|
|
43
|
+
* @throws {Error} If `data` is not raw base64.
|
|
44
|
+
*/
|
|
45
|
+
var base64ToBlob = (data, contentType) => {
|
|
46
|
+
if (data == null) {
|
|
47
|
+
console.warn("[apps-sdk] base64ToBlob: the file came without its content; read it with withData: true.");
|
|
48
|
+
return new Blob([], { type: contentType });
|
|
49
|
+
}
|
|
50
|
+
let binary;
|
|
51
|
+
try {
|
|
52
|
+
binary = atob(data);
|
|
53
|
+
} catch (error) {
|
|
54
|
+
throw new Error("The file's data is not raw base64", { cause: error });
|
|
55
|
+
}
|
|
56
|
+
const bytes = new Uint8Array(binary.length);
|
|
57
|
+
for (let index = 0; index < binary.length; index++) bytes[index] = binary.charCodeAt(index);
|
|
58
|
+
return new Blob([bytes], { type: contentType });
|
|
59
|
+
};
|
|
60
|
+
//#endregion
|
|
61
|
+
export { base64ToBlob, fileToBase64 };
|
|
62
|
+
|
|
63
|
+
//# sourceMappingURL=file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.js","names":[],"sources":["../../src/lib/file.ts"],"sourcesContent":["/**\n * fileToBase64\n *\n * The raw base64 `createFile` and `updateFile` take as `data`, from a `File` an `<input\n * type=\"file\">` gives or any `Blob`. The API stores `data` as given, so the `data:<type>;base64,`\n * prefix `FileReader` puts in front would be stored as part of the content.\n *\n * Read through `FileReader` rather than by encoding the bytes in a loop: the browser encodes\n * natively, with no binary string built byte by byte for `btoa`. An empty file reads as `data:`\n * with no comma in Chromium, so a missing comma is empty content — for an empty file only, as\n * a file with content read that way would otherwise be uploaded empty.\n *\n * @param blob - The file.\n * @returns The content as base64, without a prefix.\n */\nexport const fileToBase64 = (blob: Blob): Promise<string> =>\n new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => {\n const dataUrl = String(reader.result);\n const comma = dataUrl.indexOf(\",\");\n if (comma !== -1) {\n resolve(dataUrl.slice(comma + 1));\n } else if (blob.size === 0) {\n resolve(\"\");\n } else {\n reject(new Error(\"Unable to read the file: it read as a data URL with no content\"));\n }\n };\n reader.onerror = () => reject(reader.error ?? new Error(\"Unable to read the file\"));\n reader.readAsDataURL(blob);\n });\n\n/**\n * base64ToBlob\n *\n * A file's content, as the API returns it in `data`, decoded into a `Blob` byte for byte: to work\n * on the bytes in code, such as parsing a CSV or unzipping. Not to show the file — the app page's\n * CSP blocks a `blob:` frame, image or media; use the file's own `url` — and it decodes\n * synchronously, a byte at a time, so a file of several megabytes is better read through it.\n *\n * Without content — a file read without `withData: true` — it warns and gives an empty blob:\n * `atob(null)` decodes the text \"null\", three bytes of garbage that would pass for the file.\n *\n * @param data - The content as base64, as the hooks return it with `withData: true`.\n * @param contentType - The file's `content_type`, which becomes the blob's `type`.\n * @returns The content.\n * @throws {Error} If `data` is not raw base64.\n */\nexport const base64ToBlob = (data: string | null | undefined, contentType: string): Blob => {\n if (data == null) {\n console.warn(\n \"[apps-sdk] base64ToBlob: the file came without its content; read it with withData: true.\",\n );\n return new Blob([], { type: contentType });\n }\n\n let binary: string;\n try {\n binary = atob(data);\n } catch (error) {\n throw new Error(\"The file's data is not raw base64\", { cause: error });\n }\n const bytes = new Uint8Array(binary.length);\n for (let index = 0; index < binary.length; index++) bytes[index] = binary.charCodeAt(index);\n return new Blob([bytes], { type: contentType });\n};\n"],"mappings":";;;;;;;;;;;;;;;;AAeA,IAAa,gBAAgB,SACzB,IAAI,SAAS,SAAS,WAAW;CAC7B,MAAM,SAAS,IAAI,WAAW;CAC9B,OAAO,eAAe;EAClB,MAAM,UAAU,OAAO,OAAO,MAAM;EACpC,MAAM,QAAQ,QAAQ,QAAQ,GAAG;EACjC,IAAI,UAAU,IACV,QAAQ,QAAQ,MAAM,QAAQ,CAAC,CAAC;OAC7B,IAAI,KAAK,SAAS,GACrB,QAAQ,EAAE;OAEV,uBAAO,IAAI,MAAM,gEAAgE,CAAC;CAE1F;CACA,OAAO,gBAAgB,OAAO,OAAO,yBAAS,IAAI,MAAM,yBAAyB,CAAC;CAClF,OAAO,cAAc,IAAI;AAC7B,CAAC;;;;;;;;;;;;;;;;;AAkBL,IAAa,gBAAgB,MAAiC,gBAA8B;CACxF,IAAI,QAAQ,MAAM;EACd,QAAQ,KACJ,0FACJ;EACA,OAAO,IAAI,KAAK,CAAC,GAAG,EAAE,MAAM,YAAY,CAAC;CAC7C;CAEA,IAAI;CACJ,IAAI;EACA,SAAS,KAAK,IAAI;CACtB,SAAS,OAAO;EACZ,MAAM,IAAI,MAAM,qCAAqC,EAAE,OAAO,MAAM,CAAC;CACzE;CACA,MAAM,QAAQ,IAAI,WAAW,OAAO,MAAM;CAC1C,KAAK,IAAI,QAAQ,GAAG,QAAQ,OAAO,QAAQ,SAAS,MAAM,SAAS,OAAO,WAAW,KAAK;CAC1F,OAAO,IAAI,KAAK,CAAC,KAAK,GAAG,EAAE,MAAM,YAAY,CAAC;AAClD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queryClient.d.ts","sourceRoot":"","sources":["../../src/lib/queryClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,iBAAiB,EAAE,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAShG,KAAK,oBAAoB,GAAG,YAAY,GAAG,OAAO,CAAC;AACnD,eAAO,MAAM,UAAU,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE;
|
|
1
|
+
{"version":3,"file":"queryClient.d.ts","sourceRoot":"","sources":["../../src/lib/queryClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,iBAAiB,EAAE,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAShG,KAAK,oBAAoB,GAAG,YAAY,GAAG,OAAO,CAAC;AACnD,eAAO,MAAM,UAAU,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE;IAAE,KAAK,EAAE,oBAAoB,CAAA;CAAE,KAAK,aAAa,CAAC,CAAC,CAapF,CAAC;AAEN;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,iBAAiB,GAAI,SAAS,iBAAiB,KAAG,WAgBzD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queryClient.js","names":[],"sources":["../../src/lib/queryClient.ts"],"sourcesContent":["import { QueryClient, type QueryClientConfig, type QueryFunction } from \"@tanstack/react-query\";\n\nasync function throwIfResNotOk(res: Response) {\n if (!res.ok) {\n const text = (await res.text()) || res.statusText;\n throw new Error(`${res.status}: ${text}`);\n }\n}\n\ntype UnauthorizedBehavior = \"returnNull\" | \"throw\";\nexport const getQueryFn: <T>(options: {
|
|
1
|
+
{"version":3,"file":"queryClient.js","names":[],"sources":["../../src/lib/queryClient.ts"],"sourcesContent":["import { QueryClient, type QueryClientConfig, type QueryFunction } from \"@tanstack/react-query\";\n\nasync function throwIfResNotOk(res: Response) {\n if (!res.ok) {\n const text = (await res.text()) || res.statusText;\n throw new Error(`${res.status}: ${text}`);\n }\n}\n\ntype UnauthorizedBehavior = \"returnNull\" | \"throw\";\nexport const getQueryFn: <T>(options: { on401: UnauthorizedBehavior }) => QueryFunction<T> =\n ({ on401: unauthorizedBehavior }) =>\n async ({ queryKey }) => {\n const res = await fetch(queryKey.join(\"/\") as string, {\n credentials: \"include\",\n });\n\n if (unauthorizedBehavior === \"returnNull\" && res.status === 401) {\n return null;\n }\n\n await throwIfResNotOk(res);\n return await res.json();\n };\n\n/**\n * createQueryClient\n *\n * Builds a `QueryClient` carrying the defaults every Everysk app shares: the fetch-based\n * `queryFn` above, no retries, no refetch on focus or interval, and `staleTime: Infinity`.\n *\n * This is a factory rather than the shared instance the template exported. A module-level\n * `new QueryClient()` inside a published package is a single cache shared by every consumer\n * of that copy of the module: it cannot be configured per app, it cannot be reset, and in\n * tests it leaks state from one case into the next. The app owns the instance and passes it\n * to `QueryClientProvider` — `EveryskApp` does this for you when you don't pass one.\n *\n * @param {QueryClientConfig} [config] - Merged over the defaults, one level deep, so passing\n * `defaultOptions.queries` replaces the whole `queries` object rather than merging into it.\n * @returns {QueryClient} A fresh client.\n */\nexport const createQueryClient = (config?: QueryClientConfig): QueryClient =>\n new QueryClient({\n ...config,\n defaultOptions: {\n queries: {\n queryFn: getQueryFn({ on401: \"throw\" }),\n refetchInterval: false,\n refetchOnWindowFocus: false,\n staleTime: Infinity,\n retry: false,\n },\n mutations: {\n retry: false,\n },\n ...config?.defaultOptions,\n },\n });\n"],"mappings":";;AAEA,eAAe,gBAAgB,KAAe;CAC1C,IAAI,CAAC,IAAI,IAAI;EACT,MAAM,OAAQ,MAAM,IAAI,KAAK,KAAM,IAAI;EACvC,MAAM,IAAI,MAAM,GAAG,IAAI,OAAO,IAAI,MAAM;CAC5C;AACJ;AAGA,IAAa,cACR,EAAE,OAAO,2BACV,OAAO,EAAE,eAAe;CACpB,MAAM,MAAM,MAAM,MAAM,SAAS,KAAK,GAAG,GAAa,EAClD,aAAa,UACjB,CAAC;CAED,IAAI,yBAAyB,gBAAgB,IAAI,WAAW,KACxD,OAAO;CAGX,MAAM,gBAAgB,GAAG;CACzB,OAAO,MAAM,IAAI,KAAK;AAC1B;;;;;;;;;;;;;;;;;AAkBJ,IAAa,qBAAqB,WAC9B,IAAI,YAAY;CACZ,GAAG;CACH,gBAAgB;EACZ,SAAS;GACL,SAAS,WAAW,EAAE,OAAO,QAAQ,CAAC;GACtC,iBAAiB;GACjB,sBAAsB;GACtB,WAAW;GACX,OAAO;EACX;EACA,WAAW,EACP,OAAO,MACX;EACA,GAAG,QAAQ;CACf;AACJ,CAAC"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { WebSocketNotification, WebSocketStatus } from "../contexts/webSocketContext/types.d.ts";
|
|
2
|
+
import type { WorkflowExecution } from "../types/workflow.d.ts";
|
|
3
|
+
/** The alert a run hook shows when its failure carries no message of its own. */
|
|
4
|
+
export declare const RUN_FAILED_MESSAGE = "Unable to run the workflow. Please try again.";
|
|
5
|
+
/**
|
|
6
|
+
* The error a run ends with when its caller stopped it — the screen went away, or the app's own
|
|
7
|
+
* signal — with that signal's reason as the cause. One class for both phases, the wait and the
|
|
8
|
+
* result read, so a caller can tell a stop from a failure with `instanceof` rather than by its
|
|
9
|
+
* message.
|
|
10
|
+
*/
|
|
11
|
+
export declare class WorkflowRunAbortedError extends Error {
|
|
12
|
+
constructor(reason: unknown);
|
|
13
|
+
}
|
|
14
|
+
export type WorkflowWaitOptions = {
|
|
15
|
+
/**
|
|
16
|
+
* How long the run may go without any event before the execution is read anyway, in
|
|
17
|
+
* milliseconds. Defaults to a minute. It covers a lost event, and a long worker, which sends
|
|
18
|
+
* nothing while it runs.
|
|
19
|
+
*/
|
|
20
|
+
silenceMs?: number;
|
|
21
|
+
/** How long to wait for the run to end before giving up, in milliseconds. Defaults to 5 minutes. */
|
|
22
|
+
timeoutMs?: number;
|
|
23
|
+
/**
|
|
24
|
+
* The first gap between reads after the end event, while the run still reads RUNNING, in
|
|
25
|
+
* milliseconds. It doubles each time it passes without a new event, up to `silenceMs`.
|
|
26
|
+
* Defaults to 1 second.
|
|
27
|
+
*/
|
|
28
|
+
confirmIntervalMs?: number;
|
|
29
|
+
/**
|
|
30
|
+
* How long the socket may stay in `error` before the run is given up on as unfollowable, in
|
|
31
|
+
* milliseconds. Defaults to 30 seconds: socket.io keeps retrying after a failed reconnect, on
|
|
32
|
+
* a backoff that alone can reach about 7.5 seconds between attempts.
|
|
33
|
+
*/
|
|
34
|
+
unavailableAfterMs?: number;
|
|
35
|
+
/** Stops waiting. `useRunWorkflow` also stops when its screen unmounts. */
|
|
36
|
+
signal?: AbortSignal;
|
|
37
|
+
};
|
|
38
|
+
export type RunWorkflowToEndParams = WorkflowWaitOptions & {
|
|
39
|
+
/** Starts the run (`POST /workflows/:id/run`) and returns the execution it created. */
|
|
40
|
+
startRun: () => Promise<WorkflowExecution>;
|
|
41
|
+
/**
|
|
42
|
+
* Reads the execution; its `run_status` is what says the run ended, and how. Pass `signal` to
|
|
43
|
+
* the request, so a timeout or an abort cancels a read in flight.
|
|
44
|
+
*/
|
|
45
|
+
getExecution: (workflowExecutionId: string, signal: AbortSignal) => Promise<WorkflowExecution>;
|
|
46
|
+
/** The websocket context's `subscribe`. */
|
|
47
|
+
subscribeToEvents: (listener: (event: WebSocketNotification) => void) => () => void;
|
|
48
|
+
/**
|
|
49
|
+
* The websocket context's `subscribeStatus`, which tells a new listener the current status at
|
|
50
|
+
* once: that is how the wait learns the status it begins in.
|
|
51
|
+
*/
|
|
52
|
+
subscribeToStatus: (listener: (status: WebSocketStatus) => void) => () => void;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* runWorkflowToEnd
|
|
56
|
+
*
|
|
57
|
+
* Starts a workflow run and waits for it to end, listening to the websocket rather than polling;
|
|
58
|
+
* the end itself is read from the API. Resolves with the ended execution, whatever its
|
|
59
|
+
* `run_status` — deciding what counts as success is the caller's.
|
|
60
|
+
*
|
|
61
|
+
* The websocket says *when* to read, never *what* happened. The backend publishes a
|
|
62
|
+
* `WORKER_EXECUTION_*` event per worker and a `WORKFLOW_EXECUTION_COMPLETED|FAILED` one when the
|
|
63
|
+
* Ender finishes, all on the account's channel. That end event goes out before `run_status` is
|
|
64
|
+
* written, and its `COMPLETED` is the Ender's status, not the run's: so it triggers a read, and
|
|
65
|
+
* then more on a short, doubling delay (`confirmIntervalMs`, capped at `silenceMs`) until the run
|
|
66
|
+
* reads ended — no later event would trigger one.
|
|
67
|
+
*
|
|
68
|
+
* Delivery is at most once, with no replay, and the server cuts every socket about once an hour.
|
|
69
|
+
* So the execution is also read after `silenceMs` without any event of the run, and as soon as
|
|
70
|
+
* the socket reconnects. A read that fails in a way that may pass (no response, a 5XX, a 429) does
|
|
71
|
+
* not end the wait — the next trigger reads again — and the last such failure is the cause if the
|
|
72
|
+
* wait times out, until a read succeeds. Any other failure ends it at once: a 4XX, or anything
|
|
73
|
+
* that is not a request failure, such as a body that is not the expected JSON.
|
|
74
|
+
*
|
|
75
|
+
* The run's end cannot be followed without the socket, so a socket in `error` for
|
|
76
|
+
* `unavailableAfterMs` — its config failed, or the server dropped it — fails the wait. The run is
|
|
77
|
+
* held back until the socket is connected, so it is never started unfollowable, and nothing it
|
|
78
|
+
* publishes goes out before the wait is listening.
|
|
79
|
+
*
|
|
80
|
+
* A timeout or an abort stops everything at once through one signal: the wait, the pause between
|
|
81
|
+
* reads, and the read in flight, whose request is cancelled. The start request is abandoned
|
|
82
|
+
* rather than cancelled — `startRun` takes no signal — so the run may still begin on the server.
|
|
83
|
+
*
|
|
84
|
+
* @param params - The start and read calls, the websocket subscriptions and the wait options.
|
|
85
|
+
* @returns The execution, once its `run_status` is terminal.
|
|
86
|
+
* @throws {Error} If a wait option is not a positive number, the run cannot be started or has no
|
|
87
|
+
* execution id, a read fails for good, the socket stays unavailable for `unavailableAfterMs`, or
|
|
88
|
+
* the wait times out or is aborted (`WorkflowRunAbortedError`, with the signal's reason as the cause).
|
|
89
|
+
*/
|
|
90
|
+
export declare const runWorkflowToEnd: ({ startRun, getExecution, subscribeToEvents, subscribeToStatus, silenceMs, timeoutMs, confirmIntervalMs, unavailableAfterMs, signal, }: RunWorkflowToEndParams) => Promise<WorkflowExecution>;
|
|
91
|
+
//# sourceMappingURL=workflowRun.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflowRun.d.ts","sourceRoot":"","sources":["../../src/lib/workflowRun.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAChG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,iFAAiF;AACjF,eAAO,MAAM,kBAAkB,kDAAkD,CAAC;AAUlF;;;;;GAKG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;gBAClC,MAAM,EAAE,OAAO;CAI9B;AAmBD,MAAM,MAAM,mBAAmB,GAAG;IAC9B;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oGAAoG;IACpG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,2EAA2E;IAC3E,MAAM,CAAC,EAAE,WAAW,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG,mBAAmB,GAAG;IACvD,uFAAuF;IACvF,QAAQ,EAAE,MAAM,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC3C;;;OAGG;IACH,YAAY,EAAE,CAAC,mBAAmB,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC/F,2CAA2C;IAC3C,iBAAiB,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;IACpF;;;OAGG;IACH,iBAAiB,EAAE,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;CAClF,CAAC;AAkIF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,eAAO,MAAM,gBAAgB,GAAU,wIAUpC,sBAAsB,KAAG,OAAO,CAAC,iBAAiB,CAiEpD,CAAC"}
|