@protobase/schema 0.67.10 → 0.67.12

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.
@@ -1,9 +1,14 @@
1
1
  //#region src/built-in-field-types.d.ts
2
2
  /**
3
3
  * The field types Protobase brings, which a view chooses with `.widget(name)` like a plugin's, by the storage types
4
- * each shows: `members`, a JSON array of the user ids of an organization's members. A plugin's of the same name wins.
4
+ * each shows: `json`, any JSON value edited as JSON text, `members`, a JSON array of the user ids of an organization's members, `workflow`, a workflow's
5
+ * definition drawn as a graph to edit, and `workflow_run`, a run's id, drawn as its steps on its workflow's graph. A
6
+ * plugin's of the same name wins.
5
7
  */
6
8
  export declare const builtInFieldTypes: {
9
+ readonly json: readonly ["json"];
7
10
  readonly members: readonly ["json"];
11
+ readonly workflow: readonly ["json"];
12
+ readonly workflow_run: readonly ["uuid"];
8
13
  };
9
14
  //#endregion
@@ -1,8 +1,15 @@
1
1
  //#region src/built-in-field-types.ts
2
2
  /**
3
3
  * The field types Protobase brings, which a view chooses with `.widget(name)` like a plugin's, by the storage types
4
- * each shows: `members`, a JSON array of the user ids of an organization's members. A plugin's of the same name wins.
4
+ * each shows: `json`, any JSON value edited as JSON text, `members`, a JSON array of the user ids of an organization's members, `workflow`, a workflow's
5
+ * definition drawn as a graph to edit, and `workflow_run`, a run's id, drawn as its steps on its workflow's graph. A
6
+ * plugin's of the same name wins.
5
7
  */
6
- const builtInFieldTypes = { members: ["json"] };
8
+ const builtInFieldTypes = {
9
+ json: ["json"],
10
+ members: ["json"],
11
+ workflow: ["json"],
12
+ workflow_run: ["uuid"]
13
+ };
7
14
  //#endregion
8
15
  export { builtInFieldTypes };
@@ -11,6 +11,7 @@ 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
13
  import { workflowResources } from "./workflows/workflow-resources.js";
14
+ import { StepInput, StepInputKind, WorkflowStepType, requiredStepInputs, workflowStepTypes } from "./workflows/step-types.js";
14
15
  import { PropShapes, RefShape, pruneByShape, shapes } from "./ref-shape.js";
15
16
  import { SearchTerm, matchedSearchField, matchesSearch, searchTerms, termMatches } from "./search-match.js";
16
17
  import { defaultRecentLimit, navRecentErrors, statusTones } from "./nav-recent.js";
@@ -44,4 +45,4 @@ import { builtInFieldTypes } from "./built-in-field-types.js";
44
45
  import { CallCandidate, CallClientMessage, CallDescription, CallGuestLink, CallGuestRefusal, CallGuestState, CallLeftReason, CallLobbyGuest, CallMode, CallRemoteTrack, CallResume, CallRosterMember, CallServerMessage, CallTrackRequest, CallTrackSource, CallVideoLayer } from "./calls/call-protocol.js";
45
46
  import { guestCallsPath } from "./calls/call-guests.js";
46
47
  import { CallRing, callsChannelEvent, declineWord, ringNotice, ringsPath } from "./calls/call-rings.js";
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 };
48
+ 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, type StepInput, type StepInputKind, type WorkflowStepType, 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, requiredStepInputs, ringNotice, ringsPath, searchTerms, serviceWorkerFile, shapes, shownInputs, statusPath, statusTextProblem, statusTones, tableDisplay, termMatches, unmarkFieldRefs, updateSetErrors, updateValues, viewOfList, webhookResources, workflowResources, workflowStepTypes };
package/dist/internal.js CHANGED
@@ -19,6 +19,7 @@ import { bottomBarFor } from "./bottom-bar.js";
19
19
  import { decodeKey, encodeKey } from "./keys.js";
20
20
  import { webhookResources } from "./webhooks/webhook-resources.js";
21
21
  import { workflowResources } from "./workflows/workflow-resources.js";
22
+ import { requiredStepInputs, workflowStepTypes } from "./workflows/step-types.js";
22
23
  import { pruneByShape, shapes } from "./ref-shape.js";
23
24
  import { inRange, pluginProblem } from "./plugin-version.js";
24
25
  import { redactSecrets } from "./redact-secrets.js";
@@ -43,4 +44,4 @@ import { listColumnNames } from "./list-columns.js";
43
44
  import { builtInFieldTypes } from "./built-in-field-types.js";
44
45
  import { guestCallsPath } from "./calls/call-guests.js";
45
46
  import { callsChannelEvent, declineWord, ringNotice, ringsPath } from "./calls/call-rings.js";
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 };
47
+ 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, requiredStepInputs, ringNotice, ringsPath, searchTerms, serviceWorkerFile, shapes, shownInputs, statusPath, statusTextProblem, statusTones, tableDisplay, termMatches, unmarkFieldRefs, updateSetErrors, updateValues, viewOfList, webhookResources, workflowResources, workflowStepTypes };
@@ -0,0 +1,30 @@
1
+ //#region src/workflows/step-types.d.ts
2
+ /**
3
+ * How a step type's argument is written: `text`, one line, which may be an expression; `choice`, one of `options`;
4
+ * `json`, any JSON value or an expression, such as an object of field values.
5
+ */
6
+ export type StepInputKind = 'text' | 'choice' | 'json';
7
+ /** An argument of a step type: its name in `Arguments`, how it is written, and whether a save needs it. */
8
+ export type StepInput = {
9
+ name: string;
10
+ kind: StepInputKind;
11
+ required?: boolean;
12
+ options?: readonly string[];
13
+ };
14
+ /**
15
+ * The step types a workflow's Task names as its `Resource`, each with its arguments: the server runs them, a save
16
+ * refuses a Task without a required one, and the editor draws a form of them.
17
+ */
18
+ export declare const workflowStepTypes: {
19
+ readonly 'app:http': readonly [StepInput, StepInput, StepInput, StepInput, StepInput, StepInput];
20
+ readonly 'app:records.create': readonly [StepInput, StepInput];
21
+ readonly 'app:records.update': readonly [StepInput, StepInput, StepInput];
22
+ readonly 'app:records.get': readonly [StepInput, StepInput];
23
+ readonly 'app:records.list': readonly [StepInput, StepInput, StepInput, StepInput];
24
+ readonly 'app:mail.send': readonly [StepInput, StepInput, StepInput, StepInput, StepInput];
25
+ readonly 'app:piece': readonly [StepInput, StepInput, StepInput, StepInput];
26
+ };
27
+ export type WorkflowStepType = keyof typeof workflowStepTypes;
28
+ /** The names of the arguments each step type needs, as the definition check takes them. */
29
+ export declare const requiredStepInputs: Record<WorkflowStepType, string[]>;
30
+ //#endregion
@@ -0,0 +1,70 @@
1
+ //#region src/workflows/step-types.ts
2
+ const text = (name, required = false) => ({
3
+ name,
4
+ kind: "text",
5
+ ...required && { required }
6
+ });
7
+ const json = (name, required = false) => ({
8
+ name,
9
+ kind: "json",
10
+ ...required && { required }
11
+ });
12
+ const choice = (name, options) => ({
13
+ name,
14
+ kind: "choice",
15
+ options
16
+ });
17
+ /**
18
+ * The step types a workflow's Task names as its `Resource`, each with its arguments: the server runs them, a save
19
+ * refuses a Task without a required one, and the editor draws a form of them.
20
+ */
21
+ const workflowStepTypes = {
22
+ "app:http": [
23
+ text("url", true),
24
+ choice("method", [
25
+ "GET",
26
+ "POST",
27
+ "PUT",
28
+ "PATCH",
29
+ "DELETE"
30
+ ]),
31
+ json("headers"),
32
+ json("query"),
33
+ json("body"),
34
+ choice("response", [
35
+ "json",
36
+ "text",
37
+ "file"
38
+ ])
39
+ ],
40
+ "app:records.create": [text("resource", true), json("data", true)],
41
+ "app:records.update": [
42
+ text("resource", true),
43
+ json("key", true),
44
+ json("data", true)
45
+ ],
46
+ "app:records.get": [text("resource", true), json("key", true)],
47
+ "app:records.list": [
48
+ text("resource", true),
49
+ text("filter"),
50
+ text("order_by"),
51
+ json("limit")
52
+ ],
53
+ "app:mail.send": [
54
+ json("to", true),
55
+ text("subject", true),
56
+ text("text", true),
57
+ text("html"),
58
+ json("attachments")
59
+ ],
60
+ "app:piece": [
61
+ text("piece", true),
62
+ text("action", true),
63
+ text("connection"),
64
+ json("props")
65
+ ]
66
+ };
67
+ /** The names of the arguments each step type needs, as the definition check takes them. */
68
+ const requiredStepInputs = Object.fromEntries(Object.entries(workflowStepTypes).map(([type, inputs]) => [type, inputs.filter((input) => input.required).map((input) => input.name)]));
69
+ //#endregion
70
+ export { requiredStepInputs, workflowStepTypes };
@@ -57,6 +57,7 @@ export declare const workflowResources: (schema: string) => {
57
57
  readonly cause: Field<string | null>;
58
58
  readonly resume_at: Field<string | null>;
59
59
  readonly started_by: Field<string | null>;
60
+ readonly rerun_of: Field<string | number | null>;
60
61
  readonly tenant_id: Field<string | null>;
61
62
  readonly created_at: Field<string>;
62
63
  readonly finished_at: Field<string | null>;
@@ -74,6 +75,7 @@ export declare const workflowResources: (schema: string) => {
74
75
  readonly cause: Field<string | null>;
75
76
  readonly resume_at: Field<string | null>;
76
77
  readonly started_by: Field<string | null>;
78
+ readonly rerun_of: Field<string | number | null>;
77
79
  readonly tenant_id: Field<string | null>;
78
80
  readonly created_at: Field<string>;
79
81
  readonly finished_at: Field<string | null>;
@@ -35,7 +35,7 @@ const workflowsView = view("workflows").names({
35
35
  singular: "Workflow",
36
36
  plural: "Workflows"
37
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"),
38
+ definition: r.definition.help("Its trigger and its steps, drawn as a graph that lays itself out. Every value is read by name: the run's input as $states.context.Execution.Input, an earlier result by the variable a state assigned").widget("workflow"),
39
39
  updated_at: r.updated_at.label("Updated")
40
40
  })).list((r) => ({
41
41
  columns: [
@@ -44,7 +44,15 @@ const workflowsView = view("workflows").names({
44
44
  r.updated_at
45
45
  ],
46
46
  sort: [[r.updated_at, "desc"]]
47
- })).layout((r) => [
47
+ })).actions((a) => [a.link("test_run", {
48
+ label: "Test run",
49
+ icon: "play",
50
+ to: {
51
+ kind: "create",
52
+ resource: "workflow_runs",
53
+ values: { workflow_id: "{id}" }
54
+ }
55
+ })]).layout((r) => [
48
56
  layout.section("Workflow", [
49
57
  r.name,
50
58
  r.description,
@@ -60,9 +68,10 @@ const workflowsView = view("workflows").names({
60
68
  field: "workflow_id",
61
69
  columns: [
62
70
  "status",
63
- "version",
71
+ "started_by",
64
72
  "created_at",
65
73
  "duration_ms",
74
+ "version",
66
75
  "error"
67
76
  ]
68
77
  }),
@@ -117,6 +126,7 @@ const runsResource = (schema) => resource("workflow_runs").table(`${schema}.runs
117
126
  cause: f.text().optional().readOnly(),
118
127
  resume_at: f.timestamp().optional().readOnly(),
119
128
  started_by: f.text().optional().readOnly(),
129
+ rerun_of: f.relation("workflow_runs").optional().filterable(),
120
130
  tenant_id: f.text().optional().readOnly(),
121
131
  created_at: f.timestamp().readOnly().dbDefault().sortable(),
122
132
  finished_at: f.timestamp().optional().readOnly(),
@@ -129,8 +139,10 @@ const runsView = view("workflow_runs").names({
129
139
  singular: "Workflow run",
130
140
  plural: "Workflow runs"
131
141
  }).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) => ({
142
+ id: r.id.label("Steps").widget("workflow_run"),
132
143
  workflow_id: r.workflow_id.label("Workflow"),
133
- input: r.input.help("Read by every state as $states.context.Execution.Input"),
144
+ input: r.input.widget("json").help("Read by every state as $states.context.Execution.Input; a re-run takes the input of the run it re-runs"),
145
+ rerun_of: r.rerun_of.label("Re-run of").help("A failed run of the workflow: the re-run keeps its steps before the one that failed, and goes on from there on the workflow as it is now"),
134
146
  key: r.key.help("A workflow runs once per key, such as the record a trigger found ready"),
135
147
  status: r.status.valueLabels({
136
148
  queued: "Queued",
@@ -142,6 +154,7 @@ const runsView = view("workflow_runs").names({
142
154
  succeeded: "green",
143
155
  failed: "red"
144
156
  }),
157
+ output: r.output.widget("json"),
145
158
  resume_at: r.resume_at.label("Goes on at"),
146
159
  started_by: r.started_by.label("Started by"),
147
160
  created_at: r.created_at.label("Started"),
@@ -152,11 +165,25 @@ const runsView = view("workflow_runs").names({
152
165
  r.created_at,
153
166
  r.workflow_id,
154
167
  r.status,
168
+ r.started_by,
155
169
  r.duration_ms,
156
170
  r.error
157
171
  ],
158
172
  sort: [[r.created_at, "desc"]]
159
- })).layout((r) => [
173
+ })).actions((a) => [a.link("rerun", {
174
+ label: "Re-run from the failed step",
175
+ icon: "restart",
176
+ to: {
177
+ kind: "create",
178
+ resource: "workflow_runs",
179
+ values: {
180
+ workflow_id: "{workflow_id}",
181
+ rerun_of: "{id}"
182
+ }
183
+ },
184
+ when: "status = \"failed\""
185
+ })]).layout((r) => [
186
+ layout.section("Trace", [r.id]),
160
187
  layout.section("Run", [
161
188
  r.workflow_id,
162
189
  r.input,
@@ -168,6 +195,7 @@ const runsView = view("workflow_runs").names({
168
195
  r.status,
169
196
  r.version,
170
197
  r.started_by,
198
+ r.rerun_of,
171
199
  r.created_at,
172
200
  r.resume_at,
173
201
  r.finished_at,
@@ -185,6 +213,17 @@ const runsView = view("workflow_runs").names({
185
213
  "duration_ms",
186
214
  "error"
187
215
  ]
216
+ }),
217
+ layout.related("Re-runs", {
218
+ resource: "workflow_runs",
219
+ field: "rerun_of",
220
+ columns: [
221
+ "status",
222
+ "started_by",
223
+ "created_at",
224
+ "duration_ms",
225
+ "error"
226
+ ]
188
227
  })
189
228
  ]);
190
229
  /** Every step of every run: its input with secrets redacted, output, variables, logs, timing, try and error. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@protobase/schema",
3
- "version": "0.67.10",
3
+ "version": "0.67.12",
4
4
  "description": "Resource, field, view and access definitions for Protobase configs.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {