@tenonhq/dovetail-servicenow 0.0.49 → 0.0.50
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 +8 -1
- package/dist/cli.js +55 -3
- package/dist/cliUsage.js +24 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +5 -2
- package/dist/mcp/registry.d.ts +1 -1
- package/dist/mcp/registry.js +37 -1
- package/dist/mcp/schemas.d.ts +19 -0
- package/dist/mcp/schemas.js +14 -1
- package/dist/table/addColumn.d.ts +36 -0
- package/dist/table/addColumn.js +119 -2
- package/dist/table/designAccess.d.ts +75 -0
- package/dist/table/designAccess.js +250 -0
- package/dist/table/index.d.ts +3 -1
- package/dist/table/index.js +7 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1154,7 +1154,14 @@ Claude Code and agents: `create_view`, `set_list_layout`, `set_form_layout`,
|
|
|
1154
1154
|
`add_column` (same-scope by default; `crossScope: true` with `scope` adds a column OWNED
|
|
1155
1155
|
by another app — a Journey field on an Automate table, element `<scope>_<name>` —
|
|
1156
1156
|
guarded by `sys_db_object.alter_access` and the update set's scope, with the stored
|
|
1157
|
-
element and `sys_scope` read back; the CLI flag is `--cross-scope
|
|
1157
|
+
element and `sys_scope` read back; the CLI flag is `--cross-scope`. A cross-scope
|
|
1158
|
+
result also carries `designAccess`: the platform UI refuses cross-scope authoring
|
|
1159
|
+
without a `sys_scope_design_access` record (column scope -> table scope), so a missing
|
|
1160
|
+
one is FLAGGED — not blocking, the headless insert works without it — and
|
|
1161
|
+
`ensureDesignAccess: true` / `--ensure-design-access` creates it first in the same
|
|
1162
|
+
update set) / `design_access` (ensure that record on its own — idempotent, created in
|
|
1163
|
+
the SOURCE app's update set and read back; CLI `dove-sn design-access --source <app>
|
|
1164
|
+
--target <app> --update-set <sys_id>`, `--dry-run` only reports exists/missing) /
|
|
1158
1165
|
`add_index` (a single-column unique index via `sys_dictionary.unique`,
|
|
1159
1166
|
read back from the `v_db_index` view - uniqueness enforcement is always reported
|
|
1160
1167
|
unverified) / `index_list` (read-only: a table's database indexes from `v_db_index`,
|
package/dist/cli.js
CHANGED
|
@@ -1340,15 +1340,60 @@ async function runCreateTable(flags) {
|
|
|
1340
1340
|
return 2;
|
|
1341
1341
|
return 0;
|
|
1342
1342
|
}
|
|
1343
|
+
/**
|
|
1344
|
+
* dove-sn design-access:
|
|
1345
|
+
* --source x_cadso_journey --target x_cadso_automate
|
|
1346
|
+
* [--update-set <sys_id in source>] [--dry-run] [--json]
|
|
1347
|
+
* Ensures the sys_scope_design_access record that lets the SOURCE app author in the
|
|
1348
|
+
* TARGET app's tables (required by the platform UI for cross-scope columns). Idempotent;
|
|
1349
|
+
* --dry-run only reports whether it exists. --update-set is required unless --dry-run.
|
|
1350
|
+
*/
|
|
1351
|
+
async function runDesignAccess(flags) {
|
|
1352
|
+
if (!flags.source || !flags.target) {
|
|
1353
|
+
process.stderr.write("design-access: --source (authoring app) and --target (app that owns the tables) are required\n");
|
|
1354
|
+
return 1;
|
|
1355
|
+
}
|
|
1356
|
+
var isDryRun = flags["dry-run"] === "true";
|
|
1357
|
+
if (!isDryRun && !flags["update-set"]) {
|
|
1358
|
+
process.stderr.write("design-access: --update-set (an update set in --source) is required on the live path (only --dry-run works without one)\n");
|
|
1359
|
+
return 1;
|
|
1360
|
+
}
|
|
1361
|
+
var result = await (0, table_1.ensureDesignAccess)({
|
|
1362
|
+
client: (0, client_1.createClient)({}),
|
|
1363
|
+
sourceScope: flags.source,
|
|
1364
|
+
targetScope: flags.target,
|
|
1365
|
+
updateSetSysId: flags["update-set"],
|
|
1366
|
+
dryRun: isDryRun,
|
|
1367
|
+
});
|
|
1368
|
+
if (flags.json === "true") {
|
|
1369
|
+
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
1370
|
+
}
|
|
1371
|
+
else {
|
|
1372
|
+
process.stdout.write("[" +
|
|
1373
|
+
result.status +
|
|
1374
|
+
"] " +
|
|
1375
|
+
result.sourceScope +
|
|
1376
|
+
" -> " +
|
|
1377
|
+
result.targetScope +
|
|
1378
|
+
(result.sysId ? " (" + result.sysId + ")" : "") +
|
|
1379
|
+
"\n" +
|
|
1380
|
+
result.note +
|
|
1381
|
+
"\n");
|
|
1382
|
+
}
|
|
1383
|
+
if (result.status === "failed")
|
|
1384
|
+
return 2;
|
|
1385
|
+
return 0;
|
|
1386
|
+
}
|
|
1343
1387
|
/**
|
|
1344
1388
|
* dove-sn add-column:
|
|
1345
1389
|
* --table x_cadso_journey --label URL --type url
|
|
1346
1390
|
* [--name url] [--max-length 1024] [--reference <table>]
|
|
1347
1391
|
* [--mandatory] [--default <value>] [--dependent-on-field <element>]
|
|
1348
|
-
* [--scope x_cadso_journey] [--cross-scope] [--
|
|
1349
|
-
* [--from-json <spec.json>] [--dry-run] [--debug] [--json]
|
|
1392
|
+
* [--scope x_cadso_journey] [--cross-scope] [--ensure-design-access]
|
|
1393
|
+
* [--update-set <sys_id>] [--from-json <spec.json>] [--dry-run] [--debug] [--json]
|
|
1350
1394
|
* --update-set is required unless --dry-run. --cross-scope opts in to a column
|
|
1351
|
-
* OWNED by --scope when that differs from the table's scope
|
|
1395
|
+
* OWNED by --scope when that differs from the table's scope; a missing Design Access
|
|
1396
|
+
* record is flagged, and --ensure-design-access creates it first.
|
|
1352
1397
|
*/
|
|
1353
1398
|
async function runAddColumn(flags) {
|
|
1354
1399
|
var spec = {};
|
|
@@ -1388,6 +1433,10 @@ async function runAddColumn(flags) {
|
|
|
1388
1433
|
if (flags["cross-scope"] === "true" || spec.crossScope === true) {
|
|
1389
1434
|
params.crossScope = true;
|
|
1390
1435
|
}
|
|
1436
|
+
if (flags["ensure-design-access"] === "true" ||
|
|
1437
|
+
spec.ensureDesignAccess === true) {
|
|
1438
|
+
params.ensureDesignAccess = true;
|
|
1439
|
+
}
|
|
1391
1440
|
var us = flags["update-set"] || spec.updateSetSysId;
|
|
1392
1441
|
if (us)
|
|
1393
1442
|
params.updateSetSysId = us;
|
|
@@ -2616,6 +2665,9 @@ async function dispatch(parsed) {
|
|
|
2616
2665
|
if (parsed.command === "add-column") {
|
|
2617
2666
|
return await runAddColumn(parsed.flags);
|
|
2618
2667
|
}
|
|
2668
|
+
if (parsed.command === "design-access") {
|
|
2669
|
+
return await runDesignAccess(parsed.flags);
|
|
2670
|
+
}
|
|
2619
2671
|
if (parsed.command === "add-index") {
|
|
2620
2672
|
return await runAddIndex(parsed.flags);
|
|
2621
2673
|
}
|
package/dist/cliUsage.js
CHANGED
|
@@ -209,6 +209,10 @@ exports.VERB_USAGE = {
|
|
|
209
209
|
flag: "cross-scope",
|
|
210
210
|
note: "Opt in to a column OWNED by --scope, which differs from the table's scope (element becomes <scope>_<name>; the table must allow new fields; --update-set must be in --scope).",
|
|
211
211
|
},
|
|
212
|
+
{
|
|
213
|
+
flag: "ensure-design-access",
|
|
214
|
+
note: "Cross-scope only: create the missing sys_scope_design_access record (--scope -> table's scope) first, in the same update set. Without it a missing record is only flagged.",
|
|
215
|
+
},
|
|
212
216
|
{ flag: "update-set", value: "<sys_id>", note: "REQUIRED on the live path (only --dry-run works without one)." },
|
|
213
217
|
DRY_RUN_FLAG,
|
|
214
218
|
DEBUG_FLAG,
|
|
@@ -222,6 +226,26 @@ exports.VERB_USAGE = {
|
|
|
222
226
|
"Cross-scope: dove-sn add-column --table x_cadso_automate_email_batch --label 'Instance Step' --name instance_step --type reference --reference x_cadso_journey_instance_step --scope x_cadso_journey --cross-scope --update-set <journey set>",
|
|
223
227
|
],
|
|
224
228
|
},
|
|
229
|
+
"design-access": {
|
|
230
|
+
summary: "Ensure the sys_scope_design_access record that lets one app author in another app's tables (required by the UI for cross-scope columns)",
|
|
231
|
+
required: [
|
|
232
|
+
{ flag: "source", value: "<x_scope>", note: "The AUTHORING app (owns the record and its update set)." },
|
|
233
|
+
{ flag: "target", value: "<x_scope>", note: "The app that OWNS the tables." },
|
|
234
|
+
],
|
|
235
|
+
optional: [
|
|
236
|
+
{ flag: "update-set", value: "<sys_id>", note: "Update set in --source. REQUIRED on the live path." },
|
|
237
|
+
DRY_RUN_FLAG,
|
|
238
|
+
JSON_FLAG,
|
|
239
|
+
],
|
|
240
|
+
gate: "dry-run-flag",
|
|
241
|
+
gateNote: "--update-set is required unless --dry-run; --dry-run reports exists/missing only.",
|
|
242
|
+
example: "dove-sn design-access --source x_cadso_journey --target x_cadso_automate --update-set <journey set>",
|
|
243
|
+
notes: [
|
|
244
|
+
"Idempotent: an existing record is reported and nothing is written.",
|
|
245
|
+
"Symptom it fixes: \"Invalid 'Table' selected on the Dictionary Entry record ... can only select '<app>' tables with read access enabled\" — the table's own access flags are NOT the gate.",
|
|
246
|
+
"Exit 2 when the record could not be created or verified on read-back.",
|
|
247
|
+
],
|
|
248
|
+
},
|
|
225
249
|
"set-column": {
|
|
226
250
|
summary: "Update an EXISTING column's schema (label/mandatory/default/read-only/max-length/dependent-on-field), then verify",
|
|
227
251
|
required: [
|
package/dist/index.d.ts
CHANGED
|
@@ -21,8 +21,8 @@ export { sincPlugin } from "./plugin";
|
|
|
21
21
|
export { listTemplates, verifyArtifact, cloneSubflow, cloneActionType, resolveScope, slugInternalName, fetchActionSteps, findStepInput, triggerPublication, publishActionType, editActionType, defineActionType, planActionDefinition, validateDefineSpec, applyStepOps, verifySteps, summarizeSteps, formatStepPill, readFlow, readActionType, publishFlow, copyFlow, createFlow, buildPublishModel, editFlow, testFlow, DEFAULT_RUN_FLOW_PATH, generateSysId, topoSort, executeWritePlan, WriteOrderError, } from "./flowDesigner";
|
|
22
22
|
export type { TemplateRef, ListTemplatesParams, FlowKind, VerifyExpect, VerifyFound, VerifyFailure, VerifyReport, VerifyArtifactParams, CloneSubflowParams, CloneSubflowResult, CloneActionTypeParams, CloneActionTypeResult, CloneActionTypePlan, CloneActionTypeStepReport, TriggerPublicationParams, TriggerPublicationResult, PublishActionTypeParams, PublishActionTypeResult, EditActionTypeParams, EditActionTypeResult, EditActionTypeOps, DefineActionSpec, DefineActionInputSpec, DefineActionOutputSpec, DefineStepSpec, DefineStepVarSpec, DefineStepOutputSpec, DefineStepValue, DefineActionTypeParams, DefineActionTypeResult, DefineActionDiff, DefineActionPlan, PlanActionDefinitionParams, ActionView, StepView, StepOps, StepRecord, StepSummary, StepIoSummary, PatchStepScriptOp, SetStepInputOp, AddStepOutputOp, AddStepInputOp, ApplyStepOpsResult, VerifyStepsResult, ReadFlowParams, ReadFlowResult, FlowStep, FlowVariable, ReadActionTypeParams, ReadActionTypeResult, ActionIo, PublishFlowParams, PublishFlowResult, CopyFlowParams, CopyFlowResult, CreateFlowParams, CreateFlowResult, EditFlowParams, EditFlowResult, EditFlowOps, StepInputPatch, TestFlowParams, TestFlowResult, WriteOp, WriteOpResult, } from "./flowDesigner";
|
|
23
23
|
export type { ServiceNowClientConfig, ChoiceValue, ChoiceType, AddChoicesParams, AddChoicesResult, ChoiceActionResult, ChoiceFieldRef, RemoveChoicesParams, RemoveChoicesResult, ChoiceRemovalResult, DictionaryRecord, UpdateSetRecord, LayoutAction, LayoutRecordResult, LayoutResult, CreateViewParams, CreateViewResult, FormSectionSpec, SetFormLayoutParams, SetListLayoutParams, SetRelatedListsParams, ChunkRole, ChunkInfo, ChunkResult, PrunedResult, HostAssetsParams, HostAssetsResult, } from "./types";
|
|
24
|
-
export { createTable, projectTableGraph, buildColumnXml, normalizeColumns, resolveType, applyTableSaveOverlay, defaultAccessFlags, TYPE_MAP, DEFAULT_SUPER_CLASS, DEFAULT_SAVE_ACTION, addColumn, deriveElement, addIndex, parseIndexColumns, indexMatchesColumns, listIndexes, createIndex, validateCreateIndex, DEFAULT_INDEX_FORM_PATH, NOT_IN_UPDATE_SET, setColumn, resolveAttributes, toStoredValue, setTable, resolveTableAttributes, } from "./table";
|
|
25
|
-
export type { CreateTableParams, CreateTableResult, AddColumnParams, AddColumnResult, AddIndexParams, AddIndexResult, AddIndexVerification, ListIndexesParams, ListIndexesResult, TableIndex, CreateIndexParams, CreateIndexResult, SetColumnParams, SetColumnResult, ColumnAttributes, AttributeChange, SetTableParams, SetTableResult, TableAttributes, TableGraph, NormalizedColumn, ColumnSpec, AccessFlags, OverlaySpec, } from "./table";
|
|
24
|
+
export { createTable, projectTableGraph, buildColumnXml, normalizeColumns, resolveType, applyTableSaveOverlay, defaultAccessFlags, TYPE_MAP, DEFAULT_SUPER_CLASS, DEFAULT_SAVE_ACTION, addColumn, deriveElement, ensureDesignAccess, findDesignAccess, DESIGN_ACCESS_TABLE, addIndex, parseIndexColumns, indexMatchesColumns, listIndexes, createIndex, validateCreateIndex, DEFAULT_INDEX_FORM_PATH, NOT_IN_UPDATE_SET, setColumn, resolveAttributes, toStoredValue, setTable, resolveTableAttributes, } from "./table";
|
|
25
|
+
export type { CreateTableParams, CreateTableResult, AddColumnParams, AddColumnResult, DesignAccessFlag, EnsureDesignAccessParams, EnsureDesignAccessResult, AddIndexParams, AddIndexResult, AddIndexVerification, ListIndexesParams, ListIndexesResult, TableIndex, CreateIndexParams, CreateIndexResult, SetColumnParams, SetColumnResult, ColumnAttributes, AttributeChange, SetTableParams, SetTableResult, TableAttributes, TableGraph, NormalizedColumn, ColumnSpec, AccessFlags, OverlaySpec, } from "./table";
|
|
26
26
|
export { setField } from "./setField";
|
|
27
27
|
export { createRecord } from "./createRecord";
|
|
28
28
|
export type { RecordWriteResult, SetFieldParams, SetFieldResult, } from "./setField";
|
package/dist/index.js
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.editFlow = exports.buildPublishModel = exports.createFlow = exports.copyFlow = exports.publishFlow = exports.readActionType = exports.readFlow = exports.formatStepPill = exports.summarizeSteps = exports.verifySteps = exports.applyStepOps = exports.validateDefineSpec = exports.planActionDefinition = exports.defineActionType = exports.editActionType = exports.publishActionType = exports.triggerPublication = exports.findStepInput = exports.fetchActionSteps = exports.slugInternalName = exports.resolveScope = exports.cloneActionType = exports.cloneSubflow = exports.verifyArtifact = exports.listTemplates = exports.sincPlugin = exports.formatCreateViewResult = exports.formatLayoutResult = exports.setRelatedLists = exports.setFormLayout = exports.setListLayout = exports.createView = exports.formatRemoveChoicesResult = exports.formatAddChoicesResult = exports.formatHostAssetsResult = exports.classifyChunks = exports.hostAssets = exports.ChoiceWriteError = exports.removeChoicesFromField = exports.addChoicesToField = exports.resolveConfigFromEnvFile = exports.createClientFromEnvFile = exports.assertWriteAllowed = exports.evaluateWriteGate = exports.isCiEnvironment = exports.resolveExecutionContext = exports.PROCESSFLOW_PATH_PREFIX = exports.isProcessflowPath = exports.resolveFlowAuth = exports.createClient = void 0;
|
|
10
|
-
exports.
|
|
11
|
-
exports.SECRET_INTERNAL_TYPES = exports.SENTINEL = exports.isCapturable = exports.secretFieldsFromDictionary = exports.mergeSecretRules = exports.loadSecretRules = exports.defaultSecretRules = exports.escapeRegExp = exports.encodeXmlText = exports.encodeXmlEntities = exports.stripJsonValue = exports.stripField = exports.plannedStrips = exports.recordFieldNames = exports.readRecordTable = exports.readField = exports.verifyStripped = exports.stripSecrets = exports.DEFAULT_EXPORT_APP_TIMEOUT_MS = exports.buildPublishFields = exports.buildCreateSetFields = exports.exportApp = exports.DEFAULT_MAX_ROWS = exports.MAX_PAGE_SIZE = exports.DEFAULT_PAGE_SIZE = exports.UPDATE_XML_FIELDS = exports.xmlEscape = exports.formatUnloadDate = exports.parseStatsCount = exports.refreshTypeFields = exports.fetchUpdateXmlRows = exports.countUpdateXml = exports.countUnloadRecords = exports.renderUnload = exports.renderRemoteUpdateSet = exports.renderUpdateXmlRow = exports.exportUpdateSet = exports.PUBLISH_POLL_DELAYS_MS = exports.DEFAULT_PUBLISH_TIMEOUT_MS = exports.parseCicdProgress = exports.parseCicdPublishResponse = exports.harvestProgressResults = exports.flattenSteps = exports.classifyProgress = void 0;
|
|
10
|
+
exports.parsePublishTargets = exports.describeTarget = exports.resolveUpdateSetNaming = exports.buildPublishToUpdateSetFields = exports.buildCreateUpdateSetFields = exports.buildStartFields = exports.publishApp = exports.INVOKE_REST_METHODS = exports.invokeRest = exports.verifyReadBack = exports.readBackMatches = exports.hasHtmlEntity = exports.decodeHtmlEntities = exports.deleteRecord = exports.createRecord = exports.setField = exports.resolveTableAttributes = exports.setTable = exports.toStoredValue = exports.resolveAttributes = exports.setColumn = exports.NOT_IN_UPDATE_SET = exports.DEFAULT_INDEX_FORM_PATH = exports.validateCreateIndex = exports.createIndex = exports.listIndexes = exports.indexMatchesColumns = exports.parseIndexColumns = exports.addIndex = exports.DESIGN_ACCESS_TABLE = exports.findDesignAccess = exports.ensureDesignAccess = exports.deriveElement = exports.addColumn = exports.DEFAULT_SAVE_ACTION = exports.DEFAULT_SUPER_CLASS = exports.TYPE_MAP = exports.defaultAccessFlags = exports.applyTableSaveOverlay = exports.resolveType = exports.normalizeColumns = exports.buildColumnXml = exports.projectTableGraph = exports.createTable = exports.WriteOrderError = exports.executeWritePlan = exports.topoSort = exports.generateSysId = exports.DEFAULT_RUN_FLOW_PATH = exports.testFlow = void 0;
|
|
11
|
+
exports.SECRET_INTERNAL_TYPES = exports.SENTINEL = exports.isCapturable = exports.secretFieldsFromDictionary = exports.mergeSecretRules = exports.loadSecretRules = exports.defaultSecretRules = exports.escapeRegExp = exports.encodeXmlText = exports.encodeXmlEntities = exports.stripJsonValue = exports.stripField = exports.plannedStrips = exports.recordFieldNames = exports.readRecordTable = exports.readField = exports.verifyStripped = exports.stripSecrets = exports.DEFAULT_EXPORT_APP_TIMEOUT_MS = exports.buildPublishFields = exports.buildCreateSetFields = exports.exportApp = exports.DEFAULT_MAX_ROWS = exports.MAX_PAGE_SIZE = exports.DEFAULT_PAGE_SIZE = exports.UPDATE_XML_FIELDS = exports.xmlEscape = exports.formatUnloadDate = exports.parseStatsCount = exports.refreshTypeFields = exports.fetchUpdateXmlRows = exports.countUpdateXml = exports.countUnloadRecords = exports.renderUnload = exports.renderRemoteUpdateSet = exports.renderUpdateXmlRow = exports.exportUpdateSet = exports.PUBLISH_POLL_DELAYS_MS = exports.DEFAULT_PUBLISH_TIMEOUT_MS = exports.parseCicdProgress = exports.parseCicdPublishResponse = exports.harvestProgressResults = exports.flattenSteps = exports.classifyProgress = exports.parseProgressTree = exports.parseXmlAnswer = exports.PUBLISH_TARGETS = void 0;
|
|
12
12
|
var client_1 = require("./client");
|
|
13
13
|
Object.defineProperty(exports, "createClient", { enumerable: true, get: function () { return client_1.createClient; } });
|
|
14
14
|
Object.defineProperty(exports, "resolveFlowAuth", { enumerable: true, get: function () { return client_1.resolveFlowAuth; } });
|
|
@@ -91,6 +91,9 @@ Object.defineProperty(exports, "DEFAULT_SUPER_CLASS", { enumerable: true, get: f
|
|
|
91
91
|
Object.defineProperty(exports, "DEFAULT_SAVE_ACTION", { enumerable: true, get: function () { return table_1.DEFAULT_SAVE_ACTION; } });
|
|
92
92
|
Object.defineProperty(exports, "addColumn", { enumerable: true, get: function () { return table_1.addColumn; } });
|
|
93
93
|
Object.defineProperty(exports, "deriveElement", { enumerable: true, get: function () { return table_1.deriveElement; } });
|
|
94
|
+
Object.defineProperty(exports, "ensureDesignAccess", { enumerable: true, get: function () { return table_1.ensureDesignAccess; } });
|
|
95
|
+
Object.defineProperty(exports, "findDesignAccess", { enumerable: true, get: function () { return table_1.findDesignAccess; } });
|
|
96
|
+
Object.defineProperty(exports, "DESIGN_ACCESS_TABLE", { enumerable: true, get: function () { return table_1.DESIGN_ACCESS_TABLE; } });
|
|
94
97
|
Object.defineProperty(exports, "addIndex", { enumerable: true, get: function () { return table_1.addIndex; } });
|
|
95
98
|
Object.defineProperty(exports, "parseIndexColumns", { enumerable: true, get: function () { return table_1.parseIndexColumns; } });
|
|
96
99
|
Object.defineProperty(exports, "indexMatchesColumns", { enumerable: true, get: function () { return table_1.indexMatchesColumns; } });
|
package/dist/mcp/registry.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
10
10
|
import { z } from "zod";
|
|
11
11
|
import type { ToolAnnotations } from "@tenonhq/dovetail-mcp-kit";
|
|
12
12
|
import type { ServiceNowClient } from "../client";
|
|
13
|
-
export declare var TOOL_NAMES: readonly ["create_view", "set_list_layout", "set_form_layout", "set_related_lists", "add_choices_to_field", "remove_choices_from_field", "flow_view", "action_view", "action_edit", "action_clone", "action_define", "flow_publish", "flow_copy", "flow_create", "flow_test", "flow_edit", "create_table", "add_column", "add_index", "index_list", "index_create", "set_column", "set_table", "set_field", "create_record", "delete_record", "host_assets", "invoke_rest", "app_publish", "update_set_export", "app_export"];
|
|
13
|
+
export declare var TOOL_NAMES: readonly ["create_view", "set_list_layout", "set_form_layout", "set_related_lists", "add_choices_to_field", "remove_choices_from_field", "flow_view", "action_view", "action_edit", "action_clone", "action_define", "flow_publish", "flow_copy", "flow_create", "flow_test", "flow_edit", "create_table", "add_column", "design_access", "add_index", "index_list", "index_create", "set_column", "set_table", "set_field", "create_record", "delete_record", "host_assets", "invoke_rest", "app_publish", "update_set_export", "app_export"];
|
|
14
14
|
export type ToolName = (typeof TOOL_NAMES)[number];
|
|
15
15
|
export interface RegistryDeps {
|
|
16
16
|
/** Optional client injection for tests; defaults to createClient({}). */
|
package/dist/mcp/registry.js
CHANGED
|
@@ -57,6 +57,7 @@ exports.TOOL_NAMES = [
|
|
|
57
57
|
"flow_edit",
|
|
58
58
|
"create_table",
|
|
59
59
|
"add_column",
|
|
60
|
+
"design_access",
|
|
60
61
|
"add_index",
|
|
61
62
|
"index_list",
|
|
62
63
|
"index_create",
|
|
@@ -445,7 +446,11 @@ function buildDescriptors(deps = {}) {
|
|
|
445
446
|
"<scope>_<name>, the dictionary row and its update-set capture land in scope); the table " +
|
|
446
447
|
"must allow new fields from other scopes (sys_db_object.alter_access) and updateSetSysId " +
|
|
447
448
|
"must belong to scope — both checked on dryRun too, and the stored element + sys_scope are " +
|
|
448
|
-
"read back.
|
|
449
|
+
"read back. A cross-scope result carries designAccess { present, sysId, created }: the " +
|
|
450
|
+
"platform UI refuses cross-scope authoring without a sys_scope_design_access record " +
|
|
451
|
+
"(scope -> the table's scope), so a missing one is FLAGGED (not blocking — the headless " +
|
|
452
|
+
"insert works without it); ensureDesignAccess:true creates it first in the same update " +
|
|
453
|
+
"set. updateSetSysId is required on the live path. dryRun:true returns the plan with " +
|
|
449
454
|
"no writes.",
|
|
450
455
|
shape: schemas_1.addColumnSchema.shape,
|
|
451
456
|
handler: async function (args) {
|
|
@@ -465,12 +470,43 @@ function buildDescriptors(deps = {}) {
|
|
|
465
470
|
column: p.column,
|
|
466
471
|
scope: p.scope,
|
|
467
472
|
crossScope: p.crossScope,
|
|
473
|
+
ensureDesignAccess: p.ensureDesignAccess,
|
|
468
474
|
updateSetSysId: p.updateSetSysId,
|
|
469
475
|
dryRun: p.dryRun,
|
|
470
476
|
debug: p.debug,
|
|
471
477
|
});
|
|
472
478
|
},
|
|
473
479
|
},
|
|
480
|
+
{
|
|
481
|
+
name: "design_access",
|
|
482
|
+
annotations: dovetail_mcp_kit_1.WRITE_CREATE,
|
|
483
|
+
description: "Ensure the sys_scope_design_access record that lets sourceScope (the AUTHORING app) " +
|
|
484
|
+
"design in targetScope's tables (the app that OWNS them). The platform UI requires it " +
|
|
485
|
+
"for cross-scope columns — the symptom is \"Invalid 'Table' selected on the Dictionary " +
|
|
486
|
+
"Entry record ... can only select '<app>' tables with read access enabled\", and the " +
|
|
487
|
+
"table's own access flags are NOT the gate. Scopes are names or sys_scope sys_ids. " +
|
|
488
|
+
"Idempotent: an existing record returns status 'exists' and nothing is written. Live " +
|
|
489
|
+
"creates it via the scope-aware createRecord op switched to sourceScope, captured in " +
|
|
490
|
+
"updateSetSysId (must belong to sourceScope), then reads it back and asserts " +
|
|
491
|
+
"source/target. updateSetSysId is required on the live path; dryRun:true only reports " +
|
|
492
|
+
"exists / missing.",
|
|
493
|
+
shape: schemas_1.designAccessSchema.shape,
|
|
494
|
+
handler: async function (args) {
|
|
495
|
+
var p = schemas_1.designAccessSchema.parse(args);
|
|
496
|
+
if (p.dryRun !== true &&
|
|
497
|
+
(!p.updateSetSysId || !p.updateSetSysId.trim())) {
|
|
498
|
+
throw new Error("design_access: updateSetSysId (an update set in sourceScope) is required on " +
|
|
499
|
+
"the live path — set dryRun:true to only check whether the record exists.");
|
|
500
|
+
}
|
|
501
|
+
return (0, table_1.ensureDesignAccess)({
|
|
502
|
+
client: client(),
|
|
503
|
+
sourceScope: p.sourceScope,
|
|
504
|
+
targetScope: p.targetScope,
|
|
505
|
+
updateSetSysId: p.updateSetSysId,
|
|
506
|
+
dryRun: p.dryRun,
|
|
507
|
+
});
|
|
508
|
+
},
|
|
509
|
+
},
|
|
474
510
|
{
|
|
475
511
|
name: "add_index",
|
|
476
512
|
annotations: dovetail_mcp_kit_1.WRITE_OVERWRITE,
|
package/dist/mcp/schemas.d.ts
CHANGED
|
@@ -1891,6 +1891,7 @@ export declare var addColumnSchema: z.ZodObject<{
|
|
|
1891
1891
|
}>;
|
|
1892
1892
|
scope: z.ZodOptional<z.ZodString>;
|
|
1893
1893
|
crossScope: z.ZodOptional<z.ZodBoolean>;
|
|
1894
|
+
ensureDesignAccess: z.ZodOptional<z.ZodBoolean>;
|
|
1894
1895
|
updateSetSysId: z.ZodOptional<z.ZodString>;
|
|
1895
1896
|
dryRun: z.ZodOptional<z.ZodBoolean>;
|
|
1896
1897
|
debug: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -1911,6 +1912,7 @@ export declare var addColumnSchema: z.ZodObject<{
|
|
|
1911
1912
|
updateSetSysId?: string | undefined;
|
|
1912
1913
|
scope?: string | undefined;
|
|
1913
1914
|
crossScope?: boolean | undefined;
|
|
1915
|
+
ensureDesignAccess?: boolean | undefined;
|
|
1914
1916
|
}, {
|
|
1915
1917
|
table: string;
|
|
1916
1918
|
column: {
|
|
@@ -1928,6 +1930,23 @@ export declare var addColumnSchema: z.ZodObject<{
|
|
|
1928
1930
|
updateSetSysId?: string | undefined;
|
|
1929
1931
|
scope?: string | undefined;
|
|
1930
1932
|
crossScope?: boolean | undefined;
|
|
1933
|
+
ensureDesignAccess?: boolean | undefined;
|
|
1934
|
+
}>;
|
|
1935
|
+
export declare var designAccessSchema: z.ZodObject<{
|
|
1936
|
+
sourceScope: z.ZodString;
|
|
1937
|
+
targetScope: z.ZodString;
|
|
1938
|
+
updateSetSysId: z.ZodOptional<z.ZodString>;
|
|
1939
|
+
dryRun: z.ZodOptional<z.ZodBoolean>;
|
|
1940
|
+
}, "strip", z.ZodTypeAny, {
|
|
1941
|
+
sourceScope: string;
|
|
1942
|
+
targetScope: string;
|
|
1943
|
+
dryRun?: boolean | undefined;
|
|
1944
|
+
updateSetSysId?: string | undefined;
|
|
1945
|
+
}, {
|
|
1946
|
+
sourceScope: string;
|
|
1947
|
+
targetScope: string;
|
|
1948
|
+
dryRun?: boolean | undefined;
|
|
1949
|
+
updateSetSysId?: string | undefined;
|
|
1931
1950
|
}>;
|
|
1932
1951
|
export declare var addIndexSchema: z.ZodObject<{
|
|
1933
1952
|
table: z.ZodString;
|
package/dist/mcp/schemas.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* own file so registry.ts stays focused on wiring.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.invokeRestSchema = exports.publishAppSchema = exports.exportAppSchema = exports.exportUpdateSetSchema = exports.deleteRecordSchema = exports.createRecordSchema = exports.setFieldSchema = exports.setTableSchema = exports.tableAttributesSchema = exports.setColumnSchema = exports.columnAttributesSchema = exports.createIndexSchema = exports.listIndexesSchema = exports.addIndexSchema = exports.addColumnSchema = exports.createTableSchema = exports.columnSpecSchema = exports.hostAssetsSchema = exports.editFlowSchema = exports.defineActionSchema = exports.defineActionSpecSchema = exports.cloneActionSchema = exports.editActionSchema = exports.stepInputPatchSchema = exports.testFlowSchema = exports.createFlowSchema = exports.copyFlowSchema = exports.publishFlowSchema = exports.viewActionSchema = exports.viewFlowSchema = exports.removeChoicesFromFieldSchema = exports.addChoicesToFieldSchema = exports.choiceValueSchema = exports.setRelatedListsSchema = exports.setFormLayoutSchema = exports.formSectionSchema = exports.setListLayoutSchema = exports.createViewSchema = void 0;
|
|
7
|
+
exports.invokeRestSchema = exports.publishAppSchema = exports.exportAppSchema = exports.exportUpdateSetSchema = exports.deleteRecordSchema = exports.createRecordSchema = exports.setFieldSchema = exports.setTableSchema = exports.tableAttributesSchema = exports.setColumnSchema = exports.columnAttributesSchema = exports.createIndexSchema = exports.listIndexesSchema = exports.addIndexSchema = exports.designAccessSchema = exports.addColumnSchema = exports.createTableSchema = exports.columnSpecSchema = exports.hostAssetsSchema = exports.editFlowSchema = exports.defineActionSchema = exports.defineActionSpecSchema = exports.cloneActionSchema = exports.editActionSchema = exports.stepInputPatchSchema = exports.testFlowSchema = exports.createFlowSchema = exports.copyFlowSchema = exports.publishFlowSchema = exports.viewActionSchema = exports.viewFlowSchema = exports.removeChoicesFromFieldSchema = exports.addChoicesToFieldSchema = exports.choiceValueSchema = exports.setRelatedListsSchema = exports.setFormLayoutSchema = exports.formSectionSchema = exports.setListLayoutSchema = exports.createViewSchema = void 0;
|
|
8
8
|
const zod_1 = require("zod");
|
|
9
9
|
exports.createViewSchema = zod_1.z.object({
|
|
10
10
|
name: zod_1.z.string().min(1),
|
|
@@ -368,10 +368,23 @@ exports.addColumnSchema = zod_1.z.object({
|
|
|
368
368
|
// scope (a Journey field on an Automate table). Without it a mismatched scope is
|
|
369
369
|
// refused — on dryRun and live alike — because that is the classic wrong-scope slip.
|
|
370
370
|
crossScope: zod_1.z.boolean().optional(),
|
|
371
|
+
// Cross-scope only: create the missing sys_scope_design_access record (scope -> the
|
|
372
|
+
// table's scope) first, in the same update set. Without it a missing record is flagged.
|
|
373
|
+
ensureDesignAccess: zod_1.z.boolean().optional(),
|
|
371
374
|
updateSetSysId: zod_1.z.string().optional(),
|
|
372
375
|
dryRun: zod_1.z.boolean().optional(),
|
|
373
376
|
debug: zod_1.z.boolean().optional(),
|
|
374
377
|
});
|
|
378
|
+
// design_access: ensure the sys_scope_design_access record that lets sourceScope author
|
|
379
|
+
// in targetScope's tables. updateSetSysId (an update set in sourceScope) is optional in
|
|
380
|
+
// the schema because dryRun needs none; the live-path requirement is enforced at the tool
|
|
381
|
+
// boundary (registry.ts), matching add_column.
|
|
382
|
+
exports.designAccessSchema = zod_1.z.object({
|
|
383
|
+
sourceScope: zod_1.z.string().min(1),
|
|
384
|
+
targetScope: zod_1.z.string().min(1),
|
|
385
|
+
updateSetSysId: zod_1.z.string().optional(),
|
|
386
|
+
dryRun: zod_1.z.boolean().optional(),
|
|
387
|
+
});
|
|
375
388
|
// add-index keeps a column LIST because an index is conceptually multi-column, but the
|
|
376
389
|
// only headless lever (sys_dictionary.unique) is per-COLUMN — so addIndex REFUSES a list
|
|
377
390
|
// longer than one rather than silently building a different index than the one asked for.
|
|
@@ -34,6 +34,14 @@
|
|
|
34
34
|
* is accepted as-is) and the element ServiceNow actually stored is read back and
|
|
35
35
|
* reported, together with a `sys_scope` assertion on the read-back row.
|
|
36
36
|
*
|
|
37
|
+
* DESIGN ACCESS. Since the Zurich bw40 hotfix the platform UI also requires a
|
|
38
|
+
* `sys_scope_design_access` record (source = the column's scope, target = the table's)
|
|
39
|
+
* before one app may author in another's tables. The headless insert here does not hit
|
|
40
|
+
* that check, so a missing record does not block the column — but it is FLAGGED on every
|
|
41
|
+
* cross-scope result (`designAccess`), because the next UI edit of the column, and the
|
|
42
|
+
* target instance, will. `ensureDesignAccess: true` creates it first, in the same update
|
|
43
|
+
* set (see ./designAccess.ts).
|
|
44
|
+
*
|
|
37
45
|
* SIZING THE PHYSICAL COLUMN. A max_length carried on the INSERT sets the dictionary
|
|
38
46
|
* row but NOT the column ServiceNow actually builds — it materialises at the platform
|
|
39
47
|
* default regardless. An insert declaring string(4000) therefore leaves a varchar(255)
|
|
@@ -74,6 +82,12 @@ export interface AddColumnParams {
|
|
|
74
82
|
* and the update set must belong to the column's scope.
|
|
75
83
|
*/
|
|
76
84
|
crossScope?: boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Cross-scope only: create the sys_scope_design_access record (column scope -> table
|
|
87
|
+
* scope) when it is missing, captured in the same update set, BEFORE the column insert.
|
|
88
|
+
* Without it a missing record is only flagged on the result.
|
|
89
|
+
*/
|
|
90
|
+
ensureDesignAccess?: boolean;
|
|
77
91
|
/** Update set sys_id to capture the insert into. REQUIRED on the live path (dry-run doesn't need it). */
|
|
78
92
|
updateSetSysId?: string;
|
|
79
93
|
/** Emit diagnostic detail in the result note. */
|
|
@@ -81,6 +95,21 @@ export interface AddColumnParams {
|
|
|
81
95
|
/** Plan only — no writes. Pure + deterministic. */
|
|
82
96
|
dryRun?: boolean;
|
|
83
97
|
}
|
|
98
|
+
/** Design Access state for a cross-scope column (absent on a same-scope add). */
|
|
99
|
+
export interface DesignAccessFlag {
|
|
100
|
+
/** Always true when reported: a cross-scope column needs the record for UI/Studio work. */
|
|
101
|
+
required: true;
|
|
102
|
+
/** true = record exists (or was created); false = missing; null = could not be read. */
|
|
103
|
+
present: boolean | null;
|
|
104
|
+
/** sys_scope_design_access sys_id ("" when missing / unknown). */
|
|
105
|
+
sysId: string;
|
|
106
|
+
/** Authoring scope (the column's owner). */
|
|
107
|
+
sourceScope: string;
|
|
108
|
+
/** Table-owning scope. */
|
|
109
|
+
targetScope: string;
|
|
110
|
+
/** True when THIS run created the record. */
|
|
111
|
+
created: boolean;
|
|
112
|
+
}
|
|
84
113
|
export interface AddColumnResult {
|
|
85
114
|
status: "created" | "dry-run" | "failed" | "skipped";
|
|
86
115
|
/** The table's name (resolved; echoes the input on dry-run). */
|
|
@@ -106,6 +135,8 @@ export interface AddColumnResult {
|
|
|
106
135
|
verified: boolean;
|
|
107
136
|
/** Human-readable note (success summary, the read-back result, or the failure body). */
|
|
108
137
|
note: string;
|
|
138
|
+
/** Cross-scope only: whether the Design Access record the platform UI requires exists. */
|
|
139
|
+
designAccess?: DesignAccessFlag;
|
|
109
140
|
}
|
|
110
141
|
/**
|
|
111
142
|
* Derive the dictionary element (column name) from a label the way Studio does for
|
|
@@ -114,4 +145,9 @@ export interface AddColumnResult {
|
|
|
114
145
|
* Pass `column.name` explicitly for anything non-trivial.
|
|
115
146
|
*/
|
|
116
147
|
export declare function deriveElement(label: string, explicit?: string): string;
|
|
148
|
+
/**
|
|
149
|
+
* The Design Access sentence appended to a cross-scope result's note ("" when none).
|
|
150
|
+
* Exported for tests.
|
|
151
|
+
*/
|
|
152
|
+
export declare function designAccessNote(da: DesignAccessFlag | undefined, ensureRequested: boolean, isDryRun: boolean): string;
|
|
117
153
|
export declare function addColumn(params: AddColumnParams): Promise<AddColumnResult>;
|
package/dist/table/addColumn.js
CHANGED
|
@@ -35,6 +35,14 @@
|
|
|
35
35
|
* is accepted as-is) and the element ServiceNow actually stored is read back and
|
|
36
36
|
* reported, together with a `sys_scope` assertion on the read-back row.
|
|
37
37
|
*
|
|
38
|
+
* DESIGN ACCESS. Since the Zurich bw40 hotfix the platform UI also requires a
|
|
39
|
+
* `sys_scope_design_access` record (source = the column's scope, target = the table's)
|
|
40
|
+
* before one app may author in another's tables. The headless insert here does not hit
|
|
41
|
+
* that check, so a missing record does not block the column — but it is FLAGGED on every
|
|
42
|
+
* cross-scope result (`designAccess`), because the next UI edit of the column, and the
|
|
43
|
+
* target instance, will. `ensureDesignAccess: true` creates it first, in the same update
|
|
44
|
+
* set (see ./designAccess.ts).
|
|
45
|
+
*
|
|
38
46
|
* SIZING THE PHYSICAL COLUMN. A max_length carried on the INSERT sets the dictionary
|
|
39
47
|
* row but NOT the column ServiceNow actually builds — it materialises at the platform
|
|
40
48
|
* default regardless. An insert declaring string(4000) therefore leaves a varchar(255)
|
|
@@ -55,9 +63,11 @@
|
|
|
55
63
|
*/
|
|
56
64
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
57
65
|
exports.deriveElement = deriveElement;
|
|
66
|
+
exports.designAccessNote = designAccessNote;
|
|
58
67
|
exports.addColumn = addColumn;
|
|
59
68
|
const setField_1 = require("../setField");
|
|
60
69
|
const buildTableSave_1 = require("./buildTableSave");
|
|
70
|
+
const designAccess_1 = require("./designAccess");
|
|
61
71
|
var SYS_ID = /^[0-9a-f]{32}$/i;
|
|
62
72
|
/** Patch dependent_on_field on a sys_dictionary row, captured in the given update set. */
|
|
63
73
|
async function setDependentOnField(client, columnSysId, updateSetSysId, dependentOnField) {
|
|
@@ -262,12 +272,35 @@ async function planColumnScope(client, params, element) {
|
|
|
262
272
|
// element; an already-prefixed name is accepted as-is.
|
|
263
273
|
var prefix = owner.name + "_";
|
|
264
274
|
var prefixed = element.indexOf(prefix) === 0 ? element : prefix + element;
|
|
275
|
+
// Flag — never block on — the Design Access record the platform UI requires. A read
|
|
276
|
+
// failure is reported as UNKNOWN (null), not as missing: a blind check is not evidence.
|
|
277
|
+
var present = null;
|
|
278
|
+
var daSysId = "";
|
|
279
|
+
try {
|
|
280
|
+
daSysId = await (0, designAccess_1.findDesignAccess)({
|
|
281
|
+
client: client,
|
|
282
|
+
sourceScopeSysId: owner.sysId,
|
|
283
|
+
targetScopeSysId: resolved.scopeSysId,
|
|
284
|
+
});
|
|
285
|
+
present = daSysId !== "";
|
|
286
|
+
}
|
|
287
|
+
catch (e) {
|
|
288
|
+
present = null;
|
|
289
|
+
}
|
|
265
290
|
return {
|
|
266
291
|
resolved: resolved,
|
|
267
292
|
scopeName: owner.name,
|
|
268
293
|
scopeSysId: owner.sysId,
|
|
269
294
|
crossScope: true,
|
|
270
295
|
element: prefixed,
|
|
296
|
+
designAccess: {
|
|
297
|
+
required: true,
|
|
298
|
+
present: present,
|
|
299
|
+
sysId: daSysId,
|
|
300
|
+
sourceScope: owner.name,
|
|
301
|
+
targetScope: tableScopeName,
|
|
302
|
+
created: false,
|
|
303
|
+
},
|
|
271
304
|
};
|
|
272
305
|
}
|
|
273
306
|
/** Resolve a sys_scope sys_id to its scope NAME (e.g. "x_cadso_core"). */
|
|
@@ -277,7 +310,58 @@ async function resolveScopeName(client, scopeSysId) {
|
|
|
277
310
|
var rows = await client.table.query("sys_scope", "sys_id=" + scopeSysId, { limit: 1, fields: ["scope"] });
|
|
278
311
|
return rows.length > 0 ? (0, setField_1.fieldToString)(rows[0].scope) : "";
|
|
279
312
|
}
|
|
313
|
+
/**
|
|
314
|
+
* The Design Access sentence appended to a cross-scope result's note ("" when none).
|
|
315
|
+
* Exported for tests.
|
|
316
|
+
*/
|
|
317
|
+
function designAccessNote(da, ensureRequested, isDryRun) {
|
|
318
|
+
if (!da)
|
|
319
|
+
return "";
|
|
320
|
+
var pair = "'" + da.sourceScope + "' -> '" + da.targetScope + "'";
|
|
321
|
+
if (da.created) {
|
|
322
|
+
return (" Design Access " +
|
|
323
|
+
pair +
|
|
324
|
+
" was created (sys_scope_design_access " +
|
|
325
|
+
da.sysId +
|
|
326
|
+
").");
|
|
327
|
+
}
|
|
328
|
+
if (da.present === true) {
|
|
329
|
+
return (" Design Access " +
|
|
330
|
+
pair +
|
|
331
|
+
" is present (sys_scope_design_access " +
|
|
332
|
+
da.sysId +
|
|
333
|
+
").");
|
|
334
|
+
}
|
|
335
|
+
var state = da.present === null
|
|
336
|
+
? "could NOT be read (sys_scope_design_access query failed) — check it on the instance"
|
|
337
|
+
: "is MISSING";
|
|
338
|
+
if (isDryRun && ensureRequested && da.present === false) {
|
|
339
|
+
return (" DESIGN ACCESS REQUIRED: " +
|
|
340
|
+
pair +
|
|
341
|
+
" " +
|
|
342
|
+
state +
|
|
343
|
+
" — would create it first, in the same update set.");
|
|
344
|
+
}
|
|
345
|
+
return (" DESIGN ACCESS REQUIRED: " +
|
|
346
|
+
pair +
|
|
347
|
+
" " +
|
|
348
|
+
state +
|
|
349
|
+
". The headless insert does not need it, but UI/Studio edits of this column and the " +
|
|
350
|
+
"target instance will refuse it — re-run with --ensure-design-access (MCP: " +
|
|
351
|
+
"ensureDesignAccess:true) or create it with dove-sn design-access.");
|
|
352
|
+
}
|
|
280
353
|
async function addColumn(params) {
|
|
354
|
+
var daOut = {};
|
|
355
|
+
var result = await addColumnInner(params, daOut);
|
|
356
|
+
// The dry-run path attaches its own flag + note; every live return is decorated here so
|
|
357
|
+
// no exit path (created / skipped / any failure) can drop the flag.
|
|
358
|
+
if (!result.designAccess && daOut.value) {
|
|
359
|
+
result.designAccess = daOut.value;
|
|
360
|
+
result.note += designAccessNote(daOut.value, params.ensureDesignAccess === true, false);
|
|
361
|
+
}
|
|
362
|
+
return result;
|
|
363
|
+
}
|
|
364
|
+
async function addColumnInner(params, daOut) {
|
|
281
365
|
validate(params);
|
|
282
366
|
var client = params.client;
|
|
283
367
|
// Normalize the single column (validates label, resolves the friendly type to an
|
|
@@ -323,7 +407,8 @@ async function addColumn(params) {
|
|
|
323
407
|
: SYS_ID.test(params.table)
|
|
324
408
|
? params.table
|
|
325
409
|
: "";
|
|
326
|
-
|
|
410
|
+
var dryDa = planned ? planned.designAccess : undefined;
|
|
411
|
+
var dryResult = {
|
|
327
412
|
status: "dry-run",
|
|
328
413
|
table: planTable,
|
|
329
414
|
tableSysId: planTableSysId,
|
|
@@ -353,8 +438,12 @@ async function addColumn(params) {
|
|
|
353
438
|
wantDependent +
|
|
354
439
|
"' (which must already exist on the table)"
|
|
355
440
|
: "") +
|
|
356
|
-
", then read it back."
|
|
441
|
+
", then read it back." +
|
|
442
|
+
designAccessNote(dryDa, params.ensureDesignAccess === true, true),
|
|
357
443
|
};
|
|
444
|
+
if (dryDa)
|
|
445
|
+
dryResult.designAccess = dryDa;
|
|
446
|
+
return dryResult;
|
|
358
447
|
}
|
|
359
448
|
// ---- LIVE PATH ------------------------------------------------------------
|
|
360
449
|
// Require an explicit update set so the schema change is captured in a KNOWN
|
|
@@ -370,6 +459,34 @@ async function addColumn(params) {
|
|
|
370
459
|
var resolved = plan.resolved;
|
|
371
460
|
var scopeName = plan.scopeName;
|
|
372
461
|
element = plan.element;
|
|
462
|
+
// Create the missing Design Access record FIRST when asked — nothing about the column
|
|
463
|
+
// has been written yet, so a failure here stops cleanly with the instance untouched
|
|
464
|
+
// (or, if the record landed but did not verify, says exactly that).
|
|
465
|
+
var da = plan.designAccess;
|
|
466
|
+
if (da && da.present !== true && params.ensureDesignAccess === true) {
|
|
467
|
+
var ensured = await (0, designAccess_1.ensureDesignAccess)({
|
|
468
|
+
client: client,
|
|
469
|
+
sourceScope: da.sourceScope,
|
|
470
|
+
targetScope: da.targetScope,
|
|
471
|
+
updateSetSysId: params.updateSetSysId,
|
|
472
|
+
});
|
|
473
|
+
da = {
|
|
474
|
+
required: true,
|
|
475
|
+
present: ensured.present,
|
|
476
|
+
sysId: ensured.sysId,
|
|
477
|
+
sourceScope: da.sourceScope,
|
|
478
|
+
targetScope: da.targetScope,
|
|
479
|
+
created: ensured.status === "created",
|
|
480
|
+
};
|
|
481
|
+
if (ensured.status === "failed") {
|
|
482
|
+
var daFail = failure(resolved, col, element, params.updateSetSysId, "Design Access could not be ensured, so the column was NOT added: " +
|
|
483
|
+
ensured.note, undefined, scopeName);
|
|
484
|
+
daFail.designAccess = da;
|
|
485
|
+
return daFail;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
if (da)
|
|
489
|
+
daOut.value = da;
|
|
373
490
|
// max_length is deliberately NOT sent on the insert — see the sizing step below.
|
|
374
491
|
// Reference (and date) columns carry no max_length at all.
|
|
375
492
|
var wantLength = col.type === "reference" ? "" : col.maxLength;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-scope DESIGN ACCESS — the `sys_scope_design_access` record that lets one app
|
|
3
|
+
* author (design) inside another app's tables.
|
|
4
|
+
*
|
|
5
|
+
* Why this exists: since the Zurich bw40 hotfix (tenonworkstudio, 2026-10-04), creating a
|
|
6
|
+
* column from app S on a table owned by app T through the platform UI / Studio fails with
|
|
7
|
+
*
|
|
8
|
+
* Invalid 'Table' selected on the Dictionary Entry record. The '<table>' table is in
|
|
9
|
+
* application '<T>', but the current application is '<S>'. The 'Table' field can only
|
|
10
|
+
* select '<T>' tables with read access enabled.
|
|
11
|
+
*
|
|
12
|
+
* even when the table's own Application Access flags (read / alter / configuration) are
|
|
13
|
+
* all on. The fix is a Design Access record: source_scope = S (the authoring app),
|
|
14
|
+
* target_package = T (the app that owns the table), owned by — and captured in an update
|
|
15
|
+
* set of — S. Without it the column can still be inserted headless (the scope-aware
|
|
16
|
+
* createRecord op does not hit the UI check), but the next person to open that column in
|
|
17
|
+
* the UI, and the target instance's checks, trip over it. So add-column --cross-scope FLAGS
|
|
18
|
+
* a missing record and can create it; this module is that check + create.
|
|
19
|
+
*
|
|
20
|
+
* Read-back discipline matches add-column: a created record is read back by the returned
|
|
21
|
+
* sys_id and its source/target asserted before it is called verified. ES6 only, no
|
|
22
|
+
* optional chaining, no `any`.
|
|
23
|
+
*/
|
|
24
|
+
import type { ServiceNowClient } from "../client";
|
|
25
|
+
export declare var DESIGN_ACCESS_TABLE: string;
|
|
26
|
+
export interface ResolvedScopeRef {
|
|
27
|
+
/** Scope NAME (e.g. "x_cadso_journey"). */
|
|
28
|
+
name: string;
|
|
29
|
+
/** sys_scope sys_id. */
|
|
30
|
+
sysId: string;
|
|
31
|
+
}
|
|
32
|
+
/** Resolve a scope by NAME or sys_id; empty strings when not found. */
|
|
33
|
+
export declare function resolveScopeRef(client: ServiceNowClient, scope: string): Promise<ResolvedScopeRef>;
|
|
34
|
+
/**
|
|
35
|
+
* Find the Design Access record granting `sourceScopeSysId` design access to
|
|
36
|
+
* `targetScopeSysId`'s tables. Returns its sys_id, or "" when there is none.
|
|
37
|
+
*/
|
|
38
|
+
export declare function findDesignAccess(params: {
|
|
39
|
+
client: ServiceNowClient;
|
|
40
|
+
sourceScopeSysId: string;
|
|
41
|
+
targetScopeSysId: string;
|
|
42
|
+
}): Promise<string>;
|
|
43
|
+
export interface EnsureDesignAccessParams {
|
|
44
|
+
client: ServiceNowClient;
|
|
45
|
+
/** The AUTHORING app — scope name or sys_scope sys_id (e.g. "x_cadso_journey"). */
|
|
46
|
+
sourceScope: string;
|
|
47
|
+
/** The app that OWNS the tables — scope name or sys_scope sys_id (e.g. "x_cadso_automate"). */
|
|
48
|
+
targetScope: string;
|
|
49
|
+
/** Update set (in the SOURCE scope) to capture the record in. Required on the live path. */
|
|
50
|
+
updateSetSysId?: string;
|
|
51
|
+
/** Report whether the record exists / would be created — no writes. */
|
|
52
|
+
dryRun?: boolean;
|
|
53
|
+
}
|
|
54
|
+
export interface EnsureDesignAccessResult {
|
|
55
|
+
status: "exists" | "created" | "dry-run" | "failed";
|
|
56
|
+
/** Source (authoring) scope name. */
|
|
57
|
+
sourceScope: string;
|
|
58
|
+
/** Target (table-owning) scope name. */
|
|
59
|
+
targetScope: string;
|
|
60
|
+
/** The Design Access record's sys_id ("" when absent on dry-run, or on failure before insert). */
|
|
61
|
+
sysId: string;
|
|
62
|
+
/** True when the record is present: found, or created and read back. */
|
|
63
|
+
present: boolean;
|
|
64
|
+
/** Update set the create was captured into ("" when nothing was written). */
|
|
65
|
+
updateSetSysId: string;
|
|
66
|
+
note: string;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Make sure `sourceScope` has design access to `targetScope`'s tables. Idempotent: an
|
|
70
|
+
* existing record is reported ("exists") and nothing is written. Dry-run reports whether
|
|
71
|
+
* it exists or would be created. Live creates it through the scope-aware createRecord op
|
|
72
|
+
* switched to the SOURCE scope, captured in `updateSetSysId` (which must belong to the
|
|
73
|
+
* source scope), then reads it back.
|
|
74
|
+
*/
|
|
75
|
+
export declare function ensureDesignAccess(params: EnsureDesignAccessParams): Promise<EnsureDesignAccessResult>;
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Cross-scope DESIGN ACCESS — the `sys_scope_design_access` record that lets one app
|
|
4
|
+
* author (design) inside another app's tables.
|
|
5
|
+
*
|
|
6
|
+
* Why this exists: since the Zurich bw40 hotfix (tenonworkstudio, 2026-10-04), creating a
|
|
7
|
+
* column from app S on a table owned by app T through the platform UI / Studio fails with
|
|
8
|
+
*
|
|
9
|
+
* Invalid 'Table' selected on the Dictionary Entry record. The '<table>' table is in
|
|
10
|
+
* application '<T>', but the current application is '<S>'. The 'Table' field can only
|
|
11
|
+
* select '<T>' tables with read access enabled.
|
|
12
|
+
*
|
|
13
|
+
* even when the table's own Application Access flags (read / alter / configuration) are
|
|
14
|
+
* all on. The fix is a Design Access record: source_scope = S (the authoring app),
|
|
15
|
+
* target_package = T (the app that owns the table), owned by — and captured in an update
|
|
16
|
+
* set of — S. Without it the column can still be inserted headless (the scope-aware
|
|
17
|
+
* createRecord op does not hit the UI check), but the next person to open that column in
|
|
18
|
+
* the UI, and the target instance's checks, trip over it. So add-column --cross-scope FLAGS
|
|
19
|
+
* a missing record and can create it; this module is that check + create.
|
|
20
|
+
*
|
|
21
|
+
* Read-back discipline matches add-column: a created record is read back by the returned
|
|
22
|
+
* sys_id and its source/target asserted before it is called verified. ES6 only, no
|
|
23
|
+
* optional chaining, no `any`.
|
|
24
|
+
*/
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.DESIGN_ACCESS_TABLE = void 0;
|
|
27
|
+
exports.resolveScopeRef = resolveScopeRef;
|
|
28
|
+
exports.findDesignAccess = findDesignAccess;
|
|
29
|
+
exports.ensureDesignAccess = ensureDesignAccess;
|
|
30
|
+
const setField_1 = require("../setField");
|
|
31
|
+
var SYS_ID = /^[0-9a-f]{32}$/i;
|
|
32
|
+
var SCOPE_NAME = /^[a-z0-9_]+$/i;
|
|
33
|
+
/** Safe to splice into an encoded query: no ^, =, spaces or other operators. */
|
|
34
|
+
var SAFE_ID = /^[0-9a-z_]+$/i;
|
|
35
|
+
exports.DESIGN_ACCESS_TABLE = "sys_scope_design_access";
|
|
36
|
+
/** Resolve a scope by NAME or sys_id; empty strings when not found. */
|
|
37
|
+
async function resolveScopeRef(client, scope) {
|
|
38
|
+
var s = String(scope || "").trim();
|
|
39
|
+
if (!s)
|
|
40
|
+
return { name: "", sysId: "" };
|
|
41
|
+
if (!SYS_ID.test(s) && !SCOPE_NAME.test(s)) {
|
|
42
|
+
throw new Error("design-access: '" + s + "' is not a scope name or sys_scope sys_id.");
|
|
43
|
+
}
|
|
44
|
+
var rows = await client.table.query("sys_scope", SYS_ID.test(s) ? "sys_id=" + s : "scope=" + s, { limit: 1, fields: ["sys_id", "scope"] });
|
|
45
|
+
if (rows.length === 0)
|
|
46
|
+
return { name: "", sysId: "" };
|
|
47
|
+
return {
|
|
48
|
+
name: (0, setField_1.fieldToString)(rows[0].scope),
|
|
49
|
+
sysId: (0, setField_1.fieldToString)(rows[0].sys_id),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Find the Design Access record granting `sourceScopeSysId` design access to
|
|
54
|
+
* `targetScopeSysId`'s tables. Returns its sys_id, or "" when there is none.
|
|
55
|
+
*/
|
|
56
|
+
async function findDesignAccess(params) {
|
|
57
|
+
// Both ids are spliced into an encoded query — refuse anything that could carry a
|
|
58
|
+
// query operator (^, =, spaces) rather than querying on it.
|
|
59
|
+
if (!SAFE_ID.test(params.sourceScopeSysId) ||
|
|
60
|
+
!SAFE_ID.test(params.targetScopeSysId)) {
|
|
61
|
+
return "";
|
|
62
|
+
}
|
|
63
|
+
var rows = await params.client.table.query(exports.DESIGN_ACCESS_TABLE, "source_scope=" +
|
|
64
|
+
params.sourceScopeSysId +
|
|
65
|
+
"^target_package=" +
|
|
66
|
+
params.targetScopeSysId, { limit: 1, fields: ["sys_id"] });
|
|
67
|
+
return rows.length > 0 ? (0, setField_1.fieldToString)(rows[0].sys_id) : "";
|
|
68
|
+
}
|
|
69
|
+
/** Resolve both scopes, refusing unknown or identical ones. Shared by dry-run and live. */
|
|
70
|
+
async function resolvePair(params) {
|
|
71
|
+
if (!params || typeof params !== "object")
|
|
72
|
+
throw new Error("design-access: params object required.");
|
|
73
|
+
if (!params.client)
|
|
74
|
+
throw new Error("design-access: client is required.");
|
|
75
|
+
if (!params.sourceScope || !String(params.sourceScope).trim())
|
|
76
|
+
throw new Error("design-access: sourceScope (the authoring app) is required.");
|
|
77
|
+
if (!params.targetScope || !String(params.targetScope).trim())
|
|
78
|
+
throw new Error("design-access: targetScope (the app that owns the tables) is required.");
|
|
79
|
+
var source = await resolveScopeRef(params.client, params.sourceScope);
|
|
80
|
+
if (!source.sysId)
|
|
81
|
+
throw new Error("design-access: source scope '" +
|
|
82
|
+
params.sourceScope +
|
|
83
|
+
"' was not found in sys_scope.");
|
|
84
|
+
var target = await resolveScopeRef(params.client, params.targetScope);
|
|
85
|
+
if (!target.sysId)
|
|
86
|
+
throw new Error("design-access: target scope '" +
|
|
87
|
+
params.targetScope +
|
|
88
|
+
"' was not found in sys_scope.");
|
|
89
|
+
if (source.sysId === target.sysId)
|
|
90
|
+
throw new Error("design-access: source and target are the same scope ('" +
|
|
91
|
+
source.name +
|
|
92
|
+
"') — an app needs no design access to its own tables.");
|
|
93
|
+
return { source: source, target: target };
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Make sure `sourceScope` has design access to `targetScope`'s tables. Idempotent: an
|
|
97
|
+
* existing record is reported ("exists") and nothing is written. Dry-run reports whether
|
|
98
|
+
* it exists or would be created. Live creates it through the scope-aware createRecord op
|
|
99
|
+
* switched to the SOURCE scope, captured in `updateSetSysId` (which must belong to the
|
|
100
|
+
* source scope), then reads it back.
|
|
101
|
+
*/
|
|
102
|
+
async function ensureDesignAccess(params) {
|
|
103
|
+
var pair = await resolvePair(params);
|
|
104
|
+
var client = params.client;
|
|
105
|
+
var label = "'" + pair.source.name + "' -> '" + pair.target.name + "'";
|
|
106
|
+
var existing = await findDesignAccess({
|
|
107
|
+
client: client,
|
|
108
|
+
sourceScopeSysId: pair.source.sysId,
|
|
109
|
+
targetScopeSysId: pair.target.sysId,
|
|
110
|
+
});
|
|
111
|
+
var base = {
|
|
112
|
+
sourceScope: pair.source.name,
|
|
113
|
+
targetScope: pair.target.name,
|
|
114
|
+
};
|
|
115
|
+
if (existing) {
|
|
116
|
+
return {
|
|
117
|
+
status: "exists",
|
|
118
|
+
sourceScope: base.sourceScope,
|
|
119
|
+
targetScope: base.targetScope,
|
|
120
|
+
sysId: existing,
|
|
121
|
+
present: true,
|
|
122
|
+
updateSetSysId: "",
|
|
123
|
+
note: "Design Access " +
|
|
124
|
+
label +
|
|
125
|
+
" already exists (" +
|
|
126
|
+
exports.DESIGN_ACCESS_TABLE +
|
|
127
|
+
" " +
|
|
128
|
+
existing +
|
|
129
|
+
") — nothing to do.",
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
var us = params.updateSetSysId ? params.updateSetSysId.trim() : "";
|
|
133
|
+
if (us) {
|
|
134
|
+
if (!SAFE_ID.test(us))
|
|
135
|
+
throw new Error("design-access: update set '" + us + "' is not a sys_id.");
|
|
136
|
+
var usRows = await client.table.query("sys_update_set", "sys_id=" + us, { limit: 1, fields: ["sys_id", "name", "application"] });
|
|
137
|
+
if (usRows.length === 0)
|
|
138
|
+
throw new Error("design-access: update set '" +
|
|
139
|
+
us +
|
|
140
|
+
"' was not found in sys_update_set.");
|
|
141
|
+
if ((0, setField_1.fieldToString)(usRows[0].application) !== pair.source.sysId) {
|
|
142
|
+
throw new Error("design-access: update set '" +
|
|
143
|
+
((0, setField_1.fieldToString)(usRows[0].name) || us) +
|
|
144
|
+
"' does not belong to the source scope '" +
|
|
145
|
+
pair.source.name +
|
|
146
|
+
"' — the Design Access record is owned by the AUTHORING app and ships in its " +
|
|
147
|
+
"update set. Pass an update set in '" +
|
|
148
|
+
pair.source.name +
|
|
149
|
+
"'.");
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (params.dryRun) {
|
|
153
|
+
return {
|
|
154
|
+
status: "dry-run",
|
|
155
|
+
sourceScope: base.sourceScope,
|
|
156
|
+
targetScope: base.targetScope,
|
|
157
|
+
sysId: "",
|
|
158
|
+
present: false,
|
|
159
|
+
updateSetSysId: us,
|
|
160
|
+
note: "dry-run: no write. Design Access " +
|
|
161
|
+
label +
|
|
162
|
+
" is MISSING — would create it in scope '" +
|
|
163
|
+
pair.source.name +
|
|
164
|
+
"', captured into update set " +
|
|
165
|
+
(us || "(none provided — required on the live path)") +
|
|
166
|
+
", then read it back.",
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
if (!us) {
|
|
170
|
+
throw new Error("design-access: updateSetSysId is required on the live path so the record is " +
|
|
171
|
+
"captured in a known update set of the source scope (dry-run does not need one).");
|
|
172
|
+
}
|
|
173
|
+
var created;
|
|
174
|
+
try {
|
|
175
|
+
created = await client.claude.createRecord({
|
|
176
|
+
table: exports.DESIGN_ACCESS_TABLE,
|
|
177
|
+
fields: {
|
|
178
|
+
source_scope: pair.source.sysId,
|
|
179
|
+
target_package: pair.target.sysId,
|
|
180
|
+
},
|
|
181
|
+
scope: pair.source.name,
|
|
182
|
+
update_set_sys_id: us,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
catch (e) {
|
|
186
|
+
return failed(base, us, "", "insert failed: " + errText(e));
|
|
187
|
+
}
|
|
188
|
+
var newSysId = (0, setField_1.fieldToString)(created && created.sys_id);
|
|
189
|
+
if (!newSysId) {
|
|
190
|
+
return failed(base, us, "", "createRecord returned no sys_id — the insert may not have landed; check the instance.");
|
|
191
|
+
}
|
|
192
|
+
var rows;
|
|
193
|
+
try {
|
|
194
|
+
rows = await client.table.query(exports.DESIGN_ACCESS_TABLE, "sys_id=" + newSysId, { limit: 1, fields: ["sys_id", "source_scope", "target_package"] });
|
|
195
|
+
}
|
|
196
|
+
catch (e) {
|
|
197
|
+
return failed(base, us, newSysId, "record created but the read-back failed: " + errText(e));
|
|
198
|
+
}
|
|
199
|
+
if (rows.length === 0) {
|
|
200
|
+
return failed(base, us, newSysId, "createRecord returned " +
|
|
201
|
+
newSysId +
|
|
202
|
+
" but no record was found on read-back.");
|
|
203
|
+
}
|
|
204
|
+
var gotSource = (0, setField_1.fieldToString)(rows[0].source_scope);
|
|
205
|
+
var gotTarget = (0, setField_1.fieldToString)(rows[0].target_package);
|
|
206
|
+
if (gotSource !== pair.source.sysId || gotTarget !== pair.target.sysId) {
|
|
207
|
+
return failed(base, us, newSysId, "record " +
|
|
208
|
+
newSysId +
|
|
209
|
+
" read back as source_scope '" +
|
|
210
|
+
(gotSource || "(empty)") +
|
|
211
|
+
"' / target_package '" +
|
|
212
|
+
(gotTarget || "(empty)") +
|
|
213
|
+
"', not the requested '" +
|
|
214
|
+
pair.source.sysId +
|
|
215
|
+
"' / '" +
|
|
216
|
+
pair.target.sysId +
|
|
217
|
+
"'. Fix or delete it on the instance.");
|
|
218
|
+
}
|
|
219
|
+
return {
|
|
220
|
+
status: "created",
|
|
221
|
+
sourceScope: base.sourceScope,
|
|
222
|
+
targetScope: base.targetScope,
|
|
223
|
+
sysId: newSysId,
|
|
224
|
+
present: true,
|
|
225
|
+
updateSetSysId: us,
|
|
226
|
+
note: "Created Design Access " +
|
|
227
|
+
label +
|
|
228
|
+
" (" +
|
|
229
|
+
exports.DESIGN_ACCESS_TABLE +
|
|
230
|
+
" " +
|
|
231
|
+
newSysId +
|
|
232
|
+
") — verified on read-back, captured into update set " +
|
|
233
|
+
us +
|
|
234
|
+
".",
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
function errText(e) {
|
|
238
|
+
return e && e.message ? e.message : String(e);
|
|
239
|
+
}
|
|
240
|
+
function failed(base, updateSetSysId, sysId, note) {
|
|
241
|
+
return {
|
|
242
|
+
status: "failed",
|
|
243
|
+
sourceScope: base.sourceScope,
|
|
244
|
+
targetScope: base.targetScope,
|
|
245
|
+
sysId: sysId,
|
|
246
|
+
present: false,
|
|
247
|
+
updateSetSysId: updateSetSysId,
|
|
248
|
+
note: "design-access: " + note,
|
|
249
|
+
};
|
|
250
|
+
}
|
package/dist/table/index.d.ts
CHANGED
|
@@ -12,7 +12,9 @@ export type { ColumnSpec, AccessFlags, OverlaySpec } from "./buildTableSave";
|
|
|
12
12
|
export { resolveFormAuth, openFormSession, setCurrentApplication, getRecordForm, getNewRecordForm, getWithSession, getFormPage, parseFormInputs, postForm, scrapeCk, decodeHtmlEntities, } from "./formSession";
|
|
13
13
|
export type { FormAuth, FormSession, HarvestedForm, FetchedFormPage, PostResult, } from "./formSession";
|
|
14
14
|
export { addColumn, deriveElement } from "./addColumn";
|
|
15
|
-
export type { AddColumnParams, AddColumnResult } from "./addColumn";
|
|
15
|
+
export type { AddColumnParams, AddColumnResult, DesignAccessFlag } from "./addColumn";
|
|
16
|
+
export { ensureDesignAccess, findDesignAccess, resolveScopeRef, DESIGN_ACCESS_TABLE, } from "./designAccess";
|
|
17
|
+
export type { EnsureDesignAccessParams, EnsureDesignAccessResult, ResolvedScopeRef, } from "./designAccess";
|
|
16
18
|
export { addIndex, scanForDuplicates, parseIndexColumns, indexMatchesColumns, } from "./addIndex";
|
|
17
19
|
export type { AddIndexParams, AddIndexResult, AddIndexVerification, DuplicateScan, DuplicateValue, } from "./addIndex";
|
|
18
20
|
export { listIndexes, assertTableName } from "./listIndexes";
|
package/dist/table/index.js
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* live-validation caveat.
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.
|
|
9
|
-
exports.resolveTableAttributes = exports.setTable = exports.labelUpdateName = exports.overrideUpdateName = exports.applyInheritedWrites = void 0;
|
|
8
|
+
exports.resolveTableScope = exports.explainMaxLengthNotOverridable = exports.LABEL_LANGUAGE = exports.OVERRIDABLE = exports.findTruncationRisk = exports.toStoredValue = exports.resolveAttributes = exports.setColumn = exports.NOT_IN_UPDATE_SET = exports.DEFAULT_INDEX_FORM_PATH = exports.validateCreateIndex = exports.createIndex = exports.assertTableName = exports.listIndexes = exports.indexMatchesColumns = exports.parseIndexColumns = exports.scanForDuplicates = exports.addIndex = exports.DESIGN_ACCESS_TABLE = exports.resolveScopeRef = exports.findDesignAccess = exports.ensureDesignAccess = exports.deriveElement = exports.addColumn = exports.decodeHtmlEntities = exports.scrapeCk = exports.postForm = exports.parseFormInputs = exports.getFormPage = exports.getWithSession = exports.getNewRecordForm = exports.getRecordForm = exports.setCurrentApplication = exports.openFormSession = exports.resolveFormAuth = exports.TYPE_MAP = exports.listEditKey = exports.showInMenuKey = exports.defaultAccessFlags = exports.applyTableSaveOverlay = exports.resolveType = exports.normalizeColumns = exports.xmlEscape = exports.buildColumnXml = exports.DEFAULT_COLUMNS_REL_ID = exports.DEFAULT_SAVE_ACTION = exports.DEFAULT_SUPER_CLASS = exports.parseSysIdFromLocation = exports.projectTableGraph = exports.createTable = void 0;
|
|
9
|
+
exports.resolveTableAttributes = exports.setTable = exports.labelUpdateName = exports.overrideUpdateName = exports.applyInheritedWrites = exports.diffInherited = exports.effectiveValue = exports.findLabelRow = exports.findOverrideRow = void 0;
|
|
10
10
|
var createTable_1 = require("./createTable");
|
|
11
11
|
Object.defineProperty(exports, "createTable", { enumerable: true, get: function () { return createTable_1.createTable; } });
|
|
12
12
|
Object.defineProperty(exports, "projectTableGraph", { enumerable: true, get: function () { return createTable_1.projectTableGraph; } });
|
|
@@ -40,6 +40,11 @@ Object.defineProperty(exports, "decodeHtmlEntities", { enumerable: true, get: fu
|
|
|
40
40
|
var addColumn_1 = require("./addColumn");
|
|
41
41
|
Object.defineProperty(exports, "addColumn", { enumerable: true, get: function () { return addColumn_1.addColumn; } });
|
|
42
42
|
Object.defineProperty(exports, "deriveElement", { enumerable: true, get: function () { return addColumn_1.deriveElement; } });
|
|
43
|
+
var designAccess_1 = require("./designAccess");
|
|
44
|
+
Object.defineProperty(exports, "ensureDesignAccess", { enumerable: true, get: function () { return designAccess_1.ensureDesignAccess; } });
|
|
45
|
+
Object.defineProperty(exports, "findDesignAccess", { enumerable: true, get: function () { return designAccess_1.findDesignAccess; } });
|
|
46
|
+
Object.defineProperty(exports, "resolveScopeRef", { enumerable: true, get: function () { return designAccess_1.resolveScopeRef; } });
|
|
47
|
+
Object.defineProperty(exports, "DESIGN_ACCESS_TABLE", { enumerable: true, get: function () { return designAccess_1.DESIGN_ACCESS_TABLE; } });
|
|
43
48
|
var addIndex_1 = require("./addIndex");
|
|
44
49
|
Object.defineProperty(exports, "addIndex", { enumerable: true, get: function () { return addIndex_1.addIndex; } });
|
|
45
50
|
Object.defineProperty(exports, "scanForDuplicates", { enumerable: true, get: function () { return addIndex_1.scanForDuplicates; } });
|