pagan-artifact 0.3.2 → 0.3.4

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.
@@ -1,9 +1,25 @@
1
+ /**
2
+ * Artifact - Modern version control.
3
+ * @author Benny Schmidt (https://github.com/bennyschmidt)
4
+ * @project https://github.com/bennyschmidt/artifact
5
+ * Module: Utility / shouldIgnore (v0.3.4)
6
+ */
7
+
1
8
  const fs = require('fs');
2
9
  const path = require('path');
3
10
 
4
11
  let memoizedRules = null;
5
12
 
13
+ /**
14
+ * Parses .artignore and converts glob-like patterns into executable regex.
15
+ * @returns {RegExp[]} An array of compiled regex rules.
16
+ */
17
+
6
18
  function getRules () {
19
+ /**
20
+ * Return cached rules if they have already been processed.
21
+ */
22
+
7
23
  if (memoizedRules) {
8
24
  return memoizedRules;
9
25
  }
@@ -12,6 +28,10 @@ function getRules () {
12
28
  const ignorePath = path.join(root, '.artignore');
13
29
  const rules = [];
14
30
 
31
+ /**
32
+ * Read the ignore file and transform each line into a path-matching regex.
33
+ */
34
+
15
35
  if (fs.existsSync(ignorePath)) {
16
36
  const lines = fs.readFileSync(ignorePath, 'utf8').split(/\r?\n/);
17
37
 
@@ -22,6 +42,11 @@ function getRules () {
22
42
  continue;
23
43
  }
24
44
 
45
+ /**
46
+ * Escape special characters and translate wildcards (* and **)
47
+ * into valid regex syntax.
48
+ */
49
+
25
50
  let regexStr = line
26
51
  .replace(/[.+^${}()|[\]\\]/g, '\\$&')
27
52
  .replace(/\/\*\*\//g, '(/.+/|/)')
@@ -43,16 +68,32 @@ function getRules () {
43
68
  return rules;
44
69
  }
45
70
 
46
- function shouldIgnore (relPath) {
47
- const normalizedPath = relPath.split(path.sep).join('/');
71
+ /**
72
+ * Determines if a given relative path should be excluded from version control.
73
+ * @param {string} relativePath - The path to check.
74
+ * @returns {boolean} True if the path matches an ignore rule.
75
+ */
76
+
77
+ function shouldIgnore (relativePath) {
78
+ /**
79
+ * Normalize path separators to forward slashes and protect the internal .art folder.
80
+ */
81
+
82
+ const normalizedPath = relativePath.split(path.sep).join('/');
48
83
 
49
84
  if (normalizedPath === '.art' || normalizedPath.startsWith('.art/')) {
50
85
  return true;
51
86
  }
52
87
 
88
+ /**
89
+ * Test the path against the compiled list of ignore patterns.
90
+ */
91
+
53
92
  const rules = getRules();
54
93
 
55
- return rules.some(rule => rule.test(normalizedPath));
94
+ return rules.some(rule => {
95
+ return rule.test(normalizedPath);
96
+ });
56
97
  }
57
98
 
58
99
  module.exports = shouldIgnore;
package/workflow/index.js CHANGED
@@ -1,6 +1,8 @@
1
1
  /**
2
- * art - Modern version control.
3
- * Module: Workflow (v0.3.2)
2
+ * Artifact - Modern version control.
3
+ * @author Benny Schmidt (https://github.com/bennyschmidt)
4
+ * @project https://github.com/bennyschmidt/artifact
5
+ * Module: Workflow (v0.3.4)
4
6
  */
5
7
 
6
8
  const fs = require('fs');
@@ -9,29 +11,43 @@ const crypto = require('crypto');
9
11
 
10
12
  const getStateByHash = require('../utils/getStateByHash');
11
13
  const shouldIgnore = require('../utils/shouldIgnore');
12
-
13
- const MAX_PART_SIZE = 32000000;
14
+ const { MAX_PART_SIZE } = require('../utils/constants');
14
15
 
15
16
  /**
16
17
  * Helper to load all changes from a paginated stage directory.
18
+ * @param {string} artifactPath - Path to the .art directory.
19
+ * @returns {Object} All staged changes merged into one object.
17
20
  */
18
21
 
19
- function getStagedChanges(artPath) {
20
- const stageDir = path.join(artPath, 'stage');
21
- const manifestPath = path.join(stageDir, 'manifest.json');
22
+ function getStagedChanges (artifactPath) {
23
+ /**
24
+ * Resolve the stage directory and locate the manifest for assembly.
25
+ */
26
+
27
+ const stageDirectory = path.join(artifactPath, 'stage');
28
+ const manifestPath = path.join(stageDirectory, 'manifest.json');
22
29
 
23
- if (!fs.existsSync(stageDir) || !fs.existsSync(manifestPath)) {
30
+ if (!fs.existsSync(stageDirectory) || !fs.existsSync(manifestPath)) {
24
31
  return {};
25
32
  }
26
33
 
27
- const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
34
+ const manifest = JSON.parse(
35
+ fs.readFileSync(manifestPath, 'utf8')
36
+ );
37
+
28
38
  let allChanges = {};
29
39
 
40
+ /**
41
+ * Aggregate changes from all registered manifest parts.
42
+ */
43
+
30
44
  for (const partName of manifest.parts) {
31
- const partPath = path.join(stageDir, partName);
45
+ const partPath = path.join(stageDirectory, partName);
32
46
 
33
47
  if (fs.existsSync(partPath)) {
34
- const partData = JSON.parse(fs.readFileSync(partPath, 'utf8'));
48
+ const partData = JSON.parse(
49
+ fs.readFileSync(partPath, 'utf8')
50
+ );
35
51
 
36
52
  Object.assign(allChanges, partData.changes);
37
53
  }
@@ -42,35 +58,51 @@ function getStagedChanges(artPath) {
42
58
 
43
59
  /**
44
60
  * Compares the working directory against the last commit and pending stage.
61
+ * @returns {Object} Status report containing staged, modified, and untracked files.
45
62
  */
46
63
 
47
64
  function status () {
65
+ /**
66
+ * Initialize workspace paths and retrieve active state and staging info.
67
+ */
68
+
48
69
  const root = process.cwd();
49
- const artPath = path.join(root, '.art');
50
- const artJsonPath = path.join(artPath, 'art.json');
70
+ const artifactPath = path.join(root, '.art');
71
+ const artifactJsonPath = path.join(artifactPath, 'art.json');
51
72
 
52
- if (!fs.existsSync(artJsonPath)) {
73
+ if (!fs.existsSync(artifactJsonPath)) {
53
74
  throw new Error('No art repository found.');
54
75
  }
55
76
 
56
- const artJson = JSON.parse(fs.readFileSync(artJsonPath, 'utf8'));
57
- const activeBranch = artJson.active.branch;
77
+ const artifactJson = JSON.parse(
78
+ fs.readFileSync(artifactJsonPath, 'utf8')
79
+ );
80
+ const activeBranch = artifactJson.active.branch;
58
81
 
59
- const stagedFiles = getStagedChanges(artPath);
60
- const activeState = getStateByHash(activeBranch, artJson.active.parent) || {};
82
+ const stagedFiles = getStagedChanges(artifactPath);
83
+ const activeState = getStateByHash(activeBranch, artifactJson.active.parent) || {};
61
84
 
62
85
  const allFiles = fs.readdirSync(root, { recursive: true })
63
- .filter(f => !fs.statSync(path.join(root, f)).isDirectory());
86
+ .filter(file => {
87
+ return !fs.statSync(path.join(root, file)).isDirectory();
88
+ });
64
89
 
65
90
  const untracked = [];
66
91
  const modified = [];
67
92
  const ignored = [];
68
93
 
94
+ /**
95
+ * Categorize each file by comparing its working directory state
96
+ * to history and staging.
97
+ */
98
+
69
99
  for (const file of allFiles) {
70
100
  const isStaged = !!stagedFiles[file];
71
101
  const isActive = !!activeState[file];
72
102
 
73
- if (file === '.art' || file.startsWith(`.art${path.sep}`)) continue;
103
+ if (file === '.art' || file.startsWith(`.art${path.sep}`)) {
104
+ continue;
105
+ }
74
106
 
75
107
  const isIgnored = shouldIgnore(file);
76
108
 
@@ -83,7 +115,10 @@ function status () {
83
115
  if (!isStaged && !isActive) {
84
116
  untracked.push(file);
85
117
  } else if (!isStaged && isActive) {
86
- const currentContent = fs.readFileSync(path.join(root, file), 'utf8');
118
+ const currentContent = fs.readFileSync(
119
+ path.join(root, file),
120
+ 'utf8'
121
+ );
87
122
 
88
123
  if (currentContent !== activeState[file]) {
89
124
  modified.push(file);
@@ -93,7 +128,7 @@ function status () {
93
128
 
94
129
  return {
95
130
  activeBranch,
96
- lastCommit: artJson.active.parent,
131
+ lastCommit: artifactJson.active.parent,
97
132
  staged: Object.keys(stagedFiles),
98
133
  modified,
99
134
  untracked,
@@ -103,144 +138,202 @@ function status () {
103
138
 
104
139
  /**
105
140
  * Updates or creates a JSON diff in the stage directory.
141
+ * @param {string} targetPath - Path to the file or directory to stage.
142
+ * @returns {string} Success message.
106
143
  */
107
144
 
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);
145
+ function add (targetPath) {
146
+ /**
147
+ * Validate target and load current repository configuration.
148
+ */
114
149
 
115
- if (!fs.existsSync(fullPath)) {
116
- throw new Error(`Path does not exist: ${targetPath}`);
117
- }
150
+ const root = process.cwd();
151
+ const artifactPath = path.join(root, '.art');
152
+ const stageDirectory = path.join(artifactPath, 'stage');
153
+ const artifactJsonPath = path.join(artifactPath, 'art.json');
154
+ const fullPath = path.resolve(root, targetPath);
118
155
 
119
- const artJson = JSON.parse(fs.readFileSync(artJsonPath, 'utf8'));
120
- const activeState = getStateByHash(artJson.active.branch, artJson.active.parent) || {};
121
- const currentStaged = getStagedChanges(artPath);
156
+ if (!fs.existsSync(fullPath)) {
157
+ throw new Error(`Path does not exist: ${targetPath}`);
158
+ }
122
159
 
123
- const stats = fs.statSync(fullPath);
124
- const relativeTarget = path.relative(root, fullPath);
160
+ const artifactJson = JSON.parse(
161
+ fs.readFileSync(artifactJsonPath, 'utf8')
162
+ );
163
+ const activeState = getStateByHash(artifactJson.active.branch, artifactJson.active.parent) || {};
164
+ const currentStaged = getStagedChanges(artifactPath);
125
165
 
126
- if (!stats.isDirectory() && shouldIgnore(relativeTarget) && !activeState[relativeTarget]) {
127
- return `${relativeTarget} is being ignored.`;
128
- }
166
+ const stats = fs.statSync(fullPath);
167
+ const relativeTarget = path.relative(root, fullPath);
129
168
 
130
- let filesToProcess = [];
169
+ if (!stats.isDirectory() && shouldIgnore(relativeTarget) && !activeState[relativeTarget]) {
170
+ return `${relativeTarget} is being ignored.`;
171
+ }
131
172
 
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);
173
+ let filesToProcess = [];
137
174
 
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
- }
175
+ /**
176
+ * Identify all files to be added, respecting ignore rules unless already tracked.
177
+ */
144
178
 
145
- if (filesToProcess.length === 0) return "No changes to add.";
179
+ if (stats.isDirectory()) {
180
+ const rawFiles = fs.readdirSync(fullPath, { recursive: true });
146
181
 
147
- for (const relPath of filesToProcess) {
148
- const currentContent = fs.readFileSync(path.join(root, relPath), 'utf8');
149
- const previousContent = activeState[relPath];
182
+ for (const entry of rawFiles) {
183
+ const absoluteEntry = path.join(fullPath, entry);
184
+ const relativeEntry = path.relative(root, absoluteEntry);
150
185
 
151
- if (previousContent === undefined) {
152
- currentStaged[relPath] = { type: 'createFile', content: currentContent };
153
- } else if (currentContent !== previousContent) {
154
- let start = 0;
186
+ if (!fs.statSync(absoluteEntry).isDirectory() && !relativeEntry.startsWith('.art')) {
187
+ if (!shouldIgnore(relativeEntry) || !!activeState[relativeEntry]) {
188
+ filesToProcess.push(relativeEntry);
189
+ }
190
+ }
191
+ }
192
+ } else {
193
+ filesToProcess = [relativeTarget];
194
+ }
155
195
 
156
- while (start < previousContent.length && start < currentContent.length && previousContent[start] === currentContent[start]) {
157
- start++;
158
- }
196
+ if (filesToProcess.length === 0) {
197
+ return 'No changes to add.';
198
+ }
159
199
 
160
- let oldEnd = previousContent.length - 1;
161
- let newEnd = currentContent.length - 1;
200
+ /**
201
+ * Calculate deltas for each file and update the staging map.
202
+ */
203
+
204
+ for (const relativePath of filesToProcess) {
205
+ const currentContent = fs.readFileSync(
206
+ path.join(root, relativePath),
207
+ 'utf8'
208
+ );
209
+ const previousContent = activeState[relativePath];
210
+
211
+ if (previousContent === undefined) {
212
+ currentStaged[relativePath] = {
213
+ type: 'createFile',
214
+ content: currentContent
215
+ };
216
+ } else if (currentContent !== previousContent) {
217
+ let start = 0;
218
+
219
+ while (start < previousContent.length && start < currentContent.length && previousContent[start] === currentContent[start]) {
220
+ start++;
221
+ }
162
222
 
163
- while (oldEnd >= start && newEnd >= start && previousContent[oldEnd] === currentContent[newEnd]) {
164
- oldEnd--; newEnd--;
165
- }
223
+ let oldEnd = previousContent.length - 1;
224
+ let newEnd = currentContent.length - 1;
166
225
 
167
- const operations = [];
168
- const deletionLength = oldEnd - start + 1;
226
+ while (oldEnd >= start && newEnd >= start && previousContent[oldEnd] === currentContent[newEnd]) {
227
+ oldEnd--;
228
+ newEnd--;
229
+ }
169
230
 
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
- }
231
+ const operations = [];
232
+ const deletionLength = oldEnd - start + 1;
178
233
 
179
- const insertionContent = currentContent.slice(start, newEnd + 1);
234
+ if (deletionLength > 0) {
235
+ operations.push({
236
+ type: 'delete',
237
+ position: start,
238
+ length: deletionLength,
239
+ content: previousContent.slice(start, oldEnd + 1)
240
+ });
241
+ }
180
242
 
181
- if (insertionContent.length > 0) {
182
- operations.push({ type: 'insert', position: start, content: insertionContent });
183
- }
243
+ const insertionContent = currentContent.slice(start, newEnd + 1);
184
244
 
185
- if (operations.length > 0) {
186
- currentStaged[relPath] = operations;
187
- }
188
- }
189
- }
245
+ if (insertionContent.length > 0) {
246
+ operations.push({
247
+ type: 'insert',
248
+ position: start,
249
+ content: insertionContent
250
+ });
251
+ }
190
252
 
191
- if (fs.existsSync(stageDir)) fs.rmSync(stageDir, { recursive: true, force: true });
253
+ if (operations.length > 0) {
254
+ currentStaged[relativePath] = operations;
255
+ }
256
+ }
257
+ }
192
258
 
193
- fs.mkdirSync(stageDir, { recursive: true });
259
+ /**
260
+ * Serialize the staging map into paginated JSON files for efficient storage.
261
+ */
194
262
 
195
- const stageParts = [];
263
+ if (fs.existsSync(stageDirectory)) {
264
+ fs.rmSync(stageDirectory, { recursive: true, force: true });
265
+ }
196
266
 
197
- let currentPartChanges = {};
198
- let currentSize = 0;
267
+ fs.mkdirSync(stageDirectory, { recursive: true });
199
268
 
200
- const savePart = () => {
201
- const partName = `part.${stageParts.length}.json`;
269
+ const stageParts = [];
202
270
 
203
- fs.writeFileSync(path.join(stageDir, partName), JSON.stringify({ changes: currentPartChanges }, null, 2));
204
- stageParts.push(partName);
205
- currentPartChanges = {};
206
- currentSize = 0;
207
- };
271
+ let currentPartChanges = {};
272
+ let currentSize = 0;
273
+
274
+ const savePart = () => {
275
+ const partName = `part.${stageParts.length}.json`;
208
276
 
209
- for (const [file, changes] of Object.entries(currentStaged)) {
210
- const size = JSON.stringify(changes).length;
277
+ fs.writeFileSync(
278
+ path.join(stageDirectory, partName),
279
+ JSON.stringify({ changes: currentPartChanges }, null, 2)
280
+ );
211
281
 
212
- if (currentSize + size > MAX_PART_SIZE && Object.keys(currentPartChanges).length > 0) {
213
- savePart();
214
- }
282
+ stageParts.push(partName);
283
+ currentPartChanges = {};
284
+ currentSize = 0;
285
+ };
215
286
 
216
- currentPartChanges[file] = changes;
217
- currentSize += size;
218
- }
287
+ for (const [file, changes] of Object.entries(currentStaged)) {
288
+ const size = JSON.stringify(changes).length;
219
289
 
220
- savePart();
290
+ if (currentSize + size > MAX_PART_SIZE && Object.keys(currentPartChanges).length > 0) {
291
+ savePart();
292
+ }
221
293
 
222
- fs.writeFileSync(path.join(stageDir, 'manifest.json'), JSON.stringify({ parts: stageParts }, null, 2));
294
+ currentPartChanges[file] = changes;
295
+ currentSize += size;
296
+ }
223
297
 
224
- return `Added ${filesToProcess.length} file(s) to stage.`;
225
- }
298
+ savePart();
299
+
300
+ fs.writeFileSync(
301
+ path.join(stageDirectory, 'manifest.json'),
302
+ JSON.stringify({ parts: stageParts }, null, 2)
303
+ );
304
+
305
+ return `Added ${filesToProcess.length} file(s) to stage.`;
306
+ }
226
307
 
227
308
  /**
228
309
  * Finalizes the paginated stage into a paginated commit structure.
310
+ * @param {string} message - The commit message.
311
+ * @returns {string} Success summary.
229
312
  */
230
313
 
231
314
  function commit (message) {
232
- if (!message) throw new Error('A commit message is required.');
315
+ /**
316
+ * Validate prerequisites for a commit and calculate the unique commit hash.
317
+ */
318
+
319
+ if (!message) {
320
+ throw new Error('A commit message is required.');
321
+ }
233
322
 
234
- const MAX_PART_SIZE = 32000000;
235
- const artPath = path.join(process.cwd(), '.art');
236
- const stageDir = path.join(artPath, 'stage');
237
- const artJsonPath = path.join(artPath, 'art.json');
323
+ const root = process.cwd();
324
+ const artifactPath = path.join(root, '.art');
325
+ const stageDirectory = path.join(artifactPath, 'stage');
326
+ const artifactJsonPath = path.join(artifactPath, 'art.json');
238
327
 
239
- if (!fs.existsSync(stageDir)) throw new Error('Nothing to commit (stage is empty).');
328
+ if (!fs.existsSync(stageDirectory)) {
329
+ throw new Error('Nothing to commit (stage is empty).');
330
+ }
240
331
 
241
- const stagedChanges = getStagedChanges(artPath);
242
- const artJson = JSON.parse(fs.readFileSync(artJsonPath, 'utf8'));
243
- const branch = artJson.active.branch;
332
+ const stagedChanges = getStagedChanges(artifactPath);
333
+ const artifactJson = JSON.parse(
334
+ fs.readFileSync(artifactJsonPath, 'utf8')
335
+ );
336
+ const branch = artifactJson.active.branch;
244
337
  const timestamp = Date.now();
245
338
 
246
339
  const commitHash = crypto
@@ -248,20 +341,29 @@ function commit (message) {
248
341
  .update(JSON.stringify(stagedChanges) + timestamp + message)
249
342
  .digest('hex');
250
343
 
251
- const branchHistoryDir = path.join(artPath, 'history', 'local', branch);
344
+ const branchHistoryDirectory = path.join(artifactPath, 'history', 'local', branch);
252
345
  const commitParts = [];
253
346
 
254
347
  let currentPartChanges = {};
255
348
  let currentPartSize = 0;
256
349
 
350
+ /**
351
+ * Break the commit into paginated parts to handle large datasets.
352
+ */
353
+
257
354
  const saveCommitPart = () => {
258
- if (Object.keys(currentPartChanges).length === 0) return;
355
+ if (Object.keys(currentPartChanges).length === 0) {
356
+ return;
357
+ }
259
358
 
260
359
  const partName = `${commitHash}.part.${commitParts.length}.json`;
261
360
 
262
- fs.writeFileSync(path.join(branchHistoryDir, partName), JSON.stringify({ changes: currentPartChanges }, null, 2));
263
- commitParts.push(partName);
361
+ fs.writeFileSync(
362
+ path.join(branchHistoryDirectory, partName),
363
+ JSON.stringify({ changes: currentPartChanges }, null, 2)
364
+ );
264
365
 
366
+ commitParts.push(partName);
265
367
  currentPartChanges = {};
266
368
  currentPartSize = 0;
267
369
  };
@@ -276,33 +378,55 @@ function commit (message) {
276
378
  currentPartChanges[filePath] = changeSet;
277
379
  currentPartSize += changeSize;
278
380
  }
381
+
279
382
  saveCommitPart();
280
383
 
384
+ /**
385
+ * Finalize the commit master file and update the branch manifest.
386
+ */
387
+
281
388
  const commitMaster = {
282
389
  hash: commitHash,
283
390
  message,
284
391
  timestamp,
285
- parent: artJson.active.parent,
392
+ parent: artifactJson.active.parent,
286
393
  parts: commitParts
287
394
  };
288
395
 
289
- fs.writeFileSync(path.join(branchHistoryDir, `${commitHash}.json`), JSON.stringify(commitMaster, null, 2));
396
+ fs.writeFileSync(
397
+ path.join(branchHistoryDirectory, `${commitHash}.json`),
398
+ JSON.stringify(commitMaster, null, 2)
399
+ );
290
400
 
291
- const manifest = JSON.parse(fs.readFileSync(path.join(branchHistoryDir, 'manifest.json'), 'utf8'));
401
+ const manifest = JSON.parse(
402
+ fs.readFileSync(path.join(branchHistoryDirectory, 'manifest.json'), 'utf8')
403
+ );
292
404
 
293
405
  manifest.commits.push(commitHash);
294
- fs.writeFileSync(path.join(branchHistoryDir, 'manifest.json'), JSON.stringify(manifest, null, 2));
295
406
 
296
- artJson.active.parent = commitHash;
297
- fs.writeFileSync(artJsonPath, JSON.stringify(artJson, null, 2));
407
+ fs.writeFileSync(
408
+ path.join(branchHistoryDirectory, 'manifest.json'),
409
+ JSON.stringify(manifest, null, 2)
410
+ );
411
+
412
+ /**
413
+ * Update the active parent reference and clear the staging area.
414
+ */
415
+
416
+ artifactJson.active.parent = commitHash;
417
+
418
+ fs.writeFileSync(
419
+ artifactJsonPath,
420
+ JSON.stringify(artifactJson, null, 2)
421
+ );
298
422
 
299
- fs.rmSync(stageDir, { recursive: true, force: true });
423
+ fs.rmSync(stageDirectory, { recursive: true, force: true });
300
424
 
301
- return `[${branch} ${commitHash.slice(0, 7)}] ${message} (${commitParts.length} parts)`;
425
+ return `[${branch} ${commitHash.slice(0, 7)}] ${message}`;
302
426
  }
303
427
 
304
428
  module.exports = {
305
- __libraryVersion: '0.3.2',
429
+ __libraryVersion: '0.3.4',
306
430
  __libraryAPIName: 'Workflow',
307
431
  status,
308
432
  add,