primitive-admin 1.1.0-alpha.4 → 1.1.0-alpha.40
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 +325 -31
- package/assets/skill/skills/primitive-platform/SKILL.md +281 -0
- package/dist/bin/primitive.d.ts +2 -0
- package/dist/bin/primitive.js +266 -16
- package/dist/bin/primitive.js.map +1 -1
- package/dist/src/commands/admins.d.ts +2 -0
- package/dist/src/commands/admins.js +123 -18
- package/dist/src/commands/admins.js.map +1 -1
- package/dist/src/commands/analytics.d.ts +2 -0
- package/dist/src/commands/analytics.js +464 -55
- package/dist/src/commands/analytics.js.map +1 -1
- package/dist/src/commands/apps.d.ts +2 -0
- package/dist/src/commands/apps.js +55 -13
- package/dist/src/commands/apps.js.map +1 -1
- package/dist/src/commands/auth.d.ts +2 -0
- package/dist/src/commands/auth.js +177 -7
- package/dist/src/commands/auth.js.map +1 -1
- package/dist/src/commands/blob-buckets.d.ts +2 -0
- package/dist/src/commands/blob-buckets.js +422 -0
- package/dist/src/commands/blob-buckets.js.map +1 -0
- package/dist/src/commands/catalog.d.ts +2 -0
- package/dist/src/commands/catalog.js +34 -35
- package/dist/src/commands/catalog.js.map +1 -1
- package/dist/src/commands/collection-type-configs.d.ts +2 -0
- package/dist/src/commands/collection-type-configs.js +178 -0
- package/dist/src/commands/collection-type-configs.js.map +1 -0
- package/dist/src/commands/collections.d.ts +2 -0
- package/dist/src/commands/collections.js +515 -0
- package/dist/src/commands/collections.js.map +1 -0
- package/dist/src/commands/comparisons.d.ts +2 -0
- package/dist/src/commands/comparisons.js +6 -6
- package/dist/src/commands/comparisons.js.map +1 -1
- package/dist/src/commands/cron-triggers.d.ts +2 -0
- package/dist/src/commands/cron-triggers.js +357 -0
- package/dist/src/commands/cron-triggers.js.map +1 -0
- package/dist/src/commands/database-types.d.ts +2 -0
- package/dist/src/commands/database-types.js +471 -0
- package/dist/src/commands/database-types.js.map +1 -0
- package/dist/src/commands/databases.d.ts +2 -0
- package/dist/src/commands/databases.js +1462 -83
- package/dist/src/commands/databases.js.map +1 -1
- package/dist/src/commands/documents.d.ts +2 -0
- package/dist/src/commands/documents.js +518 -11
- package/dist/src/commands/documents.js.map +1 -1
- package/dist/src/commands/email-templates.d.ts +2 -0
- package/dist/src/commands/email-templates.js +281 -0
- package/dist/src/commands/email-templates.js.map +1 -0
- package/dist/src/commands/env.d.ts +12 -0
- package/dist/src/commands/env.js +260 -0
- package/dist/src/commands/env.js.map +1 -0
- package/dist/src/commands/group-type-configs.d.ts +2 -0
- package/dist/src/commands/group-type-configs.js +181 -0
- package/dist/src/commands/group-type-configs.js.map +1 -0
- package/dist/src/commands/groups.d.ts +2 -0
- package/dist/src/commands/groups.js +45 -43
- package/dist/src/commands/groups.js.map +1 -1
- package/dist/src/commands/guides.d.ts +159 -0
- package/dist/src/commands/guides.js +449 -35
- package/dist/src/commands/guides.js.map +1 -1
- package/dist/src/commands/init.d.ts +17 -0
- package/dist/src/commands/init.js +811 -201
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/integrations.d.ts +2 -0
- package/dist/src/commands/integrations.js +533 -46
- package/dist/src/commands/integrations.js.map +1 -1
- package/dist/src/commands/llm.d.ts +2 -0
- package/dist/src/commands/llm.js +4 -2
- package/dist/src/commands/llm.js.map +1 -1
- package/dist/src/commands/prompts.d.ts +2 -0
- package/dist/src/commands/prompts.js +50 -52
- package/dist/src/commands/prompts.js.map +1 -1
- package/dist/src/commands/rule-sets.d.ts +3 -0
- package/dist/src/commands/rule-sets.js +388 -0
- package/dist/src/commands/rule-sets.js.map +1 -0
- package/dist/src/commands/scripts.d.ts +2 -0
- package/dist/src/commands/scripts.js +667 -0
- package/dist/src/commands/scripts.js.map +1 -0
- package/dist/src/commands/secrets.d.ts +2 -0
- package/dist/src/commands/secrets.js +108 -0
- package/dist/src/commands/secrets.js.map +1 -0
- package/dist/src/commands/skill.d.ts +2 -0
- package/dist/src/commands/skill.js +29 -0
- package/dist/src/commands/skill.js.map +1 -0
- package/dist/src/commands/sync.d.ts +174 -0
- package/dist/src/commands/sync.js +4392 -235
- package/dist/src/commands/sync.js.map +1 -1
- package/dist/src/commands/tokens.d.ts +2 -0
- package/dist/src/commands/tokens.js +122 -19
- package/dist/src/commands/tokens.js.map +1 -1
- package/dist/src/commands/users.d.ts +2 -0
- package/dist/src/commands/users.js +440 -22
- package/dist/src/commands/users.js.map +1 -1
- package/dist/src/commands/waitlist.d.ts +2 -0
- package/dist/src/commands/waitlist.js +10 -10
- package/dist/src/commands/waitlist.js.map +1 -1
- package/dist/src/commands/webhooks.d.ts +2 -0
- package/dist/src/commands/webhooks.js +391 -0
- package/dist/src/commands/webhooks.js.map +1 -0
- package/dist/src/commands/workflows.d.ts +49 -0
- package/dist/src/commands/workflows.js +1009 -123
- package/dist/src/commands/workflows.js.map +1 -1
- package/dist/src/lib/api-client.d.ts +1272 -0
- package/dist/src/lib/api-client.js +1115 -83
- package/dist/src/lib/api-client.js.map +1 -1
- package/dist/src/lib/auth-flow.d.ts +8 -0
- package/dist/src/lib/block-layout.d.ts +160 -0
- package/dist/src/lib/block-layout.js +451 -0
- package/dist/src/lib/block-layout.js.map +1 -0
- package/dist/src/lib/cli-manifest.d.ts +60 -0
- package/dist/src/lib/cli-manifest.js +70 -0
- package/dist/src/lib/cli-manifest.js.map +1 -0
- package/dist/src/lib/config.d.ts +53 -0
- package/dist/src/lib/config.js +92 -53
- package/dist/src/lib/config.js.map +1 -1
- package/dist/src/lib/confirm-prompt.d.ts +83 -0
- package/dist/src/lib/confirm-prompt.js +110 -0
- package/dist/src/lib/confirm-prompt.js.map +1 -0
- package/dist/src/lib/constants.d.ts +2 -0
- package/dist/src/lib/constants.js +3 -0
- package/dist/src/lib/constants.js.map +1 -0
- package/dist/src/lib/crash-handlers.d.ts +20 -0
- package/dist/src/lib/crash-handlers.js +49 -0
- package/dist/src/lib/crash-handlers.js.map +1 -0
- package/dist/src/lib/credentials-store.d.ts +79 -0
- package/dist/src/lib/credentials-store.js +307 -0
- package/dist/src/lib/credentials-store.js.map +1 -0
- package/dist/src/lib/csv.d.ts +48 -0
- package/dist/src/lib/csv.js +177 -0
- package/dist/src/lib/csv.js.map +1 -0
- package/dist/src/lib/db-codegen/dbFingerprint.d.ts +10 -0
- package/dist/src/lib/db-codegen/dbFingerprint.js +17 -0
- package/dist/src/lib/db-codegen/dbFingerprint.js.map +1 -0
- package/dist/src/lib/db-codegen/dbGenerator.d.ts +111 -0
- package/dist/src/lib/db-codegen/dbGenerator.js +371 -0
- package/dist/src/lib/db-codegen/dbGenerator.js.map +1 -0
- package/dist/src/lib/db-codegen/dbNaming.d.ts +45 -0
- package/dist/src/lib/db-codegen/dbNaming.js +104 -0
- package/dist/src/lib/db-codegen/dbNaming.js.map +1 -0
- package/dist/src/lib/db-codegen/dbTemplates.d.ts +97 -0
- package/dist/src/lib/db-codegen/dbTemplates.js +159 -0
- package/dist/src/lib/db-codegen/dbTemplates.js.map +1 -0
- package/dist/src/lib/db-codegen/dbTsTypes.d.ts +78 -0
- package/dist/src/lib/db-codegen/dbTsTypes.js +112 -0
- package/dist/src/lib/db-codegen/dbTsTypes.js.map +1 -0
- package/dist/src/lib/env-resolver.d.ts +62 -0
- package/dist/src/lib/env-resolver.js +121 -0
- package/dist/src/lib/env-resolver.js.map +1 -0
- package/dist/src/lib/fetch.d.ts +5 -0
- package/dist/src/lib/generated-allowlist.d.ts +28 -0
- package/dist/src/lib/generated-allowlist.js +213 -0
- package/dist/src/lib/generated-allowlist.js.map +1 -0
- package/dist/src/lib/init-config.d.ts +59 -0
- package/dist/src/lib/init-config.js +113 -0
- package/dist/src/lib/init-config.js.map +1 -0
- package/dist/src/lib/migration-nag.d.ts +49 -0
- package/dist/src/lib/migration-nag.js +163 -0
- package/dist/src/lib/migration-nag.js.map +1 -0
- package/dist/src/lib/output.d.ts +86 -0
- package/dist/src/lib/output.js +150 -8
- package/dist/src/lib/output.js.map +1 -1
- package/dist/src/lib/paginate.d.ts +33 -0
- package/dist/src/lib/paginate.js +42 -0
- package/dist/src/lib/paginate.js.map +1 -0
- package/dist/src/lib/project-config.d.ts +97 -0
- package/dist/src/lib/project-config.js +209 -0
- package/dist/src/lib/project-config.js.map +1 -0
- package/dist/src/lib/query-operators.d.ts +43 -0
- package/dist/src/lib/query-operators.js +80 -0
- package/dist/src/lib/query-operators.js.map +1 -0
- package/dist/src/lib/refresh-admin-credentials.d.ts +65 -0
- package/dist/src/lib/refresh-admin-credentials.js +103 -0
- package/dist/src/lib/refresh-admin-credentials.js.map +1 -0
- package/dist/src/lib/resolve-platform.d.ts +45 -0
- package/dist/src/lib/resolve-platform.js +43 -0
- package/dist/src/lib/resolve-platform.js.map +1 -0
- package/dist/src/lib/skill-installer.d.ts +23 -0
- package/dist/src/lib/skill-installer.js +135 -0
- package/dist/src/lib/skill-installer.js.map +1 -0
- package/dist/src/lib/snapshots.d.ts +99 -0
- package/dist/src/lib/snapshots.js +357 -0
- package/dist/src/lib/snapshots.js.map +1 -0
- package/dist/src/lib/sync-paths.d.ts +72 -0
- package/dist/src/lib/sync-paths.js +130 -0
- package/dist/src/lib/sync-paths.js.map +1 -0
- package/dist/src/lib/template.d.ts +97 -0
- package/dist/src/lib/template.js +336 -62
- package/dist/src/lib/template.js.map +1 -1
- package/dist/src/lib/token-inject.d.ts +56 -0
- package/dist/src/lib/token-inject.js +204 -0
- package/dist/src/lib/token-inject.js.map +1 -0
- package/dist/src/lib/toml-database-config.d.ts +152 -0
- package/dist/src/lib/toml-database-config.js +600 -0
- package/dist/src/lib/toml-database-config.js.map +1 -0
- package/dist/src/lib/toml-metadata-config.d.ts +108 -0
- package/dist/src/lib/toml-metadata-config.js +371 -0
- package/dist/src/lib/toml-metadata-config.js.map +1 -0
- package/dist/src/lib/toml-params-validator.d.ts +129 -0
- package/dist/src/lib/toml-params-validator.js +298 -0
- package/dist/src/lib/toml-params-validator.js.map +1 -0
- package/dist/src/lib/version-check.d.ts +10 -0
- package/dist/src/lib/version-check.js +172 -0
- package/dist/src/lib/version-check.js.map +1 -0
- package/dist/src/lib/workflow-apply.d.ts +66 -0
- package/dist/src/lib/workflow-apply.js +117 -0
- package/dist/src/lib/workflow-apply.js.map +1 -0
- package/dist/src/lib/workflow-fragments.d.ts +41 -0
- package/dist/src/lib/workflow-fragments.js +121 -0
- package/dist/src/lib/workflow-fragments.js.map +1 -0
- package/dist/src/lib/workflow-toml-validator.d.ts +95 -0
- package/dist/src/lib/workflow-toml-validator.js +323 -0
- package/dist/src/lib/workflow-toml-validator.js.map +1 -0
- package/dist/src/types/index.d.ts +520 -0
- package/dist/src/validators.d.ts +64 -0
- package/dist/src/validators.js +63 -0
- package/dist/src/validators.js.map +1 -0
- package/package.json +18 -4
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validator: every `$params.X` reference inside an operation's
|
|
3
|
+
* `definition` must correspond to a declared param in
|
|
4
|
+
* `[[operations.params]]` (or the legacy JSON-string params object).
|
|
5
|
+
*
|
|
6
|
+
* Background (issue #752): a typo like `$params.proectId` used to
|
|
7
|
+
* silently no-op at runtime. With native TOML, we can catch these at
|
|
8
|
+
* `sync push` time with the file path and line number of the
|
|
9
|
+
* operation block where the bad reference appears.
|
|
10
|
+
*
|
|
11
|
+
* Design notes:
|
|
12
|
+
* - Line attribution is per-operation, not per-reference. We don't
|
|
13
|
+
* parse `definition` line-by-line; we just locate the
|
|
14
|
+
* `[[operations]]` header for the named op in the raw source and
|
|
15
|
+
* report that line. This is the load-bearing UX (jump to the
|
|
16
|
+
* offending op block); pinpointing the exact `$params.X` reference
|
|
17
|
+
* inside a sub-table would require swapping the TOML parser, which
|
|
18
|
+
* the issue explicitly leaves to implementer judgement.
|
|
19
|
+
* - We intentionally diverge from the server-side `collectParamRefs`
|
|
20
|
+
* in `database-type-operations-controller.ts:1163`. The server pushes
|
|
21
|
+
* the full path (e.g. `"X.Y"` for `$params.X.Y`); the CLI extracts
|
|
22
|
+
* only the first segment (`"X"`). Net effect: the CLI validator is
|
|
23
|
+
* more lenient than the server — `$params.X.Y` passes the CLI check
|
|
24
|
+
* when `X` alone is declared in `[[operations.params]]`, even though
|
|
25
|
+
* the server treats the full path as the lookup key. The server
|
|
26
|
+
* remains authoritative; the CLI's first-segment extraction is a
|
|
27
|
+
* pragmatic choice so authors can declare structured params (e.g.
|
|
28
|
+
* `config: { type: "object" }`) and reference sub-fields like
|
|
29
|
+
* `$params.config.subKey` without listing every sub-field
|
|
30
|
+
* individually (review feedback r3246635661).
|
|
31
|
+
*/
|
|
32
|
+
import { collectUnknownOperators } from "./query-operators.js";
|
|
33
|
+
/**
|
|
34
|
+
* Walk an arbitrary JSON-ish value and collect `$params.X` references
|
|
35
|
+
* found in string-valued leaves, returning only the first dotted segment
|
|
36
|
+
* (`"X"` for `$params.X.Y`). Intentionally more lenient than the
|
|
37
|
+
* server-side helper, which pushes the full path — see the module
|
|
38
|
+
* doc-comment for the rationale.
|
|
39
|
+
*/
|
|
40
|
+
export function collectParamRefs(value) {
|
|
41
|
+
const refs = [];
|
|
42
|
+
if (typeof value === "string") {
|
|
43
|
+
const match = value.match(/^\$params\.(.+)$/);
|
|
44
|
+
if (match) {
|
|
45
|
+
const first = match[1].split(/[.\[]/)[0];
|
|
46
|
+
if (first)
|
|
47
|
+
refs.push(first);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
else if (Array.isArray(value)) {
|
|
51
|
+
for (const item of value) {
|
|
52
|
+
refs.push(...collectParamRefs(item));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else if (value !== null && typeof value === "object") {
|
|
56
|
+
for (const v of Object.values(value)) {
|
|
57
|
+
refs.push(...collectParamRefs(v));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return refs;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Collect bare `params.X` references from a CEL string (issue #1239).
|
|
64
|
+
*
|
|
65
|
+
* Access rules reference operation params with the bare `params.X` form (no
|
|
66
|
+
* `$` prefix), unlike `definition`, which uses `$params.X` (scanned by
|
|
67
|
+
* {@link collectParamRefs}). This helper feeds the operation's `access` CEL
|
|
68
|
+
* and each per-param `access` CEL into the "referenced" set so a param used
|
|
69
|
+
* only by an access rule is not wrongly flagged "declared but not referenced".
|
|
70
|
+
*
|
|
71
|
+
* Supported forms, all whitespace-tolerant:
|
|
72
|
+
* - dot notation: `params.claimedUserId`, `params . claimedUserId`
|
|
73
|
+
* - dot path: `params.config.subField` → first segment `config`
|
|
74
|
+
* - bracket notation: `params["claimedUserId"]`, `params['claimedUserId']`
|
|
75
|
+
*
|
|
76
|
+
* Word-boundary guard: a `params` preceded by an identifier char, `$`, or `.`
|
|
77
|
+
* is NOT a match, so `$params.x` (definition syntax), `myparams.x`, and a
|
|
78
|
+
* dotted member access like `database.metadata.params.userId` are ignored —
|
|
79
|
+
* `params` only counts as the params root when it's a standalone root
|
|
80
|
+
* identifier. To avoid counting a `params.` that merely appears inside a quoted
|
|
81
|
+
* string literal (e.g. `note == "see params.docs"`), bracket keys are scanned
|
|
82
|
+
* first (they legitimately contain quotes), then string literals are stripped
|
|
83
|
+
* before the dot-notation scan.
|
|
84
|
+
*
|
|
85
|
+
* Purely additive: this only grows the referenced set, loosening the soft
|
|
86
|
+
* warning. The blocking `$params` error path is untouched.
|
|
87
|
+
*/
|
|
88
|
+
export function collectCelParamRefs(cel) {
|
|
89
|
+
if (typeof cel !== "string" || cel.length === 0)
|
|
90
|
+
return [];
|
|
91
|
+
const refs = [];
|
|
92
|
+
// Bracket notation: params["X"] / params['X']. Run before stripping string
|
|
93
|
+
// literals so the quoted key survives.
|
|
94
|
+
const bracketRe = /(?<![\w$.])params\s*\[\s*["']([^"']+)["']\s*\]/g;
|
|
95
|
+
let m;
|
|
96
|
+
while ((m = bracketRe.exec(cel)) !== null) {
|
|
97
|
+
const first = m[1].split(/[.\[]/)[0];
|
|
98
|
+
if (first)
|
|
99
|
+
refs.push(first);
|
|
100
|
+
}
|
|
101
|
+
// Drop string literals so `params.` inside a quoted string is not counted.
|
|
102
|
+
const withoutStrings = cel.replace(/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'/g, "");
|
|
103
|
+
// Dot notation: params.X (first segment only, mirroring collectParamRefs).
|
|
104
|
+
const dotRe = /(?<![\w$.])params\s*\.\s*([A-Za-z_$][\w$]*)/g;
|
|
105
|
+
while ((m = dotRe.exec(withoutStrings)) !== null) {
|
|
106
|
+
refs.push(m[1]);
|
|
107
|
+
}
|
|
108
|
+
return refs;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Collect the per-param `access` CEL strings from an operation's `params`
|
|
112
|
+
* value (object, array, or JSON string form). Used by issue #1239 to count
|
|
113
|
+
* params referenced only inside another param's `access` rule.
|
|
114
|
+
*/
|
|
115
|
+
function collectParamAccessCels(params) {
|
|
116
|
+
const cels = [];
|
|
117
|
+
if (params == null)
|
|
118
|
+
return cels;
|
|
119
|
+
let value = params;
|
|
120
|
+
if (typeof value === "string") {
|
|
121
|
+
try {
|
|
122
|
+
value = JSON.parse(value);
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
return cels;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (Array.isArray(value)) {
|
|
129
|
+
for (const row of value) {
|
|
130
|
+
if (row && typeof row === "object" && typeof row.access === "string") {
|
|
131
|
+
cels.push(row.access);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
else if (typeof value === "object" && value !== null) {
|
|
136
|
+
for (const entry of Object.values(value)) {
|
|
137
|
+
if (entry && typeof entry === "object" && typeof entry.access === "string") {
|
|
138
|
+
cels.push(entry.access);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return cels;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Normalize a `params` value (object, array, or JSON string) into the
|
|
146
|
+
* set of declared param names.
|
|
147
|
+
*/
|
|
148
|
+
export function declaredParamNames(params) {
|
|
149
|
+
const names = new Set();
|
|
150
|
+
if (params == null)
|
|
151
|
+
return names;
|
|
152
|
+
let value = params;
|
|
153
|
+
if (typeof value === "string") {
|
|
154
|
+
try {
|
|
155
|
+
value = JSON.parse(value);
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
return names;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
if (Array.isArray(value)) {
|
|
162
|
+
for (const row of value) {
|
|
163
|
+
if (row && typeof row === "object" && typeof row.name === "string") {
|
|
164
|
+
names.add(row.name);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
else if (typeof value === "object" && value !== null) {
|
|
169
|
+
for (const key of Object.keys(value)) {
|
|
170
|
+
names.add(key);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return names;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Find the 1-indexed line number in `rawToml` where the `[[operations]]`
|
|
177
|
+
* block declaring `opName` starts. Returns 0 if not found.
|
|
178
|
+
*
|
|
179
|
+
* Implementation: walk in source order, track the most recent
|
|
180
|
+
* `[[operations]]` header, and when we see a `name = "<opName>"` line
|
|
181
|
+
* before the next `[[operations]]` or top-level header, return that
|
|
182
|
+
* header's line.
|
|
183
|
+
*/
|
|
184
|
+
export function locateOperationLine(rawToml, opName) {
|
|
185
|
+
const lines = rawToml.split(/\r?\n/);
|
|
186
|
+
let lastOpHeader = 0;
|
|
187
|
+
let armed = false;
|
|
188
|
+
for (let i = 0; i < lines.length; i++) {
|
|
189
|
+
const line = lines[i].trim();
|
|
190
|
+
if (line === "[[operations]]") {
|
|
191
|
+
lastOpHeader = i + 1;
|
|
192
|
+
armed = true;
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
if (!armed)
|
|
196
|
+
continue;
|
|
197
|
+
// Another array-of-tables / top-level table → not this op anymore.
|
|
198
|
+
if (line.startsWith("[[") && line !== "[[operations]]" && !line.startsWith("[[operations.")) {
|
|
199
|
+
armed = false;
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
if (line.startsWith("[") && !line.startsWith("[[") && !line.startsWith("[operations.")) {
|
|
203
|
+
armed = false;
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
const m = line.match(/^name\s*=\s*["'](.+)["']\s*$/);
|
|
207
|
+
if (m && m[1] === opName) {
|
|
208
|
+
return lastOpHeader;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return 0;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Validate `$params` references across every operation in a parsed
|
|
215
|
+
* database-type config.
|
|
216
|
+
*
|
|
217
|
+
* Errors (blocking):
|
|
218
|
+
* - A `$params.X` reference inside `definition` where `X` is not
|
|
219
|
+
* declared in `[[operations.params]]`.
|
|
220
|
+
*
|
|
221
|
+
* Warnings (soft, not blocking):
|
|
222
|
+
* - A param declared in `[[operations.params]]` that is not referenced
|
|
223
|
+
* anywhere in `definition`. Authors may be staging a deprecation.
|
|
224
|
+
*/
|
|
225
|
+
export function validateOperations(opts) {
|
|
226
|
+
const errors = [];
|
|
227
|
+
const warnings = [];
|
|
228
|
+
for (const op of opts.operations) {
|
|
229
|
+
if (!op || !op.name)
|
|
230
|
+
continue;
|
|
231
|
+
const declared = declaredParamNames(op.params);
|
|
232
|
+
// `definitionRefs` drives the BLOCKING error loop and must stay limited to
|
|
233
|
+
// `$params.X` references inside `definition` — access CEL refs are NOT
|
|
234
|
+
// declarations, so they must never produce an "undeclared" error.
|
|
235
|
+
const definitionRefs = new Set(collectParamRefs(op.definition));
|
|
236
|
+
// Issue #1239: a param referenced only by an access CEL rule (bare
|
|
237
|
+
// `params.X`) is still referenced. The "declared but not referenced"
|
|
238
|
+
// warning uses a wider set that also counts the operation-level `access`
|
|
239
|
+
// and each per-param `access` CEL. Purely additive — the blocking error
|
|
240
|
+
// path below is built only from `definitionRefs`.
|
|
241
|
+
const referenced = new Set(definitionRefs);
|
|
242
|
+
for (const ref of collectCelParamRefs(op.access))
|
|
243
|
+
referenced.add(ref);
|
|
244
|
+
for (const cel of collectParamAccessCels(op.params)) {
|
|
245
|
+
for (const ref of collectCelParamRefs(cel))
|
|
246
|
+
referenced.add(ref);
|
|
247
|
+
}
|
|
248
|
+
const line = locateOperationLine(opts.rawToml, op.name);
|
|
249
|
+
for (const ref of definitionRefs) {
|
|
250
|
+
if (!declared.has(ref)) {
|
|
251
|
+
errors.push({
|
|
252
|
+
file: opts.filePath,
|
|
253
|
+
line,
|
|
254
|
+
op: op.name,
|
|
255
|
+
message: `$params.${ref} not declared in [[operations.params]] for operation '${op.name}'`,
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
for (const name of declared) {
|
|
260
|
+
if (!referenced.has(name)) {
|
|
261
|
+
warnings.push({
|
|
262
|
+
file: opts.filePath,
|
|
263
|
+
line,
|
|
264
|
+
op: op.name,
|
|
265
|
+
message: `param '${name}' declared but not referenced in operation '${op.name}'`,
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
// Issue #1255 (Fork 4): warn on unknown filter operators. The server only
|
|
270
|
+
// checks that `filter` is an object at push time, so a typo like
|
|
271
|
+
// `$gt` → `$gte` or an invented `$foo` slips through and throws
|
|
272
|
+
// `InvalidOperatorError` only at query execution. We warn (not error) to
|
|
273
|
+
// avoid CLI/server divergence — the operator set could drift, and the
|
|
274
|
+
// server stays authoritative.
|
|
275
|
+
const filter = op.definition && typeof op.definition === "object"
|
|
276
|
+
? op.definition.filter
|
|
277
|
+
: undefined;
|
|
278
|
+
for (const badOp of collectUnknownOperators(filter)) {
|
|
279
|
+
warnings.push({
|
|
280
|
+
file: opts.filePath,
|
|
281
|
+
line,
|
|
282
|
+
op: op.name,
|
|
283
|
+
message: `unknown filter operator '${badOp}' in operation '${op.name}' — not a recognized query operator; it will fail at query execution`,
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return { errors, warnings };
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Format a validation issue as `<file>:<line>: <message>`.
|
|
291
|
+
*/
|
|
292
|
+
export function formatIssue(issue) {
|
|
293
|
+
if (issue.line > 0) {
|
|
294
|
+
return `${issue.file}:${issue.line}: ${issue.message}`;
|
|
295
|
+
}
|
|
296
|
+
return `${issue.file}: ${issue.message}`;
|
|
297
|
+
}
|
|
298
|
+
//# sourceMappingURL=toml-params-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toml-params-validator.js","sourceRoot":"","sources":["../../../src/lib/toml-params-validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks if a newer version of the CLI is available on npm.
|
|
3
|
+
*
|
|
4
|
+
* - Stable versions (e.g. "1.0.22") check the "latest" dist-tag
|
|
5
|
+
* - Prerelease versions (e.g. "1.0.23-alpha.3") check their channel's
|
|
6
|
+
* dist-tag (e.g. "alpha"), falling back to "latest" if that tag doesn't exist
|
|
7
|
+
*
|
|
8
|
+
* Caches results per dist-tag for 4 hours. Fails silently on any error.
|
|
9
|
+
*/
|
|
10
|
+
export declare function checkForUpdate(currentVersion: string): Promise<void>;
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
2
|
+
import { homedir } from "os";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
const CONFIG_DIR = process.env.PRIMITIVE_CONFIG_DIR || join(homedir(), ".primitive");
|
|
6
|
+
const VERSION_CHECK_FILE = join(CONFIG_DIR, "version-check.json");
|
|
7
|
+
// Cache the result for 4 hours — short enough that users see new
|
|
8
|
+
// releases the same day they drop, long enough that chatty commands
|
|
9
|
+
// (sync push, tests in loops, etc.) don't hammer the npm registry.
|
|
10
|
+
const CHECK_INTERVAL_MS = 4 * 60 * 60 * 1000;
|
|
11
|
+
const NPM_PACKAGE_NAME = "primitive-admin";
|
|
12
|
+
const FETCH_TIMEOUT_MS = 3000;
|
|
13
|
+
function ensureConfigDir() {
|
|
14
|
+
if (!existsSync(CONFIG_DIR)) {
|
|
15
|
+
mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function loadCache() {
|
|
19
|
+
try {
|
|
20
|
+
if (!existsSync(VERSION_CHECK_FILE))
|
|
21
|
+
return {};
|
|
22
|
+
return JSON.parse(readFileSync(VERSION_CHECK_FILE, "utf-8"));
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return {};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function saveCache(cache) {
|
|
29
|
+
try {
|
|
30
|
+
ensureConfigDir();
|
|
31
|
+
writeFileSync(VERSION_CHECK_FILE, JSON.stringify(cache, null, 2));
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// Ignore write errors
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Extracts the prerelease channel from a version string.
|
|
39
|
+
* "1.0.23-alpha.3" → "alpha"
|
|
40
|
+
* "1.0.23-beta.1" → "beta"
|
|
41
|
+
* "1.0.23" → null
|
|
42
|
+
*/
|
|
43
|
+
function getPrereleaseChannel(version) {
|
|
44
|
+
const match = version.match(/^[^-]+-([a-zA-Z]+)/);
|
|
45
|
+
return match ? match[1] : null;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Compares two semver version strings, including prerelease handling.
|
|
49
|
+
* Returns -1 if a < b, 0 if equal, 1 if a > b.
|
|
50
|
+
*
|
|
51
|
+
* Prerelease versions are only compared against their own channel.
|
|
52
|
+
* Within the same channel, prerelease segments are compared numerically.
|
|
53
|
+
*/
|
|
54
|
+
function compareVersions(a, b) {
|
|
55
|
+
const clean = (v) => v.replace(/^v/, "");
|
|
56
|
+
const cleanA = clean(a);
|
|
57
|
+
const cleanB = clean(b);
|
|
58
|
+
// Split into core and prerelease
|
|
59
|
+
const [coreA, preA] = cleanA.split("-", 2);
|
|
60
|
+
const [coreB, preB] = cleanB.split("-", 2);
|
|
61
|
+
// Compare core version (major.minor.patch)
|
|
62
|
+
const partsA = coreA.split(".").map(Number);
|
|
63
|
+
const partsB = coreB.split(".").map(Number);
|
|
64
|
+
for (let i = 0; i < 3; i++) {
|
|
65
|
+
const ca = partsA[i] || 0;
|
|
66
|
+
const cb = partsB[i] || 0;
|
|
67
|
+
if (ca < cb)
|
|
68
|
+
return -1;
|
|
69
|
+
if (ca > cb)
|
|
70
|
+
return 1;
|
|
71
|
+
}
|
|
72
|
+
// Core versions are equal — compare prerelease
|
|
73
|
+
// No prerelease on either → equal
|
|
74
|
+
if (!preA && !preB)
|
|
75
|
+
return 0;
|
|
76
|
+
// A prerelease version is always less than the release version
|
|
77
|
+
if (preA && !preB)
|
|
78
|
+
return -1;
|
|
79
|
+
if (!preA && preB)
|
|
80
|
+
return 1;
|
|
81
|
+
// Both have prerelease — compare segments (e.g. "alpha.3" vs "alpha.5")
|
|
82
|
+
const segsA = preA.split(".");
|
|
83
|
+
const segsB = preB.split(".");
|
|
84
|
+
const len = Math.max(segsA.length, segsB.length);
|
|
85
|
+
for (let i = 0; i < len; i++) {
|
|
86
|
+
const sa = segsA[i];
|
|
87
|
+
const sb = segsB[i];
|
|
88
|
+
if (sa === undefined)
|
|
89
|
+
return -1;
|
|
90
|
+
if (sb === undefined)
|
|
91
|
+
return 1;
|
|
92
|
+
const na = Number(sa);
|
|
93
|
+
const nb = Number(sb);
|
|
94
|
+
const aIsNum = !isNaN(na);
|
|
95
|
+
const bIsNum = !isNaN(nb);
|
|
96
|
+
if (aIsNum && bIsNum) {
|
|
97
|
+
if (na < nb)
|
|
98
|
+
return -1;
|
|
99
|
+
if (na > nb)
|
|
100
|
+
return 1;
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
// Lexicographic comparison for non-numeric segments
|
|
104
|
+
if (sa < sb)
|
|
105
|
+
return -1;
|
|
106
|
+
if (sa > sb)
|
|
107
|
+
return 1;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return 0;
|
|
111
|
+
}
|
|
112
|
+
async function fetchLatestVersion(distTag) {
|
|
113
|
+
try {
|
|
114
|
+
const controller = new AbortController();
|
|
115
|
+
const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
|
|
116
|
+
const response = await fetch(`https://registry.npmjs.org/${NPM_PACKAGE_NAME}/${distTag}`, { signal: controller.signal });
|
|
117
|
+
clearTimeout(timeout);
|
|
118
|
+
if (!response.ok)
|
|
119
|
+
return null;
|
|
120
|
+
const data = await response.json();
|
|
121
|
+
return data.version;
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Checks if a newer version of the CLI is available on npm.
|
|
129
|
+
*
|
|
130
|
+
* - Stable versions (e.g. "1.0.22") check the "latest" dist-tag
|
|
131
|
+
* - Prerelease versions (e.g. "1.0.23-alpha.3") check their channel's
|
|
132
|
+
* dist-tag (e.g. "alpha"), falling back to "latest" if that tag doesn't exist
|
|
133
|
+
*
|
|
134
|
+
* Caches results per dist-tag for 4 hours. Fails silently on any error.
|
|
135
|
+
*/
|
|
136
|
+
export async function checkForUpdate(currentVersion) {
|
|
137
|
+
try {
|
|
138
|
+
const channel = getPrereleaseChannel(currentVersion);
|
|
139
|
+
const distTag = channel || "latest";
|
|
140
|
+
const cache = loadCache();
|
|
141
|
+
const now = Date.now();
|
|
142
|
+
let latestVersion = null;
|
|
143
|
+
const cached = cache[distTag];
|
|
144
|
+
if (cached && (now - cached.lastCheck) < CHECK_INTERVAL_MS) {
|
|
145
|
+
latestVersion = cached.latestVersion;
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
latestVersion = await fetchLatestVersion(distTag);
|
|
149
|
+
// If the prerelease dist-tag doesn't exist on npm, fall back to "latest"
|
|
150
|
+
// so alpha users still hear about new stable releases
|
|
151
|
+
if (!latestVersion && channel) {
|
|
152
|
+
latestVersion = await fetchLatestVersion("latest");
|
|
153
|
+
}
|
|
154
|
+
if (latestVersion) {
|
|
155
|
+
cache[distTag] = { lastCheck: now, latestVersion };
|
|
156
|
+
saveCache(cache);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (latestVersion && compareVersions(currentVersion, latestVersion) < 0) {
|
|
160
|
+
const installCmd = channel
|
|
161
|
+
? `npm i -g ${NPM_PACKAGE_NAME}@${channel}`
|
|
162
|
+
: `npm i -g ${NPM_PACKAGE_NAME}`;
|
|
163
|
+
console.error();
|
|
164
|
+
console.error(chalk.yellow(`Update available: ${chalk.dim(currentVersion)} -> ${chalk.green.bold(latestVersion)}`));
|
|
165
|
+
console.error(chalk.yellow(`Run ${chalk.cyan.bold(installCmd)} to update`));
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
// Never let version check errors affect CLI operation
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=version-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version-check.js","sourceRoot":"","sources":["../../../src/lib/version-check.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared "apply a TOML body to an existing workflow" helper.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from the `sync push` update-existing path (#1249, Fork 4) so that
|
|
5
|
+
* both `sync push` and `workflows update --from-file` push a revised body the
|
|
6
|
+
* same way. A second inlined copy would regress #807: the update is
|
|
7
|
+
* ordering-sensitive and a naive metadata-then-body sequence rejects valid
|
|
8
|
+
* sync-callable edits.
|
|
9
|
+
*
|
|
10
|
+
* Ordering invariant (#807 / codex review):
|
|
11
|
+
* 1. metadata PATCH — WITHOUT `syncCallable`. The server re-validates
|
|
12
|
+
* `syncCallable: true` against the workflow's CURRENTLY-active server
|
|
13
|
+
* steps (`loadCurrentActiveSteps`, src/admin-api.ts:4734), not the steps
|
|
14
|
+
* being pushed in the same call. So enabling sync-callable in the first
|
|
15
|
+
* PATCH would validate against the stale active steps and be rejected.
|
|
16
|
+
* 2. body write — steps to the active config (config-model) or the legacy
|
|
17
|
+
* draft slot (no active config).
|
|
18
|
+
* 3. a SECOND `syncCallable` PATCH — issued AFTER the new steps are active,
|
|
19
|
+
* so it validates against the new (compatible) steps.
|
|
20
|
+
*/
|
|
21
|
+
import type { ApiClient } from "./api-client.js";
|
|
22
|
+
/**
|
|
23
|
+
* Safely parse a JSON field that may be a string or already an object. TOML can
|
|
24
|
+
* parse inline tables as objects, so we accept both. (Same semantics as the
|
|
25
|
+
* `safeJsonParse` in sync.ts — kept here so the shared apply helper owns its
|
|
26
|
+
* own parse decision without importing back into a command module.)
|
|
27
|
+
*/
|
|
28
|
+
export declare function safeJsonParse(value: any): any;
|
|
29
|
+
export interface ApplyWorkflowBodyOptions {
|
|
30
|
+
/** Optimistic-concurrency guard for the metadata + syncCallable PATCHes. */
|
|
31
|
+
expectedModifiedAt?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Active config to overwrite in place (config-model workflows). When absent,
|
|
34
|
+
* the body falls back to the legacy draft slot — non-live for config-model
|
|
35
|
+
* workflows, which the server rejects with 409 WORKFLOW_CONFIG_MODEL.
|
|
36
|
+
*/
|
|
37
|
+
activeConfigId?: string;
|
|
38
|
+
/** When true, skip the optimistic-concurrency check (mirrors `--force`). */
|
|
39
|
+
force?: boolean;
|
|
40
|
+
}
|
|
41
|
+
export interface ApplyWorkflowBodyResult {
|
|
42
|
+
/** The freshest workflow `modifiedAt` after all PATCHes (for sync state). */
|
|
43
|
+
latestModifiedAt?: string;
|
|
44
|
+
/** Which slot the steps landed in: "active config" or "draft (legacy)". */
|
|
45
|
+
updateSlotLabel: string;
|
|
46
|
+
/** A fresh `getWorkflow` result so callers can read back configs/state. */
|
|
47
|
+
fullWorkflow: any;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Apply a parsed workflow body (metadata + steps) to an existing workflow,
|
|
51
|
+
* preserving the key/id. `workflow` is the TOML's `[workflow]` table (already
|
|
52
|
+
* merged with any explicit CLI flag overrides by the caller); `steps` is the
|
|
53
|
+
* TOML's `steps` array. The function performs the three-step ordered update
|
|
54
|
+
* and returns the latest `modifiedAt`, the slot label, and a fresh workflow.
|
|
55
|
+
*/
|
|
56
|
+
export declare function applyWorkflowBody(client: ApiClient, appId: string, workflowId: string, workflow: any, steps: any[], opts?: ApplyWorkflowBodyOptions): Promise<ApplyWorkflowBodyResult>;
|
|
57
|
+
/**
|
|
58
|
+
* Fork 2 (#1249): a TOML pushed at a specific `<id>` may also declare a `key` /
|
|
59
|
+
* `workflowKey`. If it differs from the target's actual key, that's almost
|
|
60
|
+
* certainly the wrong file — error rather than silently ignoring it. An absent
|
|
61
|
+
* TOML key is advisory and allowed (the operation targets `<id>`).
|
|
62
|
+
*
|
|
63
|
+
* Returns an error message string when there is a mismatch, otherwise null.
|
|
64
|
+
* Pure function for unit testing.
|
|
65
|
+
*/
|
|
66
|
+
export declare function workflowKeyMismatchError(tomlWorkflow: any, existingWorkflowKey: string | undefined): string | null;
|