@almadar/workspace 0.8.0 → 0.10.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/dist/__tests__/git-snapshots.test.d.ts +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +135 -6
- package/dist/index.js.map +1 -1
- package/dist/internal/backends/local.d.ts +2 -0
- package/dist/internal/backends/memory.d.ts +3 -0
- package/dist/internal/git-client.d.ts +17 -0
- package/dist/internal/types.d.ts +3 -0
- package/dist/internal/workspace-manager.d.ts +1 -1
- package/dist/service.d.ts +19 -2
- package/dist/types.d.ts +36 -0
- package/package.json +1 -1
|
@@ -4,6 +4,8 @@ export declare class LocalBackend implements WorkspaceBackend {
|
|
|
4
4
|
readFileSync(absPath: string): string;
|
|
5
5
|
writeFile(absPath: string, content: string): Promise<void>;
|
|
6
6
|
writeFileSync(absPath: string, content: string): void;
|
|
7
|
+
readFileBytes(absPath: string): Promise<Uint8Array>;
|
|
8
|
+
writeFileBytes(absPath: string, bytes: Uint8Array): Promise<void>;
|
|
7
9
|
exists(absPath: string): boolean;
|
|
8
10
|
readdir(absPath: string): Promise<string[]>;
|
|
9
11
|
readdirSync(absPath: string): string[];
|
|
@@ -4,11 +4,14 @@
|
|
|
4
4
|
import type { WorkspaceBackend } from '../types.js';
|
|
5
5
|
export declare class MemoryBackend implements WorkspaceBackend {
|
|
6
6
|
private files;
|
|
7
|
+
private bytes;
|
|
7
8
|
private dirs;
|
|
8
9
|
readFile(absPath: string): Promise<string>;
|
|
9
10
|
readFileSync(absPath: string): string;
|
|
10
11
|
writeFile(absPath: string, content: string): Promise<void>;
|
|
11
12
|
writeFileSync(absPath: string, content: string): void;
|
|
13
|
+
readFileBytes(absPath: string): Promise<Uint8Array>;
|
|
14
|
+
writeFileBytes(absPath: string, bytes: Uint8Array): Promise<void>;
|
|
12
15
|
exists(absPath: string): boolean;
|
|
13
16
|
readdir(absPath: string): Promise<string[]>;
|
|
14
17
|
readdirSync(absPath: string): string[];
|
|
@@ -12,6 +12,12 @@ export interface GitStatus {
|
|
|
12
12
|
modified: string[];
|
|
13
13
|
untracked: string[];
|
|
14
14
|
}
|
|
15
|
+
/** One commit in the history of a path — the snapshot view. */
|
|
16
|
+
export interface GitLogEntry {
|
|
17
|
+
oid: string;
|
|
18
|
+
timestamp: number;
|
|
19
|
+
subject: string;
|
|
20
|
+
}
|
|
15
21
|
export declare class GitClient {
|
|
16
22
|
private readonly cwd;
|
|
17
23
|
private readonly backend;
|
|
@@ -28,5 +34,16 @@ export declare class GitClient {
|
|
|
28
34
|
addRemote(remote: string, url: string): Promise<void>;
|
|
29
35
|
status(): Promise<GitStatus>;
|
|
30
36
|
headSha(): Promise<string | null>;
|
|
37
|
+
/**
|
|
38
|
+
* Commit history of `filepath` (newest first) — the snapshot list. NUL-delimited
|
|
39
|
+
* fields so commit subjects with tabs/spaces parse cleanly.
|
|
40
|
+
*/
|
|
41
|
+
log(filepath?: string, limit?: number): Promise<GitLogEntry[]>;
|
|
42
|
+
/** Content of `filepath` at commit `oid` — the restore read. Null if absent. */
|
|
43
|
+
show(oid: string, filepath: string): Promise<string | null>;
|
|
44
|
+
/** Bundle the whole repo into a single delta-compressed file (the durable archive). */
|
|
45
|
+
bundleAll(outAbsPath: string): Promise<void>;
|
|
46
|
+
/** Clone a bundle file into `targetDir` (hydrate a fresh workspace from the archive). */
|
|
47
|
+
cloneBundle(bundleAbsPath: string, targetDir: string): Promise<void>;
|
|
31
48
|
private exec;
|
|
32
49
|
}
|
package/dist/internal/types.d.ts
CHANGED
|
@@ -13,6 +13,9 @@ export interface WorkspaceBackend {
|
|
|
13
13
|
readFileSync(absPath: string): string;
|
|
14
14
|
writeFile(absPath: string, content: string): Promise<void>;
|
|
15
15
|
writeFileSync(absPath: string, content: string): void;
|
|
16
|
+
/** Binary read/write — for git bundle artifacts (durable archive bytes). */
|
|
17
|
+
readFileBytes(absPath: string): Promise<Uint8Array>;
|
|
18
|
+
writeFileBytes(absPath: string, bytes: Uint8Array): Promise<void>;
|
|
16
19
|
exists(absPath: string): boolean;
|
|
17
20
|
readdir(absPath: string): Promise<string[]>;
|
|
18
21
|
readdirSync(absPath: string): string[];
|
|
@@ -17,5 +17,5 @@ export declare function ensureSkeleton(backend: WorkspaceBackend, workDir: strin
|
|
|
17
17
|
export declare function ensureOrbitalSessionDir(backend: WorkspaceBackend, workDir: string, orbital: string): Promise<void>;
|
|
18
18
|
/** Write mint-time templates only when they don't exist. */
|
|
19
19
|
export declare function writeMintTemplatesIfMissing(backend: WorkspaceBackend, workDir: string, userId: string, projectName: string, appId?: string): Promise<void>;
|
|
20
|
-
/** Initialise git for the workspace if it isn't already a repo. */
|
|
20
|
+
/** Initialise git for the workspace if it isn't already a repo (+ write `.gitignore`). */
|
|
21
21
|
export declare function ensureGitInit(backend: WorkspaceBackend, workDir: string): Promise<GitClient>;
|
package/dist/service.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @packageDocumentation
|
|
8
8
|
*/
|
|
9
9
|
import type { JsonObject, JsonValue } from '@almadar/core';
|
|
10
|
-
import type { FileTreeNode, GitHubConfig, GitStatusInfo, WorkspaceObserver, WorkspaceService, WorkspaceWatchEvent } from './types.js';
|
|
10
|
+
import type { FileTreeNode, GitHubConfig, GitStatusInfo, SnapshotMeta, WorkspaceArchiveBackend, WorkspaceObserver, WorkspaceService, WorkspaceWatchEvent } from './types.js';
|
|
11
11
|
import type { WorkspaceBackend } from './internal/types.js';
|
|
12
12
|
import { SinkManager } from './internal/sink-manager.js';
|
|
13
13
|
import { GitClient } from './internal/git-client.js';
|
|
@@ -20,6 +20,7 @@ interface ServiceCtorArgs {
|
|
|
20
20
|
appId?: string;
|
|
21
21
|
git?: GitClient;
|
|
22
22
|
github?: GitHubConfig;
|
|
23
|
+
archiveBackend?: WorkspaceArchiveBackend;
|
|
23
24
|
}
|
|
24
25
|
export declare class WorkspaceServiceImpl implements WorkspaceService {
|
|
25
26
|
readonly workDir: string;
|
|
@@ -27,13 +28,20 @@ export declare class WorkspaceServiceImpl implements WorkspaceService {
|
|
|
27
28
|
private readonly backend;
|
|
28
29
|
private readonly sinks;
|
|
29
30
|
private readonly git;
|
|
30
|
-
private
|
|
31
|
+
private github;
|
|
32
|
+
private readonly archiveBackend;
|
|
31
33
|
/** Per-absolute-path serial queue. */
|
|
32
34
|
private readonly writeQueue;
|
|
33
35
|
readonly index: WorkspaceIndex;
|
|
34
36
|
constructor(args: ServiceCtorArgs);
|
|
35
37
|
get appId(): string | undefined;
|
|
36
38
|
setAppId(id: string): void;
|
|
39
|
+
/**
|
|
40
|
+
* Set (or clear) the GitHub config after open. Lets a consumer resolve the
|
|
41
|
+
* link/token lazily — e.g. from a workspace file read post-open — and wire
|
|
42
|
+
* `commitAndPush`/`pullIfLinked` without knowing it at construction time.
|
|
43
|
+
*/
|
|
44
|
+
setGitHub(config: GitHubConfig | undefined): void;
|
|
37
45
|
/** Run `op` under a per-path serial lock. */
|
|
38
46
|
private withLock;
|
|
39
47
|
/** Make sure the parent directory of `absPath` exists. */
|
|
@@ -85,6 +93,15 @@ export declare class WorkspaceServiceImpl implements WorkspaceService {
|
|
|
85
93
|
} | null>;
|
|
86
94
|
pullIfLinked(): Promise<boolean>;
|
|
87
95
|
gitStatus(): Promise<GitStatusInfo>;
|
|
96
|
+
snapshot(reason: string): Promise<{
|
|
97
|
+
oid: string;
|
|
98
|
+
} | null>;
|
|
99
|
+
listSnapshots(opts?: {
|
|
100
|
+
limit?: number;
|
|
101
|
+
}): Promise<SnapshotMeta[]>;
|
|
102
|
+
restore(oid: string): Promise<string | null>;
|
|
103
|
+
archive(): Promise<void>;
|
|
104
|
+
hydrateFromArchive(): Promise<boolean>;
|
|
88
105
|
subscribe(observer: WorkspaceObserver): () => void;
|
|
89
106
|
watch(relPath: string, onChange: (event: WorkspaceWatchEvent) => void): () => void;
|
|
90
107
|
dispose(): Promise<void>;
|
package/dist/types.d.ts
CHANGED
|
@@ -146,6 +146,24 @@ export interface GitStatusInfo {
|
|
|
146
146
|
/** Resolved when an upstream remote+branch is configured. */
|
|
147
147
|
linked: boolean;
|
|
148
148
|
}
|
|
149
|
+
/** One snapshot = one commit in the history of `schema.orb`. */
|
|
150
|
+
export interface SnapshotMeta {
|
|
151
|
+
/** Commit oid. */
|
|
152
|
+
id: string;
|
|
153
|
+
/** Commit time, epoch ms. */
|
|
154
|
+
timestamp: number;
|
|
155
|
+
/** Human reason (the `snapshot: <reason>` subject, prefix stripped). */
|
|
156
|
+
reason: string;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Durable store for the workspace's git history when there's no remote — the
|
|
160
|
+
* consumer supplies it (e.g. a Firestore-backed bundle store on cloud). The
|
|
161
|
+
* workspace produces/consumes a single `git bundle`; it stays account-agnostic.
|
|
162
|
+
*/
|
|
163
|
+
export interface WorkspaceArchiveBackend {
|
|
164
|
+
saveBundle(bytes: Uint8Array): Promise<void>;
|
|
165
|
+
loadBundle(): Promise<Uint8Array | null>;
|
|
166
|
+
}
|
|
149
167
|
/** Single node returned by `listTree(relPath?)`. */
|
|
150
168
|
export interface FileTreeNode {
|
|
151
169
|
/** Workspace-relative POSIX path (forward slashes). */
|
|
@@ -181,6 +199,8 @@ export interface OpenWorkspaceOptions {
|
|
|
181
199
|
github?: GitHubConfig;
|
|
182
200
|
/** Fallback fetcher used when the local cache misses. */
|
|
183
201
|
restore?: RestoreBackend;
|
|
202
|
+
/** Durable git-history store (bundle) for workspaces without a remote (e.g. cloud Firestore). */
|
|
203
|
+
archiveBackend?: WorkspaceArchiveBackend;
|
|
184
204
|
/**
|
|
185
205
|
* When `false`, open is a pure read: resolve an EXISTING workspace (local
|
|
186
206
|
* resume, or restore that actually yields files) but NEVER mint a fresh one.
|
|
@@ -236,6 +256,8 @@ export interface WorkspaceService {
|
|
|
236
256
|
readonly appId: string | undefined;
|
|
237
257
|
readonly workDir: string;
|
|
238
258
|
setAppId(id: string): void;
|
|
259
|
+
/** Set/clear the GitHub config post-open (resolve link/token lazily, then wire push/pull). */
|
|
260
|
+
setGitHub(config: GitHubConfig | undefined): void;
|
|
239
261
|
readOrbital(name: string): string | null;
|
|
240
262
|
writeOrbital(name: string, content: string): Promise<void>;
|
|
241
263
|
listOrbitals(): string[];
|
|
@@ -289,6 +311,20 @@ export interface WorkspaceService {
|
|
|
289
311
|
} | null>;
|
|
290
312
|
pullIfLinked(): Promise<boolean>;
|
|
291
313
|
gitStatus(): Promise<GitStatusInfo>;
|
|
314
|
+
/** Commit the current app files as a snapshot. Returns the oid, or null if nothing changed / no git. */
|
|
315
|
+
snapshot(reason: string): Promise<{
|
|
316
|
+
oid: string;
|
|
317
|
+
} | null>;
|
|
318
|
+
/** List snapshots (commits touching schema.orb), newest first. */
|
|
319
|
+
listSnapshots(opts?: {
|
|
320
|
+
limit?: number;
|
|
321
|
+
}): Promise<SnapshotMeta[]>;
|
|
322
|
+
/** Read `schema.orb` at a snapshot oid (the caller writes it back through the canonical save). */
|
|
323
|
+
restore(oid: string): Promise<string | null>;
|
|
324
|
+
/** Bundle the whole repo to the injected archive backend (durable history without a remote). No-op if unset. */
|
|
325
|
+
archive(): Promise<void>;
|
|
326
|
+
/** Reconstruct the repo from the archive backend into an empty workspace. Returns false if no archive. */
|
|
327
|
+
hydrateFromArchive(): Promise<boolean>;
|
|
292
328
|
subscribe(observer: WorkspaceObserver): () => void;
|
|
293
329
|
/**
|
|
294
330
|
* Watch a workspace-relative path (file or directory) for EXTERNAL changes —
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@almadar/workspace",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Storage-agnostic workspace primitives shared by Almadar consumers. One service, six exports, hidden paths, single observer. See docs/Almadar_Workspace.md.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|