@ibgib/space-gib 0.0.20 → 0.0.22

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.
@@ -0,0 +1,330 @@
1
+ /**
2
+ * @module client/dev-tools/vcs-workspace
3
+ *
4
+ * Dev Tools panel button handlers for in-memory VCS Workspace Projection testing in space-gib.
5
+ * Utilizes the isomorphic VcsRepository facade and WebInMemoryWorkspaceProjectionSpace_V1.
6
+ */
7
+
8
+ import { extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
9
+ import { getGlobalMetaspace_waitIfNeeded } from '@ibgib/web-gib/dist/helpers.mjs';
10
+ import { WebInMemoryWorkspaceProjectionSpace_V1 } from '@ibgib/web-gib/dist/witness/space/web-in-memory-workspace-projection-space/web-in-memory-workspace-projection-space-v1.mjs';
11
+ import { InnerSpace_V1 } from '@ibgib/core-gib/dist/witness/space/inner-space/inner-space-v1.mjs';
12
+ import { DEFAULT_INNER_SPACE_DATA_V1 } from '@ibgib/core-gib/dist/witness/space/inner-space/inner-space-types.mjs';
13
+ import { getB2tFSBranchSpaceName } from '@ibgib/core-gib/dist/vcs/branch/branch-helper.mjs';
14
+ import { VcsRepository } from '@ibgib/core-gib/dist/vcs/vcs-repository.mjs';
15
+
16
+ import { devLog, lc } from './common.mjs';
17
+
18
+ interface VcsDevState {
19
+ backingSpace?: InnerSpace_V1;
20
+ wsSpace?: WebInMemoryWorkspaceProjectionSpace_V1;
21
+ repo?: VcsRepository;
22
+ }
23
+
24
+ export const vcsDevState: VcsDevState = {};
25
+ (window as any).vcsDevState = vcsDevState;
26
+
27
+ /**
28
+ * 1. Initialize in-memory branch CAS space, VcsRepository session, and seed sample files.
29
+ */
30
+ export function initVcsInitButton(): void {
31
+ const btn = document.getElementById('btn-vcs-init') as HTMLButtonElement | null;
32
+ if (!btn) { return; }
33
+
34
+ btn.addEventListener('click', async () => {
35
+ const lc_fn = `${lc}[btn-vcs-init]`;
36
+ try {
37
+ btn.disabled = true;
38
+ devLog('⏳ Initializing in-memory branch space & sample repo via VcsRepository...');
39
+
40
+ const metaspace = await getGlobalMetaspace_waitIfNeeded();
41
+
42
+ // 1. Create dedicated in-memory branch space
43
+ const branchSpaceName = getB2tFSBranchSpaceName('main');
44
+ const backingSpace = new InnerSpace_V1({
45
+ ...DEFAULT_INNER_SPACE_DATA_V1,
46
+ name: branchSpaceName,
47
+ spaceSubPath: branchSpaceName,
48
+ uuid: 'ws_backing_cas_space_uuid',
49
+ });
50
+ await backingSpace.initialized;
51
+ vcsDevState.backingSpace = backingSpace;
52
+
53
+ // Register backingSpace in metaspace local user spaces
54
+ try {
55
+ if ((metaspace as any).localUserSpaces && !(metaspace as any).localUserSpaces.includes(backingSpace)) {
56
+ (metaspace as any).localUserSpaces.push(backingSpace);
57
+ }
58
+ if ((metaspace as any).spaces && !(metaspace as any).spaces.includes(backingSpace)) {
59
+ (metaspace as any).spaces.push(backingSpace);
60
+ }
61
+ } catch {
62
+ // Ignore
63
+ }
64
+
65
+ // 2. Instantiate WebInMemoryWorkspaceProjectionSpace_V1
66
+ const wsSpace = new WebInMemoryWorkspaceProjectionSpace_V1({
67
+ initialData: {
68
+ name: 'web_ws_space_main',
69
+ uuid: 'web_ws_uuid',
70
+ workspaceRoot: '/',
71
+ vcsFolderName: '.vcsgib',
72
+ },
73
+ backingSpace,
74
+ });
75
+ await wsSpace.initialized;
76
+ vcsDevState.wsSpace = wsSpace;
77
+
78
+ // 3. Create VcsRepository session
79
+ const repo = new VcsRepository({
80
+ metaspace,
81
+ workspaceSpace: wsSpace,
82
+ localSpace: backingSpace,
83
+ activeBranchSpace: backingSpace,
84
+ enableBranchLocking: true,
85
+ });
86
+ vcsDevState.repo = repo;
87
+
88
+ // 4. Initialize repository
89
+ await repo.init({
90
+ rootFolderName: 'my-app',
91
+ defaultBranchName: 'main',
92
+ });
93
+
94
+ // 5. Seed initial files into virtual workspace
95
+ wsSpace.setVirtualFile('README.md', '# Space-Gib In-Memory Repo\n\nThis entire repository is projected in memory inside the browser.');
96
+ wsSpace.setVirtualFile('src/index.ts', 'export const app = "space-gib in-memory demo";\nconsole.log(app);');
97
+ wsSpace.setVirtualFile('src/helper.ts', 'export function add(a: number, b: number): number {\n return a + b;\n}');
98
+ wsSpace.setVirtualFile('.ibgibignore', 'node_modules/\n*.log\n');
99
+
100
+ // 6. Initial stage & commit
101
+ await repo.add([], { all: true });
102
+ const commitRes = await repo.commit({ message: 'Initial repository commit' });
103
+
104
+ devLog(`✅ In-Memory Repo initialized via VcsRepository!\n Commit: ${commitRes.commitAddr.slice(0, 8)}\n Files: ${wsSpace.listVirtualPaths().join(', ')}`);
105
+
106
+ // Enable action buttons
107
+ setBtnDisabled('btn-vcs-list', false);
108
+ setBtnDisabled('btn-vcs-status', false);
109
+ setBtnDisabled('btn-vcs-modify', false);
110
+ setBtnDisabled('btn-vcs-reset', false);
111
+ } catch (error) {
112
+ devLog(`❌ Init failed: ${extractErrorMsg(error)}`);
113
+ console.error(`${lc_fn}`, error);
114
+ } finally {
115
+ btn.disabled = true;
116
+ }
117
+ });
118
+ }
119
+
120
+ /**
121
+ * 2. List virtual files in in-memory projection space in a single formatted card.
122
+ */
123
+ export function initVcsListButton(): void {
124
+ const btn = document.getElementById('btn-vcs-list') as HTMLButtonElement | null;
125
+ if (!btn) { return; }
126
+
127
+ btn.addEventListener('click', () => {
128
+ try {
129
+ const wsSpace = vcsDevState.wsSpace;
130
+ if (!wsSpace) {
131
+ devLog('⚠️ Repo not initialized yet. Click (1) first.');
132
+ return;
133
+ }
134
+
135
+ const paths = wsSpace.listVirtualPaths();
136
+ const lines: string[] = [
137
+ `📁 --- IN-MEMORY VIRTUAL FILES (${paths.length} entries) ---`
138
+ ];
139
+
140
+ for (const p of paths) {
141
+ const text = wsSpace.getVirtualText(p);
142
+ const isDir = text === undefined || wsSpace.getVirtualFile(p)?.length === 0;
143
+ if (isDir) {
144
+ lines.push(` 📁 [DIR] ${p}`);
145
+ } else {
146
+ const preview = (text || '').replace(/\n/g, ' ').slice(0, 40);
147
+ lines.push(` 📄 [FILE] ${p.padEnd(22)} (${String(text?.length || 0).padStart(3)} chars) -> "${preview}..."`);
148
+ }
149
+ }
150
+
151
+ devLog(lines.join('\n'));
152
+ } catch (error) {
153
+ devLog(`❌ List failed: ${extractErrorMsg(error)}`);
154
+ }
155
+ });
156
+ }
157
+
158
+ /**
159
+ * 3. Inspect repository status via VcsRepository in a single formatted card.
160
+ */
161
+ export function initVcsStatusButton(): void {
162
+ const btn = document.getElementById('btn-vcs-status') as HTMLButtonElement | null;
163
+ if (!btn) { return; }
164
+
165
+ btn.addEventListener('click', async () => {
166
+ try {
167
+ const repo = vcsDevState.repo;
168
+ if (!repo) {
169
+ devLog('⚠️ Repo not initialized yet.');
170
+ return;
171
+ }
172
+
173
+ const status = await repo.status();
174
+ const lines: string[] = [
175
+ `📋 --- VCS STATUS (Branch: ${status.branchName}) ---`
176
+ ];
177
+
178
+ if (status.staged.length === 0 && status.modified.length === 0 && status.deleted.length === 0 && status.untracked.length === 0 && status.pendingComments.length === 0) {
179
+ lines.push(' ✨ Working tree clean (no changes)');
180
+ } else {
181
+ if (status.staged.length > 0) {
182
+ lines.push(` 🟢 Staged changes (${status.staged.length}):`);
183
+ for (const s of status.staged) { lines.push(` staged: ${s.path}`); }
184
+ }
185
+
186
+ if (status.modified.length > 0) {
187
+ lines.push(` 🟡 Changes not staged for commit (${status.modified.length}):`);
188
+ for (const m of status.modified) { lines.push(` modified: ${m.path}`); }
189
+ }
190
+
191
+ if (status.deleted.length > 0) {
192
+ lines.push(` 🔴 Deleted files (${status.deleted.length}):`);
193
+ for (const d of status.deleted) { lines.push(` deleted: ${d.path}`); }
194
+ }
195
+
196
+ if (status.untracked.length > 0) {
197
+ lines.push(` ⚪ Untracked files (${status.untracked.length}):`);
198
+ for (const u of status.untracked) { lines.push(` untracked: ${u.path}`); }
199
+ }
200
+
201
+ if (status.pendingComments.length > 0) {
202
+ lines.push(` 💬 Pending companion comments (${status.pendingComments.length}):`);
203
+ for (const c of status.pendingComments) { lines.push(` note for: ${c.targetRelPath} (${c.commentRelPath})`); }
204
+ }
205
+ }
206
+
207
+ devLog(lines.join('\n'));
208
+ } catch (error) {
209
+ devLog(`❌ Status check failed: ${extractErrorMsg(error)}`);
210
+ }
211
+ });
212
+ }
213
+
214
+ /**
215
+ * 4. Modify virtual file and add an untracked file directly in memory.
216
+ */
217
+ export function initVcsModifyButton(): void {
218
+ const btn = document.getElementById('btn-vcs-modify') as HTMLButtonElement | null;
219
+ if (!btn) { return; }
220
+
221
+ btn.addEventListener('click', () => {
222
+ try {
223
+ const wsSpace = vcsDevState.wsSpace;
224
+ if (!wsSpace) {
225
+ devLog('⚠️ Repo not initialized yet.');
226
+ return;
227
+ }
228
+
229
+ const lines: string[] = [
230
+ '✏️ Simulating user edits in in-browser editor...'
231
+ ];
232
+
233
+ // Modify existing file
234
+ const newContent = 'export const app = "space-gib (EDITED LIVE IN BROWSER!)";\nconsole.log(app);\nexport const timestamp = ' + Date.now() + ';';
235
+ wsSpace.setVirtualFile('src/index.ts', newContent);
236
+ lines.push(' ✏️ Updated "src/index.ts" with new code content.');
237
+
238
+ // Add an untracked file
239
+ wsSpace.setVirtualFile('src/new-component.ts', 'export const Component = () => "<div>New UI</div>";');
240
+ lines.push(' ➕ Created untracked file "src/new-component.ts".');
241
+
242
+ // Add a companion comment file
243
+ wsSpace.setVirtualFile('src/.ib.index.ts.md', '# Architectural Note on index.ts\nEdited live from Dev Tools!');
244
+ lines.push(' 💬 Added companion comment file "src/.ib.index.ts.md".');
245
+ lines.push('👉 Click (3) VCS Status to view detected changes, or (5) to commit!');
246
+
247
+ devLog(lines.join('\n'));
248
+ setBtnDisabled('btn-vcs-commit', false);
249
+ } catch (error) {
250
+ devLog(`❌ Modify failed: ${extractErrorMsg(error)}`);
251
+ }
252
+ });
253
+ }
254
+
255
+ /**
256
+ * 5. Stage and commit modified files using VcsRepository.
257
+ */
258
+ export function initVcsCommitButton(): void {
259
+ const btn = document.getElementById('btn-vcs-commit') as HTMLButtonElement | null;
260
+ if (!btn) { return; }
261
+
262
+ btn.addEventListener('click', async () => {
263
+ try {
264
+ btn.disabled = true;
265
+ const repo = vcsDevState.repo;
266
+ if (!repo) {
267
+ devLog('⚠️ Repo not initialized yet.');
268
+ return;
269
+ }
270
+
271
+ devLog('💾 Staging and committing changes via VcsRepository...');
272
+
273
+ // Stage all modified and new files
274
+ const addRes = await repo.add([], { all: true });
275
+
276
+ // Commit with message
277
+ const commitRes = await repo.commit({
278
+ message: 'Update index.ts and add new component with companion comment',
279
+ });
280
+
281
+ const lines: string[] = [
282
+ `🎉 Committed successfully via VcsRepository!`,
283
+ ` Commit: ${commitRes.commitAddr.slice(0, 8)}`,
284
+ ` Files Changed: ${commitRes.committedPaths.join(', ')}`,
285
+ ` Companion Comments Attached: ${commitRes.ingestedCommentsCount}`,
286
+ `👉 Click (3) VCS Status to verify clean working tree.`
287
+ ];
288
+
289
+ devLog(lines.join('\n'));
290
+ } catch (error) {
291
+ devLog(`❌ Commit failed: ${extractErrorMsg(error)}`);
292
+ console.error(`${lc}[btn-vcs-commit]`, error);
293
+ } finally {
294
+ btn.disabled = false;
295
+ }
296
+ });
297
+ }
298
+
299
+ /**
300
+ * 6. Discard working tree changes by restoring from snapshot via VcsRepository.
301
+ */
302
+ export function initVcsResetButton(): void {
303
+ const btn = document.getElementById('btn-vcs-reset') as HTMLButtonElement | null;
304
+ if (!btn) { return; }
305
+
306
+ btn.addEventListener('click', async () => {
307
+ try {
308
+ const { wsSpace, repo } = vcsDevState;
309
+ if (!wsSpace || !repo) {
310
+ devLog('⚠️ Repo not initialized yet.');
311
+ return;
312
+ }
313
+
314
+ devLog('🔄 Resetting virtual working tree from branch snapshot via VcsRepository...');
315
+ await repo.restore({ all: true });
316
+
317
+ // Keep .ibgibignore in place
318
+ wsSpace.setVirtualFile('.ibgibignore', 'node_modules/\n*.log\n');
319
+
320
+ devLog('✅ Working tree restored! All uncommitted edits discarded.\n👉 Click (3) VCS Status to confirm clean state.');
321
+ } catch (error) {
322
+ devLog(`❌ Reset failed: ${extractErrorMsg(error)}`);
323
+ }
324
+ });
325
+ }
326
+
327
+ function setBtnDisabled(id: string, disabled: boolean): void {
328
+ const el = document.getElementById(id) as HTMLButtonElement | null;
329
+ if (el) { el.disabled = disabled; }
330
+ }
@@ -25,8 +25,13 @@ import { init4_7bSetupButton, init4_7bSyncButton, init4_7bCheckButton } from './
25
25
  import { init4_8bSetupButton, init4_8bSyncButton, init4_8bCheckButton } from './dev-tools/phase-4-8.mjs';
26
26
  import { init4_9bSetupButton, init4_9bSyncButton, init4_9bCheckButton } from './dev-tools/phase-4-9.mjs';
27
27
  import { init4_10bSetupButton, init4_10bSyncButton, init4_10bCheckButton } from './dev-tools/phase-4-10.mjs';
28
+ import {
29
+ initVcsInitButton, initVcsListButton, initVcsStatusButton,
30
+ initVcsModifyButton, initVcsCommitButton, initVcsResetButton,
31
+ vcsDevState
32
+ } from './dev-tools/vcs-workspace.mjs';
28
33
 
29
- export { devLog, debugState };
34
+ export { devLog, debugState, vcsDevState };
30
35
 
31
36
  /**
32
37
  * Call once inside DOMContentLoaded to wire up all dev-tool buttons.
@@ -96,6 +101,13 @@ export function initDevTools(): void {
96
101
  init4_10bSetupButton();
97
102
  init4_10bSyncButton();
98
103
  init4_10bCheckButton();
104
+
105
+ initVcsInitButton();
106
+ initVcsListButton();
107
+ initVcsStatusButton();
108
+ initVcsModifyButton();
109
+ initVcsCommitButton();
110
+ initVcsResetButton();
99
111
  } catch (error) {
100
112
  console.error(`${lc_fn} ${extractErrorMsg(error)}`);
101
113
  }
@@ -123,6 +123,7 @@
123
123
  <option value="4.8B">Row 4.8B (Phase 4.8B)</option>
124
124
  <option value="4.9B">Row 4.9B (Phase 4.9B)</option>
125
125
  <option value="4.10B">Row 4.10B (Phase 4.10B)</option>
126
+ <option value="VCS">Row VCS (In-Memory Workspace)</option>
126
127
  </select>
127
128
  </div>
128
129
 
@@ -270,6 +271,19 @@
270
271
  </div>
271
272
  </div>
272
273
 
274
+ <!-- Row VCS: In-Memory Workspace Projection & VCS Engine -->
275
+ <div class="dev-panel-row-container" data-row-id="VCS">
276
+ <span class="dev-panel-row-label">VCS</span>
277
+ <div class="dev-panel-row">
278
+ <button id="btn-vcs-init" class="dev-btn">1. Init In-Memory Repo</button>
279
+ <button id="btn-vcs-list" class="dev-btn" disabled>2. List Virtual Files</button>
280
+ <button id="btn-vcs-status" class="dev-btn" disabled>3. VCS Status</button>
281
+ <button id="btn-vcs-modify" class="dev-btn" disabled>4. Edit app.ts</button>
282
+ <button id="btn-vcs-commit" class="dev-btn" disabled>5. Commit Edits</button>
283
+ <button id="btn-vcs-reset" class="dev-btn" disabled>6. Reset / Restore</button>
284
+ </div>
285
+ </div>
286
+
273
287
  <pre id="dev-panel-log" class="dev-panel-log" aria-live="polite" aria-label="Dev log"></pre>
274
288
  </section>
275
289
  </div>
@@ -294,7 +308,7 @@
294
308
  <p class="footer-text">
295
309
  <span>© ibgib contributors</span> ·
296
310
  <a href="https://ibgib.space" class="footer-link">ibgib.space</a> ·
297
- <a href="https://github.com/ibgib" class="footer-link" target="_blank" rel="noopener">GitHub</a>
311
+ <a href="/privacy" class="footer-link" target="_blank" rel="noopener">Privacy Policy</a>
298
312
  </p>
299
313
  </footer>
300
314