@questwork/q-utilities 0.1.20 → 0.1.21

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.
@@ -69,6 +69,7 @@ __webpack_require__.d(__webpack_exports__, {
69
69
  changeCreatorOwner: () => (/* reexport */ changeCreatorOwner),
70
70
  concatStringByArray: () => (/* reexport */ concatStringByArray),
71
71
  convertString: () => (/* reexport */ convertString),
72
+ detectControlCharacters: () => (/* reexport */ detectControlCharacters),
72
73
  escapeRegex: () => (/* reexport */ escapeRegex),
73
74
  expressHelper: () => (/* reexport */ expressHelper),
74
75
  extractEmails: () => (/* reexport */ extractEmails),
@@ -87,6 +88,7 @@ __webpack_require__.d(__webpack_exports__, {
87
88
  objectHelper: () => (/* reexport */ objectHelper),
88
89
  pReduce: () => (/* reexport */ pReduce),
89
90
  padZeros: () => (/* reexport */ padZeros),
91
+ printControlCharReport: () => (/* reexport */ printControlCharReport),
90
92
  replacePlaceholders: () => (/* reexport */ replacePlaceholders),
91
93
  sanitizeText: () => (/* reexport */ sanitizeText),
92
94
  shuffleArray: () => (/* reexport */ shuffleArray),
@@ -1605,6 +1607,107 @@ function convertString(string, patternMatch = /\$\{(.+?)\}/g, value, getValueByK
1605
1607
  ;// ./lib/helpers/convertString/index.js
1606
1608
 
1607
1609
 
1610
+ ;// ./lib/helpers/detectControlCharacters/detectControlCharacters.js
1611
+ /**
1612
+ * Detects and reports hidden/control characters in a string without modifying it.
1613
+ * @param {string} input - The string to analyze.
1614
+ * @param {Object} [options] - Configuration options.
1615
+ * @param {boolean} [options.preserveBasicWhitespace=true] - Whether to consider basic whitespace as valid.
1616
+ * @returns {Object} Report object with detection results.
1617
+ */
1618
+ function detectControlCharacters(input, options = {}) {
1619
+ const {
1620
+ preserveBasicWhitespace = true,
1621
+ removeNewlines = false
1622
+ } = options
1623
+
1624
+ if (typeof input !== 'string') {
1625
+ return {
1626
+ hasControlChars: false,
1627
+ matches: [],
1628
+ inputType: typeof input,
1629
+ message: 'Input is not a string'
1630
+ }
1631
+ }
1632
+
1633
+ const matches = []
1634
+ let regex
1635
+
1636
+ if (preserveBasicWhitespace && !removeNewlines) {
1637
+ // Same regex as Phase 1 preserve mode - keep tab (\t), newline (\n), carriage return (\r)
1638
+ regex = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g
1639
+ } else {
1640
+ // Same regex as Phase 1 full removal mode - use consistent escape sequences
1641
+ regex = /[\x00-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g
1642
+ }
1643
+
1644
+ // Use a replacer function to capture matches without modifying the string
1645
+ input.replace(regex, (match, offset) => {
1646
+ matches.push({
1647
+ character: match,
1648
+ code: match.charCodeAt(0),
1649
+ hex: '0x' + match.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0'),
1650
+ position: offset,
1651
+ context: getContext(input, offset, 10) // Show surrounding text
1652
+ })
1653
+ return '' // Return empty but we don't use the result
1654
+ })
1655
+
1656
+ return {
1657
+ hasControlChars: matches.length > 0,
1658
+ matches: matches,
1659
+ totalFound: matches.length,
1660
+ inputPreview: input.length > 50 ? input.substring(0, 50) + '...' : input,
1661
+ inputLength: input.length,
1662
+ optionsUsed: { preserveBasicWhitespace },
1663
+ regexPattern: regex.toString()
1664
+ }
1665
+ }
1666
+
1667
+ /**
1668
+ * Helper function to get context around a match
1669
+ */
1670
+ function getContext(str, position, contextLength = 10) {
1671
+ const start = Math.max(0, position - contextLength)
1672
+ const end = Math.min(str.length, position + contextLength + 1)
1673
+ let context = str.substring(start, end)
1674
+
1675
+ // Replace control characters with their escape sequences for readability
1676
+ context = context.replace(/[\x00-\x1F\x7F-\x9F]/g, (match) => {
1677
+ return '\\u' + match.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0')
1678
+ })
1679
+
1680
+ return context
1681
+ }
1682
+
1683
+ /**
1684
+ * Pretty print the detection results to console
1685
+ */
1686
+ function printControlCharReport(report) {
1687
+ console.log('=== Control Character Detection Report ===')
1688
+ console.log(`Input: "${report.inputPreview}" (${report.inputLength} chars)`)
1689
+ console.log(`Options: preserveBasicWhitespace = ${report.optionsUsed.preserveBasicWhitespace}`)
1690
+ console.log(`Regex pattern: ${report.regexPattern}`)
1691
+ console.log(`Control characters found: ${report.totalFound}`)
1692
+
1693
+ if (report.hasControlChars) {
1694
+ console.log('\nšŸ“‹ Matches found:')
1695
+ report.matches.forEach((match, index) => {
1696
+ console.log(`\n${index + 1}. Character: ${JSON.stringify(match.character)}`)
1697
+ console.log(` Code: ${match.code} (${match.hex})`)
1698
+ console.log(` Position: ${match.position}`)
1699
+ console.log(` Context: "...${match.context}..."`)
1700
+ })
1701
+ } else {
1702
+ console.log('āœ… No control characters detected in Phase 1 range')
1703
+ }
1704
+
1705
+ console.log('=== End Report ===')
1706
+ }
1707
+
1708
+ ;// ./lib/helpers/detectControlCharacters/index.js
1709
+
1710
+
1608
1711
  ;// ./lib/helpers/escapeRegex/escapeRegex.js
1609
1712
  function escapeRegex(string) {
1610
1713
  return String(string).replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')
@@ -2953,6 +3056,7 @@ function tenantPlugin(schema, options) {
2953
3056
 
2954
3057
 
2955
3058
 
3059
+
2956
3060
 
2957
3061
 
2958
3062
  ;// ./lib/models/apiResponse/index.js
@@ -3872,24 +3976,47 @@ class StatusDocument extends Status {
3872
3976
 
3873
3977
  this.archived = this._ActionRecord.init(options.archived)
3874
3978
  this.completed = this._ActionRecord.init(options.completed)
3875
- this.drafted = this._ActionRecord.init(options.drafted)
3876
3979
  this.discarded = this._ActionRecord.init(options.discarded)
3980
+ this.drafted = this._ActionRecord.init(options.drafted)
3877
3981
  // this.statusType = 'StatusDocument'
3878
3982
  }
3879
3983
 
3880
- get isValid() {
3881
- return super.isValid
3882
- }
3883
-
3884
3984
  static get _classname() {
3885
3985
  return 'StatusDocument'
3886
3986
  }
3987
+ get _classname() {
3988
+ return 'StatusDocument'
3989
+ }
3990
+ get isArchived() {
3991
+ return this.created?.timestamp !== null
3992
+ }
3993
+ get isCompleted() {
3994
+ return this.completed?.timestamp !== null
3995
+ }
3996
+ get isDiscarded() {
3997
+ return this.discarded?.timestamp !== null
3998
+ }
3999
+ get isDrafted() {
4000
+ return this.drafted?.timestamp !== null
4001
+ }
4002
+ get isValid() {
4003
+ return super.isValid
4004
+ }
3887
4005
  setArchived(value, actorCode) {
3888
4006
  // const timestamp = value || Date.now()
3889
4007
  // this.archived = this.archived instanceof this._ActionRecord ? this.archived.update({ actorCode, timestamp }) : this._ActionRecord.init({ actorCode, timestamp })
3890
4008
  // return this
3891
4009
  return this.setValue(value, actorCode, 'archived')
3892
4010
  }
4011
+ setCompleted(value, actorCode) {
4012
+ return this.setValue(value, actorCode, 'completed')
4013
+ }
4014
+ setDiscarded(value, actorCode) {
4015
+ return this.setValue(value, actorCode, 'discarded')
4016
+ }
4017
+ setDrafted(value, actorCode) {
4018
+ return this.setValue(value, actorCode, 'drafted')
4019
+ }
3893
4020
  }
3894
4021
 
3895
4022
  ;// ./lib/models/status/index.js
@@ -1508,6 +1508,107 @@ function convertString(string, patternMatch = /\$\{(.+?)\}/g, value, getValueByK
1508
1508
  ;// ./lib/helpers/convertString/index.js
1509
1509
 
1510
1510
 
1511
+ ;// ./lib/helpers/detectControlCharacters/detectControlCharacters.js
1512
+ /**
1513
+ * Detects and reports hidden/control characters in a string without modifying it.
1514
+ * @param {string} input - The string to analyze.
1515
+ * @param {Object} [options] - Configuration options.
1516
+ * @param {boolean} [options.preserveBasicWhitespace=true] - Whether to consider basic whitespace as valid.
1517
+ * @returns {Object} Report object with detection results.
1518
+ */
1519
+ function detectControlCharacters(input, options = {}) {
1520
+ const {
1521
+ preserveBasicWhitespace = true,
1522
+ removeNewlines = false
1523
+ } = options
1524
+
1525
+ if (typeof input !== 'string') {
1526
+ return {
1527
+ hasControlChars: false,
1528
+ matches: [],
1529
+ inputType: typeof input,
1530
+ message: 'Input is not a string'
1531
+ }
1532
+ }
1533
+
1534
+ const matches = []
1535
+ let regex
1536
+
1537
+ if (preserveBasicWhitespace && !removeNewlines) {
1538
+ // Same regex as Phase 1 preserve mode - keep tab (\t), newline (\n), carriage return (\r)
1539
+ regex = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g
1540
+ } else {
1541
+ // Same regex as Phase 1 full removal mode - use consistent escape sequences
1542
+ regex = /[\x00-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g
1543
+ }
1544
+
1545
+ // Use a replacer function to capture matches without modifying the string
1546
+ input.replace(regex, (match, offset) => {
1547
+ matches.push({
1548
+ character: match,
1549
+ code: match.charCodeAt(0),
1550
+ hex: '0x' + match.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0'),
1551
+ position: offset,
1552
+ context: getContext(input, offset, 10) // Show surrounding text
1553
+ })
1554
+ return '' // Return empty but we don't use the result
1555
+ })
1556
+
1557
+ return {
1558
+ hasControlChars: matches.length > 0,
1559
+ matches: matches,
1560
+ totalFound: matches.length,
1561
+ inputPreview: input.length > 50 ? input.substring(0, 50) + '...' : input,
1562
+ inputLength: input.length,
1563
+ optionsUsed: { preserveBasicWhitespace },
1564
+ regexPattern: regex.toString()
1565
+ }
1566
+ }
1567
+
1568
+ /**
1569
+ * Helper function to get context around a match
1570
+ */
1571
+ function getContext(str, position, contextLength = 10) {
1572
+ const start = Math.max(0, position - contextLength)
1573
+ const end = Math.min(str.length, position + contextLength + 1)
1574
+ let context = str.substring(start, end)
1575
+
1576
+ // Replace control characters with their escape sequences for readability
1577
+ context = context.replace(/[\x00-\x1F\x7F-\x9F]/g, (match) => {
1578
+ return '\\u' + match.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0')
1579
+ })
1580
+
1581
+ return context
1582
+ }
1583
+
1584
+ /**
1585
+ * Pretty print the detection results to console
1586
+ */
1587
+ function printControlCharReport(report) {
1588
+ console.log('=== Control Character Detection Report ===')
1589
+ console.log(`Input: "${report.inputPreview}" (${report.inputLength} chars)`)
1590
+ console.log(`Options: preserveBasicWhitespace = ${report.optionsUsed.preserveBasicWhitespace}`)
1591
+ console.log(`Regex pattern: ${report.regexPattern}`)
1592
+ console.log(`Control characters found: ${report.totalFound}`)
1593
+
1594
+ if (report.hasControlChars) {
1595
+ console.log('\nšŸ“‹ Matches found:')
1596
+ report.matches.forEach((match, index) => {
1597
+ console.log(`\n${index + 1}. Character: ${JSON.stringify(match.character)}`)
1598
+ console.log(` Code: ${match.code} (${match.hex})`)
1599
+ console.log(` Position: ${match.position}`)
1600
+ console.log(` Context: "...${match.context}..."`)
1601
+ })
1602
+ } else {
1603
+ console.log('āœ… No control characters detected in Phase 1 range')
1604
+ }
1605
+
1606
+ console.log('=== End Report ===')
1607
+ }
1608
+
1609
+ ;// ./lib/helpers/detectControlCharacters/index.js
1610
+
1611
+
1511
1612
  ;// ./lib/helpers/escapeRegex/escapeRegex.js
1512
1613
  function escapeRegex(string) {
1513
1614
  return String(string).replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')
@@ -2856,6 +2957,7 @@ function tenantPlugin(schema, options) {
2856
2957
 
2857
2958
 
2858
2959
 
2960
+
2859
2961
 
2860
2962
 
2861
2963
  ;// ./lib/models/apiResponse/index.js
@@ -3775,24 +3877,47 @@ class StatusDocument extends Status {
3775
3877
 
3776
3878
  this.archived = this._ActionRecord.init(options.archived)
3777
3879
  this.completed = this._ActionRecord.init(options.completed)
3778
- this.drafted = this._ActionRecord.init(options.drafted)
3779
3880
  this.discarded = this._ActionRecord.init(options.discarded)
3881
+ this.drafted = this._ActionRecord.init(options.drafted)
3780
3882
  // this.statusType = 'StatusDocument'
3781
3883
  }
3782
3884
 
3783
- get isValid() {
3784
- return super.isValid
3785
- }
3786
-
3787
3885
  static get _classname() {
3788
3886
  return 'StatusDocument'
3789
3887
  }
3888
+ get _classname() {
3889
+ return 'StatusDocument'
3890
+ }
3891
+ get isArchived() {
3892
+ return this.created?.timestamp !== null
3893
+ }
3894
+ get isCompleted() {
3895
+ return this.completed?.timestamp !== null
3896
+ }
3897
+ get isDiscarded() {
3898
+ return this.discarded?.timestamp !== null
3899
+ }
3900
+ get isDrafted() {
3901
+ return this.drafted?.timestamp !== null
3902
+ }
3903
+ get isValid() {
3904
+ return super.isValid
3905
+ }
3790
3906
  setArchived(value, actorCode) {
3791
3907
  // const timestamp = value || Date.now()
3792
3908
  // this.archived = this.archived instanceof this._ActionRecord ? this.archived.update({ actorCode, timestamp }) : this._ActionRecord.init({ actorCode, timestamp })
3793
3909
  // return this
3794
3910
  return this.setValue(value, actorCode, 'archived')
3795
3911
  }
3912
+ setCompleted(value, actorCode) {
3913
+ return this.setValue(value, actorCode, 'completed')
3914
+ }
3915
+ setDiscarded(value, actorCode) {
3916
+ return this.setValue(value, actorCode, 'discarded')
3917
+ }
3918
+ setDrafted(value, actorCode) {
3919
+ return this.setValue(value, actorCode, 'drafted')
3920
+ }
3796
3921
  }
3797
3922
 
3798
3923
  ;// ./lib/models/status/index.js
@@ -3948,4 +4073,4 @@ function _makeSetCode(fieldName, options) {
3948
4073
  ;// ./index.js
3949
4074
 
3950
4075
 
3951
- export { ActionRecord, ApiResponse, AwsStsS3Client, KeyValueObject, Metadata, PushEnvelope, QMeta, Repo, Service, Status, StatusDocument, TemplateCompiler, TenantAwareEntity, TrackedEntity, UniqueKeyGenerator, authorize, calculateAge, changeCreatorOwner, concatStringByArray, convertString, escapeRegex, expressHelper, extractEmails, formatDate, generalPost, getValidation, getValueByKeys_getValueByKeys as getValueByKeys, groupArrayByKey, init, initFromArray, initOnlyValidFromArray, isConvertibleToNumber, makeApiResponse, makeService, mergeArraysByKey, objectHelper, pReduce, padZeros, replacePlaceholders, sanitizeText, shuffleArray, stringFormatter, stringHelper, tenantPlugin, trackingPlugin };
4076
+ export { ActionRecord, ApiResponse, AwsStsS3Client, KeyValueObject, Metadata, PushEnvelope, QMeta, Repo, Service, Status, StatusDocument, TemplateCompiler, TenantAwareEntity, TrackedEntity, UniqueKeyGenerator, authorize, calculateAge, changeCreatorOwner, concatStringByArray, convertString, detectControlCharacters, escapeRegex, expressHelper, extractEmails, formatDate, generalPost, getValidation, getValueByKeys_getValueByKeys as getValueByKeys, groupArrayByKey, init, initFromArray, initOnlyValidFromArray, isConvertibleToNumber, makeApiResponse, makeService, mergeArraysByKey, objectHelper, pReduce, padZeros, printControlCharReport, replacePlaceholders, sanitizeText, shuffleArray, stringFormatter, stringHelper, tenantPlugin, trackingPlugin };
@@ -68,6 +68,7 @@ __webpack_require__.d(__webpack_exports__, {
68
68
  changeCreatorOwner: () => (/* reexport */ changeCreatorOwner),
69
69
  concatStringByArray: () => (/* reexport */ concatStringByArray),
70
70
  convertString: () => (/* reexport */ convertString),
71
+ detectControlCharacters: () => (/* reexport */ detectControlCharacters),
71
72
  escapeRegex: () => (/* reexport */ escapeRegex),
72
73
  expressHelper: () => (/* reexport */ expressHelper),
73
74
  extractEmails: () => (/* reexport */ extractEmails),
@@ -86,6 +87,7 @@ __webpack_require__.d(__webpack_exports__, {
86
87
  objectHelper: () => (/* reexport */ objectHelper),
87
88
  pReduce: () => (/* reexport */ pReduce),
88
89
  padZeros: () => (/* reexport */ padZeros),
90
+ printControlCharReport: () => (/* reexport */ printControlCharReport),
89
91
  replacePlaceholders: () => (/* reexport */ replacePlaceholders),
90
92
  sanitizeText: () => (/* reexport */ sanitizeText),
91
93
  shuffleArray: () => (/* reexport */ shuffleArray),
@@ -1604,6 +1606,107 @@ function convertString(string, patternMatch = /\$\{(.+?)\}/g, value, getValueByK
1604
1606
  ;// ./lib/helpers/convertString/index.js
1605
1607
 
1606
1608
 
1609
+ ;// ./lib/helpers/detectControlCharacters/detectControlCharacters.js
1610
+ /**
1611
+ * Detects and reports hidden/control characters in a string without modifying it.
1612
+ * @param {string} input - The string to analyze.
1613
+ * @param {Object} [options] - Configuration options.
1614
+ * @param {boolean} [options.preserveBasicWhitespace=true] - Whether to consider basic whitespace as valid.
1615
+ * @returns {Object} Report object with detection results.
1616
+ */
1617
+ function detectControlCharacters(input, options = {}) {
1618
+ const {
1619
+ preserveBasicWhitespace = true,
1620
+ removeNewlines = false
1621
+ } = options
1622
+
1623
+ if (typeof input !== 'string') {
1624
+ return {
1625
+ hasControlChars: false,
1626
+ matches: [],
1627
+ inputType: typeof input,
1628
+ message: 'Input is not a string'
1629
+ }
1630
+ }
1631
+
1632
+ const matches = []
1633
+ let regex
1634
+
1635
+ if (preserveBasicWhitespace && !removeNewlines) {
1636
+ // Same regex as Phase 1 preserve mode - keep tab (\t), newline (\n), carriage return (\r)
1637
+ regex = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g
1638
+ } else {
1639
+ // Same regex as Phase 1 full removal mode - use consistent escape sequences
1640
+ regex = /[\x00-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g
1641
+ }
1642
+
1643
+ // Use a replacer function to capture matches without modifying the string
1644
+ input.replace(regex, (match, offset) => {
1645
+ matches.push({
1646
+ character: match,
1647
+ code: match.charCodeAt(0),
1648
+ hex: '0x' + match.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0'),
1649
+ position: offset,
1650
+ context: getContext(input, offset, 10) // Show surrounding text
1651
+ })
1652
+ return '' // Return empty but we don't use the result
1653
+ })
1654
+
1655
+ return {
1656
+ hasControlChars: matches.length > 0,
1657
+ matches: matches,
1658
+ totalFound: matches.length,
1659
+ inputPreview: input.length > 50 ? input.substring(0, 50) + '...' : input,
1660
+ inputLength: input.length,
1661
+ optionsUsed: { preserveBasicWhitespace },
1662
+ regexPattern: regex.toString()
1663
+ }
1664
+ }
1665
+
1666
+ /**
1667
+ * Helper function to get context around a match
1668
+ */
1669
+ function getContext(str, position, contextLength = 10) {
1670
+ const start = Math.max(0, position - contextLength)
1671
+ const end = Math.min(str.length, position + contextLength + 1)
1672
+ let context = str.substring(start, end)
1673
+
1674
+ // Replace control characters with their escape sequences for readability
1675
+ context = context.replace(/[\x00-\x1F\x7F-\x9F]/g, (match) => {
1676
+ return '\\u' + match.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0')
1677
+ })
1678
+
1679
+ return context
1680
+ }
1681
+
1682
+ /**
1683
+ * Pretty print the detection results to console
1684
+ */
1685
+ function printControlCharReport(report) {
1686
+ console.log('=== Control Character Detection Report ===')
1687
+ console.log(`Input: "${report.inputPreview}" (${report.inputLength} chars)`)
1688
+ console.log(`Options: preserveBasicWhitespace = ${report.optionsUsed.preserveBasicWhitespace}`)
1689
+ console.log(`Regex pattern: ${report.regexPattern}`)
1690
+ console.log(`Control characters found: ${report.totalFound}`)
1691
+
1692
+ if (report.hasControlChars) {
1693
+ console.log('\nšŸ“‹ Matches found:')
1694
+ report.matches.forEach((match, index) => {
1695
+ console.log(`\n${index + 1}. Character: ${JSON.stringify(match.character)}`)
1696
+ console.log(` Code: ${match.code} (${match.hex})`)
1697
+ console.log(` Position: ${match.position}`)
1698
+ console.log(` Context: "...${match.context}..."`)
1699
+ })
1700
+ } else {
1701
+ console.log('āœ… No control characters detected in Phase 1 range')
1702
+ }
1703
+
1704
+ console.log('=== End Report ===')
1705
+ }
1706
+
1707
+ ;// ./lib/helpers/detectControlCharacters/index.js
1708
+
1709
+
1607
1710
  ;// ./lib/helpers/escapeRegex/escapeRegex.js
1608
1711
  function escapeRegex(string) {
1609
1712
  return String(string).replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')
@@ -2952,6 +3055,7 @@ function tenantPlugin(schema, options) {
2952
3055
 
2953
3056
 
2954
3057
 
3058
+
2955
3059
 
2956
3060
 
2957
3061
  ;// ./lib/models/apiResponse/index.js
@@ -3871,24 +3975,47 @@ class StatusDocument extends Status {
3871
3975
 
3872
3976
  this.archived = this._ActionRecord.init(options.archived)
3873
3977
  this.completed = this._ActionRecord.init(options.completed)
3874
- this.drafted = this._ActionRecord.init(options.drafted)
3875
3978
  this.discarded = this._ActionRecord.init(options.discarded)
3979
+ this.drafted = this._ActionRecord.init(options.drafted)
3876
3980
  // this.statusType = 'StatusDocument'
3877
3981
  }
3878
3982
 
3879
- get isValid() {
3880
- return super.isValid
3881
- }
3882
-
3883
3983
  static get _classname() {
3884
3984
  return 'StatusDocument'
3885
3985
  }
3986
+ get _classname() {
3987
+ return 'StatusDocument'
3988
+ }
3989
+ get isArchived() {
3990
+ return this.created?.timestamp !== null
3991
+ }
3992
+ get isCompleted() {
3993
+ return this.completed?.timestamp !== null
3994
+ }
3995
+ get isDiscarded() {
3996
+ return this.discarded?.timestamp !== null
3997
+ }
3998
+ get isDrafted() {
3999
+ return this.drafted?.timestamp !== null
4000
+ }
4001
+ get isValid() {
4002
+ return super.isValid
4003
+ }
3886
4004
  setArchived(value, actorCode) {
3887
4005
  // const timestamp = value || Date.now()
3888
4006
  // this.archived = this.archived instanceof this._ActionRecord ? this.archived.update({ actorCode, timestamp }) : this._ActionRecord.init({ actorCode, timestamp })
3889
4007
  // return this
3890
4008
  return this.setValue(value, actorCode, 'archived')
3891
4009
  }
4010
+ setCompleted(value, actorCode) {
4011
+ return this.setValue(value, actorCode, 'completed')
4012
+ }
4013
+ setDiscarded(value, actorCode) {
4014
+ return this.setValue(value, actorCode, 'discarded')
4015
+ }
4016
+ setDrafted(value, actorCode) {
4017
+ return this.setValue(value, actorCode, 'drafted')
4018
+ }
3892
4019
  }
3893
4020
 
3894
4021
  ;// ./lib/models/status/index.js
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@questwork/q-utilities",
3
- "version": "0.1.20",
3
+ "version": "0.1.21",
4
4
  "description": "Questwork QUtilities",
5
5
  "author": {
6
6
  "name": "Questwork Consulting Limited",