@protobase/schema 0.67.8 → 0.67.10

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.
@@ -10,6 +10,7 @@ import { decodeKey, encodeKey } from "./keys.js";
10
10
  import { parseCapability } from "./access/capability.js";
11
11
  import { checkEventFilter } from "./events/event-models.js";
12
12
  import { webhookResources } from "./webhooks/webhook-resources.js";
13
+ import { workflowResources } from "./workflows/workflow-resources.js";
13
14
  import { PropShapes, RefShape, pruneByShape, shapes } from "./ref-shape.js";
14
15
  import { SearchTerm, matchedSearchField, matchesSearch, searchTerms, termMatches } from "./search-match.js";
15
16
  import { defaultRecentLimit, navRecentErrors, statusTones } from "./nav-recent.js";
@@ -43,4 +44,4 @@ import { builtInFieldTypes } from "./built-in-field-types.js";
43
44
  import { CallCandidate, CallClientMessage, CallDescription, CallGuestLink, CallGuestRefusal, CallGuestState, CallLeftReason, CallLobbyGuest, CallMode, CallRemoteTrack, CallResume, CallRosterMember, CallServerMessage, CallTrackRequest, CallTrackSource, CallVideoLayer } from "./calls/call-protocol.js";
44
45
  import { guestCallsPath } from "./calls/call-guests.js";
45
46
  import { CallRing, callsChannelEvent, declineWord, ringNotice, ringsPath } from "./calls/call-rings.js";
46
- export { type AddressCheck, type Availability, type CallCandidate, type CallClientMessage, type CallDescription, type CallGuestLink, type CallGuestRefusal, type CallGuestState, type CallLeftReason, type CallLobbyGuest, type CallMode, type CallRemoteTrack, type CallResume, type CallRing, type CallRosterMember, type CallServerMessage, type CallTrackRequest, type CallTrackSource, type CallVideoLayer, type FormulaNode, type Locale, type MobileReleaseAnswer, type PersonStatus, type PluginHost, type PluginRequirement, type PropShapes, type RefShape, type ReleaseBinding, type SearchTerm, type StatusInput, actionConditionError, actionInputErrors, addressErrors, addressPlaceholders, apiOriginMeta, appHrefError, applyAssistantEvent, authBasePath, availabilities, boardErrors, bottomBarFor, builtInFieldTypes, callsChannelEvent, capacitorOrigin, cardPhotoLimit, chartFields, checkEventFilter, checkedAccept, checkedProvider, confirmationMinutes, datesErrors, declineWord, decodeKey, defaultRecentLimit, deviceIdParam, devicesPath, displayFields, emailCodeMinutes, emptyAssistantState, encodeKey, fieldRefsIn, fillAddress, firstPartyCodeKey, guestCallsPath, heldStatus, historyIdParam, historyIdPattern, historyPath, hrefField, hrefPlaceholders, humanize, inRange, isFieldRef, isGroupChart, isLocale, labelFieldOf, layoutItems, leavesApp, linkActionError, listColumnNames, locales, markFieldRefs, matchedSearchField, matchesSearch, maxStatusText, mobileReleaseBasePath, mobileReleaseParams, mobileReleasePath, mobileReleaseQuery, mobileReleasesPath, navRecentErrors, parseCapability, parseFormula, parseSize, parseTable, pickLocale, pluginProblem, promptError, promptFields, pruneByShape, pushRecord, readEventStream, recordTitle, recordTitleField, redactSecrets, releaseManifestFile, releaseStatementContext, releaseStatementFile, renderPrompt, ringNotice, ringsPath, searchTerms, serviceWorkerFile, shapes, shownInputs, statusPath, statusTextProblem, statusTones, tableDisplay, termMatches, unmarkFieldRefs, updateSetErrors, updateValues, viewOfList, webhookResources };
47
+ export { type AddressCheck, type Availability, type CallCandidate, type CallClientMessage, type CallDescription, type CallGuestLink, type CallGuestRefusal, type CallGuestState, type CallLeftReason, type CallLobbyGuest, type CallMode, type CallRemoteTrack, type CallResume, type CallRing, type CallRosterMember, type CallServerMessage, type CallTrackRequest, type CallTrackSource, type CallVideoLayer, type FormulaNode, type Locale, type MobileReleaseAnswer, type PersonStatus, type PluginHost, type PluginRequirement, type PropShapes, type RefShape, type ReleaseBinding, type SearchTerm, type StatusInput, actionConditionError, actionInputErrors, addressErrors, addressPlaceholders, apiOriginMeta, appHrefError, applyAssistantEvent, authBasePath, availabilities, boardErrors, bottomBarFor, builtInFieldTypes, callsChannelEvent, capacitorOrigin, cardPhotoLimit, chartFields, checkEventFilter, checkedAccept, checkedProvider, confirmationMinutes, datesErrors, declineWord, decodeKey, defaultRecentLimit, deviceIdParam, devicesPath, displayFields, emailCodeMinutes, emptyAssistantState, encodeKey, fieldRefsIn, fillAddress, firstPartyCodeKey, guestCallsPath, heldStatus, historyIdParam, historyIdPattern, historyPath, hrefField, hrefPlaceholders, humanize, inRange, isFieldRef, isGroupChart, isLocale, labelFieldOf, layoutItems, leavesApp, linkActionError, listColumnNames, locales, markFieldRefs, matchedSearchField, matchesSearch, maxStatusText, mobileReleaseBasePath, mobileReleaseParams, mobileReleasePath, mobileReleaseQuery, mobileReleasesPath, navRecentErrors, parseCapability, parseFormula, parseSize, parseTable, pickLocale, pluginProblem, promptError, promptFields, pruneByShape, pushRecord, readEventStream, recordTitle, recordTitleField, redactSecrets, releaseManifestFile, releaseStatementContext, releaseStatementFile, renderPrompt, ringNotice, ringsPath, searchTerms, serviceWorkerFile, shapes, shownInputs, statusPath, statusTextProblem, statusTones, tableDisplay, termMatches, unmarkFieldRefs, updateSetErrors, updateValues, viewOfList, webhookResources, workflowResources };
package/dist/internal.js CHANGED
@@ -18,6 +18,7 @@ import { boardErrors, cardPhotoLimit, datesErrors, displayFields, tableDisplay }
18
18
  import { bottomBarFor } from "./bottom-bar.js";
19
19
  import { decodeKey, encodeKey } from "./keys.js";
20
20
  import { webhookResources } from "./webhooks/webhook-resources.js";
21
+ import { workflowResources } from "./workflows/workflow-resources.js";
21
22
  import { pruneByShape, shapes } from "./ref-shape.js";
22
23
  import { inRange, pluginProblem } from "./plugin-version.js";
23
24
  import { redactSecrets } from "./redact-secrets.js";
@@ -42,4 +43,4 @@ import { listColumnNames } from "./list-columns.js";
42
43
  import { builtInFieldTypes } from "./built-in-field-types.js";
43
44
  import { guestCallsPath } from "./calls/call-guests.js";
44
45
  import { callsChannelEvent, declineWord, ringNotice, ringsPath } from "./calls/call-rings.js";
45
- export { actionConditionError, actionInputErrors, addressErrors, addressPlaceholders, apiOriginMeta, appHrefError, applyAssistantEvent, authBasePath, availabilities, boardErrors, bottomBarFor, builtInFieldTypes, callsChannelEvent, capacitorOrigin, cardPhotoLimit, chartFields, checkEventFilter, checkedAccept, checkedProvider, confirmationMinutes, datesErrors, declineWord, decodeKey, defaultRecentLimit, deviceIdParam, devicesPath, displayFields, emailCodeMinutes, emptyAssistantState, encodeKey, fieldRefsIn, fillAddress, firstPartyCodeKey, guestCallsPath, heldStatus, historyIdParam, historyIdPattern, historyPath, hrefField, hrefPlaceholders, humanize, inRange, isFieldRef, isGroupChart, isLocale, labelFieldOf, layoutItems, leavesApp, linkActionError, listColumnNames, locales, markFieldRefs, matchedSearchField, matchesSearch, maxStatusText, mobileReleaseBasePath, mobileReleaseParams, mobileReleasePath, mobileReleaseQuery, mobileReleasesPath, navRecentErrors, parseCapability, parseFormula, parseSize, parseTable, pickLocale, pluginProblem, promptError, promptFields, pruneByShape, pushRecord, readEventStream, recordTitle, recordTitleField, redactSecrets, releaseManifestFile, releaseStatementContext, releaseStatementFile, renderPrompt, ringNotice, ringsPath, searchTerms, serviceWorkerFile, shapes, shownInputs, statusPath, statusTextProblem, statusTones, tableDisplay, termMatches, unmarkFieldRefs, updateSetErrors, updateValues, viewOfList, webhookResources };
46
+ export { actionConditionError, actionInputErrors, addressErrors, addressPlaceholders, apiOriginMeta, appHrefError, applyAssistantEvent, authBasePath, availabilities, boardErrors, bottomBarFor, builtInFieldTypes, callsChannelEvent, capacitorOrigin, cardPhotoLimit, chartFields, checkEventFilter, checkedAccept, checkedProvider, confirmationMinutes, datesErrors, declineWord, decodeKey, defaultRecentLimit, deviceIdParam, devicesPath, displayFields, emailCodeMinutes, emptyAssistantState, encodeKey, fieldRefsIn, fillAddress, firstPartyCodeKey, guestCallsPath, heldStatus, historyIdParam, historyIdPattern, historyPath, hrefField, hrefPlaceholders, humanize, inRange, isFieldRef, isGroupChart, isLocale, labelFieldOf, layoutItems, leavesApp, linkActionError, listColumnNames, locales, markFieldRefs, matchedSearchField, matchesSearch, maxStatusText, mobileReleaseBasePath, mobileReleaseParams, mobileReleasePath, mobileReleaseQuery, mobileReleasesPath, navRecentErrors, parseCapability, parseFormula, parseSize, parseTable, pickLocale, pluginProblem, promptError, promptFields, pruneByShape, pushRecord, readEventStream, recordTitle, recordTitleField, redactSecrets, releaseManifestFile, releaseStatementContext, releaseStatementFile, renderPrompt, ringNotice, ringsPath, searchTerms, serviceWorkerFile, shapes, shownInputs, statusPath, statusTextProblem, statusTones, tableDisplay, termMatches, unmarkFieldRefs, updateSetErrors, updateValues, viewOfList, webhookResources, workflowResources };
@@ -0,0 +1,127 @@
1
+ import { Field } from "../field.js";
2
+ import { Ref } from "../refs.js";
3
+ import { ResourceBuilder } from "../resource.js";
4
+ import { ViewBuilder } from "../view.js";
5
+ import "../index.js";
6
+ //#region src/workflows/workflow-resources.d.ts
7
+ /**
8
+ * The resources and views `workflows` adds to an app, over the tables of `schema`: Workflows with their versions, runs
9
+ * and steps. Config only; the server checks and runs them.
10
+ */
11
+ export declare const workflowResources: (schema: string) => {
12
+ workflows: ResourceBuilder<{
13
+ readonly id: Field<string>;
14
+ readonly name: Field<string>;
15
+ readonly description: Field<string | null>;
16
+ readonly definition: Field<import("zod").JSONType>;
17
+ readonly version: Field<number | null>;
18
+ readonly tenant_id: Field<string | null>;
19
+ readonly created_at: Field<string>;
20
+ readonly updated_at: Field<string>;
21
+ }, Ref<"id", string>>;
22
+ workflowsView: ViewBuilder<ResourceBuilder<{
23
+ readonly id: Field<string>;
24
+ readonly name: Field<string>;
25
+ readonly description: Field<string | null>;
26
+ readonly definition: Field<import("zod").JSONType>;
27
+ readonly version: Field<number | null>;
28
+ readonly tenant_id: Field<string | null>;
29
+ readonly created_at: Field<string>;
30
+ readonly updated_at: Field<string>;
31
+ }, Ref<"id", string>>>;
32
+ workflowVersions: ResourceBuilder<{
33
+ readonly workflow_id: Field<string | number>;
34
+ readonly version: Field<number>;
35
+ readonly definition: Field<import("zod").JSONType>;
36
+ readonly saved_by: Field<string | null>;
37
+ readonly tenant_id: Field<string | null>;
38
+ readonly saved_at: Field<string>;
39
+ }, readonly [Ref<"workflow_id", string | number>, Ref<"version", number>]>;
40
+ workflowVersionsView: ViewBuilder<ResourceBuilder<{
41
+ readonly workflow_id: Field<string | number>;
42
+ readonly version: Field<number>;
43
+ readonly definition: Field<import("zod").JSONType>;
44
+ readonly saved_by: Field<string | null>;
45
+ readonly tenant_id: Field<string | null>;
46
+ readonly saved_at: Field<string>;
47
+ }, readonly [Ref<"workflow_id", string | number>, Ref<"version", number>]>>;
48
+ workflowRuns: ResourceBuilder<{
49
+ readonly id: Field<string>;
50
+ readonly workflow_id: Field<string | number>;
51
+ readonly version: Field<number | null>;
52
+ readonly input: Field<import("zod").JSONType>;
53
+ readonly key: Field<string | null>;
54
+ readonly status: Field<"waiting" | "failed" | "queued" | "running" | "succeeded">;
55
+ readonly output: Field<import("zod").JSONType>;
56
+ readonly error: Field<string | null>;
57
+ readonly cause: Field<string | null>;
58
+ readonly resume_at: Field<string | null>;
59
+ readonly started_by: Field<string | null>;
60
+ readonly tenant_id: Field<string | null>;
61
+ readonly created_at: Field<string>;
62
+ readonly finished_at: Field<string | null>;
63
+ readonly duration_ms: Field<string | null>;
64
+ }, Ref<"id", string>>;
65
+ workflowRunsView: ViewBuilder<ResourceBuilder<{
66
+ readonly id: Field<string>;
67
+ readonly workflow_id: Field<string | number>;
68
+ readonly version: Field<number | null>;
69
+ readonly input: Field<import("zod").JSONType>;
70
+ readonly key: Field<string | null>;
71
+ readonly status: Field<"waiting" | "failed" | "queued" | "running" | "succeeded">;
72
+ readonly output: Field<import("zod").JSONType>;
73
+ readonly error: Field<string | null>;
74
+ readonly cause: Field<string | null>;
75
+ readonly resume_at: Field<string | null>;
76
+ readonly started_by: Field<string | null>;
77
+ readonly tenant_id: Field<string | null>;
78
+ readonly created_at: Field<string>;
79
+ readonly finished_at: Field<string | null>;
80
+ readonly duration_ms: Field<string | null>;
81
+ }, Ref<"id", string>>>;
82
+ workflowSteps: ResourceBuilder<{
83
+ readonly id: Field<string>;
84
+ readonly run_id: Field<string | number>;
85
+ readonly tenant_id: Field<string | null>;
86
+ readonly scope: Field<string>;
87
+ readonly seq: Field<number>;
88
+ readonly state: Field<string>;
89
+ readonly type: Field<string>;
90
+ readonly status: Field<"failed" | "succeeded" | "retrying" | "caught">;
91
+ readonly attempt: Field<number>;
92
+ readonly input: Field<import("zod").JSONType>;
93
+ readonly output: Field<import("zod").JSONType>;
94
+ readonly assigned: Field<import("zod").JSONType>;
95
+ readonly next: Field<string | null>;
96
+ readonly resume_at: Field<string | null>;
97
+ readonly error: Field<string | null>;
98
+ readonly cause: Field<string | null>;
99
+ readonly logs: Field<import("zod").JSONType>;
100
+ readonly started_at: Field<string>;
101
+ readonly finished_at: Field<string>;
102
+ readonly duration_ms: Field<string | null>;
103
+ }, Ref<"id", string>>;
104
+ workflowStepsView: ViewBuilder<ResourceBuilder<{
105
+ readonly id: Field<string>;
106
+ readonly run_id: Field<string | number>;
107
+ readonly tenant_id: Field<string | null>;
108
+ readonly scope: Field<string>;
109
+ readonly seq: Field<number>;
110
+ readonly state: Field<string>;
111
+ readonly type: Field<string>;
112
+ readonly status: Field<"failed" | "succeeded" | "retrying" | "caught">;
113
+ readonly attempt: Field<number>;
114
+ readonly input: Field<import("zod").JSONType>;
115
+ readonly output: Field<import("zod").JSONType>;
116
+ readonly assigned: Field<import("zod").JSONType>;
117
+ readonly next: Field<string | null>;
118
+ readonly resume_at: Field<string | null>;
119
+ readonly error: Field<string | null>;
120
+ readonly cause: Field<string | null>;
121
+ readonly logs: Field<import("zod").JSONType>;
122
+ readonly started_at: Field<string>;
123
+ readonly finished_at: Field<string>;
124
+ readonly duration_ms: Field<string | null>;
125
+ }, Ref<"id", string>>>;
126
+ };
127
+ //#endregion
@@ -0,0 +1,287 @@
1
+ import { f } from "../fields.js";
2
+ import { resource } from "../resource.js";
3
+ import { view } from "../view.js";
4
+ import { layout } from "../layout.js";
5
+ //#region src/workflows/workflow-resources.ts
6
+ const runStatuses = [
7
+ "queued",
8
+ "running",
9
+ "waiting",
10
+ "succeeded",
11
+ "failed"
12
+ ];
13
+ const stepStatuses = [
14
+ "succeeded",
15
+ "retrying",
16
+ "caught",
17
+ "failed"
18
+ ];
19
+ /**
20
+ * Workflows: a trigger and a state machine in the States Language with JSONata, checked on every save, each changed definition a new version. A
21
+ * role's wildcard such as `*.read` reaches none of the workflow resources: their runs read and send data as the
22
+ * definition says, so each is granted on its own.
23
+ */
24
+ const workflowsResource = (schema) => resource("workflows").table(`${schema}.workflows`).fields({
25
+ id: f.uuid().readOnly().dbDefault(),
26
+ name: f.text().min(1).max(100).filterable().sortable(),
27
+ description: f.text().optional().max(2e3),
28
+ definition: f.json(),
29
+ version: f.integer().optional().readOnly(),
30
+ tenant_id: f.text().optional().readOnly(),
31
+ created_at: f.timestamp().readOnly().dbDefault(),
32
+ updated_at: f.timestamp().readOnly().dbDefault().sortable()
33
+ }).primaryKey((r) => r.id).tenant((r) => r.tenant_id).search((r) => [r.name]).explicitGrants();
34
+ const workflowsView = view("workflows").names({
35
+ singular: "Workflow",
36
+ plural: "Workflows"
37
+ }).icon("workflow").title((r) => r.name).help("Steps that run one after another along their edges, written in the States Language with JSONata expressions. Each save that changes its definition is a new version; a run keeps the version it started on.").fields((r) => ({
38
+ definition: r.definition.help("Its trigger and its state machine in the States Language with JSONata, every value read by name: the run's input as $states.context.Execution.Input, an earlier result by the variable a state assigned"),
39
+ updated_at: r.updated_at.label("Updated")
40
+ })).list((r) => ({
41
+ columns: [
42
+ r.name,
43
+ r.version,
44
+ r.updated_at
45
+ ],
46
+ sort: [[r.updated_at, "desc"]]
47
+ })).layout((r) => [
48
+ layout.section("Workflow", [
49
+ r.name,
50
+ r.description,
51
+ r.definition
52
+ ]),
53
+ layout.sidebar([
54
+ r.version,
55
+ r.created_at,
56
+ r.updated_at
57
+ ]),
58
+ layout.related("Runs", {
59
+ resource: "workflow_runs",
60
+ field: "workflow_id",
61
+ columns: [
62
+ "status",
63
+ "version",
64
+ "created_at",
65
+ "duration_ms",
66
+ "error"
67
+ ]
68
+ }),
69
+ layout.related("Versions", {
70
+ resource: "workflow_versions",
71
+ field: "workflow_id",
72
+ columns: [
73
+ "version",
74
+ "saved_by",
75
+ "saved_at"
76
+ ]
77
+ })
78
+ ]);
79
+ /** Each version of a workflow's definition, as it was saved. */
80
+ const versionsResource = (schema) => resource("workflow_versions").table(`${schema}.versions`).fields({
81
+ workflow_id: f.relation("workflows").readOnly().filterable(),
82
+ version: f.integer().readOnly().sortable(),
83
+ definition: f.json().readOnly(),
84
+ saved_by: f.text().optional().readOnly(),
85
+ tenant_id: f.text().optional().readOnly(),
86
+ saved_at: f.timestamp().readOnly().dbDefault()
87
+ }).primaryKey((r) => [r.workflow_id, r.version]).tenant((r) => r.tenant_id).explicitGrants().access({
88
+ create: () => false,
89
+ update: () => false,
90
+ delete: () => false
91
+ });
92
+ const versionsView = view("workflow_versions").names({
93
+ singular: "Workflow version",
94
+ plural: "Workflow versions"
95
+ }).icon("history").title((r) => r.version).fields((r) => ({
96
+ saved_by: r.saved_by.label("Saved by"),
97
+ saved_at: r.saved_at.label("Saved")
98
+ })).list((r) => ({
99
+ columns: [
100
+ r.workflow_id,
101
+ r.version,
102
+ r.saved_by,
103
+ r.saved_at
104
+ ],
105
+ sort: [[r.version, "desc"]]
106
+ }));
107
+ /** A run of a workflow, started by creating it with its input: it runs the version its workflow has then. */
108
+ const runsResource = (schema) => resource("workflow_runs").table(`${schema}.runs`).fields({
109
+ id: f.uuid().readOnly().dbDefault(),
110
+ workflow_id: f.relation("workflows").filterable(),
111
+ version: f.integer().optional().readOnly(),
112
+ input: f.json().optional(),
113
+ key: f.text().optional().max(200),
114
+ status: f.enum(runStatuses).readOnly().dbDefault().filterable(),
115
+ output: f.json().optional().readOnly(),
116
+ error: f.text().optional().readOnly(),
117
+ cause: f.text().optional().readOnly(),
118
+ resume_at: f.timestamp().optional().readOnly(),
119
+ started_by: f.text().optional().readOnly(),
120
+ tenant_id: f.text().optional().readOnly(),
121
+ created_at: f.timestamp().readOnly().dbDefault().sortable(),
122
+ finished_at: f.timestamp().optional().readOnly(),
123
+ duration_ms: f.bigint().optional().readOnly()
124
+ }).primaryKey((r) => r.id).tenant((r) => r.tenant_id).author((r) => r.started_by).explicitGrants().access({
125
+ update: () => false,
126
+ delete: () => false
127
+ });
128
+ const runsView = view("workflow_runs").names({
129
+ singular: "Workflow run",
130
+ plural: "Workflow runs"
131
+ }).icon("play").title((r) => r.created_at).help("A run of a workflow with its input. It takes up where it stands after a restart; each of its steps is listed with what it read, gave and logged.").fields((r) => ({
132
+ workflow_id: r.workflow_id.label("Workflow"),
133
+ input: r.input.help("Read by every state as $states.context.Execution.Input"),
134
+ key: r.key.help("A workflow runs once per key, such as the record a trigger found ready"),
135
+ status: r.status.valueLabels({
136
+ queued: "Queued",
137
+ running: "Running",
138
+ waiting: "Waiting",
139
+ succeeded: "Succeeded",
140
+ failed: "Failed"
141
+ }).valueColors({
142
+ succeeded: "green",
143
+ failed: "red"
144
+ }),
145
+ resume_at: r.resume_at.label("Goes on at"),
146
+ started_by: r.started_by.label("Started by"),
147
+ created_at: r.created_at.label("Started"),
148
+ finished_at: r.finished_at.label("Finished"),
149
+ duration_ms: r.duration_ms.label("Duration (ms)")
150
+ })).list((r) => ({
151
+ columns: [
152
+ r.created_at,
153
+ r.workflow_id,
154
+ r.status,
155
+ r.duration_ms,
156
+ r.error
157
+ ],
158
+ sort: [[r.created_at, "desc"]]
159
+ })).layout((r) => [
160
+ layout.section("Run", [
161
+ r.workflow_id,
162
+ r.input,
163
+ r.output,
164
+ r.error,
165
+ r.cause
166
+ ]),
167
+ layout.sidebar([
168
+ r.status,
169
+ r.version,
170
+ r.started_by,
171
+ r.created_at,
172
+ r.resume_at,
173
+ r.finished_at,
174
+ r.duration_ms
175
+ ]),
176
+ layout.related("Steps", {
177
+ resource: "workflow_steps",
178
+ field: "run_id",
179
+ columns: [
180
+ "scope",
181
+ "seq",
182
+ "state",
183
+ "status",
184
+ "attempt",
185
+ "duration_ms",
186
+ "error"
187
+ ]
188
+ })
189
+ ]);
190
+ /** Every step of every run: its input with secrets redacted, output, variables, logs, timing, try and error. */
191
+ const stepsResource = (schema) => resource("workflow_steps").table(`${schema}.steps`).fields({
192
+ id: f.bigint().readOnly().sortable(),
193
+ run_id: f.relation("workflow_runs").readOnly().filterable(),
194
+ tenant_id: f.text().optional().readOnly(),
195
+ scope: f.text().readOnly(),
196
+ seq: f.integer().readOnly(),
197
+ state: f.text().readOnly().filterable(),
198
+ type: f.text().readOnly(),
199
+ status: f.enum(stepStatuses).readOnly().filterable(),
200
+ attempt: f.integer().readOnly(),
201
+ input: f.json().optional().readOnly(),
202
+ output: f.json().optional().readOnly(),
203
+ assigned: f.json().optional().readOnly(),
204
+ next: f.text().optional().readOnly(),
205
+ resume_at: f.timestamp().optional().readOnly(),
206
+ error: f.text().optional().readOnly(),
207
+ cause: f.text().optional().readOnly(),
208
+ logs: f.json().readOnly(),
209
+ started_at: f.timestamp().readOnly(),
210
+ finished_at: f.timestamp().readOnly(),
211
+ duration_ms: f.bigint().optional().readOnly()
212
+ }).primaryKey((r) => r.id).tenant((r) => r.tenant_id).explicitGrants().access({
213
+ create: () => false,
214
+ update: () => false,
215
+ delete: () => false
216
+ });
217
+ const stepsView = view("workflow_steps").names({
218
+ singular: "Workflow step",
219
+ plural: "Workflow steps"
220
+ }).icon("list-checks").title((r) => r.state).fields((r) => ({
221
+ run_id: r.run_id.label("Run"),
222
+ scope: r.scope.help("Where the step ran: empty for the run itself, or the Map item, such as Each.3[0]").format("code"),
223
+ seq: r.seq.label("Step"),
224
+ attempt: r.attempt.label("Try"),
225
+ status: r.status.valueLabels({
226
+ succeeded: "Succeeded",
227
+ retrying: "Retried",
228
+ caught: "Caught",
229
+ failed: "Failed"
230
+ }).valueColors({
231
+ succeeded: "green",
232
+ failed: "red"
233
+ }),
234
+ input: r.input.help("The app's secrets, and fields whose name says they hold one such as Authorization, are blanked out"),
235
+ assigned: r.assigned.label("Variables assigned"),
236
+ next: r.next.label("Goes on to"),
237
+ resume_at: r.resume_at.label("Next state not before"),
238
+ duration_ms: r.duration_ms.label("Duration (ms)")
239
+ })).list((r) => ({
240
+ columns: [
241
+ r.run_id,
242
+ r.scope,
243
+ r.seq,
244
+ r.state,
245
+ r.status,
246
+ r.attempt,
247
+ r.duration_ms,
248
+ r.error
249
+ ],
250
+ sort: [[r.id, "asc"]]
251
+ })).layout((r) => [layout.section("Step", [
252
+ r.run_id,
253
+ r.state,
254
+ r.type,
255
+ r.scope,
256
+ r.seq,
257
+ r.input,
258
+ r.output,
259
+ r.assigned,
260
+ r.logs,
261
+ r.error,
262
+ r.cause
263
+ ]), layout.sidebar([
264
+ r.status,
265
+ r.attempt,
266
+ r.next,
267
+ r.resume_at,
268
+ r.started_at,
269
+ r.finished_at,
270
+ r.duration_ms
271
+ ])]);
272
+ /**
273
+ * The resources and views `workflows` adds to an app, over the tables of `schema`: Workflows with their versions, runs
274
+ * and steps. Config only; the server checks and runs them.
275
+ */
276
+ const workflowResources = (schema) => ({
277
+ workflows: workflowsResource(schema),
278
+ workflowsView,
279
+ workflowVersions: versionsResource(schema),
280
+ workflowVersionsView: versionsView,
281
+ workflowRuns: runsResource(schema),
282
+ workflowRunsView: runsView,
283
+ workflowSteps: stepsResource(schema),
284
+ workflowStepsView: stepsView
285
+ });
286
+ //#endregion
287
+ export { workflowResources };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@protobase/schema",
3
- "version": "0.67.8",
3
+ "version": "0.67.10",
4
4
  "description": "Resource, field, view and access definitions for Protobase configs.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {