@sonisoft/now-sdk-ext-core 6.6.3 → 6.8.0

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.
Files changed (79) hide show
  1. package/README.md +6 -0
  2. package/dist/comm/http/FormHtmlParser.d.ts +34 -0
  3. package/dist/comm/http/FormHtmlParser.js +227 -0
  4. package/dist/comm/http/FormHtmlParser.js.map +1 -0
  5. package/dist/comm/http/FormRecordModels.d.ts +120 -0
  6. package/dist/comm/http/FormRecordModels.js +6 -0
  7. package/dist/comm/http/FormRecordModels.js.map +1 -0
  8. package/dist/comm/http/FormRecordWriter.d.ts +99 -0
  9. package/dist/comm/http/FormRecordWriter.js +385 -0
  10. package/dist/comm/http/FormRecordWriter.js.map +1 -0
  11. package/dist/comm/http/HTTPRequest.d.ts +4 -0
  12. package/dist/comm/http/RequestHandler.d.ts +1 -0
  13. package/dist/comm/http/RequestHandler.js +34 -22
  14. package/dist/comm/http/RequestHandler.js.map +1 -1
  15. package/dist/comm/http/internal/FormTransportModels.d.ts +26 -0
  16. package/dist/comm/http/internal/FormTransportModels.js +2 -0
  17. package/dist/comm/http/internal/FormTransportModels.js.map +1 -0
  18. package/dist/exception/FormSubmitError.d.ts +13 -0
  19. package/dist/exception/FormSubmitError.js +19 -0
  20. package/dist/exception/FormSubmitError.js.map +1 -0
  21. package/dist/exception/WorkflowValidationError.d.ts +24 -0
  22. package/dist/exception/WorkflowValidationError.js +24 -0
  23. package/dist/exception/WorkflowValidationError.js.map +1 -0
  24. package/dist/index.d.ts +19 -0
  25. package/dist/index.js +19 -0
  26. package/dist/index.js.map +1 -1
  27. package/dist/sn/metadata/MetadataFormWriter.d.ts +13 -0
  28. package/dist/sn/metadata/MetadataFormWriter.js +264 -0
  29. package/dist/sn/metadata/MetadataFormWriter.js.map +1 -0
  30. package/dist/sn/metadata/MetadataModels.d.ts +44 -0
  31. package/dist/sn/metadata/MetadataModels.js +2 -0
  32. package/dist/sn/metadata/MetadataModels.js.map +1 -0
  33. package/dist/sn/metadata/MetadataScopeError.d.ts +5 -0
  34. package/dist/sn/metadata/MetadataScopeError.js +10 -0
  35. package/dist/sn/metadata/MetadataScopeError.js.map +1 -0
  36. package/dist/sn/metadata/MetadataVerificationError.d.ts +11 -0
  37. package/dist/sn/metadata/MetadataVerificationError.js +20 -0
  38. package/dist/sn/metadata/MetadataVerificationError.js.map +1 -0
  39. package/dist/sn/metadata/internal/MetadataPreferences.d.ts +12 -0
  40. package/dist/sn/metadata/internal/MetadataPreferences.js +27 -0
  41. package/dist/sn/metadata/internal/MetadataPreferences.js.map +1 -0
  42. package/dist/sn/metadata/internal/MetadataReader.d.ts +9 -0
  43. package/dist/sn/metadata/internal/MetadataReader.js +55 -0
  44. package/dist/sn/metadata/internal/MetadataReader.js.map +1 -0
  45. package/dist/sn/variables/VariableDefinitions.d.ts +23 -0
  46. package/dist/sn/variables/VariableDefinitions.js +106 -0
  47. package/dist/sn/variables/VariableDefinitions.js.map +1 -0
  48. package/dist/sn/variables/VariableModels.d.ts +49 -0
  49. package/dist/sn/variables/VariableModels.js +6 -0
  50. package/dist/sn/variables/VariableModels.js.map +1 -0
  51. package/dist/sn/workflow/WorkflowConversionModels.d.ts +209 -0
  52. package/dist/sn/workflow/WorkflowConversionModels.js +2 -0
  53. package/dist/sn/workflow/WorkflowConversionModels.js.map +1 -0
  54. package/dist/sn/workflow/WorkflowDiagramClient.d.ts +70 -0
  55. package/dist/sn/workflow/WorkflowDiagramClient.js +151 -0
  56. package/dist/sn/workflow/WorkflowDiagramClient.js.map +1 -0
  57. package/dist/sn/workflow/WorkflowFlowConversion.d.ts +19 -0
  58. package/dist/sn/workflow/WorkflowFlowConversion.js +1013 -0
  59. package/dist/sn/workflow/WorkflowFlowConversion.js.map +1 -0
  60. package/dist/sn/workflow/WorkflowFlowHints.d.ts +3 -0
  61. package/dist/sn/workflow/WorkflowFlowHints.js +36 -0
  62. package/dist/sn/workflow/WorkflowFlowHints.js.map +1 -0
  63. package/dist/sn/workflow/WorkflowFluentGenerator.d.ts +17 -0
  64. package/dist/sn/workflow/WorkflowFluentGenerator.js +348 -0
  65. package/dist/sn/workflow/WorkflowFluentGenerator.js.map +1 -0
  66. package/dist/sn/workflow/WorkflowGraphML.d.ts +39 -0
  67. package/dist/sn/workflow/WorkflowGraphML.js +162 -0
  68. package/dist/sn/workflow/WorkflowGraphML.js.map +1 -0
  69. package/dist/sn/workflow/WorkflowManager.d.ts +236 -6
  70. package/dist/sn/workflow/WorkflowManager.js +1443 -15
  71. package/dist/sn/workflow/WorkflowManager.js.map +1 -1
  72. package/dist/sn/workflow/WorkflowModels.d.ts +738 -0
  73. package/dist/sn/workflow/WorkflowStructure.d.ts +137 -0
  74. package/dist/sn/workflow/WorkflowStructure.js +368 -0
  75. package/dist/sn/workflow/WorkflowStructure.js.map +1 -0
  76. package/dist/sn/workflow/WorkflowViews.d.ts +104 -0
  77. package/dist/sn/workflow/WorkflowViews.js +408 -0
  78. package/dist/sn/workflow/WorkflowViews.js.map +1 -0
  79. package/package.json +2 -1
package/README.md CHANGED
@@ -926,6 +926,12 @@ npm test
926
926
  npm pack
927
927
  ```
928
928
 
929
+ ## ServiceNow SDK upgrades
930
+
931
+ New `@servicenow/sdk` releases are rolled through sn-credstore, core, the CLI and the MCP
932
+ server by a scheduled routine. Its runbook and scripts (`scripts/sdk-watch/`) are described in
933
+ [docs/SDK_UPGRADE_ROUTINE.md](docs/SDK_UPGRADE_ROUTINE.md).
934
+
929
935
  ## 📝 License
930
936
 
931
937
  MIT License - see LICENSE file for details
@@ -0,0 +1,34 @@
1
+ import type { FormTransportLoadOptions, FormTransportSnapshot } from "./internal/FormTransportModels.js";
2
+ /**
3
+ * Parse a form page.
4
+ *
5
+ * @param html The form page
6
+ * @param table The table the form belongs to
7
+ * @throws Error when the page is not a form for `table` (e.g. a login page or an error page)
8
+ */
9
+ export declare function parseFormHtml(html: string, table: string, options?: FormTransportLoadOptions): FormTransportSnapshot;
10
+ /**
11
+ * Split `<table>.<varField>.var__m_<model>.<element>` into its parts.
12
+ * Returns undefined for ordinary (possibly dot-walked) field names.
13
+ */
14
+ export declare function splitVariableName(name: string, table: string): {
15
+ field: string;
16
+ model: string;
17
+ element: string;
18
+ } | undefined;
19
+ /**
20
+ * Messages shown on a classic UI page, split by severity.
21
+ */
22
+ export declare function parseFormMessages(html: string): {
23
+ errors: string[];
24
+ info: string[];
25
+ };
26
+ /**
27
+ * Read the action and sys_id that `modal_dialog_form_response.do` reports after a
28
+ * successful form submit. Returns undefined when the page is anything else — which is
29
+ * how a rejected submit (re-rendered form, error page) shows up.
30
+ */
31
+ export declare function parseFormResponse(html: string): {
32
+ action: string;
33
+ sysId: string;
34
+ } | undefined;
@@ -0,0 +1,227 @@
1
+ import { Parser } from "htmlparser2";
2
+ /**
3
+ * Parses classic UI form pages (`/<table>.do`) into a {@link FormSnapshot}.
4
+ *
5
+ * Kept separate from the writer so it can be exercised against fixture HTML. Only the
6
+ * controls a browser would submit for the record are kept: `<table>.*` inputs,
7
+ * textareas and selects, plus the hidden tokens a submit must echo back. Display-only
8
+ * mirrors (`sys_display.*`, `sys_select.*`, `sys_original.*`) are ignored — posting a
9
+ * `sys_select` value is how the UI ends up storing a reference it only displayed.
10
+ */
11
+ const TOKENS = new Set([
12
+ "sys_uniqueValue", "sysparm_encoded_record", "sys_modCount", "onLoad_sys_updated_on", "sys_row",
13
+ ]);
14
+ /**
15
+ * Parse a form page.
16
+ *
17
+ * @param html The form page
18
+ * @param table The table the form belongs to
19
+ * @throws Error when the page is not a form for `table` (e.g. a login page or an error page)
20
+ */
21
+ export function parseFormHtml(html, table, options = {}) {
22
+ const renderedInputs = {};
23
+ const pageTokens = [];
24
+ const prefix = `${table}.`;
25
+ const tokens = {};
26
+ const actions = {};
27
+ const controls = new Map();
28
+ const types = new Map();
29
+ const mandatory = new Set();
30
+ let target;
31
+ let textarea = null;
32
+ let select = null;
33
+ let option = null;
34
+ const keep = (name) => !!name && name.startsWith(prefix) && !name.endsWith(".ui_policy_sensitive");
35
+ const parser = new Parser({
36
+ onopentag(tag, attrs) {
37
+ switch (tag) {
38
+ case "input": {
39
+ const name = attrs.name;
40
+ if (name === "sys_target")
41
+ target = attrs.value;
42
+ if (TOKENS.has(name))
43
+ tokens[name] = attrs.value ?? "";
44
+ if (options.captureRenderedInputs && name)
45
+ renderedInputs[name] = attrs.value ?? "";
46
+ if (options.tokenSource === "page" && name === "sysparm_ck")
47
+ pageTokens.push(attrs.value ?? "");
48
+ if (!keep(name))
49
+ return;
50
+ const type = (attrs.type || "text").toLowerCase();
51
+ if (type === "button" || type === "submit" || type === "image")
52
+ return;
53
+ if ((type === "checkbox" || type === "radio") && attrs.checked === undefined)
54
+ return;
55
+ controls.set(name, { name, value: attrs.value ?? "" });
56
+ return;
57
+ }
58
+ case "textarea":
59
+ if (keep(attrs.name) || (options.captureRenderedInputs && attrs.name))
60
+ textarea = { name: attrs.name, text: "" };
61
+ return;
62
+ case "select":
63
+ if (keep(attrs.name) || (options.captureRenderedInputs && attrs.name))
64
+ select = { name: attrs.name, options: [] };
65
+ return;
66
+ case "option":
67
+ if (select)
68
+ option = { value: attrs.value, label: "", selected: attrs.selected !== undefined };
69
+ return;
70
+ case "button":
71
+ if (attrs["data-action-name"] && attrs.gsft_id)
72
+ actions[attrs["data-action-name"]] = attrs.gsft_id;
73
+ return;
74
+ case "div":
75
+ if (attrs["data-type"] === "label" && attrs.id?.startsWith("label.") && attrs.type) {
76
+ types.set(attrs.id.slice("label.".length), attrs.type);
77
+ }
78
+ return;
79
+ case "span":
80
+ if (attrs.id?.startsWith("status.") && attrs.mandatory === "true") {
81
+ mandatory.add(attrs.id.slice("status.".length));
82
+ }
83
+ return;
84
+ }
85
+ },
86
+ ontext(text) {
87
+ if (textarea)
88
+ textarea.text += text;
89
+ if (option)
90
+ option.label += text;
91
+ },
92
+ onclosetag(tag) {
93
+ if (tag === "textarea" && textarea) {
94
+ if (options.captureRenderedInputs)
95
+ renderedInputs[textarea.name] = textarea.text;
96
+ if (keep(textarea.name))
97
+ controls.set(textarea.name, { name: textarea.name, value: textarea.text });
98
+ textarea = null;
99
+ }
100
+ else if (tag === "option" && select && option) {
101
+ select.options.push({ value: option.value ?? option.label, label: option.label.trim(), selected: option.selected });
102
+ option = null;
103
+ }
104
+ else if (tag === "select" && select) {
105
+ const chosen = select.options.find(o => o.selected) ?? select.options[0];
106
+ if (options.captureRenderedInputs)
107
+ renderedInputs[select.name] = chosen?.value ?? "";
108
+ if (keep(select.name))
109
+ controls.set(select.name, {
110
+ name: select.name,
111
+ value: chosen ? chosen.value : "",
112
+ choices: select.options.map(o => ({ value: o.value, label: o.label })),
113
+ });
114
+ select = null;
115
+ }
116
+ },
117
+ }, { decodeEntities: true, lowerCaseAttributeNames: true, lowerCaseTags: true });
118
+ parser.write(html);
119
+ parser.end();
120
+ if (target !== table || tokens.sys_uniqueValue === undefined) {
121
+ throw new Error(`The response was not a ${table} form (it may be a login or error page)`);
122
+ }
123
+ const fields = {};
124
+ const variables = {};
125
+ for (const control of controls.values()) {
126
+ const type = types.get(control.name);
127
+ if (type)
128
+ control.type = type;
129
+ if (mandatory.has(control.name))
130
+ control.mandatory = true;
131
+ const variable = splitVariableName(control.name, table);
132
+ // Keyed by column and element: a form can show the same element on two glide_var columns.
133
+ if (variable)
134
+ variables[`${variable.field}.${variable.element}`] = { ...control, ...variable };
135
+ else
136
+ fields[control.name] = control;
137
+ }
138
+ if (options.tokenSource === "page" && (!pageTokens.length || pageTokens.some(token => !token || token !== pageTokens[0]))) {
139
+ throw new Error("csrf_token_unavailable");
140
+ }
141
+ const sysId = tokens.sys_uniqueValue;
142
+ return {
143
+ table,
144
+ sysId,
145
+ isNewRecord: tokens.sys_row === "-1",
146
+ encodedRecord: tokens.sysparm_encoded_record ?? "",
147
+ modCount: tokens.sys_modCount ?? "",
148
+ updatedOn: tokens.onLoad_sys_updated_on ?? "",
149
+ actions,
150
+ fields,
151
+ variables,
152
+ ...(options.captureRenderedInputs ? { renderedInputs } : {}),
153
+ ...(options.tokenSource === "page" ? { pageToken: pageTokens[0] } : {}),
154
+ };
155
+ }
156
+ /**
157
+ * Split `<table>.<varField>.var__m_<model>.<element>` into its parts.
158
+ * Returns undefined for ordinary (possibly dot-walked) field names.
159
+ */
160
+ export function splitVariableName(name, table) {
161
+ const parts = name.slice(table.length + 1).split(".");
162
+ if (parts.length !== 3 || !parts[1].startsWith("var__m_"))
163
+ return undefined;
164
+ return { field: parts[0], model: parts[1], element: parts[2] };
165
+ }
166
+ /**
167
+ * Messages shown on a classic UI page, split by severity.
168
+ */
169
+ export function parseFormMessages(html) {
170
+ const errors = [];
171
+ const info = [];
172
+ // Message containers do not nest, so the most recent one decides the severity.
173
+ let current = null;
174
+ let text = null;
175
+ const parser = new Parser({
176
+ onopentag(tag, attrs) {
177
+ const cls = attrs.class ?? "";
178
+ if (tag === "div" && /\boutputmsg\b/.test(cls)) {
179
+ current = /outputmsg_error|notification-error/.test(cls) ? "error" : "info";
180
+ }
181
+ if (current && tag === "span" && /\boutputmsg_text\b/.test(cls))
182
+ text = "";
183
+ },
184
+ ontext(t) {
185
+ if (text !== null)
186
+ text += t;
187
+ },
188
+ onclosetag(tag) {
189
+ if (tag === "span" && text !== null) {
190
+ const message = text.replace(/\s+/g, " ").trim();
191
+ if (message)
192
+ (current === "error" ? errors : info).push(message);
193
+ text = null;
194
+ }
195
+ },
196
+ }, { decodeEntities: true, lowerCaseAttributeNames: true });
197
+ parser.write(html);
198
+ parser.end();
199
+ return { errors, info };
200
+ }
201
+ /**
202
+ * Read the action and sys_id that `modal_dialog_form_response.do` reports after a
203
+ * successful form submit. Returns undefined when the page is anything else — which is
204
+ * how a rejected submit (re-rendered form, error page) shows up.
205
+ */
206
+ export function parseFormResponse(html) {
207
+ let inResponse = false;
208
+ const values = {};
209
+ const parser = new Parser({
210
+ onopentag(tag, attrs) {
211
+ if (tag === "span" && /\bmodal_dialog_form_response\b/.test(attrs.class ?? ""))
212
+ inResponse = true;
213
+ else if (inResponse && tag === "input" && attrs.name)
214
+ values[attrs.name] = attrs.value ?? "";
215
+ },
216
+ onclosetag(tag) {
217
+ if (tag === "span")
218
+ inResponse = false;
219
+ },
220
+ }, { decodeEntities: true, lowerCaseAttributeNames: true });
221
+ parser.write(html);
222
+ parser.end();
223
+ if (!values.action || !values.sysid)
224
+ return undefined;
225
+ return { action: values.action, sysId: values.sysid };
226
+ }
227
+ //# sourceMappingURL=FormHtmlParser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormHtmlParser.js","sourceRoot":"","sources":["../../../src/comm/http/FormHtmlParser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Models for {@link FormRecordWriter}: writing a record through the classic UI form
3
+ * (`/<table>.do`) the way a browser does.
4
+ */
5
+ /**
6
+ * A duration accepted for a `glide_duration` form field. Numbers are seconds.
7
+ */
8
+ export interface FormDurationInput {
9
+ days?: number;
10
+ hours?: number;
11
+ minutes?: number;
12
+ seconds?: number;
13
+ }
14
+ /**
15
+ * A value for a form field or a variable.
16
+ *
17
+ * - `boolean` is posted as `true`/`false`
18
+ * - an array is posted comma-separated (glide_list)
19
+ * - a `number` or {@link FormDurationInput} on a `glide_duration` field is posted as `D HH:MM:SS`
20
+ * - `null` posts an empty value
21
+ * - anything else is posted as its string form, exactly as given
22
+ */
23
+ export type FormValueInput = string | number | boolean | null | string[] | FormDurationInput;
24
+ /**
25
+ * One control on a loaded form.
26
+ */
27
+ export interface FormControl {
28
+ /** The posted parameter name, e.g. `wf_activity.name` or `wf_activity.vars.var__m_<id>.script` */
29
+ name: string;
30
+ /** The value the form would post if left untouched */
31
+ value: string;
32
+ /** Field type from the form label (e.g. `choice`, `boolean`, `glide_duration`, `reference`), when the form declares one */
33
+ type?: string;
34
+ /** Whether the form marks the field mandatory */
35
+ mandatory?: boolean;
36
+ /** Options offered by a choice field, in form order */
37
+ choices?: Array<{
38
+ value: string;
39
+ label: string;
40
+ }>;
41
+ }
42
+ /**
43
+ * A variable (glide_var) element exposed by a loaded form.
44
+ */
45
+ export interface FormVariableControl extends FormControl {
46
+ /** The glide_var column on the record, e.g. `vars` or `inputs` */
47
+ field: string;
48
+ /** The variable model table name, e.g. `var__m_3961a1da0a0a0b5c00ecd84822f70d85` */
49
+ model: string;
50
+ /** The variable element name, e.g. `timer_type` */
51
+ element: string;
52
+ }
53
+ /**
54
+ * A parsed classic form: the tokens a submit must echo back plus every control.
55
+ */
56
+ export interface FormSnapshot {
57
+ /** Table the form belongs to */
58
+ table: string;
59
+ /** sys_id the form will insert as (pre-assigned for new records) or the record being edited */
60
+ sysId: string;
61
+ /** True when the form was loaded for a new record (`sys_id=-1`) */
62
+ isNewRecord: boolean;
63
+ /**
64
+ * Opaque, signed form-load state. Carries values that are not form inputs, such as
65
+ * fields set through `sysparm_query` at load time. Required for the submit to apply
66
+ * variables.
67
+ */
68
+ encodedRecord: string;
69
+ /** `sys_modCount` of the record when the form was loaded */
70
+ modCount: string;
71
+ /** `onLoad_sys_updated_on` of the record when the form was loaded */
72
+ updatedOn: string;
73
+ /** Form-action UI action sys_ids keyed by action name (e.g. `sysverb_insert`, `sysverb_update`) */
74
+ actions: Record<string, string>;
75
+ /** Ordinary field controls, keyed by posted name */
76
+ fields: Record<string, FormControl>;
77
+ /**
78
+ * Variable controls, keyed by `<variable column>.<element>` (e.g. `vars.timer_type`): a
79
+ * form can show the same element on more than one glide_var column.
80
+ */
81
+ variables: Record<string, FormVariableControl>;
82
+ }
83
+ /**
84
+ * Options for loading a form.
85
+ */
86
+ export interface FormLoadOptions {
87
+ /** Form view (`sysparm_view`). Defaults to the table's default view. */
88
+ view?: string;
89
+ /**
90
+ * Encoded query applied to a new record at load time (`sysparm_query`), e.g.
91
+ * `workflow_version=<id>^activity_definition=<id>`. Fields set this way travel in the
92
+ * encoded record, so they apply even when they are not on the form.
93
+ */
94
+ initialQuery?: string;
95
+ }
96
+ /**
97
+ * Options for inserting or updating a record through its form.
98
+ */
99
+ export interface FormWriteOptions extends FormLoadOptions {
100
+ /** Field values keyed by column name (e.g. `{ name: 'Wait 1 day' }`). Dot-walked names are not supported. */
101
+ fields?: Record<string, FormValueInput>;
102
+ /** Variable values keyed by element name. Unknown elements are rejected. */
103
+ variables?: Record<string, FormValueInput>;
104
+ /**
105
+ * Which glide_var column the variables belong to, when the form exposes more than
106
+ * one (e.g. ATF step `inputs` vs `outputs`). Defaults to the only one present.
107
+ */
108
+ variableField?: string;
109
+ }
110
+ /**
111
+ * Result of a form write.
112
+ */
113
+ export interface FormWriteResult {
114
+ /** sys_id of the inserted or updated record */
115
+ sysId: string;
116
+ /** The form action that ran */
117
+ action: 'sysverb_insert' | 'sysverb_update';
118
+ /** Info messages the instance returned with the response */
119
+ messages: string[];
120
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Models for {@link FormRecordWriter}: writing a record through the classic UI form
3
+ * (`/<table>.do`) the way a browser does.
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=FormRecordModels.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormRecordModels.js","sourceRoot":"","sources":["../../../src/comm/http/FormRecordModels.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,99 @@
1
+ import type { FormTransportLoadOptions, FormTransportSubmitOptions, FormTransportSnapshot, FormTransportResult } from "./internal/FormTransportModels.js";
2
+ import { ServiceNowInstance } from "../../sn/ServiceNowInstance.js";
3
+ import { FormControl, FormDurationInput, FormLoadOptions, FormSnapshot, FormValueInput, FormWriteOptions, FormWriteResult } from "./FormRecordModels.js";
4
+ /**
5
+ * Writes a record through its classic UI form (`/<table>.do`), exactly as a browser does:
6
+ * load the form, then submit it with the form's tokens.
7
+ *
8
+ * This is a low-level tool for writing directly to an instance when the record is NOT
9
+ * authored in a now-sdk application. Its reason to exist is variable-backed records
10
+ * (any table with a glide_var column, e.g. `wf_activity.vars`): the form submit is the
11
+ * path that writes their `sys_variable_value` rows, where REST writes to that table run
12
+ * into ACLs. Records that belong in a now-sdk app (ATF tests, flows, …) should be
13
+ * authored there instead.
14
+ *
15
+ * Why two requests: a new record's form carries values that are not form inputs —
16
+ * anything set through `sysparm_query` at load time, such as the record's variable
17
+ * model — inside the signed `sysparm_encoded_record`. A submit without it inserts the
18
+ * record but silently drops every variable.
19
+ *
20
+ * Only the values you pass are posted. The instance fills in everything else the same
21
+ * way the form would: variable defaults on insert, current values on update.
22
+ */
23
+ declare class FormTransport {
24
+ private _logger;
25
+ private _instance;
26
+ constructor(instance: ServiceNowInstance);
27
+ /**
28
+ * Load a record's form.
29
+ *
30
+ * @param table Table name
31
+ * @param sysId Record sys_id, or `-1` for a new record
32
+ * @param options View and, for new records, the initial query
33
+ * @throws Error when the page is not the expected form, or the record does not exist
34
+ */
35
+ loadForm(table: string, sysId?: string, options?: FormTransportLoadOptions): Promise<FormTransportSnapshot>;
36
+ /**
37
+ * Submit a form you already loaded. Use this to inspect the form's variables (names,
38
+ * types, choices) before deciding what to write.
39
+ */
40
+ submit(snapshot: FormTransportSnapshot, action: string, options?: FormTransportSubmitOptions): Promise<FormTransportResult>;
41
+ /** Validate caller values without submitting the form. */
42
+ validate(snapshot: FormSnapshot, options: FormWriteOptions): void;
43
+ /**
44
+ * Turn caller values into posted form parameters, validating variables against the
45
+ * form so a misspelt element fails loudly instead of being silently ignored.
46
+ */
47
+ private buildFields;
48
+ private variablesFor;
49
+ requireExists(table: string, sysId: string): Promise<void>;
50
+ private guardedLanding;
51
+ private request;
52
+ private requireTable;
53
+ private text;
54
+ private sanitizeError;
55
+ }
56
+ /** Shared internal transport. Excluded from the package barrel. */
57
+ export declare function createFormTransport(instance: ServiceNowInstance): FormTransport;
58
+ /** Write ordinary records through classic forms with the established defaults. */
59
+ export declare class FormRecordWriter {
60
+ private _transport;
61
+ constructor(instance: ServiceNowInstance);
62
+ loadForm(table: string, sysId?: string, options?: FormLoadOptions): Promise<FormSnapshot>;
63
+ /**
64
+ * Insert a record through its form.
65
+ *
66
+ * @param table Table name
67
+ * @param options Field values, variable values, view and initial query
68
+ * @returns The new record's sys_id and any info messages
69
+ * @throws InvalidParameterException for unknown variables or invalid choice values
70
+ * @throws FormSubmitError when the instance does not accept the submit
71
+ */
72
+ insert(table: string, options?: FormWriteOptions): Promise<FormWriteResult>;
73
+ /**
74
+ * Update a record through its form. Fields and variables you do not pass keep their
75
+ * current values.
76
+ *
77
+ * @param table Table name
78
+ * @param sysId Record sys_id
79
+ * @param options Field values, variable values and view
80
+ * @throws InvalidParameterException for unknown variables or invalid choice values
81
+ * @throws FormSubmitError when the instance does not accept the submit
82
+ */
83
+ update(table: string, sysId: string, options?: FormWriteOptions): Promise<FormWriteResult>;
84
+ submit(snapshot: FormSnapshot, action: "sysverb_insert" | "sysverb_update", options?: FormWriteOptions): Promise<FormWriteResult>;
85
+ }
86
+ /**
87
+ * Encode a caller value the way the form posts it.
88
+ *
89
+ * @param value The caller's value
90
+ * @param control The form control it is going to, when known (drives duration and choice handling)
91
+ */
92
+ export declare function encodeFormValue(value: FormValueInput, control?: FormControl): string;
93
+ /**
94
+ * Durations post in the form's display format, `D HH:MM:SS`. The stored format
95
+ * (`1970-01-03 01:02:03`) and plain seconds are not understood by the form, so both are
96
+ * converted here.
97
+ */
98
+ export declare function encodeDuration(value: number | string | FormDurationInput): string;
99
+ export {};