zinkee 0.1.40 → 0.1.41
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/.github/workflows/npm-publish.yml +77 -0
- package/.github/workflows/pr-checks.yml +36 -0
- package/AGENTS.md +4 -3
- package/dist/index.js +41 -13
- package/dist/index.js.map +1 -1
- package/docs/npm-release.md +34 -65
- package/docs/superpowers/specs/2026-07-30-cli-pr-checks-design.md +37 -0
- package/package.json +5 -1
- package/src/commands/automations.test.ts +140 -0
- package/src/commands/automations.ts +48 -13
- package/.claude/settings.local.json +0 -70
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
name: Publish to npm
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
id-token: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
publish:
|
|
14
|
+
name: Publish package
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- name: Checkout repository
|
|
19
|
+
uses: actions/checkout@v6
|
|
20
|
+
|
|
21
|
+
- name: Set up Node.js
|
|
22
|
+
uses: actions/setup-node@v6
|
|
23
|
+
with:
|
|
24
|
+
node-version: 24
|
|
25
|
+
registry-url: https://registry.npmjs.org
|
|
26
|
+
package-manager-cache: false
|
|
27
|
+
|
|
28
|
+
- name: Check package version
|
|
29
|
+
id: version
|
|
30
|
+
shell: bash
|
|
31
|
+
run: |
|
|
32
|
+
package_name="$(node -p "require('./package.json').name")"
|
|
33
|
+
package_version="$(node -p "require('./package.json').version")"
|
|
34
|
+
|
|
35
|
+
set +e
|
|
36
|
+
lookup_output="$(npm view "${package_name}@${package_version}" version 2>&1)"
|
|
37
|
+
lookup_status=$?
|
|
38
|
+
set -e
|
|
39
|
+
|
|
40
|
+
if [ "$lookup_status" -eq 0 ]; then
|
|
41
|
+
echo "${package_name}@${package_version} is already published; skipping."
|
|
42
|
+
echo "already-published=true" >> "$GITHUB_OUTPUT"
|
|
43
|
+
elif echo "$lookup_output" | grep -q "E404"; then
|
|
44
|
+
echo "${package_name}@${package_version} is not published yet."
|
|
45
|
+
echo "already-published=false" >> "$GITHUB_OUTPUT"
|
|
46
|
+
else
|
|
47
|
+
echo "$lookup_output" >&2
|
|
48
|
+
exit "$lookup_status"
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
- name: Set up trusted publishing
|
|
52
|
+
if: steps.version.outputs.already-published == 'false'
|
|
53
|
+
run: npm install --global npm@11.5.1
|
|
54
|
+
|
|
55
|
+
- name: Install dependencies
|
|
56
|
+
if: steps.version.outputs.already-published == 'false'
|
|
57
|
+
run: npm ci
|
|
58
|
+
|
|
59
|
+
- name: Run tests
|
|
60
|
+
if: steps.version.outputs.already-published == 'false'
|
|
61
|
+
run: npm test
|
|
62
|
+
|
|
63
|
+
- name: Run typecheck
|
|
64
|
+
if: steps.version.outputs.already-published == 'false'
|
|
65
|
+
run: npm run typecheck
|
|
66
|
+
|
|
67
|
+
- name: Build project
|
|
68
|
+
if: steps.version.outputs.already-published == 'false'
|
|
69
|
+
run: npm run build
|
|
70
|
+
|
|
71
|
+
- name: Inspect package contents
|
|
72
|
+
if: steps.version.outputs.already-published == 'false'
|
|
73
|
+
run: npm pack --dry-run
|
|
74
|
+
|
|
75
|
+
- name: Publish package
|
|
76
|
+
if: steps.version.outputs.already-published == 'false'
|
|
77
|
+
run: npm publish --access public
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
name: PR Checks
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
validate:
|
|
13
|
+
name: Test, Typecheck, and Build
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- name: Checkout repository
|
|
18
|
+
uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Set up Node.js
|
|
21
|
+
uses: actions/setup-node@v4
|
|
22
|
+
with:
|
|
23
|
+
node-version: 24
|
|
24
|
+
cache: npm
|
|
25
|
+
|
|
26
|
+
- name: Install dependencies
|
|
27
|
+
run: npm ci
|
|
28
|
+
|
|
29
|
+
- name: Run tests
|
|
30
|
+
run: npm test
|
|
31
|
+
|
|
32
|
+
- name: Run typecheck
|
|
33
|
+
run: npm run typecheck
|
|
34
|
+
|
|
35
|
+
- name: Build project
|
|
36
|
+
run: npm run build
|
package/AGENTS.md
CHANGED
|
@@ -101,8 +101,9 @@ Prefer focused command tests and parser/client unit tests.
|
|
|
101
101
|
|
|
102
102
|
- Versioning is patch-only today (`0.1.x`). Bump the patch number unless the
|
|
103
103
|
team decides to move to a different scheme.
|
|
104
|
-
-
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
- If an agent determines that a PR requires a new published version, it must
|
|
105
|
+
bump the version in `package.json` in that same PR and keep
|
|
106
|
+
`package-lock.json` in sync. User-visible changes (new commands, fixed
|
|
107
|
+
examples, behaviour changes) always require this.
|
|
107
108
|
- Before bumping, fetch `origin/main` to make sure the version you pick isn't
|
|
108
109
|
already taken by another PR that merged ahead of yours.
|
package/dist/index.js
CHANGED
|
@@ -7392,23 +7392,45 @@ function readJsonValueOption(raw, rawFile, rawLabel, rawFileLabel) {
|
|
|
7392
7392
|
function readJsonObjectOption(raw, rawFile, rawLabel, rawFileLabel) {
|
|
7393
7393
|
return readJsonValueOption(raw, rawFile, rawLabel, rawFileLabel) ?? {};
|
|
7394
7394
|
}
|
|
7395
|
+
var NO_VALUE_COMPARATORS = /* @__PURE__ */ new Set([
|
|
7396
|
+
"chg",
|
|
7397
|
+
"changes",
|
|
7398
|
+
"ie",
|
|
7399
|
+
"is_empty",
|
|
7400
|
+
"ine",
|
|
7401
|
+
"is_not_empty"
|
|
7402
|
+
]);
|
|
7403
|
+
function isNoValueComparator(comparator) {
|
|
7404
|
+
return NO_VALUE_COMPARATORS.has(comparator.toLowerCase());
|
|
7405
|
+
}
|
|
7406
|
+
function conditionFormatError(input) {
|
|
7407
|
+
return new CliError(
|
|
7408
|
+
"invalid_cli_usage",
|
|
7409
|
+
`Expected condition in the form field:comparator:value, or field:comparator for comparators without value (chg, ie, ine), received "${input}".`
|
|
7410
|
+
);
|
|
7411
|
+
}
|
|
7395
7412
|
function parseCondition(input) {
|
|
7396
7413
|
const firstSeparator = input.indexOf(":");
|
|
7397
7414
|
const secondSeparator = input.indexOf(":", firstSeparator + 1);
|
|
7398
|
-
if (firstSeparator <= 0
|
|
7399
|
-
throw
|
|
7400
|
-
|
|
7401
|
-
|
|
7402
|
-
);
|
|
7415
|
+
if (firstSeparator <= 0) {
|
|
7416
|
+
throw conditionFormatError(input);
|
|
7417
|
+
}
|
|
7418
|
+
if (secondSeparator === -1) {
|
|
7419
|
+
const field2 = input.slice(0, firstSeparator).trim();
|
|
7420
|
+
const comparator2 = input.slice(firstSeparator + 1).trim();
|
|
7421
|
+
if (!field2 || !comparator2 || !isNoValueComparator(comparator2)) {
|
|
7422
|
+
throw conditionFormatError(input);
|
|
7423
|
+
}
|
|
7424
|
+
return { field: field2, comparator: comparator2, values: [] };
|
|
7425
|
+
}
|
|
7426
|
+
if (secondSeparator <= firstSeparator + 1) {
|
|
7427
|
+
throw conditionFormatError(input);
|
|
7403
7428
|
}
|
|
7404
7429
|
const field = input.slice(0, firstSeparator).trim();
|
|
7405
7430
|
const comparator = input.slice(firstSeparator + 1, secondSeparator).trim();
|
|
7406
7431
|
const value = input.slice(secondSeparator + 1).trim();
|
|
7407
7432
|
if (!field || !comparator || !value) {
|
|
7408
|
-
throw
|
|
7409
|
-
"invalid_cli_usage",
|
|
7410
|
-
`Expected condition in the form field:comparator:value, received "${input}".`
|
|
7411
|
-
);
|
|
7433
|
+
throw conditionFormatError(input);
|
|
7412
7434
|
}
|
|
7413
7435
|
return {
|
|
7414
7436
|
field,
|
|
@@ -7555,10 +7577,11 @@ function normalizeAutomationConditions(conditions, label, options) {
|
|
|
7555
7577
|
const field = typeof condition.field === "string" ? condition.field.trim() : "";
|
|
7556
7578
|
const comparator = typeof condition.comparator === "string" ? condition.comparator.trim() : "";
|
|
7557
7579
|
const values = condition.values;
|
|
7558
|
-
|
|
7580
|
+
const allowsEmptyValues = isNoValueComparator(comparator);
|
|
7581
|
+
if (!field || !comparator || !Array.isArray(values) || values.length === 0 && !allowsEmptyValues) {
|
|
7559
7582
|
throw new CliError(
|
|
7560
7583
|
"invalid_cli_usage",
|
|
7561
|
-
`Expected ${label} ${index + 1} to contain "field", "comparator", and a non-empty "values" array.`
|
|
7584
|
+
`Expected ${label} ${index + 1} to contain "field", "comparator", and a non-empty "values" array (comparators without value, e.g. chg/ie/ine, accept an empty array).`
|
|
7562
7585
|
);
|
|
7563
7586
|
}
|
|
7564
7587
|
return {
|
|
@@ -8035,7 +8058,7 @@ function addTriggerPayloadOptions(command) {
|
|
|
8035
8058
|
[]
|
|
8036
8059
|
).option(
|
|
8037
8060
|
"--condition <field:comparator:value>",
|
|
8038
|
-
"trigger condition",
|
|
8061
|
+
"trigger condition (use field:comparator for comparators without value: chg, ie, ine)",
|
|
8039
8062
|
collectValues,
|
|
8040
8063
|
[]
|
|
8041
8064
|
).option(
|
|
@@ -8062,7 +8085,12 @@ function addActionPayloadOptions(command) {
|
|
|
8062
8085
|
return command.option(
|
|
8063
8086
|
"--type <type>",
|
|
8064
8087
|
"action type (create_record|update_record|search_records|send_message|http_request|execute_plugin|generate_document)"
|
|
8065
|
-
).option("--name <name>", "action name").option("--target-schema <uuid>", "target schema id").option("--map <field=value>", "field mapping", collectValues, []).option("--map-json <field=json>", "JSON field mapping", collectValues, []).option(
|
|
8088
|
+
).option("--name <name>", "action name").option("--target-schema <uuid>", "target schema id").option("--map <field=value>", "field mapping", collectValues, []).option("--map-json <field=json>", "JSON field mapping", collectValues, []).option(
|
|
8089
|
+
"--condition <field:comparator:value>",
|
|
8090
|
+
"action condition (use field:comparator for comparators without value: ie, ine)",
|
|
8091
|
+
collectValues,
|
|
8092
|
+
[]
|
|
8093
|
+
).option("--condition-json <json>", "action condition as JSON", collectValues, []).option("--use-trigger-record", "use the triggering record").option("--method <method>", "HTTP method").option("--url <url>", "HTTP target URL").option("--header <key=value>", "HTTP header", collectValues, []).option("--body <json>", "HTTP request body as JSON").option("--body-file <path>", "path to HTTP request body JSON").option("--content-type <type>", "HTTP content type").option(
|
|
8066
8094
|
"--timeout-ms <n>",
|
|
8067
8095
|
"HTTP timeout in milliseconds",
|
|
8068
8096
|
parseNonNegativeInteger
|