@tenonhq/dovetail-core 0.0.85

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 (78) hide show
  1. package/README.md +6 -0
  2. package/dist/FileLogger.js +207 -0
  3. package/dist/FileUtils.js +387 -0
  4. package/dist/Logger.js +88 -0
  5. package/dist/MultiScopeWatcher.js +615 -0
  6. package/dist/PluginManager.js +125 -0
  7. package/dist/_defaultOptionsOLD.js +44 -0
  8. package/dist/allScopesCommands.js +418 -0
  9. package/dist/appUtils.js +929 -0
  10. package/dist/benchmark.js +104 -0
  11. package/dist/bootstrap.js +62 -0
  12. package/dist/claudeCommand.js +60 -0
  13. package/dist/clickupCommands.js +472 -0
  14. package/dist/clickupPushHelper.js +33 -0
  15. package/dist/commander.js +466 -0
  16. package/dist/commands.js +378 -0
  17. package/dist/config.js +697 -0
  18. package/dist/constants.js +15 -0
  19. package/dist/createRecordCommand.js +314 -0
  20. package/dist/dashboardCommand.js +38 -0
  21. package/dist/defaultOptions.js +14 -0
  22. package/dist/deleteRecordCommand.js +282 -0
  23. package/dist/flowDesigner/values.js +55 -0
  24. package/dist/genericUtils.js +189 -0
  25. package/dist/gitUtils.js +99 -0
  26. package/dist/index.js +35 -0
  27. package/dist/initSystem/corePlugin.js +344 -0
  28. package/dist/initSystem/discovery.js +107 -0
  29. package/dist/initSystem/orchestrator.js +408 -0
  30. package/dist/logMessages.js +82 -0
  31. package/dist/loginCommand.js +20 -0
  32. package/dist/migrateCommand.js +123 -0
  33. package/dist/projectFiles.js +32 -0
  34. package/dist/recentEdits.js +66 -0
  35. package/dist/schemaCommand.js +85 -0
  36. package/dist/snClient.js +519 -0
  37. package/dist/tests/benchmarkRefresh.test.js +265 -0
  38. package/dist/tests/clickupCommands.test.js +384 -0
  39. package/dist/tests/clickupPushHelper.test.js +124 -0
  40. package/dist/tests/configFallback.test.js +68 -0
  41. package/dist/tests/cred.test.js +59 -0
  42. package/dist/tests/discovery.test.js +67 -0
  43. package/dist/tests/ensureUpdateSetWarnings.test.js +218 -0
  44. package/dist/tests/errorLogLevels.test.js +273 -0
  45. package/dist/tests/example.test.js +6 -0
  46. package/dist/tests/fileContextSkipReason.test.js +116 -0
  47. package/dist/tests/globalDebounce.test.js +308 -0
  48. package/dist/tests/migrateCommand.test.js +113 -0
  49. package/dist/tests/multi-scope-watcher.test.js +558 -0
  50. package/dist/tests/orchestrator.test.js +23 -0
  51. package/dist/tests/pushFiles.test.js +248 -0
  52. package/dist/tests/rateLimitCoordination.test.js +271 -0
  53. package/dist/tests/resolveConfigReadOnly.test.js +67 -0
  54. package/dist/tests/retryOnHttpErr.test.js +154 -0
  55. package/dist/tests/scopeCaching.test.js +115 -0
  56. package/dist/tests/serializeUpdateSetConfig.test.js +325 -0
  57. package/dist/tests/snClient.fallback.test.js +120 -0
  58. package/dist/tests/syncManifestRefresh.test.js +287 -0
  59. package/dist/tests/syncManifestWhitelist.test.js +192 -0
  60. package/dist/tests/taskClear.test.js +170 -0
  61. package/dist/tests/taskStaleness.test.js +220 -0
  62. package/dist/tests/unwrapSNResponseError.test.js +145 -0
  63. package/dist/tests/v2Values.test.js +79 -0
  64. package/dist/tests/validateTaskId.test.js +304 -0
  65. package/dist/tests/verifyUpdateSetSwitch.test.js +277 -0
  66. package/dist/tests/writeEnvVar.test.js +119 -0
  67. package/dist/updateSetCommands.js +702 -0
  68. package/dist/wizard.js +40 -0
  69. package/package.json +69 -0
  70. package/skills/dove-configure-pipeline.md +158 -0
  71. package/skills/dove-create-plugin.md +174 -0
  72. package/skills/dove-create-record.md +135 -0
  73. package/skills/dove-debug-build.md +117 -0
  74. package/skills/dove-delete-record.md +104 -0
  75. package/skills/dove-manage-tables.md +174 -0
  76. package/skills/dove-manage-update-sets.md +88 -0
  77. package/skills/dove-setup-project.md +154 -0
  78. package/skills/dove-troubleshoot-sync.md +113 -0
package/dist/wizard.js ADDED
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getLoginInfo = getLoginInfo;
7
+ exports.setupDotEnv = setupDotEnv;
8
+ const inquirer_1 = __importDefault(require("inquirer"));
9
+ const FileUtils_1 = require("./FileUtils");
10
+ async function getLoginInfo() {
11
+ return await inquirer_1.default.prompt([
12
+ {
13
+ type: "input",
14
+ name: "instance",
15
+ message: "What instance would you like to connect to?(ex. test123.service-now.com)",
16
+ },
17
+ {
18
+ type: "input",
19
+ name: "username",
20
+ message: "What is your username on that instance?",
21
+ },
22
+ {
23
+ type: "password",
24
+ name: "password",
25
+ message: "What is your password on that instance?",
26
+ },
27
+ ]);
28
+ }
29
+ async function setupDotEnv(answers) {
30
+ process.env.SN_USER = answers.username;
31
+ process.env.SN_PASSWORD = answers.password;
32
+ process.env.SN_INSTANCE = answers.instance;
33
+ (0, FileUtils_1.writeEnvVars)({
34
+ vars: [
35
+ { key: "SN_USER", value: answers.username },
36
+ { key: "SN_PASSWORD", value: answers.password },
37
+ { key: "SN_INSTANCE", value: answers.instance },
38
+ ],
39
+ });
40
+ }
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "@tenonhq/dovetail-core",
3
+ "version": "0.0.85",
4
+ "description": "Next-gen file syncer",
5
+ "license": "GPL-3.0",
6
+ "main": "./dist/index.js",
7
+ "author": "Multiple",
8
+ "private": false,
9
+ "scripts": {
10
+ "copy:skills": "mkdir -p skills && cp ../../skills/*.md ./skills/",
11
+ "prepack": "npm run copy:skills && tsc && npm run validate-dist",
12
+ "validate-dist": "node -e \"var fs=require('fs');if(!fs.existsSync('./dist/index.js')){console.error('FATAL: dist/index.js missing after build');process.exit(1)}\"",
13
+ "test": "jest --ci --reporters=jest-junit --reporters=default --coverage --coverageReporters=cobertura --coverageReporters=html",
14
+ "version:bump": "node ./../../Scripts/bump-version.js ./package.json",
15
+ "postpublish": "npm run version:bump"
16
+ },
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "https://github.com/tenonhq/dovetail.git"
20
+ },
21
+ "engines": {
22
+ "node": ">=20.0.0"
23
+ },
24
+ "devDependencies": {
25
+ "@tenonhq/dovetail-types": "^0.0.17",
26
+ "@types/dotenv": "^6.1.1",
27
+ "@types/inquirer": "^8.2.10",
28
+ "@types/jest": "^29.5.5",
29
+ "@types/lodash": "^4.14.199",
30
+ "@types/node": ">=20.8.4",
31
+ "@types/prettier": "^2.7.3",
32
+ "@types/progress": "^2.0.5",
33
+ "@types/tough-cookie": "^4.0.5",
34
+ "@types/yargs": "^17.0.28",
35
+ "jest": "^29.7.0",
36
+ "jest-junit": "^16.0.0",
37
+ "ts-jest": "^29.1.1",
38
+ "typescript": "^5.2.2"
39
+ },
40
+ "dependencies": {
41
+ "@tenonhq/dovetail-clickup": "^0.0.7",
42
+ "@tenonhq/dovetail-schema": "^0.0.5",
43
+ "axios": "^1.5.1",
44
+ "axios-cookiejar-support": "^4.0.7",
45
+ "axios-rate-limit": "^1.3.0",
46
+ "chalk": "^4.1.2",
47
+ "chokidar": "^3.5.3",
48
+ "dotenv": "^16.3.1",
49
+ "inquirer": "^8.2.6",
50
+ "lodash": "^4.17.21",
51
+ "prettier": "3.0.3",
52
+ "progress": "^2.0.3",
53
+ "tough-cookie": "^4.1.3",
54
+ "winston": "^3.11.0",
55
+ "yargs": "^17.7.2"
56
+ },
57
+ "bin": {
58
+ "dove": "./dist/index.js",
59
+ "sinc": "./dist/index.js"
60
+ },
61
+ "files": [
62
+ "dist/**/*",
63
+ "skills/**/*",
64
+ "README.md"
65
+ ],
66
+ "publishConfig": {
67
+ "access": "public"
68
+ }
69
+ }
@@ -0,0 +1,158 @@
1
+ # Configure Dovetail Build Pipeline
2
+
3
+ ## Task
4
+ $ARGUMENTS
5
+
6
+ ## Instructions for Claude
7
+
8
+ ### Directory Context
9
+
10
+ Dovetail commands can be run from two locations:
11
+ - **From `ServiceNow/` directory:** `npx sinc <command>`
12
+ - **From Craftsman root:** `npm run sinc:<command>` (proxy scripts)
13
+
14
+ Available root scripts: `sinc:init`, `sinc:start`, `sinc:dev`, `sinc:build`, `sinc:deploy`, `sinc:push`, `sinc:refresh`, `sinc:status`
15
+
16
+ When running from Craftsman root, `dove.config.js` is at `ServiceNow/dove.config.js`. When running from `ServiceNow/`, it is at `./dove.config.js`. Use the path appropriate to the current working directory.
17
+
18
+ ---
19
+
20
+ The user wants to configure or modify their `dove.config.js` plugin pipeline. Help them set up the `rules` array with the correct plugins, ordering, and options.
21
+
22
+ ### Key Principles
23
+
24
+ 1. **Rule matching is first-match-wins.** Place the most specific regex patterns first. If `.secret.ts` should have no plugins, that rule MUST come before the generic `.ts` rule.
25
+ 2. **Plugin chain is sequential.** The output of one plugin feeds into the next. Order matters.
26
+ 3. **Babel preset execution is REVERSED** (last preset runs first), but **Babel plugin execution is FORWARD** (first plugin runs first). This is standard Babel behavior but confusing in config.
27
+
28
+ ### Step 1: Identify the user's file types and needs
29
+
30
+ Ask what file types they have if not specified:
31
+ - `.ts` files (server-side TypeScript)
32
+ - `.js` files (server-side JavaScript)
33
+ - `.client.js` or `.wp.js` files (client-side, need Webpack bundling)
34
+ - `.scss` files (SCSS stylesheets)
35
+ - Any files that should be excluded from processing
36
+
37
+ ### Step 2: Build the rules array
38
+
39
+ For each file type, construct a rule using these templates:
40
+
41
+ **Server-side TypeScript (most common):**
42
+ ```javascript
43
+ {
44
+ match: /\.ts$/,
45
+ plugins: [
46
+ {
47
+ name: "@tenonhq/dovetail-typescript-plugin",
48
+ options: { transpile: false }
49
+ },
50
+ {
51
+ name: "@tenonhq/dovetail-babel-plugin",
52
+ options: {
53
+ presets: [
54
+ "@tenonhq/dovetail-servicenow",
55
+ "@babel/env",
56
+ "@babel/typescript"
57
+ ],
58
+ plugins: [
59
+ "@tenonhq/dovetail-remove-modules",
60
+ "@babel/proposal-class-properties",
61
+ "@babel/proposal-object-rest-spread"
62
+ ]
63
+ }
64
+ }
65
+ ]
66
+ }
67
+ ```
68
+
69
+ **Server-side JavaScript:**
70
+ ```javascript
71
+ {
72
+ match: /\.js$/,
73
+ plugins: [
74
+ {
75
+ name: "@tenonhq/dovetail-babel-plugin",
76
+ options: {
77
+ presets: [
78
+ "@tenonhq/dovetail-servicenow",
79
+ "@babel/env"
80
+ ],
81
+ plugins: [
82
+ "@tenonhq/dovetail-remove-modules"
83
+ ]
84
+ }
85
+ }
86
+ ]
87
+ }
88
+ ```
89
+
90
+ **Client-side Webpack bundle:**
91
+ ```javascript
92
+ {
93
+ match: /\.wp\.js$/,
94
+ plugins: [
95
+ {
96
+ name: "@tenonhq/dovetail-webpack-plugin",
97
+ options: {
98
+ configGenerator: (context) => ({
99
+ mode: "production",
100
+ output: { library: context.name }
101
+ })
102
+ }
103
+ }
104
+ ]
105
+ }
106
+ ```
107
+
108
+ **SCSS:**
109
+ ```javascript
110
+ {
111
+ match: /\.scss$/,
112
+ plugins: [
113
+ { name: "@tenonhq/dovetail-sass-plugin", options: {} }
114
+ ]
115
+ }
116
+ ```
117
+
118
+ **Skip processing:**
119
+ ```javascript
120
+ {
121
+ match: /\.secret\.ts$/,
122
+ plugins: []
123
+ }
124
+ ```
125
+
126
+ ### Step 3: Assemble the complete config
127
+
128
+ Write the full `dove.config.js` with rules ordered most-specific to least-specific. Include other fields: `sourceDirectory`, `buildDirectory`, `excludes`, `includes`, `tableOptions`, `refreshInterval`, `scopes`.
129
+
130
+ ### Step 4: List npm install commands
131
+
132
+ Provide a single `npm i -D` command with all required packages.
133
+
134
+ ### Available Plugins Reference
135
+
136
+ | Plugin | Purpose | npm Package |
137
+ |--------|---------|-------------|
138
+ | TypeScript | Type-check and/or transpile `.ts` | `@tenonhq/dovetail-typescript-plugin` |
139
+ | Babel | Run Babel transforms | `@tenonhq/dovetail-babel-plugin` |
140
+ | ESLint | Lint before sync (blocks on errors) | `@tenonhq/dovetail-eslint-plugin` |
141
+ | Prettier | Format output code | `@tenonhq/dovetail-prettier-plugin` |
142
+ | SASS | Compile SCSS to CSS | `@tenonhq/dovetail-sass-plugin` |
143
+ | Webpack | Bundle frontend JS | `@tenonhq/dovetail-webpack-plugin` |
144
+
145
+ ### Babel Sub-Packages (used inside babel-plugin options)
146
+
147
+ | Package | Purpose | Config Key |
148
+ |---------|---------|------------|
149
+ | `@tenonhq/dovetail-babel-plugin-remove-modules` | Strip import/export for ServiceNow | `plugins: ["@tenonhq/dovetail-remove-modules"]` |
150
+ | `@tenonhq/dovetail-babel-preset-servicenow` | Sanitize for Rhino engine | `presets: ["@tenonhq/dovetail-servicenow"]` |
151
+
152
+ ### Critical Warnings
153
+
154
+ - **Never use `useBuiltIns`** with `@babel/env` -- ServiceNow's Rhino engine locks base class prototypes, so polyfills will fail.
155
+ - **Always include `@tenonhq/dovetail-servicenow`** as the FIRST Babel preset listed (runs last) for server-side code -- it handles `__proto__` and reserved word issues.
156
+ - **Always include `@tenonhq/dovetail-remove-modules`** as a Babel plugin for server-side code -- ServiceNow does not support ES modules.
157
+ - If using TypeScript plugin for type-checking only (`transpile: false`), Babel must handle the actual transpilation.
158
+ - Webpack rules MUST come before generic `.js` rules in the rules array.
@@ -0,0 +1,174 @@
1
+ # Create a Custom Dovetail Plugin
2
+
3
+ ## Task
4
+ $ARGUMENTS
5
+
6
+ ## Instructions for Claude
7
+
8
+ ### Directory Context
9
+
10
+ Dovetail commands can be run from two locations:
11
+ - **From `ServiceNow/` directory:** `npx sinc <command>`
12
+ - **From Craftsman root:** `npm run sinc:<command>` (proxy scripts)
13
+
14
+ Available root scripts: `sinc:init`, `sinc:start`, `sinc:dev`, `sinc:build`, `sinc:deploy`, `sinc:push`, `sinc:refresh`, `sinc:status`
15
+
16
+ Plugin files and `dove.config.js` live in the `ServiceNow/` directory. When referencing paths from the Craftsman root, prefix with `ServiceNow/`.
17
+
18
+ ---
19
+
20
+ Help the user create a custom Dovetail build plugin. A plugin is a Node.js module that transforms file content during the build pipeline.
21
+
22
+ ### Plugin Interface
23
+
24
+ A Dovetail plugin must export an object with a `run` function:
25
+
26
+ ```typescript
27
+ interface Plugin {
28
+ run: (
29
+ context: FileContext,
30
+ content: string,
31
+ options: any
32
+ ) => Promise<PluginResults>;
33
+ }
34
+
35
+ interface FileContext {
36
+ filePath: string; // Absolute path to the source file
37
+ name: string; // Record display name
38
+ tableName: string; // ServiceNow table name
39
+ targetField: string; // Field name in ServiceNow
40
+ ext: string; // File extension
41
+ sys_id: string; // ServiceNow record sys_id
42
+ scope: string; // Application scope
43
+ }
44
+
45
+ interface PluginResults {
46
+ success: boolean; // If false, build is halted
47
+ output: string; // Transformed content (passed to next plugin)
48
+ }
49
+ ```
50
+
51
+ ### Minimal Plugin Template
52
+
53
+ ```javascript
54
+ // my-dovetail-plugin/index.js
55
+ module.exports = {
56
+ run: async function(context, content, options) {
57
+ try {
58
+ let output = content;
59
+
60
+ // Example: Add a header comment
61
+ if (options.addHeader) {
62
+ output = "// Generated from " + context.name + "\n" + output;
63
+ }
64
+
65
+ return { success: true, output: output };
66
+ } catch (e) {
67
+ console.error("Plugin error: " + e.message);
68
+ return { success: false, output: "" };
69
+ }
70
+ }
71
+ };
72
+ ```
73
+
74
+ ### Plugin Registration in dove.config.js
75
+
76
+ ```javascript
77
+ rules: [
78
+ {
79
+ match: /\.ts$/,
80
+ plugins: [
81
+ {
82
+ name: "my-dovetail-plugin",
83
+ options: { addHeader: true }
84
+ }
85
+ ]
86
+ }
87
+ ]
88
+ ```
89
+
90
+ **Important:** Dovetail resolves plugins from `node_modules/` using the plugin name as a path segment. For local plugins, you have three options:
91
+
92
+ 1. **Use npm link:**
93
+ ```bash
94
+ cd plugins/my-plugin && npm link
95
+ npm link my-dovetail-plugin
96
+ ```
97
+ 2. **Use npm workspaces** (recommended for monorepos)
98
+ 3. **Publish to npm** as a scoped package (recommended for shared plugins)
99
+
100
+ ### Using the FileContext
101
+
102
+ ```javascript
103
+ run: async function(context, content, options) {
104
+ // Different behavior per table
105
+ if (context.tableName === "sys_script_include") {
106
+ // Server-side script include
107
+ } else if (context.tableName === "sp_widget") {
108
+ // Service Portal widget
109
+ }
110
+
111
+ // Different behavior per file extension
112
+ if (context.ext === ".ts") {
113
+ // TypeScript file
114
+ }
115
+
116
+ console.log("Processing: " + context.name + " (" + context.sys_id + ")");
117
+
118
+ return { success: true, output: content };
119
+ }
120
+ ```
121
+
122
+ ### Plugin Chain Behavior
123
+
124
+ Plugins run sequentially. Each plugin receives the OUTPUT of the previous plugin as its `content` parameter. If any plugin returns `{ success: false }`, the entire build for that file is halted.
125
+
126
+ ```
127
+ Source File Content
128
+ |
129
+ v
130
+ Plugin 1 (e.g., TypeScript type-check) --> output
131
+ |
132
+ v
133
+ Plugin 2 (e.g., Babel transpile) --> output
134
+ |
135
+ v
136
+ Plugin 3 (e.g., Prettier format) --> output
137
+ |
138
+ v
139
+ Final content pushed to ServiceNow
140
+ ```
141
+
142
+ ### Example: Minification Plugin
143
+
144
+ ```javascript
145
+ // my-minify-plugin/index.js
146
+ var terser = require("terser");
147
+
148
+ module.exports = {
149
+ run: async function(context, content, options) {
150
+ try {
151
+ if (context.ext === ".css" || context.ext === ".scss") {
152
+ return { success: true, output: content };
153
+ }
154
+
155
+ var result = await terser.minify(content, {
156
+ compress: options.compress !== false,
157
+ mangle: options.mangle !== false
158
+ });
159
+
160
+ return { success: true, output: result.code };
161
+ } catch (e) {
162
+ console.error("Minification failed for " + context.name + ": " + e.message);
163
+ return { success: false, output: "" };
164
+ }
165
+ }
166
+ };
167
+ ```
168
+
169
+ ### Error Handling
170
+
171
+ - Return `{ success: false, output: "" }` to stop the build for that file
172
+ - Throw an exception for unexpected errors (caught by PluginManager)
173
+ - Log useful error messages -- they appear in the Dovetail console output
174
+ - Check `dovetail-debug-*.log` for detailed error traces
@@ -0,0 +1,135 @@
1
+ # Create ServiceNow Records
2
+
3
+ ## Task
4
+ $ARGUMENTS
5
+
6
+ ## Instructions for Claude
7
+
8
+ ### Directory Context
9
+
10
+ Dovetail commands can be run from two locations:
11
+ - **From `ServiceNow/` directory:** `npx sinc <command>`
12
+ - **From Craftsman root:** `npm run sinc:<command>` (proxy scripts)
13
+
14
+ The `create` command requires running from the `ServiceNow/` directory directly, as it accepts flags and arguments that npm run scripts don't forward.
15
+
16
+ ---
17
+
18
+ Help the user create new records on a ServiceNow instance using Dovetail's `create` command. After creation, the record is automatically pulled back and scaffolded locally.
19
+
20
+ ### Command Syntax
21
+
22
+ ```bash
23
+ npx dove create <table> [options]
24
+ ```
25
+
26
+ ### Options
27
+
28
+ | Flag | Alias | Type | Description |
29
+ |------|-------|------|-------------|
30
+ | `--name` | `-n` | string | Record name |
31
+ | `--scope` | `-s` | string | Target scope (e.g., x_cadso_core) |
32
+ | `--from` | `-f` | string | Path to JSON file with field values |
33
+ | `--field` | | array | Inline field values (key=value) |
34
+ | `--ci` | | boolean | Skip interactive prompts |
35
+
36
+ ### Examples
37
+
38
+ #### Create a Script Include (interactive)
39
+
40
+ ```bash
41
+ npx dove create sys_script_include
42
+ # Prompts for: name, scope
43
+ ```
44
+
45
+ #### Create with flags
46
+
47
+ ```bash
48
+ npx dove create sys_script_include --name "MyNewUtil" --scope x_cadso_core
49
+ ```
50
+
51
+ #### Create with inline field values
52
+
53
+ ```bash
54
+ npx dove create sys_script_include \
55
+ --name "MyNewUtil" \
56
+ --scope x_cadso_core \
57
+ --field active=true \
58
+ --field access=public
59
+ ```
60
+
61
+ #### Create from JSON file
62
+
63
+ ```bash
64
+ npx dove create sys_script_include --from new-script.json --scope x_cadso_core
65
+ ```
66
+
67
+ **JSON file format (`new-script.json`):**
68
+ ```json
69
+ {
70
+ "name": "MyNewUtil",
71
+ "active": "true",
72
+ "access": "public",
73
+ "script": "var MyNewUtil = Class.create();\nMyNewUtil.prototype = {\n initialize: function() {},\n type: 'MyNewUtil'\n};"
74
+ }
75
+ ```
76
+
77
+ #### Create a Business Rule
78
+
79
+ ```bash
80
+ npx dove create sys_script --name "Validate Record" --scope x_cadso_automate
81
+ ```
82
+
83
+ #### CI/Automation mode
84
+
85
+ ```bash
86
+ npx dove create sys_script_include \
87
+ --name "AutoCreated" \
88
+ --scope x_cadso_core \
89
+ --from record.json \
90
+ --ci
91
+ ```
92
+
93
+ ### What Happens After Create
94
+
95
+ 1. **Record is created** on the ServiceNow instance via the `api/cadso/dovetail/createRecord` endpoint
96
+ 2. **GlideRecord** uses `initialize()` and `newRecord()` to ensure all default values are set
97
+ 3. **Manifest is refreshed** for the target scope
98
+ 4. **Local files are scaffolded** — directory, field files (script.js, etc.), and metaData.json
99
+ 5. **You can immediately begin editing** the local files and push changes
100
+
101
+ ### Update Set Integration
102
+
103
+ If the target scope has an active update set configured (via `.dove-update-sets.json` or the dashboard), the new record is created within that update set.
104
+
105
+ ```bash
106
+ # Set up update set first
107
+ npx dove createUpdateSet --name "FEAT-123" --scope x_cadso_core
108
+
109
+ # Create record — automatically goes into FEAT-123 update set
110
+ npx dove create sys_script_include --name "NewFeature" --scope x_cadso_core
111
+ ```
112
+
113
+ ### Common Table Names
114
+
115
+ | Table | Creates |
116
+ |-------|---------|
117
+ | `sys_script_include` | Script Include (server-side utility class) |
118
+ | `sys_script` | Business Rule |
119
+ | `sys_ui_script` | UI Script (client-side) |
120
+ | `sys_ui_page` | UI Page |
121
+ | `sys_ux_client_script` | UX Client Script |
122
+ | `sys_processor` | Processor |
123
+ | `sys_ws_operation` | REST API Operation |
124
+ | `sys_rest_message_fn` | REST Message Function |
125
+ | `sys_ui_action` | UI Action |
126
+ | `sysevent_script_action` | Event Script Action |
127
+
128
+ ### Troubleshooting
129
+
130
+ - **"Table name is required"** — Provide the table as the first argument: `npx dove create sys_script_include`
131
+ - **"Record name is required"** — Use `--name` flag or include `name` in the JSON file
132
+ - **"Scope is required in CI mode"** — Add `--scope x_cadso_core` when using `--ci`
133
+ - **"Failed to create record"** — Check that the `api/cadso/dovetail/createRecord` endpoint exists on the target instance
134
+ - **"Local sync failed"** — Record was created on instance. Run `npx dove refresh` to pull it manually
135
+ - **Record not in expected update set** — Verify `.dove-update-sets.json` has the correct scope mapping. Use `npx dove currentUpdateSet` to check
@@ -0,0 +1,117 @@
1
+ # Debug Dovetail Build Transformations
2
+
3
+ ## Task
4
+ $ARGUMENTS
5
+
6
+ ## Instructions for Claude
7
+
8
+ ### Directory Context
9
+
10
+ Dovetail commands can be run from two locations:
11
+ - **From `ServiceNow/` directory:** `npx sinc <command>`
12
+ - **From Craftsman root:** `npm run sinc:<command>` (proxy scripts)
13
+
14
+ Available root scripts: `sinc:init`, `sinc:start`, `sinc:dev`, `sinc:build`, `sinc:deploy`, `sinc:push`, `sinc:refresh`, `sinc:status`
15
+
16
+ When this skill references `npx sinc <command>`, use `npm run sinc:<command>` if working from the Craftsman root. The `build/` and `src/` directories referenced below are at `ServiceNow/build/` and `ServiceNow/src/` relative to the Craftsman root.
17
+
18
+ ---
19
+
20
+ Help the user understand, inspect, or debug the Dovetail build transformation pipeline -- what happens between source code and what reaches ServiceNow.
21
+
22
+ ### Step 1: Run a Local Build
23
+
24
+ To see build output without pushing to ServiceNow:
25
+
26
+ ```bash
27
+ npx dove build
28
+ ```
29
+
30
+ Output files appear in the `build/` directory (configured via `buildDirectory` in `dove.config.js`), mirroring the source directory structure.
31
+
32
+ To build only changed files (compared to a git branch):
33
+
34
+ ```bash
35
+ npx dove build --diff main
36
+ ```
37
+
38
+ ### Step 2: Compare Source vs Output
39
+
40
+ ```
41
+ src/sys_script_include/MyScript/script.ts <-- Source (TypeScript)
42
+ build/sys_script_include/MyScript/script.ts <-- Output (transpiled JS)
43
+ ```
44
+
45
+ ### Step 3: Understand Transformation Stages
46
+
47
+ For a typical TypeScript server-side pipeline (`typescript-plugin` + `babel-plugin`):
48
+
49
+ **Stage 1: TypeScript Plugin** (`transpile: false`)
50
+ - Runs the TypeScript compiler for type checking only
51
+ - Does NOT modify the code
52
+ - Errors here = TypeScript type errors
53
+
54
+ **Stage 2: Babel Plugin** (with presets and plugins)
55
+
56
+ Babel plugins run first (in order):
57
+ 1. `@tenonhq/dovetail-remove-modules` -- Strips `import`/`export` statements
58
+ 2. `@babel/proposal-class-properties` -- Transforms class property syntax
59
+ 3. `@babel/proposal-object-rest-spread` -- Transforms `...spread` syntax
60
+
61
+ Babel presets run in reverse order:
62
+ 1. `@babel/typescript` (listed last, runs first) -- Strips type annotations
63
+ 2. `@babel/env` -- Transpiles ES6+ to ES5
64
+ 3. `@tenonhq/dovetail-servicenow` (listed first, runs last) -- Sanitizes for Rhino: replaces `__proto__` with `__proto_sn__`, converts `obj.default` to `obj["default"]`
65
+
66
+ ### Step 4: Diagnose Common Issues
67
+
68
+ **"Cannot read property 'X' of undefined" in ServiceNow**
69
+ - Likely: `import` statements were not removed. Check that `@tenonhq/dovetail-remove-modules` is in Babel plugins.
70
+ - The import variable becomes `undefined` because ServiceNow has no module system.
71
+
72
+ **"Illegal access to reserved word" in ServiceNow**
73
+ - Likely: Missing `@tenonhq/dovetail-servicenow` preset. Code like `obj.default` or `obj.class` crashes Rhino.
74
+ - Fix: Ensure `@tenonhq/dovetail-servicenow` is the FIRST preset listed (= runs LAST).
75
+
76
+ **"__proto__" security error in ServiceNow**
77
+ - Likely: Missing `@tenonhq/dovetail-servicenow` preset. Babel's class transpilation generates `__proto__` references.
78
+
79
+ **"TypeError: Cannot extend a non-class" or prototype errors**
80
+ - Likely: Using `useBuiltIns` with `@babel/env`. Rhino locks base class prototypes.
81
+ - Fix: Remove `useBuiltIns` from `@babel/env` config.
82
+
83
+ **Build succeeds but code does nothing in ServiceNow**
84
+ - Check if `export default` was on the main class/function. The `remove-modules` plugin strips exports. In ServiceNow script includes, the class/function name must match the script include name.
85
+
86
+ ### Special Comment Tags
87
+
88
+ The `@tenonhq/dovetail-remove-modules` Babel plugin supports these comment tags:
89
+
90
+ **`@keepModule`** -- Preserve an import (for actual ServiceNow modules):
91
+ ```javascript
92
+ //@keepModule
93
+ import moduleDos from "myModuleDos";
94
+ ```
95
+
96
+ **`@expandModule`** -- Expand imports to dot notation:
97
+ ```javascript
98
+ //@expandModule
99
+ import { helper } from "x_cadso_core";
100
+ // becomes: x_cadso_core.helper
101
+ ```
102
+
103
+ **`@moduleAlias=newName`** -- Rename the module reference with `@expandModule`:
104
+ ```javascript
105
+ //@expandModule
106
+ //@moduleAlias=MyApp
107
+ import { helper } from "x_cadso_core";
108
+ // becomes: MyApp.helper
109
+ ```
110
+
111
+ ### Step 5: Test Incrementally
112
+
113
+ If you cannot determine which stage causes an issue:
114
+
115
+ 1. **Remove all plugins** from the rule and push raw source -- does it work?
116
+ 2. **Add plugins back one at a time** and rebuild after each addition.
117
+ 3. **Check the `build/` directory** after each rebuild to see intermediate output.