primitive-admin 1.0.48 → 1.0.50
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 +102 -2
- package/assets/skill/skills/primitive-platform/SKILL.md +85 -30
- package/dist/bin/primitive.d.ts +2 -0
- package/dist/bin/primitive.js +66 -1
- package/dist/bin/primitive.js.map +1 -1
- package/dist/src/commands/admins.d.ts +2 -0
- package/dist/src/commands/analytics.d.ts +2 -0
- package/dist/src/commands/apps.d.ts +2 -0
- package/dist/src/commands/apps.js +20 -0
- package/dist/src/commands/apps.js.map +1 -1
- package/dist/src/commands/auth.d.ts +2 -0
- package/dist/src/commands/blob-buckets.d.ts +2 -0
- package/dist/src/commands/catalog.d.ts +2 -0
- package/dist/src/commands/collection-type-configs.d.ts +2 -0
- package/dist/src/commands/collections.d.ts +2 -0
- package/dist/src/commands/comparisons.d.ts +2 -0
- package/dist/src/commands/cron-triggers.d.ts +2 -0
- package/dist/src/commands/cron-triggers.js +8 -15
- package/dist/src/commands/cron-triggers.js.map +1 -1
- package/dist/src/commands/database-types.d.ts +2 -0
- package/dist/src/commands/databases.d.ts +2 -0
- package/dist/src/commands/databases.js +31 -0
- package/dist/src/commands/databases.js.map +1 -1
- package/dist/src/commands/documents.d.ts +2 -0
- package/dist/src/commands/email-templates.d.ts +2 -0
- package/dist/src/commands/env.d.ts +12 -0
- package/dist/src/commands/group-type-configs.d.ts +2 -0
- package/dist/src/commands/groups.d.ts +2 -0
- package/dist/src/commands/guides.d.ts +84 -0
- package/dist/src/commands/guides.js +201 -24
- package/dist/src/commands/guides.js.map +1 -1
- package/dist/src/commands/init.d.ts +17 -0
- package/dist/src/commands/init.js +63 -25
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/integrations.d.ts +2 -0
- package/dist/src/commands/integrations.js +22 -5
- package/dist/src/commands/integrations.js.map +1 -1
- package/dist/src/commands/llm.d.ts +2 -0
- package/dist/src/commands/prompts.d.ts +2 -0
- package/dist/src/commands/rule-sets.d.ts +2 -0
- package/dist/src/commands/secrets.d.ts +2 -0
- package/dist/src/commands/skill.d.ts +2 -0
- package/dist/src/commands/sync.d.ts +113 -0
- package/dist/src/commands/sync.js +366 -12
- package/dist/src/commands/sync.js.map +1 -1
- package/dist/src/commands/tokens.d.ts +2 -0
- package/dist/src/commands/tokens.js +104 -1
- package/dist/src/commands/tokens.js.map +1 -1
- package/dist/src/commands/users.d.ts +2 -0
- package/dist/src/commands/waitlist.d.ts +2 -0
- package/dist/src/commands/waitlist.js +1 -1
- package/dist/src/commands/waitlist.js.map +1 -1
- package/dist/src/commands/webhooks.d.ts +2 -0
- package/dist/src/commands/workflows.d.ts +49 -0
- package/dist/src/commands/workflows.js +74 -21
- package/dist/src/commands/workflows.js.map +1 -1
- package/dist/src/lib/api-client.d.ts +1244 -0
- package/dist/src/lib/api-client.js +30 -0
- package/dist/src/lib/api-client.js.map +1 -1
- package/dist/src/lib/auth-flow.d.ts +8 -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 +37 -0
- package/dist/src/lib/confirm-prompt.d.ts +66 -0
- package/dist/src/lib/confirm-prompt.js +85 -0
- package/dist/src/lib/confirm-prompt.js.map +1 -0
- package/dist/src/lib/constants.d.ts +2 -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/csv.d.ts +48 -0
- package/dist/src/lib/db-codegen/dbFingerprint.d.ts +10 -0
- package/dist/src/lib/db-codegen/dbGenerator.d.ts +111 -0
- package/dist/src/lib/db-codegen/dbNaming.d.ts +45 -0
- package/dist/src/lib/db-codegen/dbTemplates.d.ts +97 -0
- package/dist/src/lib/db-codegen/dbTemplates.js +31 -10
- package/dist/src/lib/db-codegen/dbTemplates.js.map +1 -1
- package/dist/src/lib/db-codegen/dbTsTypes.d.ts +78 -0
- package/dist/src/lib/db-codegen/dbTsTypes.js +2 -2
- package/dist/src/lib/db-codegen/dbTsTypes.js.map +1 -1
- package/dist/src/lib/env-resolver.d.ts +62 -0
- package/dist/src/lib/fetch.d.ts +5 -0
- package/dist/src/lib/init-config.d.ts +46 -0
- package/dist/src/lib/init-config.js +7 -0
- package/dist/src/lib/init-config.js.map +1 -1
- package/dist/src/lib/migration-nag.d.ts +49 -0
- package/dist/src/lib/output.d.ts +49 -0
- package/dist/src/lib/output.js +25 -1
- package/dist/src/lib/output.js.map +1 -1
- package/dist/src/lib/paginate.d.ts +33 -0
- package/dist/src/lib/project-config.d.ts +97 -0
- package/dist/src/lib/refresh-admin-credentials.d.ts +65 -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/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 +29 -1
- package/dist/src/lib/sync-paths.js.map +1 -1
- package/dist/src/lib/template.d.ts +93 -0
- 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 +132 -0
- package/dist/src/lib/toml-params-validator.d.ts +95 -0
- package/dist/src/lib/version-check.d.ts +10 -0
- package/dist/src/lib/workflow-fragments.d.ts +41 -0
- package/dist/src/lib/workflow-toml-validator.d.ts +86 -0
- package/dist/src/lib/workflow-toml-validator.js +31 -1
- package/dist/src/lib/workflow-toml-validator.js.map +1 -1
- package/dist/src/types/index.d.ts +513 -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 +8 -2
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project-scoped configuration (.primitive/config.json).
|
|
3
|
+
*
|
|
4
|
+
* This module handles loading, validating, and saving the project config file
|
|
5
|
+
* that lives inside the .primitive/ directory at the project root. The config
|
|
6
|
+
* defines named environments (dev, prod, staging, etc.) with their API URLs
|
|
7
|
+
* and app IDs.
|
|
8
|
+
*
|
|
9
|
+
* Design:
|
|
10
|
+
* - Config file: .primitive/config.json (or any ancestor directory)
|
|
11
|
+
* - The .primitive/ directory groups the committable config and the
|
|
12
|
+
* gitignored local state (credentials, sync data) in one place.
|
|
13
|
+
* - Format: JSON
|
|
14
|
+
* - Schema is versioned (currently 1). Future versions use semver-ish
|
|
15
|
+
* caret range compatibility: we accept any config where major version
|
|
16
|
+
* matches CURRENT_CONFIG_VERSION.
|
|
17
|
+
* - Invalid configs throw — we do NOT silently ignore malformed files.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Current schema version. Increment the major version when making
|
|
21
|
+
* backward-incompatible changes. Older configs will be rejected.
|
|
22
|
+
*/
|
|
23
|
+
export declare const CURRENT_CONFIG_VERSION = 1;
|
|
24
|
+
/**
|
|
25
|
+
* The config file lives inside the .primitive/ directory, not at the
|
|
26
|
+
* project root. This keeps the project root clean and groups all
|
|
27
|
+
* Primitive state (config, credentials, sync data) under one directory.
|
|
28
|
+
*/
|
|
29
|
+
export declare const PROJECT_CONFIG_DIR = ".primitive";
|
|
30
|
+
export declare const PROJECT_CONFIG_FILENAME = "config.json";
|
|
31
|
+
/** Display name used in user-facing messages. */
|
|
32
|
+
export declare const PROJECT_CONFIG_DISPLAY_NAME = ".primitive/config.json";
|
|
33
|
+
export interface ProjectEnvironment {
|
|
34
|
+
apiUrl: string;
|
|
35
|
+
appId?: string;
|
|
36
|
+
appName?: string;
|
|
37
|
+
/** Optional notes about this environment. */
|
|
38
|
+
description?: string;
|
|
39
|
+
}
|
|
40
|
+
export interface ProjectConfig {
|
|
41
|
+
/** Schema version (currently 1). */
|
|
42
|
+
version: number;
|
|
43
|
+
/**
|
|
44
|
+
* Default environment name to use when --env is not specified and
|
|
45
|
+
* PRIMITIVE_ENV is unset.
|
|
46
|
+
*/
|
|
47
|
+
defaultEnvironment?: string;
|
|
48
|
+
/**
|
|
49
|
+
* Named environments keyed by short name (e.g. "dev", "prod", "staging").
|
|
50
|
+
*/
|
|
51
|
+
environments: Record<string, ProjectEnvironment>;
|
|
52
|
+
}
|
|
53
|
+
export declare class ProjectConfigError extends Error {
|
|
54
|
+
readonly path?: string;
|
|
55
|
+
constructor(message: string, path?: string);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Walks upward from `startDir` looking for a `.primitive/config.json` file.
|
|
59
|
+
* Returns the absolute path to the config file, or null if not found.
|
|
60
|
+
*
|
|
61
|
+
* Allows running `primitive` commands from subdirectories of a project,
|
|
62
|
+
* much like `git` walks up to find `.git`.
|
|
63
|
+
*/
|
|
64
|
+
export declare function findProjectConfigPath(startDir?: string): string | null;
|
|
65
|
+
/**
|
|
66
|
+
* Returns the project root directory (the parent of .primitive/ that contains
|
|
67
|
+
* .primitive/config.json), or null if no project config is found.
|
|
68
|
+
*
|
|
69
|
+
* When the PRIMITIVE_PROJECT_CONFIG env var override is active, the config
|
|
70
|
+
* file may not live inside a `.primitive/` directory (e.g. in tests), so
|
|
71
|
+
* we simply go up one level from the file.
|
|
72
|
+
*/
|
|
73
|
+
export declare function findProjectRoot(startDir?: string): string | null;
|
|
74
|
+
/**
|
|
75
|
+
* Validates a raw parsed object against the ProjectConfig schema.
|
|
76
|
+
* Throws ProjectConfigError with a helpful message on any problem.
|
|
77
|
+
*/
|
|
78
|
+
export declare function validateProjectConfig(raw: unknown, sourcePath?: string): ProjectConfig;
|
|
79
|
+
/**
|
|
80
|
+
* Loads and validates the project config from a specific file path.
|
|
81
|
+
* Throws ProjectConfigError on I/O errors, JSON parse errors, or schema
|
|
82
|
+
* validation failures — we deliberately do NOT swallow these, because a
|
|
83
|
+
* broken config should be noisy so the user can fix it.
|
|
84
|
+
*/
|
|
85
|
+
export declare function loadProjectConfigFromPath(path: string): ProjectConfig;
|
|
86
|
+
/**
|
|
87
|
+
* Loads the project config by searching upward from the current directory.
|
|
88
|
+
* Returns null (not an error) if no .primitive/config.json is found anywhere.
|
|
89
|
+
* Still throws ProjectConfigError if a config IS found but is invalid.
|
|
90
|
+
*/
|
|
91
|
+
export declare function loadProjectConfig(startDir?: string): ProjectConfig | null;
|
|
92
|
+
/**
|
|
93
|
+
* Writes a project config to disk as pretty-printed JSON. Callers are
|
|
94
|
+
* responsible for ensuring the parent directory exists — this function
|
|
95
|
+
* does not try to be clever about location.
|
|
96
|
+
*/
|
|
97
|
+
export declare function saveProjectConfig(path: string, config: ProjectConfig): void;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helper for refreshing the admin access token via the CLI auth API.
|
|
3
|
+
*
|
|
4
|
+
* Why this module exists:
|
|
5
|
+
*
|
|
6
|
+
* - `ApiClient.refreshToken()` already POSTs to /admin/api/auth/refresh
|
|
7
|
+
* before every API call when the access token is near expiry.
|
|
8
|
+
* - `primitive token` (issue #772) now needs the same exchange so it can
|
|
9
|
+
* auto-refresh a stale token before printing it.
|
|
10
|
+
* - `primitive login --token-stdin` does the same POST a third time to
|
|
11
|
+
* bootstrap credentials from a refresh token piped from another CLI.
|
|
12
|
+
*
|
|
13
|
+
* Putting the HTTP exchange + response parsing in one place keeps the
|
|
14
|
+
* response-shape contract in a single spot (server returns both `jwt` and
|
|
15
|
+
* `accessToken` — see `src/index.ts:2349-2356`) and means future server
|
|
16
|
+
* changes to that endpoint require touching exactly one CLI file.
|
|
17
|
+
*
|
|
18
|
+
* Design notes:
|
|
19
|
+
*
|
|
20
|
+
* - This module **does not** depend on `api-client.ts`. `ApiClient` imports
|
|
21
|
+
* it, not the other way around — that prevents the avoidable module cycle
|
|
22
|
+
* codex flagged in the design review.
|
|
23
|
+
* - It defines its own `RefreshError` so callers can map failures to
|
|
24
|
+
* whatever error type (or exit code) makes sense for their surface.
|
|
25
|
+
* `ApiClient` translates these to `ApiError`; the `token` command
|
|
26
|
+
* translates them to an `error()` + `process.exit(1)`.
|
|
27
|
+
* - It **does not save** the refreshed credentials. The caller decides
|
|
28
|
+
* whether to persist (the `token` command does; `ApiClient.refreshToken`
|
|
29
|
+
* does). Keeping persistence caller-owned matches the existing
|
|
30
|
+
* "storage is owned by `credentials-store.ts`" convention.
|
|
31
|
+
* - It **does not print anything**. Output (success/failure messaging) is
|
|
32
|
+
* the caller's responsibility — important because the `token` command
|
|
33
|
+
* must keep stdout clean for piping.
|
|
34
|
+
*/
|
|
35
|
+
import type { Credentials } from "../types/index.js";
|
|
36
|
+
/**
|
|
37
|
+
* Reasons a refresh attempt can fail. `unauthorized` covers any HTTP non-2xx
|
|
38
|
+
* response (typically a 401 from an expired/invalid refresh token).
|
|
39
|
+
* `network` covers transport-level failures (DNS, ECONNREFUSED, etc.).
|
|
40
|
+
* `missing-refresh-token` is a precondition failure — there's no token to
|
|
41
|
+
* send.
|
|
42
|
+
*/
|
|
43
|
+
export type RefreshFailureKind = "missing-refresh-token" | "unauthorized" | "network";
|
|
44
|
+
export declare class RefreshError extends Error {
|
|
45
|
+
kind: RefreshFailureKind;
|
|
46
|
+
statusCode?: number;
|
|
47
|
+
cause?: unknown;
|
|
48
|
+
constructor(message: string, kind: RefreshFailureKind, statusCode?: number, cause?: unknown);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Exchange the stored refresh token for a fresh `accessToken`. Returns a new
|
|
52
|
+
* `Credentials` object — the caller is responsible for persistence via
|
|
53
|
+
* `saveCredentials()` (or whatever storage the caller owns).
|
|
54
|
+
*
|
|
55
|
+
* Server contract: `POST {serverUrl}/admin/api/auth/refresh` with
|
|
56
|
+
* { refreshToken: string }
|
|
57
|
+
* Response (200):
|
|
58
|
+
* { jwt, accessToken, refreshToken, expiresAt }
|
|
59
|
+
*
|
|
60
|
+
* We accept `accessToken` as the canonical field and fall back to `jwt` for
|
|
61
|
+
* forward-compat (the server currently emits both — see issue #772 codex
|
|
62
|
+
* cleanup #3). Login's legacy `data.token` form is dropped — no server
|
|
63
|
+
* version that's still in support emits that field.
|
|
64
|
+
*/
|
|
65
|
+
export declare function refreshAdminCredentials(credentials: Credentials): Promise<Credentials>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure resolution of the target platform for `primitive init`.
|
|
3
|
+
*
|
|
4
|
+
* Background (issue #1009): `primitive init` must become platform-aware. The
|
|
5
|
+
* commander `-p, --platform` option no longer carries a `"web"` default, so an
|
|
6
|
+
* omitted flag is `undefined` and distinguishable from an explicit
|
|
7
|
+
* `--platform web`. Resolution follows a 4-case interactivity contract:
|
|
8
|
+
*
|
|
9
|
+
* (a) explicit `--platform` flag set -> use it (never prompt)
|
|
10
|
+
* (b) init-config TOML present (configPlatform may be set) -> use config
|
|
11
|
+
* value, else fall back to "web" (never prompt)
|
|
12
|
+
* (c) interactive TTY, no flag, no config -> prompt with `select`
|
|
13
|
+
* (d) non-TTY, no flag, no config -> fall back to "web" WITHOUT
|
|
14
|
+
* hanging and WITHOUT the `ERR_USE_AFTER_CLOSE` crash that
|
|
15
|
+
* `@inquirer/prompts` `select` throws on a closed/piped stdin
|
|
16
|
+
* (same hazard family hardened in #972/#999 — see `confirm-prompt.ts`).
|
|
17
|
+
*
|
|
18
|
+
* Extracting the decision into a pure function (with injectable `isTTY` /
|
|
19
|
+
* `promptFn`, mirroring `confirm-prompt.ts`) makes the otherwise
|
|
20
|
+
* terminal-dependent interactivity contract unit-testable.
|
|
21
|
+
*/
|
|
22
|
+
export type Platform = "web" | "ios";
|
|
23
|
+
/** Prompt thunk returning the chosen platform. Injectable for testing. */
|
|
24
|
+
export type PlatformPromptFn = () => Promise<Platform>;
|
|
25
|
+
export interface ResolvePlatformOptions {
|
|
26
|
+
/** Value of the explicit `--platform` flag, or `undefined` when omitted. */
|
|
27
|
+
flag?: Platform;
|
|
28
|
+
/** `platform` key from a loaded `.primitive-init.toml`, if a config is present. */
|
|
29
|
+
configPlatform?: Platform;
|
|
30
|
+
/**
|
|
31
|
+
* Whether a non-interactive init-config file is in effect. When `true`, the
|
|
32
|
+
* prompt is skipped entirely (case b) regardless of TTY.
|
|
33
|
+
*/
|
|
34
|
+
hasConfig: boolean;
|
|
35
|
+
/** Whether stdin is an interactive TTY. Inject `false` to exercise case (d). */
|
|
36
|
+
isTTY: boolean;
|
|
37
|
+
/** Prompt function used only in the interactive case (c). */
|
|
38
|
+
promptFn: PlatformPromptFn;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Resolve the target platform per the 4-case interactivity contract above.
|
|
42
|
+
*
|
|
43
|
+
* @returns the resolved platform (`"web"` or `"ios"`).
|
|
44
|
+
*/
|
|
45
|
+
export declare function resolvePlatform(options: ResolvePlatformOptions): Promise<Platform>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure resolution of the target platform for `primitive init`.
|
|
3
|
+
*
|
|
4
|
+
* Background (issue #1009): `primitive init` must become platform-aware. The
|
|
5
|
+
* commander `-p, --platform` option no longer carries a `"web"` default, so an
|
|
6
|
+
* omitted flag is `undefined` and distinguishable from an explicit
|
|
7
|
+
* `--platform web`. Resolution follows a 4-case interactivity contract:
|
|
8
|
+
*
|
|
9
|
+
* (a) explicit `--platform` flag set -> use it (never prompt)
|
|
10
|
+
* (b) init-config TOML present (configPlatform may be set) -> use config
|
|
11
|
+
* value, else fall back to "web" (never prompt)
|
|
12
|
+
* (c) interactive TTY, no flag, no config -> prompt with `select`
|
|
13
|
+
* (d) non-TTY, no flag, no config -> fall back to "web" WITHOUT
|
|
14
|
+
* hanging and WITHOUT the `ERR_USE_AFTER_CLOSE` crash that
|
|
15
|
+
* `@inquirer/prompts` `select` throws on a closed/piped stdin
|
|
16
|
+
* (same hazard family hardened in #972/#999 — see `confirm-prompt.ts`).
|
|
17
|
+
*
|
|
18
|
+
* Extracting the decision into a pure function (with injectable `isTTY` /
|
|
19
|
+
* `promptFn`, mirroring `confirm-prompt.ts`) makes the otherwise
|
|
20
|
+
* terminal-dependent interactivity contract unit-testable.
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Resolve the target platform per the 4-case interactivity contract above.
|
|
24
|
+
*
|
|
25
|
+
* @returns the resolved platform (`"web"` or `"ios"`).
|
|
26
|
+
*/
|
|
27
|
+
export async function resolvePlatform(options) {
|
|
28
|
+
// (a) explicit flag wins, no prompt.
|
|
29
|
+
if (options.flag !== undefined) {
|
|
30
|
+
return options.flag;
|
|
31
|
+
}
|
|
32
|
+
// (b) non-interactive config present: use its platform or default to web.
|
|
33
|
+
if (options.hasConfig) {
|
|
34
|
+
return options.configPlatform ?? "web";
|
|
35
|
+
}
|
|
36
|
+
// (c) interactive TTY, no flag, no config: prompt.
|
|
37
|
+
if (options.isTTY) {
|
|
38
|
+
return options.promptFn();
|
|
39
|
+
}
|
|
40
|
+
// (d) non-TTY, no flag, no config: never prompt; fall back to web.
|
|
41
|
+
return "web";
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=resolve-platform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-platform.js","sourceRoot":"","sources":["../../../src/lib/resolve-platform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAuBH;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,OAA+B;IAE/B,qCAAqC;IACrC,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,OAAO,CAAC,IAAI,CAAC;IACtB,CAAC;IAED,0EAA0E;IAC1E,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QACtB,OAAO,OAAO,CAAC,cAAc,IAAI,KAAK,CAAC;IACzC,CAAC;IAED,mDAAmD;IACnD,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,OAAO,OAAO,CAAC,QAAQ,EAAE,CAAC;IAC5B,CAAC;IAED,mEAAmE;IACnE,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns true if the skill is currently installed.
|
|
3
|
+
*/
|
|
4
|
+
export declare function isSkillInstalled(): boolean;
|
|
5
|
+
/**
|
|
6
|
+
* Auto-update an already-installed skill if a newer version is bundled.
|
|
7
|
+
* Called after command execution for non-init, non-skill commands.
|
|
8
|
+
* If the skill is not installed, shows a non-blocking hint instead.
|
|
9
|
+
* Never throws — fails silently like version-check.
|
|
10
|
+
*/
|
|
11
|
+
export declare function checkSkillStatus(): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Explicitly install or reinstall the skill. Shows output.
|
|
14
|
+
*/
|
|
15
|
+
export declare function installSkillExplicit(): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Uninstall the skill.
|
|
18
|
+
*/
|
|
19
|
+
export declare function uninstallSkill(): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Show current skill installation status.
|
|
22
|
+
*/
|
|
23
|
+
export declare function skillStatus(): void;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sync snapshots — point-in-time backups of a sync directory taken before a
|
|
3
|
+
* destructive `sync pull` overwrites local TOML state (issue #578, Phase 1).
|
|
4
|
+
*
|
|
5
|
+
* A snapshot is a full recursive copy of the live sync tree (including
|
|
6
|
+
* `.primitive-sync.json`, the content-hash baseline) into a timestamped slot
|
|
7
|
+
* under the snapshots root:
|
|
8
|
+
*
|
|
9
|
+
* <snapshotsRoot>/<YYYY-MM-DDTHH-MM-SS>/
|
|
10
|
+
* <full pre-pull copy of the sync tree, incl. .primitive-sync.json>
|
|
11
|
+
* .snapshot-complete # integrity marker, written LAST
|
|
12
|
+
* .audit-id # ULID cross-link (Phase 2; absent in P1)
|
|
13
|
+
*
|
|
14
|
+
* The `.snapshot-complete` marker is written last so a partial/interrupted
|
|
15
|
+
* copy is detectable: `restoreSnapshot` refuses any snapshot missing it.
|
|
16
|
+
*
|
|
17
|
+
* Snapshots fail LOUD — `createSnapshot` throws if it can't write a complete
|
|
18
|
+
* snapshot. The caller (sync pull) aborts before touching any local file so we
|
|
19
|
+
* never perform a destructive pull without a recoverable backup.
|
|
20
|
+
*
|
|
21
|
+
* Restore is staged-then-swapped: the snapshot is materialized into a sibling
|
|
22
|
+
* temp dir, then the live `configDir` is atomically replaced, so a mid-restore
|
|
23
|
+
* crash never leaves a half-written tree.
|
|
24
|
+
*/
|
|
25
|
+
/** Marker file written LAST inside a snapshot to prove it completed. */
|
|
26
|
+
export declare const SNAPSHOT_COMPLETE_MARKER = ".snapshot-complete";
|
|
27
|
+
/** Cross-link to the audit entry that produced the snapshot (Phase 2). */
|
|
28
|
+
export declare const SNAPSHOT_AUDIT_ID_MARKER = ".audit-id";
|
|
29
|
+
export interface SnapshotResult {
|
|
30
|
+
/** Snapshot id — the timestamp directory name (YYYY-MM-DDTHH-MM-SS). */
|
|
31
|
+
id: string;
|
|
32
|
+
/** Absolute path to the snapshot directory. */
|
|
33
|
+
path: string;
|
|
34
|
+
}
|
|
35
|
+
export interface SnapshotInfo {
|
|
36
|
+
/** Snapshot id — the timestamp directory name. */
|
|
37
|
+
id: string;
|
|
38
|
+
/** Absolute path to the snapshot directory. */
|
|
39
|
+
path: string;
|
|
40
|
+
/** Whether the `.snapshot-complete` marker is present. */
|
|
41
|
+
complete: boolean;
|
|
42
|
+
/** The audit entry id this snapshot is cross-linked to, if any. */
|
|
43
|
+
auditId: string | null;
|
|
44
|
+
/** Creation time (from the directory mtime). */
|
|
45
|
+
createdAt: Date;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Snapshot the current `syncDir` into a new timestamped slot under
|
|
49
|
+
* `snapshotsRoot`. Returns the created snapshot, or `null` when there's
|
|
50
|
+
* nothing to back up (missing/empty `syncDir`).
|
|
51
|
+
*
|
|
52
|
+
* Fails LOUD: throws if the copy or marker write fails. The partial snapshot
|
|
53
|
+
* dir is best-effort cleaned up before rethrowing so a failed snapshot never
|
|
54
|
+
* leaves a marker-less husk behind.
|
|
55
|
+
*/
|
|
56
|
+
export declare function createSnapshot(syncDir: string, snapshotsRoot: string, opts?: {
|
|
57
|
+
auditId?: string;
|
|
58
|
+
now?: Date;
|
|
59
|
+
}): SnapshotResult | null;
|
|
60
|
+
/**
|
|
61
|
+
* List snapshots under `snapshotsRoot`, newest-first. Returns an empty array
|
|
62
|
+
* if the root doesn't exist. Each entry reports whether it's complete and any
|
|
63
|
+
* cross-linked audit id.
|
|
64
|
+
*/
|
|
65
|
+
export declare function listSnapshots(snapshotsRoot: string): SnapshotInfo[];
|
|
66
|
+
/**
|
|
67
|
+
* Resolve a snapshot by id within `snapshotsRoot`. Accepts either the full
|
|
68
|
+
* timestamp directory name OR a unique prefix of at least `minPrefix`
|
|
69
|
+
* characters (default 8). Returns the matching snapshot, or throws a clear
|
|
70
|
+
* error on no-match / ambiguous-prefix.
|
|
71
|
+
*
|
|
72
|
+
* When `id` is omitted, resolves to the most recent COMPLETE snapshot.
|
|
73
|
+
*/
|
|
74
|
+
export declare function resolveSnapshot(snapshotsRoot: string, id: string | undefined, minPrefix?: number): SnapshotInfo;
|
|
75
|
+
/**
|
|
76
|
+
* Restore a snapshot into `syncDir`, replacing whatever is there.
|
|
77
|
+
*
|
|
78
|
+
* Refuses to restore a snapshot missing the `.snapshot-complete` marker
|
|
79
|
+
* (partial/corrupted snapshot). The internal marker files (`.snapshot-complete`,
|
|
80
|
+
* `.audit-id`) are NOT copied into the restored tree.
|
|
81
|
+
*
|
|
82
|
+
* Staged-then-swapped: the snapshot is materialized into a sibling temp dir,
|
|
83
|
+
* then `syncDir` is atomically replaced, so a mid-restore crash never leaves a
|
|
84
|
+
* half-written tree.
|
|
85
|
+
*
|
|
86
|
+
* `opts.preserveDir` names a directory (the snapshots root) that lives INSIDE
|
|
87
|
+
* `syncDir` and must survive the full-tree swap — the Fork-4 legacy `--dir`
|
|
88
|
+
* case, where backups sit at `<syncDir>/.snapshots/`. Without preserving it,
|
|
89
|
+
* the swap would wipe the user's entire snapshot history on restore.
|
|
90
|
+
*/
|
|
91
|
+
export declare function restoreSnapshot(snapshotPath: string, syncDir: string, opts?: {
|
|
92
|
+
preserveDir?: string;
|
|
93
|
+
}): void;
|
|
94
|
+
/**
|
|
95
|
+
* Prune snapshots older than `retentionDays` from `snapshotsRoot`. Only the
|
|
96
|
+
* given slot is touched (cross-slot retention is independent — each slot has
|
|
97
|
+
* its own snapshots root). No-op if the root doesn't exist.
|
|
98
|
+
*/
|
|
99
|
+
export declare function pruneSnapshots(snapshotsRoot: string, retentionDays?: number): void;
|