primitive-admin 1.1.0 → 1.2.0-alpha.0
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 +11 -11
- package/assets/skill/skills/primitive-platform/SKILL.md +6 -0
- package/dist/src/commands/collections.js +20 -17
- package/dist/src/commands/collections.js.map +1 -1
- package/dist/src/commands/database-types.js +13 -313
- package/dist/src/commands/database-types.js.map +1 -1
- package/dist/src/commands/databases.js +0 -19
- package/dist/src/commands/databases.js.map +1 -1
- package/dist/src/commands/groups.js +16 -0
- package/dist/src/commands/groups.js.map +1 -1
- package/dist/src/commands/llm.js +9 -6
- package/dist/src/commands/llm.js.map +1 -1
- package/dist/src/commands/settings.d.ts +18 -0
- package/dist/src/commands/settings.js +54 -0
- package/dist/src/commands/settings.js.map +1 -0
- package/dist/src/commands/sync.d.ts +1 -4
- package/dist/src/commands/sync.js +42 -45
- package/dist/src/commands/sync.js.map +1 -1
- package/dist/src/commands/workflows.js +3 -3
- package/dist/src/commands/workflows.js.map +1 -1
- package/dist/src/lib/api-client.d.ts +3 -40
- package/dist/src/lib/api-client.js +20 -69
- package/dist/src/lib/api-client.js.map +1 -1
- package/dist/src/lib/app-match-guard.d.ts +44 -0
- package/dist/src/lib/app-match-guard.js +72 -0
- package/dist/src/lib/app-match-guard.js.map +1 -0
- package/dist/src/lib/collection-export.d.ts +37 -9
- package/dist/src/lib/collection-export.js +48 -12
- package/dist/src/lib/collection-export.js.map +1 -1
- package/dist/src/lib/function-triggers.d.ts +66 -0
- package/dist/src/lib/function-triggers.js +285 -0
- package/dist/src/lib/function-triggers.js.map +1 -0
- package/dist/src/lib/generated-allowlist.js +0 -1
- package/dist/src/lib/generated-allowlist.js.map +1 -1
- package/dist/src/lib/generated-config-surfaces.js +56 -32
- package/dist/src/lib/generated-config-surfaces.js.map +1 -1
- package/dist/src/lib/generated-sdk-types.d.ts +1 -1
- package/dist/src/lib/generated-sdk-types.js +1 -1
- package/dist/src/lib/generated-sdk-types.js.map +1 -1
- package/dist/src/lib/generated-workflow-model-fields.d.ts +20 -0
- package/dist/src/lib/generated-workflow-model-fields.js +53 -0
- package/dist/src/lib/generated-workflow-model-fields.js.map +1 -0
- package/dist/src/lib/google-client-secret-status.d.ts +35 -0
- package/dist/src/lib/google-client-secret-status.js +56 -0
- package/dist/src/lib/google-client-secret-status.js.map +1 -0
- package/dist/src/lib/log-inspection.d.ts +1 -6
- package/dist/src/lib/log-inspection.js +5 -7
- package/dist/src/lib/log-inspection.js.map +1 -1
- package/dist/src/lib/migration-nag.d.ts +2 -2
- package/dist/src/lib/migration-nag.js +4 -3
- package/dist/src/lib/migration-nag.js.map +1 -1
- package/dist/src/lib/paginate.d.ts +8 -24
- package/dist/src/lib/paginate.js +8 -21
- package/dist/src/lib/paginate.js.map +1 -1
- package/dist/src/lib/sync-dir-selector.d.ts +1 -1
- package/dist/src/lib/sync-dir-selector.js +1 -1
- package/dist/src/lib/toml-database-config.js +2 -2
- package/dist/src/lib/toml-database-config.js.map +1 -1
- package/dist/src/lib/workflow-field-descriptor.d.ts +91 -0
- package/dist/src/lib/workflow-field-descriptor.js +153 -0
- package/dist/src/lib/workflow-field-descriptor.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `primitive settings` — the app-settings READER (issue #1033, Phase 2;
|
|
3
|
+
* narrowed to a reader by #2645).
|
|
4
|
+
*
|
|
5
|
+
* App settings are authored in `app.toml` and applied with `sync push`, so
|
|
6
|
+
* this group carries the one thing the file cannot answer: what the server is
|
|
7
|
+
* actually running. `settings get` renders the server-effective settings —
|
|
8
|
+
* `get` rather than `show`, so the read verb is the same word on every
|
|
9
|
+
* configuration surface.
|
|
10
|
+
*
|
|
11
|
+
* `settings pull`, `settings diff` and `settings push` are gone. They operated
|
|
12
|
+
* on the same `app.toml` and the same `entities.app` hash `sync` owns, so they
|
|
13
|
+
* were a second pathway to one piece of state; `sync pull|diff|push --only app`
|
|
14
|
+
* is the single one. The remaining command logic lives in
|
|
15
|
+
* `sync-app-settings.ts`, shared with `sync`.
|
|
16
|
+
*/
|
|
17
|
+
import { ApiClient } from "../lib/api-client.js";
|
|
18
|
+
import { resolveAppId } from "../lib/config.js";
|
|
19
|
+
import { showAppSettings } from "./sync-app-settings.js";
|
|
20
|
+
export function registerSettingsCommands(program) {
|
|
21
|
+
const settings = program
|
|
22
|
+
.command("settings")
|
|
23
|
+
.description("View the app settings the server is running")
|
|
24
|
+
.addHelpText("after", `
|
|
25
|
+
Examples:
|
|
26
|
+
$ primitive settings get # Render current server settings
|
|
27
|
+
$ primitive settings get --json # Machine-readable
|
|
28
|
+
$ primitive sync pull --only app # Write server settings to app.toml
|
|
29
|
+
$ primitive config set app app.baseUrl=https://example.com
|
|
30
|
+
$ primitive sync diff --only app # Show local app.toml vs server
|
|
31
|
+
$ primitive sync push --only app # Apply app.toml edits to the server
|
|
32
|
+
|
|
33
|
+
app.toml is the ONLY way to manage app configuration (issue #2645): a full
|
|
34
|
+
\`sync push\` applies it, and \`sync push --only app\` applies it alone.
|
|
35
|
+
\`primitive config fields app\` lists its keys, types and defaults. The Google OAuth
|
|
36
|
+
client secret is an ordinary [auth] key holding a reference into the app's
|
|
37
|
+
secret store, never the secret itself: store the value with
|
|
38
|
+
'primitive secrets set GOOGLE_CLIENT_SECRET --value <secret>', then set
|
|
39
|
+
googleClientSecret = "{{secrets.GOOGLE_CLIENT_SECRET}}" in app.toml. A literal
|
|
40
|
+
secret there is rejected by the server.
|
|
41
|
+
`);
|
|
42
|
+
// settings get
|
|
43
|
+
settings
|
|
44
|
+
.command("get")
|
|
45
|
+
.description("Show the current server-effective app settings")
|
|
46
|
+
.argument("[app-id]", "App ID (uses current app if not specified)")
|
|
47
|
+
.option("--app <app-id>", "App ID")
|
|
48
|
+
.option("--json", "Output as JSON")
|
|
49
|
+
.action(async (appId, options) => {
|
|
50
|
+
const resolvedAppId = resolveAppId(appId, options);
|
|
51
|
+
await showAppSettings(new ApiClient(), resolvedAppId, options);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../../src/commands/settings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,MAAM,UAAU,wBAAwB,CAAC,OAAgB;IACvD,MAAM,QAAQ,GAAG,OAAO;SACrB,OAAO,CAAC,UAAU,CAAC;SACnB,WAAW,CAAC,6CAA6C,CAAC;SAC1D,WAAW,CACV,OAAO,EACP;;;;;;;;;;;;;;;;;CAiBL,CACI,CAAC;IAEJ,eAAe;IACf,QAAQ;SACL,OAAO,CAAC,KAAK,CAAC;SACd,WAAW,CAAC,gDAAgD,CAAC;SAC7D,QAAQ,CAAC,UAAU,EAAE,4CAA4C,CAAC;SAClE,MAAM,CAAC,gBAAgB,EAAE,QAAQ,CAAC;SAClC,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;SAClC,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QAC/B,MAAM,aAAa,GAAG,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACnD,MAAM,eAAe,CAAC,IAAI,SAAS,EAAE,EAAE,aAAa,EAAE,OAAO,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -706,9 +706,6 @@ export declare function buildBlobBucketUpdatePayload(bucket: any): any;
|
|
|
706
706
|
* first-wins rule: making the file's meaning depend on entry order is the kind
|
|
707
707
|
* of implicit behavior this issue exists to remove, and silently picking one
|
|
708
708
|
* would let the repo claim something the server does not do.
|
|
709
|
-
*
|
|
710
|
-
* `isActive` is accepted as a legacy spelling — the create leg read it before
|
|
711
|
-
* pull ever wrote a marker, so a hand-authored file carrying it keeps working.
|
|
712
709
|
*/
|
|
713
710
|
export declare function promptActiveConfigName(configs: any[]): string | undefined;
|
|
714
711
|
/**
|
|
@@ -1554,7 +1551,7 @@ export declare function hashLocalConfigForDiff(spec: ConfigDiffSpec, parsedToml:
|
|
|
1554
1551
|
* Hash a SERVER entity the same way, by serializing it into the file `sync
|
|
1555
1552
|
* pull` would write and hashing that — so the two sides are normalized
|
|
1556
1553
|
* identically by construction, and a legacy encoding on disk (a JSON-string
|
|
1557
|
-
* operation
|
|
1554
|
+
* operation) is not a false `Modified`.
|
|
1558
1555
|
*
|
|
1559
1556
|
* `extra` carries the sibling rows a type's file also holds: a database type's
|
|
1560
1557
|
* operations and subscriptions, which the list response does not include.
|
|
@@ -1698,12 +1698,9 @@ const PROMPT_CONFIG_DEFAULT_STATUS = fieldServerDefault(PROMPT_CONFIG_TABLE, "st
|
|
|
1698
1698
|
* first-wins rule: making the file's meaning depend on entry order is the kind
|
|
1699
1699
|
* of implicit behavior this issue exists to remove, and silently picking one
|
|
1700
1700
|
* would let the repo claim something the server does not do.
|
|
1701
|
-
*
|
|
1702
|
-
* `isActive` is accepted as a legacy spelling — the create leg read it before
|
|
1703
|
-
* pull ever wrote a marker, so a hand-authored file carrying it keeps working.
|
|
1704
1701
|
*/
|
|
1705
1702
|
export function promptActiveConfigName(configs) {
|
|
1706
|
-
const marked = (configs || []).filter((c) => c?.active === true
|
|
1703
|
+
const marked = (configs || []).filter((c) => c?.active === true);
|
|
1707
1704
|
if (marked.length > 1) {
|
|
1708
1705
|
throw new Error(`Only one [[configs]] entry may set active = true; found ${marked.length} ` +
|
|
1709
1706
|
`(${marked.map((c) => c.name).join(", ")}).`);
|
|
@@ -4012,7 +4009,7 @@ export function parseDatabaseTypeToml(tomlData) {
|
|
|
4012
4009
|
},
|
|
4013
4010
|
}));
|
|
4014
4011
|
canonicalizeDatabaseTypeConfig(typeConfig);
|
|
4015
|
-
//
|
|
4012
|
+
// The `ruleSetName` reference; it resolves to an id later.
|
|
4016
4013
|
applyRuleSetReference(typeSection, typeConfig);
|
|
4017
4014
|
if (tomlData.triggers) {
|
|
4018
4015
|
typeConfig.triggers = tomlData.triggers;
|
|
@@ -4081,13 +4078,16 @@ export function parseRuleSetToml(tomlData) {
|
|
|
4081
4078
|
/**
|
|
4082
4079
|
* Read a config's rule-set reference off its TOML table (#2644).
|
|
4083
4080
|
*
|
|
4084
|
-
*
|
|
4085
|
-
* `ruleSetId` — and the name form is left as `_ruleSetName` for
|
|
4081
|
+
* One spelling, the portable `ruleSetName`, left as `_ruleSetName` for
|
|
4086
4082
|
* `resolveRuleSetReference` to turn into an id once the app's rule sets are
|
|
4087
|
-
* known.
|
|
4088
|
-
*
|
|
4083
|
+
* known. Absent means no reference, which push sends as an explicit `null` so
|
|
4084
|
+
* removing the line clears it (#1567). The id spelling `ruleSetId` is retired
|
|
4085
|
+
* (#3997): the preflight refuses it through `retired-keys.ts`, and it is never
|
|
4086
|
+
* read here, so no id authored in TOML reaches the wire.
|
|
4089
4087
|
*/
|
|
4090
4088
|
function applyRuleSetReference(section, entity) {
|
|
4089
|
+
// The payload builder put the `ruleSetName` value on the `ruleSetId` field;
|
|
4090
|
+
// the resolver sets the real id.
|
|
4091
4091
|
delete entity.ruleSetId;
|
|
4092
4092
|
if (section.ruleSetName && section.ruleSetName !== "") {
|
|
4093
4093
|
// Trimmed to match the name the server stores for the rule set itself
|
|
@@ -4097,9 +4097,6 @@ function applyRuleSetReference(section, entity) {
|
|
|
4097
4097
|
? section.ruleSetName.trim()
|
|
4098
4098
|
: section.ruleSetName;
|
|
4099
4099
|
}
|
|
4100
|
-
else if (section.ruleSetId && section.ruleSetId !== "") {
|
|
4101
|
-
entity.ruleSetId = section.ruleSetId;
|
|
4102
|
-
}
|
|
4103
4100
|
}
|
|
4104
4101
|
/** Drop keys the TOML did not carry, so `"x" in entity` stays meaningful. */
|
|
4105
4102
|
function dropUndefined(entity) {
|
|
@@ -4162,22 +4159,22 @@ export function parseCollectionTypeConfigToml(tomlData) {
|
|
|
4162
4159
|
// the SAME push parser before hashing.
|
|
4163
4160
|
//
|
|
4164
4161
|
// Parsing through the push parser — rather than hashing the raw parsed TOML —
|
|
4165
|
-
// is what makes the comparison encoding-independent, and is why the
|
|
4162
|
+
// is what makes the comparison encoding-independent, and is why the known
|
|
4166
4163
|
// false-diff traps do not fire: a legacy JSON-string operation and the native
|
|
4167
4164
|
// `[operations.definition]` table the server emits normalize to one shape
|
|
4168
|
-
// (`normalizeOperationFromToml`); a `ruleSetName` reference
|
|
4169
|
-
//
|
|
4170
|
-
//
|
|
4171
|
-
//
|
|
4172
|
-
//
|
|
4173
|
-
//
|
|
4165
|
+
// (`normalizeOperationFromToml`); a `ruleSetName` reference resolves to the id
|
|
4166
|
+
// the server holds (`normalizeRuleSetRefForDiff`); an omitted `autoAddCreator`
|
|
4167
|
+
// picks up the same default the server serializes (`parseGroupTypeConfigToml`);
|
|
4168
|
+
// and a metadata-category's identity is read from the parsed
|
|
4169
|
+
// `[metadataCategoryConfig]` content, not the filename. Hashing raw parsed TOML
|
|
4170
|
+
// would show a false `Modified` for each of those equivalent forms.
|
|
4174
4171
|
/**
|
|
4175
4172
|
* Resolve a parsed entity's rule-set reference to a stable id for hashing.
|
|
4176
4173
|
* `parseGroupTypeConfigToml` / `parseCollectionTypeConfigToml` /
|
|
4177
|
-
* `parseDatabaseTypeToml` leave
|
|
4178
|
-
*
|
|
4179
|
-
*
|
|
4180
|
-
*
|
|
4174
|
+
* `parseDatabaseTypeToml` leave the `ruleSetName` reference as `_ruleSetName`;
|
|
4175
|
+
* resolving it to `ruleSetId` here means the local file and the server entity
|
|
4176
|
+
* hash the same reference. `throwOnMissing: false` so an unresolvable name
|
|
4177
|
+
* degrades gracefully rather than aborting the diff.
|
|
4181
4178
|
*
|
|
4182
4179
|
* When the name does NOT resolve — a typo, or a rule set added locally in the
|
|
4183
4180
|
* same tree but not yet on the server — `resolveRuleSetReference` deletes
|
|
@@ -5066,7 +5063,7 @@ export function hashLocalConfigForDiff(spec, parsedToml, maps, extra) {
|
|
|
5066
5063
|
* Hash a SERVER entity the same way, by serializing it into the file `sync
|
|
5067
5064
|
* pull` would write and hashing that — so the two sides are normalized
|
|
5068
5065
|
* identically by construction, and a legacy encoding on disk (a JSON-string
|
|
5069
|
-
* operation
|
|
5066
|
+
* operation) is not a false `Modified`.
|
|
5070
5067
|
*
|
|
5071
5068
|
* `extra` carries the sibling rows a type's file also holds: a database type's
|
|
5072
5069
|
* operations and subscriptions, which the list response does not include.
|
|
@@ -17263,28 +17260,28 @@ What a push guarantees (two stages):
|
|
|
17263
17260
|
let unchangedCount = 0;
|
|
17264
17261
|
// ---- database-type-configs/ pass ----
|
|
17265
17262
|
if (dbFiles.length > 0) {
|
|
17266
|
-
//
|
|
17267
|
-
//
|
|
17268
|
-
//
|
|
17269
|
-
//
|
|
17270
|
-
//
|
|
17271
|
-
//
|
|
17272
|
-
|
|
17273
|
-
|
|
17274
|
-
|
|
17275
|
-
|
|
17276
|
-
|
|
17277
|
-
const migrateSyncState = loadSyncState(configDir);
|
|
17278
|
-
if (migrateSyncState?.entities?.ruleSets) {
|
|
17279
|
-
for (const [fileKey, entry] of Object.entries(migrateSyncState.entities.ruleSets)) {
|
|
17280
|
-
if (entry && typeof entry === "object" && "id" in entry && entry.id) {
|
|
17281
|
-
// fileKey is the sanitized rule-set name (see config pull at
|
|
17282
|
-
// sync.ts:1385). It's the same shape the server returned and
|
|
17283
|
-
// matches what a TOML file's ruleSetName field would carry.
|
|
17284
|
-
ruleSetIdToName.set(entry.id, fileKey);
|
|
17285
|
-
}
|
|
17286
|
-
}
|
|
17263
|
+
// #3997 — refuse a tree carrying a retired key (the id-based
|
|
17264
|
+
// `ruleSetId`) with the message `config push` gives, before anything is
|
|
17265
|
+
// rewritten. This is a separate pass, not a check inside the loop below:
|
|
17266
|
+
// that loop writes each file and saves sync state before it parses the
|
|
17267
|
+
// next, so an in-loop abort would leave earlier files rewritten. Every
|
|
17268
|
+
// offending file is reported, so the author fixes the tree once.
|
|
17269
|
+
const retiredKeyErrors = [];
|
|
17270
|
+
for (const file of dbFiles) {
|
|
17271
|
+
const message = configUnknownKeyError(`database-type-configs/${file}`, parseTomlFile(join(dbTypesDir, file)), DATABASE_TYPE_TABLE);
|
|
17272
|
+
if (message)
|
|
17273
|
+
retiredKeyErrors.push(message);
|
|
17287
17274
|
}
|
|
17275
|
+
if (retiredKeyErrors.length > 0) {
|
|
17276
|
+
for (const message of retiredKeyErrors)
|
|
17277
|
+
error(` ${message}`);
|
|
17278
|
+
error(`Aborting migrate-toml: ${retiredKeyErrors.length} database-type ` +
|
|
17279
|
+
"file(s) carry a retired or unrecognized key; nothing was rewritten.");
|
|
17280
|
+
process.exit(1);
|
|
17281
|
+
}
|
|
17282
|
+
// The parser yields the rule-set reference only as `_ruleSetName`,
|
|
17283
|
+
// which the serializer prefers, so there is no id to map to a name.
|
|
17284
|
+
const ruleSetIdToName = new Map();
|
|
17288
17285
|
for (const file of dbFiles) {
|
|
17289
17286
|
const filePath = join(dbTypesDir, file);
|
|
17290
17287
|
const rawBefore = readFileSync(filePath, "utf-8");
|