@snutils/snu 0.3.3 → 0.3.5

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 (55) hide show
  1. package/README.md +8 -1
  2. package/dist/cli/format.d.ts +0 -3
  3. package/dist/cli/format.d.ts.map +1 -1
  4. package/dist/cli/format.js +45 -3
  5. package/dist/cli/format.js.map +1 -1
  6. package/dist/cli/index.d.ts.map +1 -1
  7. package/dist/cli/index.js +124 -1
  8. package/dist/cli/index.js.map +1 -1
  9. package/dist/cli/permissions.d.ts +52 -0
  10. package/dist/cli/permissions.d.ts.map +1 -0
  11. package/dist/cli/permissions.js +159 -0
  12. package/dist/cli/permissions.js.map +1 -0
  13. package/dist/mcp/index.d.ts.map +1 -1
  14. package/dist/mcp/index.js +13 -2
  15. package/dist/mcp/index.js.map +1 -1
  16. package/dist/nowsdk/NowSdkBuild.d.ts +53 -0
  17. package/dist/nowsdk/NowSdkBuild.d.ts.map +1 -0
  18. package/dist/nowsdk/NowSdkBuild.js +152 -0
  19. package/dist/nowsdk/NowSdkBuild.js.map +1 -0
  20. package/dist/nowsdk/NowSdkFlows.d.ts +99 -0
  21. package/dist/nowsdk/NowSdkFlows.d.ts.map +1 -0
  22. package/dist/nowsdk/NowSdkFlows.js +203 -0
  23. package/dist/nowsdk/NowSdkFlows.js.map +1 -0
  24. package/dist/nowsdk/NowSdkProject.d.ts +71 -0
  25. package/dist/nowsdk/NowSdkProject.d.ts.map +1 -0
  26. package/dist/nowsdk/NowSdkProject.js +341 -0
  27. package/dist/nowsdk/NowSdkProject.js.map +1 -0
  28. package/dist/nowsdk/NowSdkPull.d.ts +147 -0
  29. package/dist/nowsdk/NowSdkPull.d.ts.map +1 -0
  30. package/dist/nowsdk/NowSdkPull.js +809 -0
  31. package/dist/nowsdk/NowSdkPull.js.map +1 -0
  32. package/dist/registry.d.ts.map +1 -1
  33. package/dist/registry.js +115 -1
  34. package/dist/registry.js.map +1 -1
  35. package/dist/server/config.d.ts +19 -1
  36. package/dist/server/config.d.ts.map +1 -1
  37. package/dist/server/config.js +62 -63
  38. package/dist/server/config.js.map +1 -1
  39. package/dist/server/dispatcher.d.ts +1 -0
  40. package/dist/server/dispatcher.d.ts.map +1 -1
  41. package/dist/server/dispatcher.js +72 -23
  42. package/dist/server/dispatcher.js.map +1 -1
  43. package/dist/server/httpBridge.d.ts.map +1 -1
  44. package/dist/server/httpBridge.js +2 -0
  45. package/dist/server/httpBridge.js.map +1 -1
  46. package/dist/server/policy.d.ts.map +1 -1
  47. package/dist/server/policy.js +8 -0
  48. package/dist/server/policy.js.map +1 -1
  49. package/dist/server/wsBridge.d.ts.map +1 -1
  50. package/dist/server/wsBridge.js +7 -1
  51. package/dist/server/wsBridge.js.map +1 -1
  52. package/dist/types.d.ts +6 -0
  53. package/dist/types.d.ts.map +1 -1
  54. package/dist/types.js.map +1 -1
  55. package/package.json +1 -1
@@ -0,0 +1,203 @@
1
+ "use strict";
2
+ // Deploy and pull for NOW SDK apps as used by agents and the `snu` CLI, in
3
+ // both the VS Code bridge and the standalone `snu serve` bridge. Each host
4
+ // passes its own transport to the SN Utils helper tab; the steps and the
5
+ // outcomes are the same everywhere. The editor commands (NowSdkDeploy.ts) use
6
+ // the same building blocks with interactive prompts instead of flags.
7
+ //
8
+ // Kept free of `vscode` imports. packages/snu/src/nowsdk/ holds a
9
+ // byte-identical copy; src/test/nowSdkShared.test.ts fails when they drift.
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.NowSdkFlowError = void 0;
12
+ exports.describeChange = describeChange;
13
+ exports.deployFlow = deployFlow;
14
+ exports.pullFlow = pullFlow;
15
+ const NowSdkProject_1 = require("./NowSdkProject");
16
+ const NowSdkBuild_1 = require("./NowSdkBuild");
17
+ const NowSdkPull_1 = require("./NowSdkPull");
18
+ class NowSdkFlowError extends Error {
19
+ code;
20
+ details;
21
+ constructor(code, message, details) {
22
+ super(message);
23
+ this.code = code;
24
+ this.details = details;
25
+ }
26
+ }
27
+ exports.NowSdkFlowError = NowSdkFlowError;
28
+ function loadProject(root) {
29
+ try {
30
+ const project = (0, NowSdkProject_1.readNowSdkProject)(root);
31
+ (0, NowSdkProject_1.assertSupportedProject)(project);
32
+ (0, NowSdkProject_1.assertSupportedSdk)(project.root);
33
+ return project;
34
+ }
35
+ catch (e) {
36
+ throw new NowSdkFlowError('E_INVALID_PARAMS', e?.message || String(e));
37
+ }
38
+ }
39
+ const hasAppId = (project) => /^[0-9a-f]{32}$/.test(project.scopeId);
40
+ /** "UI Page Todo Board (html; built from your UI source)" */
41
+ function describeChange(c) {
42
+ const parts = [
43
+ c.status === 'removed' ? 'deleted on the instance' : c.status === 'new' ? 'new on the instance' : '',
44
+ c.fields && c.fields.length ? c.fields.join(', ') : '',
45
+ c.reason || '',
46
+ ].filter(Boolean);
47
+ return parts.length ? `${c.label} (${parts.join('; ')})` : c.label;
48
+ }
49
+ const describe = (changes) => {
50
+ const shown = changes.slice(0, 5).map(describeChange).join(', ');
51
+ return changes.length > 5 ? `${shown} and ${changes.length - 5} more` : shown;
52
+ };
53
+ /**
54
+ * Build, check the instance for changes made since the last deploy or pull,
55
+ * and install. Changes on the instance stop the deploy unless `force` is set.
56
+ */
57
+ async function deployFlow(root, transport, opts = {}) {
58
+ const project = loadProject(root);
59
+ const log = (text) => transport.log?.(text);
60
+ const app = { name: project.name, scope: project.scope, version: project.version };
61
+ const canCheck = transport.canDownload && hasAppId(project) && (0, NowSdkPull_1.hasBaseline)(project.root, transport.instanceName);
62
+ // The instance download runs while the app builds; the comparison needs both.
63
+ let checkError = null;
64
+ const download = canCheck
65
+ ? transport.download(project).catch((e) => {
66
+ checkError = e;
67
+ return null;
68
+ })
69
+ : Promise.resolve(null);
70
+ let pkg;
71
+ try {
72
+ pkg = await (0, NowSdkBuild_1.buildNowSdkPackage)(project.root, log);
73
+ }
74
+ catch (e) {
75
+ throw new NowSdkFlowError(e instanceof NowSdkProject_1.NowSdkProjectError ? 'E_INVALID_PARAMS' : 'E_COMMAND_FAILED', e?.message || String(e));
76
+ }
77
+ const instanceZip = await download;
78
+ if (checkError) {
79
+ const why = checkError?.message || String(checkError);
80
+ log(`Could not check ${transport.instanceName} for changes: ${why}`);
81
+ // The deploy would be refused for the same reason.
82
+ if (['E_PRO_REQUIRED', 'E_PAUSED'].includes(checkError?.code))
83
+ throw new NowSdkFlowError(checkError.code, why, { app });
84
+ // Without the check a deploy could overwrite work on the instance unseen.
85
+ if (!opts.force) {
86
+ throw new NowSdkFlowError('E_CONFIRM_REQUIRED', `Could not check ${transport.instanceName} for changes made since the last deploy or pull (${why}). Retry, or deploy with force to install without the check.`, { checkFailed: true, app });
87
+ }
88
+ }
89
+ const conflicts = instanceZip ? (0, NowSdkPull_1.deployConflicts)(project.root, transport.instanceName, instanceZip, project.appOutputDir) : null;
90
+ const changes = conflicts?.overwritten || [];
91
+ if (changes.length > 0 && !opts.force) {
92
+ const unpullable = changes.filter((c) => c.generated);
93
+ throw new NowSdkFlowError('E_INSTANCE_CHANGED', `The deploy would overwrite ${changes.length} change${changes.length === 1 ? '' : 's'} made on ${transport.instanceName} since the last deploy or pull: ${describe(changes)}. ` +
94
+ (unpullable.length === changes.length
95
+ ? 'A pull cannot bring these in: copy the changes into the source by hand, or deploy with force to overwrite them.'
96
+ : 'Pull them into the project first (snu sdk pull), or deploy with force to overwrite them.' +
97
+ (unpullable.length ? ` A pull cannot bring in ${unpullable.map((c) => c.label).join(', ')}; copy those by hand.` : '')), { changes, instanceOnly: conflicts?.instanceOnly || [], app });
98
+ }
99
+ let raw;
100
+ try {
101
+ raw = await transport.deploy(pkg);
102
+ }
103
+ catch (e) {
104
+ if (e?.code === 'E_TIMEOUT') {
105
+ throw new NowSdkFlowError('E_TIMEOUT', `No deploy result within ${NowSdkBuild_1.DEPLOY_TIMEOUT_MS / 60000} minutes. The install may still have finished: check the app on the instance before deploying again.`);
106
+ }
107
+ throw e;
108
+ }
109
+ const outcome = (0, NowSdkBuild_1.summarizeDeployResult)(raw);
110
+ if (!outcome.installed) {
111
+ const code = ['E_PRO_REQUIRED', 'E_USER_REJECTED', 'E_PAUSED'].includes(outcome.code || '') ? outcome.code : 'E_COMMAND_FAILED';
112
+ const reason = outcome.reason ? ` (${outcome.reason})` : '';
113
+ throw new NowSdkFlowError(code, `${outcome.error}${reason}`, { ...outcome, app });
114
+ }
115
+ (0, NowSdkProject_1.writeDeployLink)(project.root, { instance: transport.instanceName, url: transport.instanceUrl });
116
+ (0, NowSdkPull_1.markDeployed)(project.root, transport.instanceName);
117
+ let baselineRecorded = false;
118
+ if (transport.canDownload && hasAppId(project)) {
119
+ try {
120
+ await (0, NowSdkPull_1.saveBaselineFromPackage)(project.root, transport.instanceName, await transport.download(project));
121
+ baselineRecorded = true;
122
+ }
123
+ catch (e) {
124
+ log(`Could not record the ${transport.instanceName} baseline: ${e?.message || e}`);
125
+ }
126
+ }
127
+ return {
128
+ ...outcome,
129
+ app,
130
+ instance: transport.instanceName,
131
+ ...(changes.length > 0 ? { overwritten: changes } : {}),
132
+ ...(conflicts?.instanceOnly.length ? { instanceOnly: conflicts.instanceOnly } : {}),
133
+ baselineRecorded,
134
+ // Whether the deploy was checked against changes on the instance.
135
+ instanceChecked: instanceZip !== null,
136
+ };
137
+ }
138
+ /**
139
+ * Pull the instance's version of the app into the project. Applied when git
140
+ * can show and undo it (the affected files have no uncommitted edits);
141
+ * otherwise it stops unless `force` is set. `dryRun` only lists the changes.
142
+ */
143
+ async function pullFlow(root, transport, opts = {}) {
144
+ const project = loadProject(root);
145
+ const log = (text) => transport.log?.(text);
146
+ const app = { name: project.name, scope: project.scope, version: project.version };
147
+ if (!hasAppId(project)) {
148
+ throw new NowSdkFlowError('E_INVALID_PARAMS', `Pull needs the application sys_id as scopeId in now.config.json; ${project.name} has "${project.scopeId}".`);
149
+ }
150
+ if (!transport.canDownload) {
151
+ throw new NowSdkFlowError('E_UNSUPPORTED_HOST', 'The connected SN Utils helper tab cannot pull NOW SDK apps. Update SN Utils and reopen the ScriptSync helper tab.');
152
+ }
153
+ const zip = await transport.download(project);
154
+ let staged;
155
+ try {
156
+ staged = await (0, NowSdkPull_1.stagePull)(project.root, zip, log);
157
+ }
158
+ catch (e) {
159
+ throw new NowSdkFlowError(e instanceof NowSdkProject_1.NowSdkProjectError ? 'E_INVALID_PARAMS' : 'E_COMMAND_FAILED', e?.message || String(e));
160
+ }
161
+ try {
162
+ const changes = staged.changes.map((c) => ({ path: c.path, status: c.status }));
163
+ const toApply = staged.changes.filter((c) => c.status !== 'removed');
164
+ const notOnInstance = staged.changes.filter((c) => c.status === 'removed').map((c) => c.path);
165
+ const base = { app, instance: transport.instanceName, changes };
166
+ if (opts.dryRun)
167
+ return { ...base, applied: [], dryRun: true };
168
+ if (toApply.length > 0) {
169
+ const dirty = await (0, NowSdkPull_1.gitUncommittedPaths)(project.root, toApply.map((c) => c.path));
170
+ if ((dirty === null || dirty.length > 0) && !opts.force) {
171
+ const why = dirty === null
172
+ ? 'The project is not in a git repository, so a pull cannot be reviewed or undone there.'
173
+ : `${dirty.length} file${dirty.length === 1 ? '' : 's'} the pull would change ${dirty.length === 1 ? 'has' : 'have'} uncommitted edits: ${dirty.join(', ')}. Commit or stash them first.`;
174
+ throw new NowSdkFlowError('E_CONFIRM_REQUIRED', `${why} Pull with force to apply anyway, or with dryRun to only list the changes.`, { ...base, uncommitted: dirty });
175
+ }
176
+ (0, NowSdkPull_1.applyPullWithUndo)(project.root, staged.stagingRoot, toApply);
177
+ }
178
+ const firstPull = !(0, NowSdkPull_1.hasPulledBefore)(project.root);
179
+ (0, NowSdkPull_1.markPulled)(project.root, transport.instanceName);
180
+ (0, NowSdkProject_1.writeDeployLink)(project.root, { instance: transport.instanceName, url: transport.instanceUrl });
181
+ // Changes the SDK's pull cannot bring in stay at their old version in
182
+ // the baseline, so the next deploy keeps warning about them.
183
+ const notPulled = (await (0, NowSdkPull_1.instanceChangesFromPackage)(project.root, transport.instanceName, zip)).filter((c) => c.generated);
184
+ try {
185
+ await (0, NowSdkPull_1.saveBaselineFromPackage)(project.root, transport.instanceName, zip, log, notPulled.map((c) => c.file).filter(Boolean));
186
+ }
187
+ catch (e) {
188
+ log(`Could not record the ${transport.instanceName} baseline: ${e?.message || e}`);
189
+ }
190
+ return {
191
+ ...base,
192
+ applied: toApply.map((c) => c.path),
193
+ upToDate: staged.changes.length === 0,
194
+ ...(notOnInstance.length ? { notOnInstance } : {}),
195
+ ...(firstPull && toApply.length ? { firstPull: true } : {}),
196
+ ...(notPulled.length ? { notPulled: notPulled.map(({ label, status, reason }) => ({ label, status, reason })) } : {}),
197
+ };
198
+ }
199
+ finally {
200
+ (0, NowSdkPull_1.cleanupPull)(staged.tempDir);
201
+ }
202
+ }
203
+ //# sourceMappingURL=NowSdkFlows.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NowSdkFlows.js","sourceRoot":"","sources":["../../src/nowsdk/NowSdkFlows.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ export declare const NOW_CONFIG_FILE = "now.config.json";
2
+ export interface NowSdkProject {
3
+ root: string;
4
+ name: string;
5
+ scope: string;
6
+ scopeId: string;
7
+ version: string;
8
+ appOutputDir: string;
9
+ packOutputDir: string;
10
+ /** now.config.json `type`: 'package' (default) or 'configuration'. */
11
+ type: string;
12
+ /** now.config.json `installAs`, e.g. 'store'. */
13
+ installAs: string;
14
+ hasHostedPlugins: boolean;
15
+ }
16
+ /** ServiceNow SDK versions whose packages and install protocol match what ScriptSync sends. */
17
+ export declare const SUPPORTED_SDK: {
18
+ min: string;
19
+ belowMajor: number;
20
+ };
21
+ export interface NowSdkDeployLink {
22
+ instance: string;
23
+ url: string;
24
+ }
25
+ export declare class NowSdkProjectError extends Error {
26
+ }
27
+ /**
28
+ * The NOW SDK project root that contains `filePath`, or null. When `stopAt` is
29
+ * given, only directories from the file's folder up to and including `stopAt`
30
+ * are checked, so a project outside that folder never matches.
31
+ */
32
+ export declare function findNowSdkProjectRoot(filePath: string, stopAt?: string): string | null;
33
+ export declare function readNowSdkProject(root: string): NowSdkProject;
34
+ /**
35
+ * Refuse app types ScriptSync does not deploy or pull the way the SDK does,
36
+ * with a pointer to `now-sdk install` / `now-sdk transform` for them.
37
+ */
38
+ export declare function assertSupportedProject(project: NowSdkProject): void;
39
+ /** The ServiceNow SDK version installed in the project, or null when it is not installed. */
40
+ export declare function readSdkVersion(root: string): string | null;
41
+ /** Refuse SDK versions outside the range whose packages ScriptSync handles. */
42
+ export declare function assertSupportedSdk(root: string): string;
43
+ /**
44
+ * Flow and action record ids in the built app, for activating them after an
45
+ * install (the SDK's own post-install step). Read from the build output file
46
+ * names, which follow `<table>_<sys_id>.xml`.
47
+ */
48
+ export declare function listFlowRecordIds(appOutputDir: string): {
49
+ flows: string[];
50
+ actions: string[];
51
+ };
52
+ /** The zip path reported by `now-sdk pack`, or null. */
53
+ export declare function parsePackOutput(output: string): string | null;
54
+ /** Newest `.zip` in a folder, used when the pack output could not be parsed. */
55
+ export declare function findNewestZip(dir: string): string | null;
56
+ /**
57
+ * The instance this project deploys to. Stored in `.snu/deploy.json` inside the
58
+ * project, next to a `.gitignore` that keeps the folder out of git: the link is
59
+ * a personal choice, not project configuration.
60
+ */
61
+ export declare function readDeployLink(root: string): NowSdkDeployLink | null;
62
+ export declare function writeDeployLink(root: string, link: NowSdkDeployLink): void;
63
+ /** NOW SDK project roots under `root`, a few levels deep, skipping build and dependency folders. */
64
+ export declare function findNowSdkProjects(root: string, maxDepth?: number): string[];
65
+ /**
66
+ * The project an agent asked for. `projectPath` (relative to `root`, or
67
+ * absolute) must stay inside `root`, symlinks included. Without it, `root`
68
+ * must contain exactly one project.
69
+ */
70
+ export declare function resolveNowSdkProjectRoot(root: string, projectPath?: string): string;
71
+ //# sourceMappingURL=NowSdkProject.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NowSdkProject.d.ts","sourceRoot":"","sources":["../../src/nowsdk/NowSdkProject.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,eAAe,oBAAoB,CAAC;AAIjD,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,OAAO,CAAC;CAC1B;AAED,+FAA+F;AAC/F,eAAO,MAAM,aAAa;;;CAAkC,CAAC;AAE7D,MAAM,WAAW,gBAAgB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACZ;AAED,qBAAa,kBAAmB,SAAQ,KAAK;CAAG;AAqBhD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYtF;AAoBD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAwB7D;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAWnE;AAOD,6FAA6F;AAC7F,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAO1D;AAED,+EAA+E;AAC/E,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAYvD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAgB9F;AAED,wDAAwD;AACxD,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG7D;AAED,gFAAgF;AAChF,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiBxD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAQpE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAM1E;AAID,oGAAoG;AACpG,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,SAAI,GAAG,MAAM,EAAE,CAsBvE;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAqBnF"}
@@ -0,0 +1,341 @@
1
+ "use strict";
2
+ // ServiceNow SDK (NOW SDK / Fluent) project support.
3
+ //
4
+ // A folder containing `now.config.json` is a NOW SDK project. Its sources
5
+ // (`*.now.ts`, `src/server/**`) compile into an application package; they are
6
+ // never ScriptSync field files, so the field sync must skip them entirely and
7
+ // the app is deployed as a whole package instead (see NowSdkDeploy.ts).
8
+ //
9
+ // Kept free of `vscode` imports so it can be unit tested under plain Node.
10
+ // packages/snu/src/nowsdk/ holds a byte-identical copy for the standalone
11
+ // bridge; src/test/nowSdkShared.test.ts fails when the two drift.
12
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ var desc = Object.getOwnPropertyDescriptor(m, k);
15
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
16
+ desc = { enumerable: true, get: function() { return m[k]; } };
17
+ }
18
+ Object.defineProperty(o, k2, desc);
19
+ }) : (function(o, m, k, k2) {
20
+ if (k2 === undefined) k2 = k;
21
+ o[k2] = m[k];
22
+ }));
23
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
24
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
25
+ }) : function(o, v) {
26
+ o["default"] = v;
27
+ });
28
+ var __importStar = (this && this.__importStar) || (function () {
29
+ var ownKeys = function(o) {
30
+ ownKeys = Object.getOwnPropertyNames || function (o) {
31
+ var ar = [];
32
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
33
+ return ar;
34
+ };
35
+ return ownKeys(o);
36
+ };
37
+ return function (mod) {
38
+ if (mod && mod.__esModule) return mod;
39
+ var result = {};
40
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
41
+ __setModuleDefault(result, mod);
42
+ return result;
43
+ };
44
+ })();
45
+ Object.defineProperty(exports, "__esModule", { value: true });
46
+ exports.NowSdkProjectError = exports.SUPPORTED_SDK = exports.NOW_CONFIG_FILE = void 0;
47
+ exports.findNowSdkProjectRoot = findNowSdkProjectRoot;
48
+ exports.readNowSdkProject = readNowSdkProject;
49
+ exports.assertSupportedProject = assertSupportedProject;
50
+ exports.readSdkVersion = readSdkVersion;
51
+ exports.assertSupportedSdk = assertSupportedSdk;
52
+ exports.listFlowRecordIds = listFlowRecordIds;
53
+ exports.parsePackOutput = parsePackOutput;
54
+ exports.findNewestZip = findNewestZip;
55
+ exports.readDeployLink = readDeployLink;
56
+ exports.writeDeployLink = writeDeployLink;
57
+ exports.findNowSdkProjects = findNowSdkProjects;
58
+ exports.resolveNowSdkProjectRoot = resolveNowSdkProjectRoot;
59
+ const fs = __importStar(require("fs"));
60
+ const path = __importStar(require("path"));
61
+ exports.NOW_CONFIG_FILE = 'now.config.json';
62
+ const LINK_DIR = '.snu';
63
+ const LINK_FILE = 'deploy.json';
64
+ /** ServiceNow SDK versions whose packages and install protocol match what ScriptSync sends. */
65
+ exports.SUPPORTED_SDK = { min: '4.1.0', belowMajor: 5 };
66
+ class NowSdkProjectError extends Error {
67
+ }
68
+ exports.NowSdkProjectError = NowSdkProjectError;
69
+ // Directory -> "contains now.config.json", briefly cached because the field
70
+ // sync asks for every saved and watched file.
71
+ const CACHE_TTL_MS = 5000;
72
+ const configCache = new Map();
73
+ function dirHasNowConfig(dir) {
74
+ const cached = configCache.get(dir);
75
+ const now = Date.now();
76
+ if (cached && now - cached.at < CACHE_TTL_MS)
77
+ return cached.has;
78
+ let has = false;
79
+ try {
80
+ has = fs.statSync(path.join(dir, exports.NOW_CONFIG_FILE)).isFile();
81
+ }
82
+ catch {
83
+ has = false;
84
+ }
85
+ configCache.set(dir, { has, at: now });
86
+ return has;
87
+ }
88
+ /**
89
+ * The NOW SDK project root that contains `filePath`, or null. When `stopAt` is
90
+ * given, only directories from the file's folder up to and including `stopAt`
91
+ * are checked, so a project outside that folder never matches.
92
+ */
93
+ function findNowSdkProjectRoot(filePath, stopAt) {
94
+ if (!filePath)
95
+ return null;
96
+ const limit = stopAt ? path.resolve(stopAt) : undefined;
97
+ let dir = path.dirname(path.resolve(filePath));
98
+ if (limit && dir !== limit && !dir.startsWith(limit + path.sep))
99
+ return null;
100
+ while (true) {
101
+ if (dirHasNowConfig(dir))
102
+ return dir;
103
+ if (limit && dir === limit)
104
+ return null;
105
+ const parent = path.dirname(dir);
106
+ if (parent === dir)
107
+ return null;
108
+ dir = parent;
109
+ }
110
+ }
111
+ function readJson(file) {
112
+ try {
113
+ return JSON.parse(fs.readFileSync(file, 'utf8'));
114
+ }
115
+ catch (e) {
116
+ throw new NowSdkProjectError(`Could not read ${path.basename(file)}: ${e?.message || e}`);
117
+ }
118
+ }
119
+ /** Resolve a configured output folder, refusing anything outside the project. */
120
+ function projectDir(root, configured, fallback) {
121
+ const rel = typeof configured === 'string' && configured.trim() ? configured.trim() : fallback;
122
+ const resolved = path.resolve(root, rel);
123
+ if (resolved !== root && !resolved.startsWith(root + path.sep)) {
124
+ throw new NowSdkProjectError(`Output folder "${rel}" is outside the project.`);
125
+ }
126
+ return resolved;
127
+ }
128
+ function readNowSdkProject(root) {
129
+ const resolvedRoot = path.resolve(root);
130
+ const config = readJson(path.join(resolvedRoot, exports.NOW_CONFIG_FILE));
131
+ const pkg = readJson(path.join(resolvedRoot, 'package.json'));
132
+ const scope = String(config?.scope || '');
133
+ const scopeId = String(config?.scopeId || '');
134
+ const version = String(pkg?.version || '');
135
+ if (!/^[a-z][a-z0-9_]{1,17}$/.test(scope))
136
+ throw new NowSdkProjectError(`Invalid scope "${scope}" in ${exports.NOW_CONFIG_FILE}.`);
137
+ if (!/^([0-9a-f]{32}|global)$/.test(scopeId))
138
+ throw new NowSdkProjectError(`Invalid scopeId "${scopeId}" in ${exports.NOW_CONFIG_FILE}.`);
139
+ if (!/^[0-9A-Za-z.+-]{1,32}$/.test(version))
140
+ throw new NowSdkProjectError(`Invalid or missing version in package.json.`);
141
+ return {
142
+ root: resolvedRoot,
143
+ name: String(config?.name || scope),
144
+ scope,
145
+ scopeId,
146
+ version,
147
+ appOutputDir: projectDir(resolvedRoot, config?.appOutputDir, path.join('dist', 'app')),
148
+ packOutputDir: projectDir(resolvedRoot, config?.packOutputDir, 'target'),
149
+ type: String(config?.type || 'package'),
150
+ installAs: String(config?.installAs || ''),
151
+ hasHostedPlugins: !!config?.hostedPlugins && Object.keys(config.hostedPlugins).length > 0,
152
+ };
153
+ }
154
+ /**
155
+ * Refuse app types ScriptSync does not deploy or pull the way the SDK does,
156
+ * with a pointer to `now-sdk install` / `now-sdk transform` for them.
157
+ */
158
+ function assertSupportedProject(project) {
159
+ const fallback = 'Use the ServiceNow SDK itself (now-sdk install / now-sdk transform) for this app.';
160
+ if (project.type === 'configuration') {
161
+ throw new NowSdkProjectError(`${project.name} is a configuration project, which the SDK installs into an update set. That is not supported yet. ${fallback}`);
162
+ }
163
+ if (project.installAs === 'store' || project.hasHostedPlugins) {
164
+ throw new NowSdkProjectError(`${project.name} installs as a Store app (installAs "store" or hostedPlugins). That is not supported yet. ${fallback}`);
165
+ }
166
+ if (project.scope === 'global' || project.scopeId === 'global') {
167
+ throw new NowSdkProjectError(`${project.name} is a global-scope app. That is not supported yet. ${fallback}`);
168
+ }
169
+ }
170
+ function versionParts(version) {
171
+ const m = /^(\d+)\.(\d+)\.(\d+)/.exec(version || '');
172
+ return m ? [Number(m[1]), Number(m[2]), Number(m[3])] : null;
173
+ }
174
+ /** The ServiceNow SDK version installed in the project, or null when it is not installed. */
175
+ function readSdkVersion(root) {
176
+ try {
177
+ const pkg = JSON.parse(fs.readFileSync(path.join(root, 'node_modules', '@servicenow', 'sdk', 'package.json'), 'utf8'));
178
+ return typeof pkg?.version === 'string' ? pkg.version : null;
179
+ }
180
+ catch {
181
+ return null;
182
+ }
183
+ }
184
+ /** Refuse SDK versions outside the range whose packages ScriptSync handles. */
185
+ function assertSupportedSdk(root) {
186
+ const version = readSdkVersion(root);
187
+ if (!version) {
188
+ throw new NowSdkProjectError(`The ServiceNow SDK is not installed in ${path.basename(root)}. Run npm install in the project first.`);
189
+ }
190
+ const have = versionParts(version);
191
+ const min = versionParts(exports.SUPPORTED_SDK.min);
192
+ const tooOld = !have || have[0] < min[0] || (have[0] === min[0] && (have[1] < min[1] || (have[1] === min[1] && have[2] < min[2])));
193
+ if (tooOld || (have && have[0] >= exports.SUPPORTED_SDK.belowMajor)) {
194
+ throw new NowSdkProjectError(`${path.basename(root)} uses ServiceNow SDK ${version}; ScriptSync supports ${exports.SUPPORTED_SDK.min} up to ${exports.SUPPORTED_SDK.belowMajor - 1}.x. Use now-sdk install and now-sdk transform, or update the SDK in the project.`);
195
+ }
196
+ return version;
197
+ }
198
+ /**
199
+ * Flow and action record ids in the built app, for activating them after an
200
+ * install (the SDK's own post-install step). Read from the build output file
201
+ * names, which follow `<table>_<sys_id>.xml`.
202
+ */
203
+ function listFlowRecordIds(appOutputDir) {
204
+ const flows = [];
205
+ const actions = [];
206
+ let files = [];
207
+ try {
208
+ files = fs.readdirSync(path.join(appOutputDir, 'update'));
209
+ }
210
+ catch {
211
+ return { flows, actions };
212
+ }
213
+ for (const f of files) {
214
+ let m = /^sys_hub_flow_([0-9a-f]{32})\.xml$/.exec(f);
215
+ if (m) {
216
+ flows.push(m[1]);
217
+ continue;
218
+ }
219
+ m = /^sys_hub_action_type_definition_([0-9a-f]{32})\.xml$/.exec(f);
220
+ if (m)
221
+ actions.push(m[1]);
222
+ }
223
+ return { flows, actions };
224
+ }
225
+ /** The zip path reported by `now-sdk pack`, or null. */
226
+ function parsePackOutput(output) {
227
+ const m = /artifact emitted as "([^"]+\.zip)"/i.exec(output || '');
228
+ return m ? m[1] : null;
229
+ }
230
+ /** Newest `.zip` in a folder, used when the pack output could not be parsed. */
231
+ function findNewestZip(dir) {
232
+ let newest = null;
233
+ let entries = [];
234
+ try {
235
+ entries = fs.readdirSync(dir);
236
+ }
237
+ catch {
238
+ return null;
239
+ }
240
+ for (const f of entries) {
241
+ if (!f.toLowerCase().endsWith('.zip'))
242
+ continue;
243
+ const full = path.join(dir, f);
244
+ try {
245
+ const mtime = fs.statSync(full).mtimeMs;
246
+ if (!newest || mtime > newest.mtime)
247
+ newest = { file: full, mtime };
248
+ }
249
+ catch { }
250
+ }
251
+ return newest ? newest.file : null;
252
+ }
253
+ /**
254
+ * The instance this project deploys to. Stored in `.snu/deploy.json` inside the
255
+ * project, next to a `.gitignore` that keeps the folder out of git: the link is
256
+ * a personal choice, not project configuration.
257
+ */
258
+ function readDeployLink(root) {
259
+ try {
260
+ const link = JSON.parse(fs.readFileSync(path.join(root, LINK_DIR, LINK_FILE), 'utf8'));
261
+ if (link && typeof link.instance === 'string' && link.instance && typeof link.url === 'string' && /^https?:\/\//.test(link.url)) {
262
+ return { instance: link.instance, url: link.url };
263
+ }
264
+ }
265
+ catch { }
266
+ return null;
267
+ }
268
+ function writeDeployLink(root, link) {
269
+ const dir = path.join(root, LINK_DIR);
270
+ fs.mkdirSync(dir, { recursive: true });
271
+ const ignore = path.join(dir, '.gitignore');
272
+ if (!fs.existsSync(ignore))
273
+ fs.writeFileSync(ignore, '*\n');
274
+ fs.writeFileSync(path.join(dir, LINK_FILE), JSON.stringify({ instance: link.instance, url: link.url }, null, 2) + '\n');
275
+ }
276
+ const SKIP_DIRS = new Set(['node_modules', '.git', 'dist', 'target', '.snu', '.vscode']);
277
+ /** NOW SDK project roots under `root`, a few levels deep, skipping build and dependency folders. */
278
+ function findNowSdkProjects(root, maxDepth = 3) {
279
+ const found = [];
280
+ const walk = (dir, depth) => {
281
+ if (dirHasNowConfig(dir)) {
282
+ found.push(dir);
283
+ return; // a project does not contain further projects
284
+ }
285
+ if (depth >= maxDepth)
286
+ return;
287
+ let entries = [];
288
+ try {
289
+ entries = fs.readdirSync(dir, { withFileTypes: true });
290
+ }
291
+ catch {
292
+ return;
293
+ }
294
+ for (const e of entries) {
295
+ if (e.isDirectory() && !e.isSymbolicLink() && !SKIP_DIRS.has(e.name) && !e.name.startsWith('.')) {
296
+ walk(path.join(dir, e.name), depth + 1);
297
+ }
298
+ }
299
+ };
300
+ walk(path.resolve(root), 0);
301
+ return found.sort();
302
+ }
303
+ /**
304
+ * The project an agent asked for. `projectPath` (relative to `root`, or
305
+ * absolute) must stay inside `root`, symlinks included. Without it, `root`
306
+ * must contain exactly one project.
307
+ */
308
+ function resolveNowSdkProjectRoot(root, projectPath) {
309
+ const base = path.resolve(root);
310
+ let realBase = base;
311
+ try {
312
+ realBase = fs.realpathSync(base);
313
+ }
314
+ catch { }
315
+ if (projectPath) {
316
+ const target = path.resolve(base, projectPath);
317
+ const inside = (p, r) => p === r || p.startsWith(r + path.sep);
318
+ if (!inside(target, base))
319
+ throw new NowSdkProjectError(`projectPath must be inside ${base}.`);
320
+ let realTarget = target;
321
+ try {
322
+ realTarget = fs.realpathSync(target);
323
+ }
324
+ catch {
325
+ throw new NowSdkProjectError(`projectPath not found: ${projectPath}`);
326
+ }
327
+ if (!inside(realTarget, realBase))
328
+ throw new NowSdkProjectError(`projectPath must be inside ${base}.`);
329
+ const dir = fs.statSync(realTarget).isDirectory() ? realTarget : path.dirname(realTarget);
330
+ if (!dirHasNowConfig(dir))
331
+ throw new NowSdkProjectError(`No ${exports.NOW_CONFIG_FILE} in ${projectPath}.`);
332
+ return dir;
333
+ }
334
+ const projects = findNowSdkProjects(base);
335
+ if (projects.length === 1)
336
+ return projects[0];
337
+ if (projects.length === 0)
338
+ throw new NowSdkProjectError(`No NOW SDK project (${exports.NOW_CONFIG_FILE}) found under ${base}.`);
339
+ throw new NowSdkProjectError(`Several NOW SDK projects found; pass projectPath: ${projects.map((p) => path.relative(base, p) || '.').join(', ')}`);
340
+ }
341
+ //# sourceMappingURL=NowSdkProject.js.map