pagan-artifact 0.2.9 → 0.3.1

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/bin/art.js CHANGED
@@ -2,10 +2,11 @@
2
2
 
3
3
  /**
4
4
  * art - Modern version control.
5
- * CLI (v0.2.9)
5
+ * CLI (v0.3.1)
6
6
  */
7
7
 
8
8
  const art = require('../index.js');
9
+ const path = require('path');
9
10
 
10
11
  const [,, command, ...args] = process.argv;
11
12
 
@@ -69,7 +70,19 @@ async function run() {
69
70
 
70
71
  if (ignored && ignored.length > 0) {
71
72
  console.log('\nIgnored files:');
72
- ignored.forEach(f => console.log(`${GRAY}\t${f}${RESET}`));
73
+
74
+ const compressedIgnored = new Set();
75
+
76
+ ignored.forEach(f => {
77
+ const parts = f.split(path.sep);
78
+ if (parts.length > 1) {
79
+ compressedIgnored.add(`${parts[0]}${path.sep}`);
80
+ } else {
81
+ compressedIgnored.add(f);
82
+ }
83
+ });
84
+
85
+ compressedIgnored.forEach(f => console.log(`${GRAY}\t${f}${RESET}`));
73
86
  }
74
87
 
75
88
  if (untracked.length === 0 && modified.length === 0 && staged.length === 0) {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * art - Modern version control.
3
- * Module: Branching (v0.2.9)
3
+ * Module: Branching (v0.3.1)
4
4
  */
5
5
 
6
6
  const fs = require('fs');
@@ -26,6 +26,7 @@ function branch ({ name, isDelete = false } = {}) {
26
26
  });
27
27
  }
28
28
 
29
+ const normalizedName = name.toLowerCase();
29
30
  const illegalRegExp = /[\/\\]/g;
30
31
  const controlRegExp = /[\x00-\x1f\x80-\x9f]/g;
31
32
  const reservedRegExp = /^\.+$/;
@@ -89,20 +90,25 @@ function branch ({ name, isDelete = false } = {}) {
89
90
 
90
91
  if (initialCommits.length > 0) {
91
92
  const sourceBranchPath = path.join(localHistoryPath, sourceBranchName);
93
+ const sourceRemotePath = path.join(remoteHistoryPath, sourceBranchName);
92
94
 
93
95
  for (const hash of initialCommits) {
94
- const masterFile = path.join(sourceBranchPath, `${hash}.json`);
96
+ let masterFile = path.join(sourceBranchPath, `${hash}.json`);
97
+ let currentSrcDir = sourceBranchPath;
98
+
99
+ if (!fs.existsSync(masterFile)) {
100
+ masterFile = path.join(sourceRemotePath, `${hash}.json`);
101
+ currentSrcDir = sourceRemotePath;
102
+ }
95
103
 
96
104
  if (fs.existsSync(masterFile)) {
97
- // Copy the Master File
98
105
  fs.copyFileSync(masterFile, path.join(branchLocalPath, `${hash}.json`));
99
106
 
100
- // Detect and copy all Parts
101
107
  const commitMaster = JSON.parse(fs.readFileSync(masterFile, 'utf8'));
102
108
 
103
109
  if (commitMaster.parts && Array.isArray(commitMaster.parts)) {
104
110
  for (const partName of commitMaster.parts) {
105
- const srcPart = path.join(sourceBranchPath, partName);
111
+ const srcPart = path.join(currentSrcDir, partName);
106
112
  const destPart = path.join(branchLocalPath, partName);
107
113
 
108
114
  if (fs.existsSync(srcPart)) {
@@ -287,11 +293,11 @@ function checkout (branchName, { force = false } = {}) {
287
293
  JSON.stringify({ parts: Array.from({ length: partCount }, (_, i) => `part.${i}.json`) }, null, 2)
288
294
  );
289
295
 
290
- return `Merged ${targetBranch}. ${partCount} stage parts created. Resolve conflicts and art commit.`;
296
+ return `Merged ${targetBranch}.`;
291
297
  }
292
298
 
293
299
  module.exports = {
294
- __libraryVersion: '0.2.9',
300
+ __libraryVersion: '0.3.1',
295
301
  __libraryAPIName: 'Branching',
296
302
  branch,
297
303
  checkout,
package/caches/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * art - Modern version control.
3
- * Module: Caches (v0.2.9)
3
+ * Module: Caches (v0.3.1)
4
4
  */
5
5
 
6
6
  const fs = require('fs');
@@ -9,15 +9,16 @@ const path = require('path');
9
9
  const { checkout } = require('../branching/index.js');
10
10
  const getStateByHash = require('../utils/getStateByHash');
11
11
 
12
+ const MAX_PART_SIZE = 32000000;
13
+
12
14
  /**
13
- * Helper to load all changes from a paginated stage directory.
15
+ * Helper to load all changes from a paginated directory (Stage or Stash).
14
16
  */
15
17
 
16
- function getStagedChanges(artPath) {
17
- const stageDir = path.join(artPath, 'stage');
18
- const manifestPath = path.join(stageDir, 'manifest.json');
18
+ function getPaginatedChanges (dirPath) {
19
+ const manifestPath = path.join(dirPath, 'manifest.json');
19
20
 
20
- if (!fs.existsSync(stageDir) || !fs.existsSync(manifestPath)) {
21
+ if (!fs.existsSync(dirPath) || !fs.existsSync(manifestPath)) {
21
22
  return {};
22
23
  }
23
24
 
@@ -26,7 +27,7 @@ function getStagedChanges(artPath) {
26
27
  let allChanges = {};
27
28
 
28
29
  for (const partName of manifest.parts) {
29
- const partPath = path.join(stageDir, partName);
30
+ const partPath = path.join(dirPath, partName);
30
31
 
31
32
  if (fs.existsSync(partPath)) {
32
33
  const partData = JSON.parse(fs.readFileSync(partPath, 'utf8'));
@@ -39,30 +40,28 @@ function getStagedChanges(artPath) {
39
40
  }
40
41
 
41
42
  /**
42
- * Helper to write changes to a paginated stage directory.
43
+ * Helper to write changes to a paginated directory.
43
44
  */
44
45
 
45
- function saveStagedChanges(artPath, changes) {
46
- const MAX_PART_SIZE = 32000000;
47
- const stageDir = path.join(artPath, 'stage');
48
-
49
- if (fs.existsSync(stageDir)) {
50
- fs.rmSync(stageDir, { recursive: true, force: true });
46
+ function savePaginatedChanges (dirPath, changes) {
47
+ if (fs.existsSync(dirPath)) {
48
+ fs.rmSync(dirPath, { recursive: true, force: true });
51
49
  }
52
50
 
53
- fs.mkdirSync(stageDir, { recursive: true });
51
+ fs.mkdirSync(dirPath, { recursive: true });
54
52
 
55
- const stageParts = [];
53
+ const parts = [];
56
54
 
57
55
  let currentPartChanges = {};
58
56
  let currentSize = 0;
59
57
 
60
58
  const savePart = () => {
61
- const partName = `part.${stageParts.length}.json`;
59
+ if (Object.keys(currentPartChanges).length === 0) return;
62
60
 
63
- fs.writeFileSync(path.join(stageDir, partName), JSON.stringify({ changes: currentPartChanges }, null, 2));
64
- stageParts.push(partName);
61
+ const partName = `part.${parts.length}.json`;
65
62
 
63
+ fs.writeFileSync(path.join(dirPath, partName), JSON.stringify({ changes: currentPartChanges }, null, 2));
64
+ parts.push(partName);
66
65
  currentPartChanges = {};
67
66
  currentSize = 0;
68
67
  };
@@ -79,14 +78,9 @@ function saveStagedChanges(artPath, changes) {
79
78
  }
80
79
 
81
80
  savePart();
82
-
83
- fs.writeFileSync(path.join(stageDir, 'manifest.json'), JSON.stringify({ parts: stageParts }, null, 2));
81
+ fs.writeFileSync(path.join(dirPath, 'manifest.json'), JSON.stringify({ parts }, null, 2));
84
82
  }
85
83
 
86
- /**
87
- * Moves changes to a cache folder, or restores the most recent stash.
88
- */
89
-
90
84
  function stash ({ pop = false, list = false } = {}) {
91
85
  const root = process.cwd();
92
86
  const artPath = path.join(root, '.art');
@@ -97,14 +91,14 @@ function stash ({ pop = false, list = false } = {}) {
97
91
  if (list) {
98
92
  if (!fs.existsSync(cachePath)) return [];
99
93
 
100
- const stashFiles = fs.readdirSync(cachePath)
101
- .filter(f => f.startsWith('stash_') && f.endsWith('.json'))
94
+ const stashDirs = fs.readdirSync(cachePath)
95
+ .filter(d => d.startsWith('stash_') && fs.statSync(path.join(cachePath, d)).isDirectory())
102
96
  .sort();
103
97
 
104
- return stashFiles.map((file, index) => ({
105
- id: `stash@{${stashFiles.length - 1 - index}}`,
106
- date: new Date(parseInt(file.replace('stash_', '').replace('.json', ''))).toLocaleString(),
107
- file
98
+ return stashDirs.map((dirName, index) => ({
99
+ id: `stash@{${stashDirs.length - 1 - index}}`,
100
+ date: new Date(parseInt(dirName.replace('stash_', ''))).toLocaleString(),
101
+ dirName
108
102
  }));
109
103
  }
110
104
 
@@ -112,18 +106,16 @@ function stash ({ pop = false, list = false } = {}) {
112
106
  if (!fs.existsSync(cachePath)) throw new Error('No stashes found.');
113
107
 
114
108
  const stashes = fs.readdirSync(cachePath)
115
- .filter(f => f.startsWith('stash_') && f.endsWith('.json'))
109
+ .filter(d => d.startsWith('stash_') && fs.statSync(path.join(cachePath, d)).isDirectory())
116
110
  .sort();
117
111
 
118
- if (stashes.length === 0) {
119
- throw new Error('No stashes found.');
120
- }
112
+ if (stashes.length === 0) throw new Error('No stashes found.');
121
113
 
122
- const latestStashName = stashes[stashes.length - 1];
123
- const latestStashPath = path.join(cachePath, latestStashName);
124
- const stashData = JSON.parse(fs.readFileSync(latestStashPath, 'utf8'));
114
+ const latestStashDirName = stashes[stashes.length - 1];
115
+ const latestStashPath = path.join(cachePath, latestStashDirName);
116
+ const stashChanges = getPaginatedChanges(latestStashPath);
125
117
 
126
- for (const [filePath, changeSet] of Object.entries(stashData.changes)) {
118
+ for (const [filePath, changeSet] of Object.entries(stashChanges)) {
127
119
  const fullPath = path.join(root, filePath);
128
120
 
129
121
  if (Array.isArray(changeSet)) {
@@ -146,9 +138,8 @@ function stash ({ pop = false, list = false } = {}) {
146
138
  }
147
139
  }
148
140
 
149
- fs.unlinkSync(latestStashPath);
150
-
151
- return `Restored changes from ${latestStashName}.`;
141
+ fs.rmSync(latestStashPath, { recursive: true, force: true });
142
+ return `Restored changes from ${latestStashDirName}.`;
152
143
  }
153
144
 
154
145
  const artJson = JSON.parse(fs.readFileSync(artJsonPath, 'utf8'));
@@ -160,12 +151,16 @@ function stash ({ pop = false, list = false } = {}) {
160
151
  const stashChanges = {};
161
152
 
162
153
  for (const file of allWorkDirFiles) {
163
- const currentContent = fs.readFileSync(path.join(root, file), 'utf8');
154
+ const fullPath = path.join(root, file);
155
+ const currentBuffer = fs.readFileSync(fullPath);
156
+ const isBinary = currentBuffer.includes(0);
157
+
158
+ const currentContent = isBinary ? null : currentBuffer.toString('utf8');
164
159
  const previousContent = activeState[file];
165
160
 
166
161
  if (previousContent === undefined) {
167
- stashChanges[file] = { type: 'createFile', content: currentContent };
168
- } else if (currentContent !== previousContent) {
162
+ stashChanges[file] = { type: 'createFile', content: isBinary ? currentBuffer.toString('base64') : currentContent };
163
+ } else if (currentContent !== previousContent && !isBinary) {
169
164
  let start = 0;
170
165
 
171
166
  while (start < previousContent.length && start < currentContent.length && previousContent[start] === currentContent[start]) {
@@ -189,7 +184,9 @@ function stash ({ pop = false, list = false } = {}) {
189
184
 
190
185
  if (insCont.length > 0) ops.push({ type: 'insert', position: start, content: insCont });
191
186
 
192
- if (ops.length > 0) stashChanges[file] = ops;
187
+ if (ops.length > 0) {
188
+ stashChanges[file] = ops;
189
+ }
193
190
  }
194
191
  }
195
192
 
@@ -199,15 +196,12 @@ function stash ({ pop = false, list = false } = {}) {
199
196
  }
200
197
  }
201
198
 
202
- if (Object.keys(stashChanges).length === 0) {
203
- return 'No local changes to stash.';
204
- }
205
-
206
- if (!fs.existsSync(cachePath)) fs.mkdirSync(cachePath, { recursive: true });
199
+ if (Object.keys(stashChanges).length === 0) return 'No local changes to stash.';
207
200
 
208
201
  const timestamp = Date.now();
202
+ const newStashPath = path.join(cachePath, `stash_${timestamp}`);
209
203
 
210
- fs.writeFileSync(path.join(cachePath, `stash_${timestamp}.json`), JSON.stringify({ changes: stashChanges }, null, 2));
204
+ savePaginatedChanges(newStashPath, stashChanges);
211
205
 
212
206
  if (fs.existsSync(stageDir)) {
213
207
  fs.rmSync(stageDir, { recursive: true, force: true });
@@ -215,13 +209,9 @@ function stash ({ pop = false, list = false } = {}) {
215
209
 
216
210
  checkout(artJson.active.branch, { force: true });
217
211
 
218
- return `Saved working directory changes to stash_${timestamp}.json and reverted to clean state.`;
212
+ return `Saved working directory changes to stash_${timestamp} and reverted to clean state.`;
219
213
  }
220
214
 
221
- /**
222
- * Wipes the stage and moves the active parent pointer if a hash is provided.
223
- */
224
-
225
215
  function reset (hash) {
226
216
  const artPath = path.join(process.cwd(), '.art');
227
217
  const stageDir = path.join(artPath, 'stage');
@@ -231,18 +221,14 @@ function reset (hash) {
231
221
  fs.rmSync(stageDir, { recursive: true, force: true });
232
222
  }
233
223
 
234
- if (!hash) {
235
- return 'Staging area cleared.';
236
- }
224
+ if (!hash) return 'Staging area cleared.';
237
225
 
238
226
  const artJson = JSON.parse(fs.readFileSync(artJsonPath, 'utf8'));
239
227
  const branch = artJson.active.branch;
240
228
  const branchPath = path.join(artPath, 'history/local', branch);
241
229
  const commitPath = path.join(branchPath, `${hash}.json`);
242
230
 
243
- if (!fs.existsSync(commitPath)) {
244
- throw new Error(`Commit ${hash} not found in branch ${branch}.`);
245
- }
231
+ if (!fs.existsSync(commitPath)) throw new Error(`Commit ${hash} not found in branch ${branch}.`);
246
232
 
247
233
  artJson.active.parent = hash;
248
234
  fs.writeFileSync(artJsonPath, JSON.stringify(artJson, null, 2));
@@ -258,34 +244,24 @@ function reset (hash) {
258
244
 
259
245
  checkout(branch);
260
246
 
261
- return `Head is now at ${hash.slice(0, 7)}. Working directory updated.`;
247
+ return `Branch is now at ${hash.slice(0, 7)}. Working directory updated.`;
262
248
  }
263
249
 
264
- /**
265
- * Marks a file for deletion by adding a "deleteFile" entry to the stage.
266
- */
267
-
268
250
  function rm (filePath) {
269
251
  const artPath = path.join(process.cwd(), '.art');
270
252
  const fullPath = path.join(process.cwd(), filePath);
253
+ const stage = getPaginatedChanges(path.join(artPath, 'stage'));
271
254
 
272
- const stage = getStagedChanges(artPath);
255
+ stage[filePath] = { type: 'deleteFile' };
256
+ savePaginatedChanges(path.join(artPath, 'stage'), stage);
273
257
 
274
- stage[filePath] = {
275
- type: 'deleteFile'
276
- };
277
-
278
- saveStagedChanges(artPath, stage);
279
-
280
- if (fs.existsSync(fullPath)) {
281
- fs.unlinkSync(fullPath);
282
- }
258
+ if (fs.existsSync(fullPath)) fs.unlinkSync(fullPath);
283
259
 
284
260
  return `File ${filePath} marked for removal.`;
285
261
  }
286
262
 
287
263
  module.exports = {
288
- __libraryVersion: '0.2.9',
264
+ __libraryVersion: '0.3.1',
289
265
  __libraryAPIName: 'Caches',
290
266
  stash,
291
267
  reset,
package/changes/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * art - Modern version control.
3
- * Module: Changes (v0.2.9)
3
+ * Module: Changes (v0.3.1)
4
4
  */
5
5
 
6
6
  const fs = require('fs');
@@ -34,8 +34,6 @@ function log () {
34
34
 
35
35
  let output = `Branch: ${branch}\n\n`;
36
36
 
37
- // Display commits in reverse chronological order
38
-
39
37
  for (let i = manifest.commits.length - 1; i >= 0; i--) {
40
38
  const hash = manifest.commits[i];
41
39
  const commitMasterPath = path.join(branchPath, `${hash}.json`);
@@ -57,7 +55,7 @@ function log () {
57
55
  * @returns {object} Formatted diff output and staged file list.
58
56
  */
59
57
 
60
- function diff () {
58
+ function diff () {
61
59
  const root = process.cwd();
62
60
  const artPath = path.join(root, '.art');
63
61
  const artJsonPath = path.join(artPath, 'art.json');
@@ -78,10 +76,13 @@ function log () {
78
76
 
79
77
  for (const filePath of currentFiles) {
80
78
  const fullPath = path.join(root, filePath);
81
- const currentContent = fs.readFileSync(fullPath, 'utf8');
79
+ const currentBuffer = fs.readFileSync(fullPath);
80
+ const isBinary = currentBuffer.includes(0);
81
+
82
+ const currentContent = isBinary ? null : currentBuffer.toString('utf8');
82
83
  const previousContent = lastCommitState[filePath] || '';
83
84
 
84
- if (currentContent !== previousContent) {
85
+ if (!isBinary && currentContent !== previousContent) {
85
86
  let start = 0;
86
87
 
87
88
  while (start < previousContent.length && start < currentContent.length && previousContent[start] === currentContent[start]) {
@@ -101,6 +102,12 @@ function log () {
101
102
  deleted: previousContent.slice(start, oldEnd + 1),
102
103
  added: currentContent.slice(start, newEnd + 1)
103
104
  });
105
+ } else if (isBinary) {
106
+ const prevHash = lastCommitState[filePath] ? 'exists' : 'null';
107
+
108
+ if (prevHash === 'null') {
109
+ fileDiffs.push({ file: filePath, added: '<Binary Data>', deleted: '' });
110
+ }
104
111
  }
105
112
  }
106
113
 
@@ -115,8 +122,10 @@ function log () {
115
122
 
116
123
  for (const partName of manifest.parts) {
117
124
  const partPath = path.join(stageDir, partName);
125
+
118
126
  if (fs.existsSync(partPath)) {
119
127
  const partData = JSON.parse(fs.readFileSync(partPath, 'utf8'));
128
+
120
129
  Object.keys(partData.changes).forEach(file => stagedFilesSet.add(file));
121
130
  }
122
131
  }
@@ -127,7 +136,7 @@ function log () {
127
136
  }
128
137
 
129
138
  module.exports = {
130
- __libraryVersion: '0.2.9',
139
+ __libraryVersion: '0.3.1',
131
140
  __libraryAPIName: 'Changes',
132
141
  log,
133
142
  diff
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * art - Modern version control.
3
- * Module: Contributions (v0.2.9)
3
+ * Module: Contributions (v0.3.1)
4
4
  */
5
5
 
6
6
  const fs = require('fs');
@@ -60,7 +60,10 @@ async function fetchRemote () {
60
60
  method: 'POST',
61
61
  headers: { 'Content-Type': 'application/json' },
62
62
  body: JSON.stringify({
63
- type: 'history', handle, repo, branch,
63
+ type: 'history',
64
+ handle,
65
+ repo,
66
+ branch,
64
67
  ...(token && { personalAccessToken: token })
65
68
  })
66
69
  });
@@ -171,20 +174,22 @@ async function push () {
171
174
  const handle = remoteParts.pop();
172
175
 
173
176
  const localBranchPath = path.join(artPath, 'history/local', branch);
177
+ const remoteBranchPath = path.join(artPath, 'history/remote', branch);
174
178
  const localManifest = JSON.parse(fs.readFileSync(path.join(localBranchPath, 'manifest.json'), 'utf8'));
175
179
 
176
180
  const response = await fetch(`${ARTIFACT_HOST}/manifest`, {
177
181
  method: 'POST',
178
182
  headers: { 'Content-Type': 'application/json' },
179
183
  body: JSON.stringify({
180
- type: 'history', handle, repo, branch,
181
-
184
+ type: 'history',
185
+ handle,
186
+ repo,
187
+ branch,
182
188
  ...(token && { personalAccessToken: token })
183
189
  })
184
190
  });
185
191
 
186
192
  const remoteManifest = await response.json();
187
-
188
193
  const missingCommits = localManifest.commits.filter(hash => !remoteManifest.commits.includes(hash));
189
194
 
190
195
  if (missingCommits.length === 0) {
@@ -208,13 +213,17 @@ async function push () {
208
213
  }
209
214
  }
210
215
 
216
+ const currentRemoteManifestPath = path.join(remoteBranchPath, 'manifest.json');
217
+ const currentRemoteManifest = fs.existsSync(currentRemoteManifestPath)
218
+ ? JSON.parse(fs.readFileSync(currentRemoteManifestPath, 'utf8'))
219
+ : { commits: [] };
220
+
211
221
  for (const commitHash of missingCommits) {
212
222
  const commitMaster = JSON.parse(fs.readFileSync(path.join(localBranchPath, `${commitHash}.json`), 'utf8'));
213
223
 
214
- await fetch(`${ARTIFACT_HOST}/push`, {
224
+ const pushRes = await fetch(`${ARTIFACT_HOST}/push`, {
215
225
  method: 'POST',
216
226
  headers: { 'Content-Type': 'application/json' },
217
-
218
227
  body: JSON.stringify({
219
228
  handle, repo, branch, commit: commitMaster,
220
229
 
@@ -224,12 +233,14 @@ async function push () {
224
233
  })
225
234
  });
226
235
 
236
+ if (!pushRes.ok) throw new Error(`Server rejected push for commit ${commitHash}`);
237
+
227
238
  rootData = null;
228
239
 
229
240
  for (const partName of commitMaster.parts) {
230
241
  const partData = JSON.parse(fs.readFileSync(path.join(localBranchPath, partName), 'utf8'));
231
242
 
232
- await fetch(`${ARTIFACT_HOST}/commit/part`, {
243
+ const partRes = await fetch(`${ARTIFACT_HOST}/commit/part`, {
233
244
  method: 'POST',
234
245
  headers: { 'Content-Type': 'application/json' },
235
246
  body: JSON.stringify({
@@ -237,10 +248,13 @@ async function push () {
237
248
  ...(token && { personalAccessToken: token })
238
249
  })
239
250
  });
251
+
252
+ if (!partRes.ok) throw new Error(`Server failed to receive part ${partName}`);
240
253
  }
241
- }
242
254
 
243
- fs.writeFileSync(path.join(artPath, 'history/remote', branch, 'manifest.json'), JSON.stringify(localManifest, null, 2));
255
+ currentRemoteManifest.commits.push(commitHash);
256
+ fs.writeFileSync(currentRemoteManifestPath, JSON.stringify(currentRemoteManifest, null, 2));
257
+ }
244
258
 
245
259
  return `Pushed ${missingCommits.length} commits to remote.`;
246
260
  }
package/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * art - Modern version control.
3
- * Core Library Entry Point (v0.2.9)
3
+ * Core Library Entry Point (v0.3.1)
4
4
  */
5
5
 
6
6
  const Setup = require('./setup');
@@ -50,7 +50,7 @@ const art = {
50
50
 
51
51
  // Metadata
52
52
 
53
- version: '0.2.9',
53
+ version: '0.3.1',
54
54
  modules: [
55
55
  Setup.__libraryAPIName,
56
56
  Workflow.__libraryAPIName,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pagan-artifact",
3
- "version": "0.2.9",
3
+ "version": "0.3.1",
4
4
  "description": "Modern version control.",
5
5
  "main": "index.js",
6
6
  "bin": {
package/setup/index.js CHANGED
@@ -1,137 +1,135 @@
1
1
  /**
2
2
  * art - Modern version control.
3
- * Module: Setup (v0.2.9)
3
+ * Module: Setup (v0.3.1)
4
4
  */
5
5
 
6
6
  const fs = require('fs');
7
7
  const path = require('path');
8
8
 
9
9
  const pkg = require('../package.json');
10
- const { remote } = require('../contributions');
11
10
  const shouldIgnore = require('../utils/shouldIgnore');
12
11
 
13
12
  const ARTIFACT_HOST = pkg.artConfig.host || 'http://localhost:1337';
13
+ const MAX_PART_CHARS = 32000000;
14
14
 
15
15
  /**
16
- * Initializes the local .art directory structure.
16
+ * Internal helper to create the .art directory tree.
17
17
  */
18
18
 
19
- function init (directoryPath = process.cwd()) {
20
- const artDirectory = path.join(directoryPath, '.art');
21
-
22
- const folders = [
23
- '',
24
- 'root',
25
- 'history',
26
- 'history/local',
27
- 'history/local/main',
28
- 'history/remote',
29
- 'history/remote/main'
30
- ];
31
-
32
- if (fs.existsSync(artDirectory)) {
33
- return `Reinitialized existing art repository in ${artDirectory}`;
34
- }
19
+ function ensureDirStructure(artDirectory) {
20
+ const folders = [
21
+ '',
22
+ 'root',
23
+ 'history',
24
+ 'history/local',
25
+ 'history/local/main',
26
+ 'history/remote',
27
+ 'history/remote/main'
28
+ ];
29
+
30
+ for (const folder of folders) {
31
+ const fullPath = path.join(artDirectory, folder);
32
+
33
+ if (!fs.existsSync(fullPath)) {
34
+ fs.mkdirSync(fullPath, { recursive: true });
35
+ }
36
+ }
37
+ }
35
38
 
36
- for (const folder of folders) {
37
- const fullPath = path.join(artDirectory, folder);
39
+ /**
40
+ * Initializes the local .art directory structure and indexes current files.
41
+ */
38
42
 
39
- if (!fs.existsSync(fullPath)) {
40
- fs.mkdirSync(fullPath, { recursive: true });
41
- }
42
- }
43
+ function init (directoryPath = process.cwd()) {
44
+ const artDirectory = path.join(directoryPath, '.art');
43
45
 
44
- const files = fs.readdirSync(directoryPath, { recursive: true })
45
- .filter(f => {
46
- const isInternal = f === '.art' || f.startsWith('.art' + path.sep);
46
+ if (fs.existsSync(artDirectory)) {
47
+ return `Reinitialized existing art repository in ${artDirectory}.`;
48
+ }
47
49
 
48
- return !isInternal && !shouldIgnore(f);
49
- });
50
+ ensureDirStructure(artDirectory);
50
51
 
51
- const rootMasterManifest = { parts: [] };
52
+ const files = fs.readdirSync(directoryPath, { recursive: true })
53
+ .filter(f => {
54
+ const isInternal = f === '.art' || f.startsWith('.art' + path.sep);
52
55
 
53
- let currentPartFiles = [];
54
- let currentPartChars = 0;
56
+ return !isInternal && !shouldIgnore(f);
57
+ });
55
58
 
56
- const MAX_PART_CHARS = 32000000;
59
+ const rootMasterManifest = { parts: [] };
57
60
 
58
- const saveManifestPart = () => {
59
- if (currentPartFiles.length === 0) return;
61
+ let currentPartFiles = [];
62
+ let currentPartChars = 0;
60
63
 
61
- const partIndex = rootMasterManifest.parts.length;
62
- const partName = `manifest.part.${Date.now()}.${partIndex}.json`;
63
- const partPath = path.join(artDirectory, 'root', partName);
64
+ const saveManifestPart = () => {
65
+ if (currentPartFiles.length === 0) return;
64
66
 
65
- fs.writeFileSync(
66
- partPath,
67
- JSON.stringify({ files: currentPartFiles }, null, 2)
68
- );
67
+ const partIndex = rootMasterManifest.parts.length;
68
+ const partName = `manifest.part.${partIndex}.json`;
69
+ const partPath = path.join(artDirectory, 'root', partName);
69
70
 
70
- rootMasterManifest.parts.push(partName);
71
+ fs.writeFileSync(
72
+ partPath,
73
+ JSON.stringify({ files: currentPartFiles }, null, 2)
74
+ );
71
75
 
72
- currentPartFiles = [];
73
- currentPartChars = 0;
74
- };
76
+ rootMasterManifest.parts.push(partName);
77
+ currentPartFiles = [];
78
+ currentPartChars = 0;
79
+ };
75
80
 
76
- for (const file of files) {
77
- const fullPath = path.join(directoryPath, file);
81
+ for (const file of files) {
82
+ const fullPath = path.join(directoryPath, file);
78
83
 
79
- if (fs.lstatSync(fullPath).isFile()) {
80
- const content = fs.readFileSync(fullPath, 'utf8');
84
+ if (fs.lstatSync(fullPath).isFile()) {
85
+ const content = fs.readFileSync(fullPath, 'utf8');
81
86
 
82
- if (currentPartChars + content.length > MAX_PART_CHARS && currentPartFiles.length > 0) {
83
- saveManifestPart();
84
- }
87
+ if (currentPartChars + content.length > MAX_PART_CHARS && currentPartFiles.length > 0) {
88
+ saveManifestPart();
89
+ }
85
90
 
86
- currentPartFiles.push({
87
- path: file,
88
- content: content
89
- });
91
+ currentPartFiles.push({
92
+ path: file,
93
+ content: content
94
+ });
90
95
 
91
- currentPartChars += content.length;
92
- }
93
- }
96
+ currentPartChars += content.length;
97
+ }
98
+ }
94
99
 
95
- saveManifestPart();
100
+ saveManifestPart();
96
101
 
97
- fs.writeFileSync(
98
- path.join(artDirectory, 'root/manifest.json'),
99
- JSON.stringify(rootMasterManifest, null, 2)
100
- );
102
+ fs.writeFileSync(
103
+ path.join(artDirectory, 'root/manifest.json'),
104
+ JSON.stringify(rootMasterManifest, null, 2)
105
+ );
101
106
 
102
- fs.writeFileSync(
103
- path.join(artDirectory, 'history/local/main/manifest.json'),
104
- JSON.stringify({ commits: [] }, null, 2)
105
- );
107
+ fs.writeFileSync(
108
+ path.join(artDirectory, 'history/local/main/manifest.json'),
109
+ JSON.stringify({ commits: [] }, null, 2)
110
+ );
106
111
 
107
- fs.writeFileSync(
108
- path.join(artDirectory, 'history/remote/main/manifest.json'),
109
- JSON.stringify({ commits: [] }, null, 2)
110
- );
112
+ fs.writeFileSync(
113
+ path.join(artDirectory, 'history/remote/main/manifest.json'),
114
+ JSON.stringify({ commits: [] }, null, 2)
115
+ );
111
116
 
112
- const artFile = {
113
- active: { branch: 'main', parent: null },
114
- remote: '',
115
- configuration: { handle: '', personalAccessToken: '' }
116
- };
117
+ const artFile = {
118
+ active: { branch: 'main', parent: null },
119
+ remote: '',
120
+ configuration: { handle: '', personalAccessToken: '' }
121
+ };
117
122
 
118
- fs.writeFileSync(
119
- path.join(artDirectory, 'art.json'),
120
- JSON.stringify(artFile, null, 2)
121
- );
123
+ fs.writeFileSync(
124
+ path.join(artDirectory, 'art.json'),
125
+ JSON.stringify(artFile, null, 2)
126
+ );
122
127
 
123
- return `Initialized empty art repository in ${artDirectory} with ${rootMasterManifest.parts.length} manifest part(s).`;
124
- }
128
+ return `Initialized empty art repository in ${artDirectory}.`;
129
+ }
125
130
 
126
131
  /**
127
- * Clone a repository
128
- * @param {string} repoSlug - The handle/repo identifier.
129
- * @param {string} providedToken - Optional token for authentication.
130
- */
131
-
132
- /**
133
- * art - Modern version control.
134
- * Module: Setup (v0.2.9) - Clone logic
132
+ * Clone a repository and replay history.
135
133
  */
136
134
 
137
135
  async function clone (repoSlug, providedToken = null) {
@@ -148,19 +146,20 @@ async function clone (repoSlug, providedToken = null) {
148
146
  }
149
147
 
150
148
  fs.mkdirSync(targetPath, { recursive: true });
151
- init(targetPath);
149
+
150
+ const artPath = path.join(targetPath, '.art');
151
+
152
+ ensureDirStructure(artPath);
152
153
  process.chdir(targetPath);
153
154
 
154
155
  try {
155
- const artPath = path.join(targetPath, '.art');
156
156
  const artJsonPath = path.join(artPath, 'art.json');
157
- const artJson = JSON.parse(fs.readFileSync(artJsonPath, 'utf8'));
158
157
 
159
- if (providedToken) {
160
- artJson.configuration.personalAccessToken = providedToken;
161
- }
162
-
163
- artJson.remote = `${ARTIFACT_HOST}/${handle}/${repo}`;
158
+ const artJson = {
159
+ active: { branch: 'main', parent: null },
160
+ remote: `${ARTIFACT_HOST}/${handle}/${repo}`,
161
+ configuration: { handle: '', personalAccessToken: providedToken || '' }
162
+ };
164
163
 
165
164
  fs.writeFileSync(artJsonPath, JSON.stringify(artJson, null, 2));
166
165
 
@@ -174,7 +173,6 @@ async function clone (repoSlug, providedToken = null) {
174
173
  handle,
175
174
  repo,
176
175
  branch: 'main',
177
-
178
176
  ...(token && { personalAccessToken: token })
179
177
  })
180
178
  });
@@ -209,7 +207,6 @@ async function clone (repoSlug, providedToken = null) {
209
207
  });
210
208
 
211
209
  const historyManifest = await historyRes.json();
212
-
213
210
  const localHistoryDir = path.join(artPath, 'history/local/main');
214
211
  const remoteHistoryDir = path.join(artPath, 'history/remote/main');
215
212
 
@@ -217,10 +214,19 @@ async function clone (repoSlug, providedToken = null) {
217
214
  const commitRes = await fetch(`${ARTIFACT_HOST}/commit`, {
218
215
  method: 'POST',
219
216
  headers: { 'Content-Type': 'application/json' },
220
- body: JSON.stringify({ handle, repo, branch: 'main', hash: commitHash, ...(token && { personalAccessToken: token }) })
217
+ body: JSON.stringify({
218
+ handle,
219
+ repo,
220
+ branch: 'main',
221
+ hash: commitHash,
222
+
223
+ ...(token && { personalAccessToken: token
224
+ })
225
+ })
221
226
  });
222
227
 
223
228
  const commitMaster = await commitRes.json();
229
+
224
230
  let fullChanges = {};
225
231
 
226
232
  if (commitMaster.parts && commitMaster.parts.length > 0) {
@@ -232,7 +238,6 @@ async function clone (repoSlug, providedToken = null) {
232
238
  });
233
239
 
234
240
  const partData = await partRes.json();
235
-
236
241
  fs.writeFileSync(path.join(localHistoryDir, partName), JSON.stringify(partData, null, 2));
237
242
  fs.writeFileSync(path.join(remoteHistoryDir, partName), JSON.stringify(partData, null, 2));
238
243
 
@@ -252,7 +257,6 @@ async function clone (repoSlug, providedToken = null) {
252
257
 
253
258
  if (Array.isArray(changeSet)) {
254
259
  let content = fs.existsSync(fullPath) ? fs.readFileSync(fullPath, 'utf8') : '';
255
-
256
260
  for (const op of changeSet) {
257
261
  if (op.type === 'insert') {
258
262
  content = content.slice(0, op.position) + op.content + content.slice(op.position);
@@ -260,7 +264,6 @@ async function clone (repoSlug, providedToken = null) {
260
264
  content = content.slice(0, op.position) + content.slice(op.position + op.length);
261
265
  }
262
266
  }
263
-
264
267
  fs.writeFileSync(fullPath, content);
265
268
  } else if (changeSet.type === 'createFile') {
266
269
  fs.mkdirSync(path.dirname(fullPath), { recursive: true });
@@ -292,8 +295,7 @@ async function clone (repoSlug, providedToken = null) {
292
295
  /**
293
296
  * Updates the configuration in art.json.
294
297
  */
295
-
296
- function config (key, value) {
298
+ function config(key, value) {
297
299
  const manifestPath = path.join(process.cwd(), '.art', 'art.json');
298
300
 
299
301
  if (!fs.existsSync(manifestPath)) {
@@ -304,7 +306,6 @@ function config (key, value) {
304
306
 
305
307
  if (key && value !== undefined) {
306
308
  manifest.configuration[key] = value;
307
-
308
309
  fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
309
310
  }
310
311
 
@@ -316,5 +317,6 @@ module.exports = {
316
317
  __libraryAPIName: 'Setup',
317
318
  init,
318
319
  clone,
319
- config
320
+ config,
321
+ ensureDirStructure
320
322
  };
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * art - Modern version control.
3
- * Module: Utils (v0.2.9)
3
+ * Module: Utils (v0.3.1)
4
4
  */
5
5
 
6
6
  const fs = require('fs');
package/workflow/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * art - Modern version control.
3
- * Module: Workflow (v0.2.9)
3
+ * Module: Workflow (v0.3.1)
4
4
  */
5
5
 
6
6
  const fs = require('fs');
@@ -10,6 +10,8 @@ const crypto = require('crypto');
10
10
  const getStateByHash = require('../utils/getStateByHash');
11
11
  const shouldIgnore = require('../utils/shouldIgnore');
12
12
 
13
+ const MAX_PART_SIZE = 32000000;
14
+
13
15
  /**
14
16
  * Helper to load all changes from a paginated stage directory.
15
17
  */
@@ -27,8 +29,10 @@ function getStagedChanges(artPath) {
27
29
 
28
30
  for (const partName of manifest.parts) {
29
31
  const partPath = path.join(stageDir, partName);
32
+
30
33
  if (fs.existsSync(partPath)) {
31
34
  const partData = JSON.parse(fs.readFileSync(partPath, 'utf8'));
35
+
32
36
  Object.assign(allChanges, partData.changes);
33
37
  }
34
38
  }
@@ -72,6 +76,7 @@ function status () {
72
76
 
73
77
  if (isIgnored && !isActive && !isStaged) {
74
78
  ignored.push(file);
79
+
75
80
  continue;
76
81
  }
77
82
 
@@ -79,6 +84,7 @@ function status () {
79
84
  untracked.push(file);
80
85
  } else if (!isStaged && isActive) {
81
86
  const currentContent = fs.readFileSync(path.join(root, file), 'utf8');
87
+
82
88
  if (currentContent !== activeState[file]) {
83
89
  modified.push(file);
84
90
  }
@@ -99,118 +105,124 @@ function status () {
99
105
  * Updates or creates a JSON diff in the stage directory.
100
106
  */
101
107
 
102
- function add (targetPath) {
103
- const MAX_PART_SIZE = 32000000;
104
- const root = process.cwd();
105
- const artPath = path.join(root, '.art');
106
- const stageDir = path.join(artPath, 'stage');
107
- const artJsonPath = path.join(artPath, 'art.json');
108
- const fullPath = path.resolve(root, targetPath);
108
+ function add (targetPath) {
109
+ const root = process.cwd();
110
+ const artPath = path.join(root, '.art');
111
+ const stageDir = path.join(artPath, 'stage');
112
+ const artJsonPath = path.join(artPath, 'art.json');
113
+ const fullPath = path.resolve(root, targetPath);
109
114
 
110
- if (!fs.existsSync(fullPath)) throw new Error(`Path does not exist: ${targetPath}`);
115
+ if (!fs.existsSync(fullPath)) {
116
+ throw new Error(`Path does not exist: ${targetPath}`);
117
+ }
111
118
 
112
- const artJson = JSON.parse(fs.readFileSync(artJsonPath, 'utf8'));
113
- const activeState = getStateByHash(artJson.active.branch, artJson.active.parent) || {};
114
- const currentStaged = getStagedChanges(artPath);
119
+ const artJson = JSON.parse(fs.readFileSync(artJsonPath, 'utf8'));
120
+ const activeState = getStateByHash(artJson.active.branch, artJson.active.parent) || {};
121
+ const currentStaged = getStagedChanges(artPath);
115
122
 
116
- const stats = fs.statSync(fullPath);
117
- const relativeTarget = path.relative(root, fullPath);
123
+ const stats = fs.statSync(fullPath);
124
+ const relativeTarget = path.relative(root, fullPath);
118
125
 
119
- if (!stats.isDirectory() && shouldIgnore(relativeTarget) && !activeState[relativeTarget]) {
120
- return `${relativeTarget} is being ignored.`;
121
- }
126
+ if (!stats.isDirectory() && shouldIgnore(relativeTarget) && !activeState[relativeTarget]) {
127
+ return `${relativeTarget} is being ignored.`;
128
+ }
122
129
 
123
- let filesToProcess = [];
130
+ let filesToProcess = [];
124
131
 
125
- if (stats.isDirectory()) {
126
- filesToProcess = fs.readdirSync(fullPath, { recursive: true })
127
- .filter(f => {
128
- const absF = path.join(fullPath, f);
129
- const relF = path.relative(root, absF);
132
+ if (stats.isDirectory()) {
133
+ filesToProcess = fs.readdirSync(fullPath, { recursive: true })
134
+ .filter(f => {
135
+ const absF = path.join(fullPath, f);
136
+ const relF = path.relative(root, absF);
130
137
 
131
- return !fs.statSync(absF).isDirectory() && !relF.startsWith('.art') && (!shouldIgnore(relF) || !!activeState[relF]);
132
- })
133
- .map(f => path.relative(root, path.join(fullPath, f)));
134
- } else {
135
- filesToProcess = [relativeTarget];
136
- }
138
+ return !fs.statSync(absF).isDirectory() && !relF.startsWith('.art') && (!shouldIgnore(relF) || !!activeState[relF]);
139
+ })
140
+ .map(f => path.relative(root, path.join(fullPath, f)));
141
+ } else {
142
+ filesToProcess = [relativeTarget];
143
+ }
137
144
 
138
- if (filesToProcess.length === 0) return "No changes to add.";
145
+ if (filesToProcess.length === 0) return "No changes to add.";
139
146
 
140
- for (const relPath of filesToProcess) {
141
- const currentContent = fs.readFileSync(path.join(root, relPath), 'utf8');
142
- const previousContent = activeState[relPath];
147
+ for (const relPath of filesToProcess) {
148
+ const currentContent = fs.readFileSync(path.join(root, relPath), 'utf8');
149
+ const previousContent = activeState[relPath];
143
150
 
144
- if (previousContent === undefined) {
145
- currentStaged[relPath] = { type: 'createFile', content: currentContent };
146
- } else if (currentContent !== previousContent) {
147
- let start = 0;
151
+ if (previousContent === undefined) {
152
+ currentStaged[relPath] = { type: 'createFile', content: currentContent };
153
+ } else if (currentContent !== previousContent) {
154
+ let start = 0;
148
155
 
149
- while (start < previousContent.length && start < currentContent.length && previousContent[start] === currentContent[start]) {
150
- start++;
151
- }
156
+ while (start < previousContent.length && start < currentContent.length && previousContent[start] === currentContent[start]) {
157
+ start++;
158
+ }
152
159
 
153
- let oldEnd = previousContent.length - 1;
154
- let newEnd = currentContent.length - 1;
160
+ let oldEnd = previousContent.length - 1;
161
+ let newEnd = currentContent.length - 1;
155
162
 
156
- while (oldEnd >= start && newEnd >= start && previousContent[oldEnd] === currentContent[newEnd]) {
157
- oldEnd--; newEnd--;
158
- }
163
+ while (oldEnd >= start && newEnd >= start && previousContent[oldEnd] === currentContent[newEnd]) {
164
+ oldEnd--; newEnd--;
165
+ }
159
166
 
160
- const operations = [];
161
- const deletionLength = oldEnd - start + 1;
167
+ const operations = [];
168
+ const deletionLength = oldEnd - start + 1;
162
169
 
163
- if (deletionLength > 0) {
164
- operations.push({ type: 'delete', position: start, length: deletionLength });
165
- }
170
+ if (deletionLength > 0) {
171
+ operations.push({
172
+ type: 'delete',
173
+ position: start,
174
+ length: deletionLength,
175
+ content: previousContent.slice(start, oldEnd + 1)
176
+ });
177
+ }
166
178
 
167
- const insertionContent = currentContent.slice(start, newEnd + 1);
179
+ const insertionContent = currentContent.slice(start, newEnd + 1);
168
180
 
169
- if (insertionContent.length > 0) {
170
- operations.push({ type: 'insert', position: start, content: insertionContent });
171
- }
181
+ if (insertionContent.length > 0) {
182
+ operations.push({ type: 'insert', position: start, content: insertionContent });
183
+ }
172
184
 
173
- if (operations.length > 0) {
174
- currentStaged[relPath] = operations;
175
- }
176
- }
177
- }
185
+ if (operations.length > 0) {
186
+ currentStaged[relPath] = operations;
187
+ }
188
+ }
189
+ }
178
190
 
179
- if (fs.existsSync(stageDir)) fs.rmSync(stageDir, { recursive: true, force: true });
191
+ if (fs.existsSync(stageDir)) fs.rmSync(stageDir, { recursive: true, force: true });
180
192
 
181
- fs.mkdirSync(stageDir, { recursive: true });
193
+ fs.mkdirSync(stageDir, { recursive: true });
182
194
 
183
- const stageParts = [];
195
+ const stageParts = [];
184
196
 
185
- let currentPartChanges = {};
186
- let currentSize = 0;
197
+ let currentPartChanges = {};
198
+ let currentSize = 0;
187
199
 
188
- const savePart = () => {
189
- const partName = `part.${stageParts.length}.json`;
200
+ const savePart = () => {
201
+ const partName = `part.${stageParts.length}.json`;
190
202
 
191
- fs.writeFileSync(path.join(stageDir, partName), JSON.stringify({ changes: currentPartChanges }, null, 2));
192
- stageParts.push(partName);
193
- currentPartChanges = {};
194
- currentSize = 0;
195
- };
203
+ fs.writeFileSync(path.join(stageDir, partName), JSON.stringify({ changes: currentPartChanges }, null, 2));
204
+ stageParts.push(partName);
205
+ currentPartChanges = {};
206
+ currentSize = 0;
207
+ };
196
208
 
197
- for (const [file, changes] of Object.entries(currentStaged)) {
198
- const size = JSON.stringify(changes).length;
209
+ for (const [file, changes] of Object.entries(currentStaged)) {
210
+ const size = JSON.stringify(changes).length;
199
211
 
200
- if (currentSize + size > MAX_PART_SIZE && Object.keys(currentPartChanges).length > 0) {
201
- savePart();
202
- }
212
+ if (currentSize + size > MAX_PART_SIZE && Object.keys(currentPartChanges).length > 0) {
213
+ savePart();
214
+ }
203
215
 
204
- currentPartChanges[file] = changes;
205
- currentSize += size;
206
- }
216
+ currentPartChanges[file] = changes;
217
+ currentSize += size;
218
+ }
207
219
 
208
- savePart();
220
+ savePart();
209
221
 
210
- fs.writeFileSync(path.join(stageDir, 'manifest.json'), JSON.stringify({ parts: stageParts }, null, 2));
222
+ fs.writeFileSync(path.join(stageDir, 'manifest.json'), JSON.stringify({ parts: stageParts }, null, 2));
211
223
 
212
- return `Added ${filesToProcess.length} file(s) to paginated stage.`;
213
- }
224
+ return `Added ${filesToProcess.length} file(s) to stage.`;
225
+ }
214
226
 
215
227
  /**
216
228
  * Finalizes the paginated stage into a paginated commit structure.
@@ -290,7 +302,7 @@ function commit (message) {
290
302
  }
291
303
 
292
304
  module.exports = {
293
- __libraryVersion: '0.2.9',
305
+ __libraryVersion: '0.3.1',
294
306
  __libraryAPIName: 'Workflow',
295
307
  status,
296
308
  add,