affinirum 1.2.2 → 1.2.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.
package/README.md CHANGED
@@ -22,13 +22,15 @@ Target: ES2022 [browser+NodeJS][ESM+CJS].
22
22
 
23
23
  ## Specifications
24
24
 
25
- Script can contain multiple semicolon-separated expressions, and blocks of statements.
26
- The value of a block is determined by the value of the last expression.
25
+ A script may contain multiple expressions separated by semicolons, as well as blocks of statements.
26
+ The value of a block is defined by the value of its last expression.
27
27
  - Scientific notation is supported for floating point numbers, like *0.1281e+2*.
28
28
  - ISO Timestamps prefixed with **@**, like *@2025-05-11T19:09:21.320Z*.
29
- - Hexadecimal buffer values are enclosed in backtick (**\`**) quotes, like *\`10ab0901\`*.
30
- - String literals are enclosed in single (**'**), or double (**"**) quotes, like *'string value1'*, or *"string value2"*.
29
+ - Hexadecimal buffer values are enclosed in backticks (**\`**), like *\`10ab0901\`*.
30
+ - String literals may be enclosed in single (**'**), or double (**"**) quotes, like *'string value1'*, or *"string value2"*.
31
+ - Line comments begin with a double slash (**//**), while block comments are enclosed in triple slashes (**///**).
31
32
 
33
+ ### Arrays
32
34
  Array is an ordered sequence of values of any type.
33
35
  It is defined by comma-separated values enclosed in brackets (**[]**),
34
36
  like *[0,1,2]*, *["a","b","c"]*.
@@ -39,6 +41,7 @@ Array elements can be accessed using the access operator (**.**),
39
41
 
40
42
  Easy way to check if array contains an index is to use presence operator (**?**), like *theArray?50*.
41
43
 
44
+ ### Objects
42
45
  Object is a container of named values of any type.
43
46
  It is defined by comma-separated key-value pair enclosed in brackets (**[]**) where key is separated from value by colon (**:**),
44
47
  like *["key1":100, "key2":"abc"]*, *["a":0,"b":"str":"c":valueVar]*.
@@ -50,13 +53,14 @@ Object properties can be accessed using the access operator (**.**) with a strin
50
53
 
51
54
  Easy way to check if object contains a key is to use presence operator (**?**), like *theObject?myKey*.
52
55
 
56
+ ### Functions
53
57
  A function is a callable code unit that produces a value.
54
58
  The set of built-in functions can be extended through configuration entries.
55
59
  Additionally, subroutines (functions defined in code) can be created.
56
60
 
57
- Valid variable and function names must start with a letter or underscore (**\_**)
58
- and can be followed by any combination of alphanumeric characters or underscores,
59
- like *x*, *\_a1*, *abc25*.
61
+ Valid variable and function names must start with a letter, number sign (**\#**), dollar sign (**\$**), or underscore (**\_**)
62
+ and can be followed by any combination of alphanumeric characters, number signs, dollar signs, or underscores,
63
+ like *x*, *\_a1$*, *abc25*.
60
64
 
61
65
  Whitespace characters are ignored.
62
66
 
@@ -118,7 +122,7 @@ Unknown or variant type is declared as **??**.
118
122
  - Arithmetic division assignment: **/=**
119
123
  - Arithmetic remainder assignment: **%=**
120
124
 
121
- ### Constants
125
+ ### Predefined Constants
122
126
 
123
127
  #### Boolean
124
128
  - **boolean Boolean.Or(values:array...)** — Boolean disjunction
@@ -179,21 +183,21 @@ Unknown or variant type is declared as **??**.
179
183
  - **object Object.Merge(values: array...)** — Merge multiple objects
180
184
 
181
185
  #### AN
182
- - **string AN.Format(value: string, whitespace: string?)** — Format string as AN
186
+ - **string AN.Format(value: ??, whitespace: string?)** — Format string as AN
183
187
 
184
188
  #### JSON
185
189
  - **string JSON.Format(value: void | boolean | float | string | array | object, whitespace: string?)** — Format as JSON string
186
190
  - **void | boolean | float | string | array | object JSON.Parse(value: string)** — Parse JSON-formatted string
187
191
 
188
192
 
189
- ### Functions
193
+ ### Predefined Functions
190
194
 
191
195
  #### General Functions
192
196
  - **?? ??.Coalesce(otherwise: ??)** — Null coalescence
193
197
  - **boolean ??.Equal(value: ??)** — Equals to
194
198
  - **boolean ??.Unequal(value: ??)** — Not equals to
195
199
  - **buffer float | integer | string.Encode(encoding: string?)** — Encode value to buffer
196
- - **string boolean | float | integer | buffer | string | array | object.Format(radix: integer?, separator: string?)** — Format value to string
200
+ - **string ??.Format(formatting: integer? | string?)** — Format value to string
197
201
 
198
202
  #### Array Functions
199
203
  - **?? array.First(condition: function)** — First item satisfying condition
@@ -380,6 +380,28 @@ export class ParserState extends ParserFrame {
380
380
  ++this._end;
381
381
  this._fragment = funcDivideAssignment;
382
382
  break;
383
+ case "/":
384
+ if (this._expr.charAt(++this._end) === '/') {
385
+ ++this._end;
386
+ while (this._expr.charAt(this._end) !== ""
387
+ && (this._expr.charAt(this._end) !== c
388
+ || this._expr.charAt(this._end - 1) !== c
389
+ || this._expr.charAt(this._end - 2) !== c)) {
390
+ ++this._end;
391
+ }
392
+ if (this._end >= this._expr.length) {
393
+ this._start = this._expr.length;
394
+ throw new Error(`missing closing comment mark`);
395
+ }
396
+ ++this._end;
397
+ }
398
+ else {
399
+ while (this._expr.charAt(this._end) !== ""
400
+ && this._expr.charAt(this._end) !== "\n") {
401
+ ++this._end;
402
+ }
403
+ }
404
+ break;
383
405
  default:
384
406
  this._fragment = funcDivide;
385
407
  break;
@@ -396,25 +418,6 @@ export class ParserState extends ParserFrame {
396
418
  break;
397
419
  }
398
420
  break;
399
- case "$":
400
- switch (this._expr.charAt(this._end)) {
401
- case "$":
402
- while (this._expr.charAt(this._end) !== "" && this._expr.charAt(this._end) !== "\n") {
403
- ++this._end;
404
- }
405
- break;
406
- default:
407
- while (this._expr.charAt(this._end) !== "" && this._expr.charAt(this._end) !== c) {
408
- ++this._end;
409
- }
410
- if (this._end >= this._expr.length) {
411
- this._start = this._expr.length;
412
- throw new Error(`missing closing comment mark ${c}`);
413
- }
414
- ++this._end;
415
- break;
416
- }
417
- break;
418
421
  case "^":
419
422
  this._fragment = funcPower;
420
423
  break;
@@ -443,7 +446,8 @@ export class ParserState extends ParserFrame {
443
446
  while (isTimeSymbol(this._expr.charAt(this._end))) {
444
447
  ++this._end;
445
448
  }
446
- if (this._expr.charAt(this._end) === "." && isNumericSymbol(this._expr.charAt(this._end + 1))) {
449
+ if (this._expr.charAt(this._end) === "."
450
+ && isNumericSymbol(this._expr.charAt(this._end + 1))) {
447
451
  ++this._end;
448
452
  while (isNumericSymbol(this._expr.charAt(this._end))) {
449
453
  ++this._end;
@@ -456,7 +460,8 @@ export class ParserState extends ParserFrame {
456
460
  this._fragment = new Literal(new Date(this._expr.substring(this._start + 1, this._end)));
457
461
  break;
458
462
  case "`":
459
- while (this._expr.charAt(this._end) !== "" && this._expr.charAt(this._end) !== c) {
463
+ while (this._expr.charAt(this._end) !== ""
464
+ && this._expr.charAt(this._end) !== c) {
460
465
  ++this._end;
461
466
  }
462
467
  if (this._end >= this._expr.length) {
@@ -468,7 +473,8 @@ export class ParserState extends ParserFrame {
468
473
  break;
469
474
  case "\"":
470
475
  case "'":
471
- while (this._expr.charAt(this._end) !== "" && this._expr.charAt(this._end) !== c) {
476
+ while (this._expr.charAt(this._end) !== ""
477
+ && this._expr.charAt(this._end) !== c) {
472
478
  ++this._end;
473
479
  }
474
480
  if (this._end >= this._expr.length) {
@@ -570,7 +576,8 @@ export class ParserState extends ParserFrame {
570
576
  }
571
577
  if (this._expr.charAt(this._end) === "e") {
572
578
  ++this._end;
573
- if (isNumericSymbol(this._expr.charAt(this._end)) || isSignSymbol(this._expr.charAt(this._end))) {
579
+ if (isNumericSymbol(this._expr.charAt(this._end))
580
+ || isSignSymbol(this._expr.charAt(this._end))) {
574
581
  ++this._end;
575
582
  while (isNumericSymbol(this._expr.charAt(this._end))) {
576
583
  ++this._end;
package/dst/Value.d.ts CHANGED
@@ -1,3 +1,5 @@
1
- export type Value = undefined | null | number | boolean | Date | bigint | ArrayBuffer | string | Value[] | {
1
+ export type PrimitiveValue = undefined | null | number | boolean | Date | bigint | ArrayBuffer | string;
2
+ export type DataValue = PrimitiveValue | Value[] | {
2
3
  [key: string]: Value;
3
- } | ((...args: any[]) => Value);
4
+ };
5
+ export type Value = DataValue | ((...args: any[]) => Value);
@@ -383,6 +383,28 @@ class ParserState extends ParserFrame_js_1.ParserFrame {
383
383
  ++this._end;
384
384
  this._fragment = funcDivideAssignment;
385
385
  break;
386
+ case "/":
387
+ if (this._expr.charAt(++this._end) === '/') {
388
+ ++this._end;
389
+ while (this._expr.charAt(this._end) !== ""
390
+ && (this._expr.charAt(this._end) !== c
391
+ || this._expr.charAt(this._end - 1) !== c
392
+ || this._expr.charAt(this._end - 2) !== c)) {
393
+ ++this._end;
394
+ }
395
+ if (this._end >= this._expr.length) {
396
+ this._start = this._expr.length;
397
+ throw new Error(`missing closing comment mark`);
398
+ }
399
+ ++this._end;
400
+ }
401
+ else {
402
+ while (this._expr.charAt(this._end) !== ""
403
+ && this._expr.charAt(this._end) !== "\n") {
404
+ ++this._end;
405
+ }
406
+ }
407
+ break;
386
408
  default:
387
409
  this._fragment = Number_js_1.funcDivide;
388
410
  break;
@@ -399,25 +421,6 @@ class ParserState extends ParserFrame_js_1.ParserFrame {
399
421
  break;
400
422
  }
401
423
  break;
402
- case "$":
403
- switch (this._expr.charAt(this._end)) {
404
- case "$":
405
- while (this._expr.charAt(this._end) !== "" && this._expr.charAt(this._end) !== "\n") {
406
- ++this._end;
407
- }
408
- break;
409
- default:
410
- while (this._expr.charAt(this._end) !== "" && this._expr.charAt(this._end) !== c) {
411
- ++this._end;
412
- }
413
- if (this._end >= this._expr.length) {
414
- this._start = this._expr.length;
415
- throw new Error(`missing closing comment mark ${c}`);
416
- }
417
- ++this._end;
418
- break;
419
- }
420
- break;
421
424
  case "^":
422
425
  this._fragment = Number_js_1.funcPower;
423
426
  break;
@@ -446,7 +449,8 @@ class ParserState extends ParserFrame_js_1.ParserFrame {
446
449
  while ((0, String_js_1.isTimeSymbol)(this._expr.charAt(this._end))) {
447
450
  ++this._end;
448
451
  }
449
- if (this._expr.charAt(this._end) === "." && (0, String_js_1.isNumericSymbol)(this._expr.charAt(this._end + 1))) {
452
+ if (this._expr.charAt(this._end) === "."
453
+ && (0, String_js_1.isNumericSymbol)(this._expr.charAt(this._end + 1))) {
450
454
  ++this._end;
451
455
  while ((0, String_js_1.isNumericSymbol)(this._expr.charAt(this._end))) {
452
456
  ++this._end;
@@ -459,7 +463,8 @@ class ParserState extends ParserFrame_js_1.ParserFrame {
459
463
  this._fragment = new Literal(new Date(this._expr.substring(this._start + 1, this._end)));
460
464
  break;
461
465
  case "`":
462
- while (this._expr.charAt(this._end) !== "" && this._expr.charAt(this._end) !== c) {
466
+ while (this._expr.charAt(this._end) !== ""
467
+ && this._expr.charAt(this._end) !== c) {
463
468
  ++this._end;
464
469
  }
465
470
  if (this._end >= this._expr.length) {
@@ -471,7 +476,8 @@ class ParserState extends ParserFrame_js_1.ParserFrame {
471
476
  break;
472
477
  case "\"":
473
478
  case "'":
474
- while (this._expr.charAt(this._end) !== "" && this._expr.charAt(this._end) !== c) {
479
+ while (this._expr.charAt(this._end) !== ""
480
+ && this._expr.charAt(this._end) !== c) {
475
481
  ++this._end;
476
482
  }
477
483
  if (this._end >= this._expr.length) {
@@ -573,7 +579,8 @@ class ParserState extends ParserFrame_js_1.ParserFrame {
573
579
  }
574
580
  if (this._expr.charAt(this._end) === "e") {
575
581
  ++this._end;
576
- if ((0, String_js_1.isNumericSymbol)(this._expr.charAt(this._end)) || (0, String_js_1.isSignSymbol)(this._expr.charAt(this._end))) {
582
+ if ((0, String_js_1.isNumericSymbol)(this._expr.charAt(this._end))
583
+ || (0, String_js_1.isSignSymbol)(this._expr.charAt(this._end))) {
577
584
  ++this._end;
578
585
  while ((0, String_js_1.isNumericSymbol)(this._expr.charAt(this._end))) {
579
586
  ++this._end;
@@ -48,7 +48,7 @@ exports.funcDerive = new Constant_js_1.Constant((value, transform) => value?.map
48
48
  exports.funcFilter = new Constant_js_1.Constant((value, predicate) => value?.filter((v, i, a) => predicate(v, BigInt(i), a)), Type_js_1.Type.functionType(Type_js_1.Type.Array, [Type_js_1.Type.Array, typePredicate]));
49
49
  exports.funcReduce = new Constant_js_1.Constant((value, reducer, initial) => initial != null
50
50
  ? value?.reduce((p, v, i, a) => reducer(p, v, BigInt(i), a), initial)
51
- : value?.reduce((p, v, i, a) => reducer(p, v, BigInt(i), a)), Type_js_1.Type.functionType(Type_js_1.Type.Unknown, [Type_js_1.Type.Array, Type_js_1.Type.functionType(Type_js_1.Type.Unknown, [Type_js_1.Type.Unknown, Type_js_1.Type.Unknown, Type_js_1.Type.OptionalInteger, Type_js_1.Type.OptionalArray])]));
51
+ : value?.reduce((p, v, i, a) => reducer(p, v, BigInt(i), a)), Type_js_1.Type.functionType(Type_js_1.Type.Unknown, [Type_js_1.Type.Array, Type_js_1.Type.functionType(Type_js_1.Type.Unknown, [Type_js_1.Type.Unknown, Type_js_1.Type.Unknown, Type_js_1.Type.OptionalInteger, Type_js_1.Type.OptionalArray]), Type_js_1.Type.Unknown]));
52
52
  exports.funcCompose = new Constant_js_1.Constant((value, callback) => {
53
53
  if (value == null) {
54
54
  return undefined;
@@ -68,7 +68,7 @@ exports.funcAppend = new Constant_js_1.Constant((value, ...items) => {
68
68
  value?.push(items);
69
69
  return value;
70
70
  }, typeVariadicInsert);
71
- const funcJoin = new Constant_js_1.Constant((...values) => values.flat(Infinity).reduce((acc, val) => [...acc, val], []), Type_js_1.Type.functionType(Type_js_1.Type.Array, [Type_js_1.Type.Array], true));
71
+ const funcJoin = new Constant_js_1.Constant((...values) => values.flat(Infinity), Type_js_1.Type.functionType(Type_js_1.Type.Array, [Type_js_1.Type.Array], true));
72
72
  const funcRange = new Constant_js_1.Constant((value1, value2) => {
73
73
  const min = value1 < value2 ? value1 : value2;
74
74
  const max = value1 > value2 ? value1 : value2;
@@ -9,7 +9,7 @@ const isNumericSymbol = (c) => c >= "0" && c <= "9";
9
9
  exports.isNumericSymbol = isNumericSymbol;
10
10
  const isAlphanumericSymbol = (c) => c >= "a" && c <= "z" || c >= "0" && c <= "9";
11
11
  exports.isAlphanumericSymbol = isAlphanumericSymbol;
12
- const isTokenStartSymbol = (c) => c >= "a" && c <= "z" || c >= "A" && c <= "Z" || c === "_";
12
+ const isTokenStartSymbol = (c) => c >= "a" && c <= "z" || c >= "A" && c <= "Z" || c === "_" || c === "#" || c === "$";
13
13
  exports.isTokenStartSymbol = isTokenStartSymbol;
14
14
  const isTokenSymbol = (c) => (0, exports.isTokenStartSymbol)(c) || (0, exports.isNumericSymbol)(c);
15
15
  exports.isTokenSymbol = isTokenSymbol;
@@ -14,21 +14,43 @@ const encodeTimestamp = (value, encoding = "int64") => {
14
14
  exports.encodeTimestamp = encodeTimestamp;
15
15
  const decodeTimestamp = (value, encoding = "int64", byteOffset) => value ? new Date(Number(new DataView(value).getBigInt64(byteOffset == null ? 0 : Number(byteOffset), encoding === "int64le"))) : undefined;
16
16
  exports.decodeTimestamp = decodeTimestamp;
17
- const formatTimestamp = (value, radix) => {
17
+ const formatTimestamp = (value, template) => {
18
18
  if (value == null) {
19
19
  return "";
20
20
  }
21
- const str = value.toISOString();
22
- switch (radix) {
23
- case 1: return str.slice(0, 4);
24
- case 2: return str.slice(5, 7);
25
- case 3: return str.slice(8, 10);
26
- case 4: return str.slice(11, 13);
27
- case 5: return str.slice(14, 16);
28
- case 6: return str.slice(17, 19);
29
- case 7: return str.slice(20, 23);
30
- default: return str;
21
+ if (!template || typeof template !== "string") {
22
+ return value.toISOString();
31
23
  }
24
+ const map = template.includes("Z")
25
+ ? {
26
+ YYYY: value.getUTCFullYear(),
27
+ YY: value.getUTCFullYear() % 100,
28
+ MM: value.getUTCMonth() + 1,
29
+ DD: value.getUTCDate(),
30
+ hh: value.getUTCHours(),
31
+ mm: value.getUTCMinutes(),
32
+ ss: value.getUTCSeconds(),
33
+ fff: value.getUTCMilliseconds(),
34
+ }
35
+ : {
36
+ YYYY: value.getFullYear(),
37
+ YY: value.getFullYear() % 100,
38
+ MM: value.getMonth() + 1,
39
+ DD: value.getDate(),
40
+ hh: value.getHours(),
41
+ mm: value.getMinutes(),
42
+ ss: value.getSeconds(),
43
+ fff: value.getMilliseconds(),
44
+ };
45
+ return template.replaceAll("Z", "")
46
+ .replace("YYYY", map.YYYY.toString())
47
+ .replace("YY", map.YY.toString().padStart(2, "0"))
48
+ .replace("MM", map.MM.toString().padStart(2, "0"))
49
+ .replace("DD", map.DD.toString().padStart(2, "0"))
50
+ .replace("hh", map.hh.toString().padStart(2, "0"))
51
+ .replace("mm", map.mm.toString().padStart(2, "0"))
52
+ .replace("ss", map.ss.toString().padStart(2, "0"))
53
+ .replace("fff", map.fff.toString().padStart(3, "0"));
32
54
  };
33
55
  exports.formatTimestamp = formatTimestamp;
34
56
  const parseTimestamp = (value) => {
@@ -73,24 +73,24 @@ const encode = (value, encoding) => value == null
73
73
  ? Object.entries(value).map(([k, v]) => (0, Buffer_js_1.concatBuffers)((0, exports.encode)(k, encoding), (0, exports.encode)(v, encoding))).reduce((acc, val) => (0, Buffer_js_1.concatBuffers)(acc, val))
74
74
  : new Uint8Array(0).buffer;
75
75
  exports.encode = encode;
76
- const format = (value, radix, separator = "") => value == null
76
+ const format = (value, formatting) => value == null
77
77
  ? "null"
78
78
  : typeof value === "boolean"
79
79
  ? value.toString()
80
80
  : value instanceof Date
81
- ? (0, Timestamp_js_1.formatTimestamp)(value, radix ? Number(radix) : undefined)
81
+ ? (0, Timestamp_js_1.formatTimestamp)(value, String(formatting))
82
82
  : typeof value === "number"
83
- ? (0, Float_js_1.formatReal)(value, radix ? Number(radix) : undefined)
83
+ ? (0, Float_js_1.formatReal)(value, formatting ? Number(formatting) : undefined)
84
84
  : typeof value === "bigint"
85
- ? value.toString(radix ? Number(radix) : undefined)
85
+ ? value.toString(formatting ? Number(formatting) : undefined)
86
86
  : value instanceof ArrayBuffer
87
87
  ? (0, Buffer_js_1.formatBuffer)(value)
88
88
  : typeof value === "string"
89
89
  ? value
90
90
  : Array.isArray(value)
91
- ? value.map((i) => (0, exports.format)(i, radix)).join(separator)
91
+ ? "array"
92
92
  : typeof value === "object"
93
- ? Object.entries(value).map(([k, v]) => `${(0, exports.format)(k)}${radix}${(0, exports.format)(v)}`).join(separator)
93
+ ? "object"
94
94
  : "function";
95
95
  exports.format = format;
96
96
  const typeEquator = Type_js_1.Type.functionType(Type_js_1.Type.Boolean, [Type_js_1.Type.Unknown, Type_js_1.Type.Unknown]);
@@ -98,4 +98,4 @@ exports.funcCoalesce = new Constant_js_1.Constant((value, valueOtherwise) => val
98
98
  exports.funcEqual = new Constant_js_1.Constant((value1, value2) => (0, exports.equate)(value1, value2), typeEquator);
99
99
  exports.funcNotEqual = new Constant_js_1.Constant((value1, value2) => !(0, exports.equate)(value1, value2), typeEquator);
100
100
  exports.funcEncode = new Constant_js_1.Constant((value, encoding) => (0, exports.encode)(value, encoding), Type_js_1.Type.union(Type_js_1.Type.functionType(Type_js_1.Type.Buffer, [Type_js_1.Type.Boolean]), Type_js_1.Type.functionType(Type_js_1.Type.Buffer, [Type_js_1.Type.Timestamp, Type_js_1.Type.OptionalString]), Type_js_1.Type.functionType(Type_js_1.Type.Buffer, [Type_js_1.Type.Float, Type_js_1.Type.OptionalString]), Type_js_1.Type.functionType(Type_js_1.Type.Buffer, [Type_js_1.Type.Integer, Type_js_1.Type.OptionalString]), Type_js_1.Type.functionType(Type_js_1.Type.Buffer, [Type_js_1.Type.String, Type_js_1.Type.OptionalString]), Type_js_1.Type.functionType(Type_js_1.Type.Buffer, [Type_js_1.Type.Array, Type_js_1.Type.OptionalString]), Type_js_1.Type.functionType(Type_js_1.Type.Buffer, [Type_js_1.Type.Object, Type_js_1.Type.OptionalString])));
101
- exports.funcFormat = new Constant_js_1.Constant((value, radix, separator = "") => (0, exports.format)(value, radix == null ? undefined : Number(radix), separator), Type_js_1.Type.union(Type_js_1.Type.functionType(Type_js_1.Type.String, [Type_js_1.Type.Boolean]), Type_js_1.Type.functionType(Type_js_1.Type.String, [Type_js_1.Type.Timestamp, Type_js_1.Type.OptionalInteger]), Type_js_1.Type.functionType(Type_js_1.Type.String, [Type_js_1.Type.Float, Type_js_1.Type.OptionalInteger]), Type_js_1.Type.functionType(Type_js_1.Type.String, [Type_js_1.Type.Integer, Type_js_1.Type.OptionalInteger]), Type_js_1.Type.functionType(Type_js_1.Type.String, [Type_js_1.Type.Buffer]), Type_js_1.Type.functionType(Type_js_1.Type.String, [Type_js_1.Type.Array, Type_js_1.Type.OptionalInteger, Type_js_1.Type.OptionalString]), Type_js_1.Type.functionType(Type_js_1.Type.String, [Type_js_1.Type.Object, Type_js_1.Type.OptionalInteger, Type_js_1.Type.OptionalString])));
101
+ exports.funcFormat = new Constant_js_1.Constant((value, formatting) => (0, exports.format)(value, formatting == null ? undefined : typeof formatting === 'string' ? formatting : Number(formatting)), Type_js_1.Type.union(Type_js_1.Type.functionType(Type_js_1.Type.String, [Type_js_1.Type.Boolean]), Type_js_1.Type.functionType(Type_js_1.Type.String, [Type_js_1.Type.Timestamp, Type_js_1.Type.OptionalString]), Type_js_1.Type.functionType(Type_js_1.Type.String, [Type_js_1.Type.Float, Type_js_1.Type.OptionalInteger]), Type_js_1.Type.functionType(Type_js_1.Type.String, [Type_js_1.Type.Integer, Type_js_1.Type.OptionalInteger]), Type_js_1.Type.functionType(Type_js_1.Type.String, [Type_js_1.Type.Buffer]), Type_js_1.Type.functionType(Type_js_1.Type.String, [Type_js_1.Type.Array]), Type_js_1.Type.functionType(Type_js_1.Type.String, [Type_js_1.Type.Object]), Type_js_1.Type.functionType(Type_js_1.Type.String, [Type_js_1.Type.Function])));
@@ -45,7 +45,7 @@ export const funcDerive = new Constant((value, transform) => value?.map((v, i, a
45
45
  export const funcFilter = new Constant((value, predicate) => value?.filter((v, i, a) => predicate(v, BigInt(i), a)), Type.functionType(Type.Array, [Type.Array, typePredicate]));
46
46
  export const funcReduce = new Constant((value, reducer, initial) => initial != null
47
47
  ? value?.reduce((p, v, i, a) => reducer(p, v, BigInt(i), a), initial)
48
- : value?.reduce((p, v, i, a) => reducer(p, v, BigInt(i), a)), Type.functionType(Type.Unknown, [Type.Array, Type.functionType(Type.Unknown, [Type.Unknown, Type.Unknown, Type.OptionalInteger, Type.OptionalArray])]));
48
+ : value?.reduce((p, v, i, a) => reducer(p, v, BigInt(i), a)), Type.functionType(Type.Unknown, [Type.Array, Type.functionType(Type.Unknown, [Type.Unknown, Type.Unknown, Type.OptionalInteger, Type.OptionalArray]), Type.Unknown]));
49
49
  export const funcCompose = new Constant((value, callback) => {
50
50
  if (value == null) {
51
51
  return undefined;
@@ -65,7 +65,7 @@ export const funcAppend = new Constant((value, ...items) => {
65
65
  value?.push(items);
66
66
  return value;
67
67
  }, typeVariadicInsert);
68
- const funcJoin = new Constant((...values) => values.flat(Infinity).reduce((acc, val) => [...acc, val], []), Type.functionType(Type.Array, [Type.Array], true));
68
+ const funcJoin = new Constant((...values) => values.flat(Infinity), Type.functionType(Type.Array, [Type.Array], true));
69
69
  const funcRange = new Constant((value1, value2) => {
70
70
  const min = value1 < value2 ? value1 : value2;
71
71
  const max = value1 > value2 ? value1 : value2;
@@ -3,7 +3,7 @@ import { Type } from "../Type.js";
3
3
  export const isSignSymbol = (c) => c === "+" || c === "-";
4
4
  export const isNumericSymbol = (c) => c >= "0" && c <= "9";
5
5
  export const isAlphanumericSymbol = (c) => c >= "a" && c <= "z" || c >= "0" && c <= "9";
6
- export const isTokenStartSymbol = (c) => c >= "a" && c <= "z" || c >= "A" && c <= "Z" || c === "_";
6
+ export const isTokenStartSymbol = (c) => c >= "a" && c <= "z" || c >= "A" && c <= "Z" || c === "_" || c === "#" || c === "$";
7
7
  export const isTokenSymbol = (c) => isTokenStartSymbol(c) || isNumericSymbol(c);
8
8
  export const isDateSeparatorSymbol = (c) => c === "-";
9
9
  export const isTimeSeparatorSymbol = (c) => c === ":";
@@ -2,7 +2,7 @@ import { Constant } from "../Constant.js";
2
2
  export type TimestampEncoding = "int64" | "int64le";
3
3
  export declare const encodeTimestamp: (value?: Date, encoding?: TimestampEncoding) => ArrayBuffer;
4
4
  export declare const decodeTimestamp: (value?: ArrayBuffer, encoding?: TimestampEncoding, byteOffset?: bigint) => Date | undefined;
5
- export declare const formatTimestamp: (value?: Date, radix?: number) => string;
5
+ export declare const formatTimestamp: (value?: Date, template?: string) => string;
6
6
  export declare const funcYear: Constant;
7
7
  export declare const funcMonth: Constant;
8
8
  export declare const funcMonthIndex: Constant;
@@ -9,21 +9,43 @@ export const encodeTimestamp = (value, encoding = "int64") => {
9
9
  return buf;
10
10
  };
11
11
  export const decodeTimestamp = (value, encoding = "int64", byteOffset) => value ? new Date(Number(new DataView(value).getBigInt64(byteOffset == null ? 0 : Number(byteOffset), encoding === "int64le"))) : undefined;
12
- export const formatTimestamp = (value, radix) => {
12
+ export const formatTimestamp = (value, template) => {
13
13
  if (value == null) {
14
14
  return "";
15
15
  }
16
- const str = value.toISOString();
17
- switch (radix) {
18
- case 1: return str.slice(0, 4);
19
- case 2: return str.slice(5, 7);
20
- case 3: return str.slice(8, 10);
21
- case 4: return str.slice(11, 13);
22
- case 5: return str.slice(14, 16);
23
- case 6: return str.slice(17, 19);
24
- case 7: return str.slice(20, 23);
25
- default: return str;
16
+ if (!template || typeof template !== "string") {
17
+ return value.toISOString();
26
18
  }
19
+ const map = template.includes("Z")
20
+ ? {
21
+ YYYY: value.getUTCFullYear(),
22
+ YY: value.getUTCFullYear() % 100,
23
+ MM: value.getUTCMonth() + 1,
24
+ DD: value.getUTCDate(),
25
+ hh: value.getUTCHours(),
26
+ mm: value.getUTCMinutes(),
27
+ ss: value.getUTCSeconds(),
28
+ fff: value.getUTCMilliseconds(),
29
+ }
30
+ : {
31
+ YYYY: value.getFullYear(),
32
+ YY: value.getFullYear() % 100,
33
+ MM: value.getMonth() + 1,
34
+ DD: value.getDate(),
35
+ hh: value.getHours(),
36
+ mm: value.getMinutes(),
37
+ ss: value.getSeconds(),
38
+ fff: value.getMilliseconds(),
39
+ };
40
+ return template.replaceAll("Z", "")
41
+ .replace("YYYY", map.YYYY.toString())
42
+ .replace("YY", map.YY.toString().padStart(2, "0"))
43
+ .replace("MM", map.MM.toString().padStart(2, "0"))
44
+ .replace("DD", map.DD.toString().padStart(2, "0"))
45
+ .replace("hh", map.hh.toString().padStart(2, "0"))
46
+ .replace("mm", map.mm.toString().padStart(2, "0"))
47
+ .replace("ss", map.ss.toString().padStart(2, "0"))
48
+ .replace("fff", map.fff.toString().padStart(3, "0"));
27
49
  };
28
50
  const parseTimestamp = (value) => {
29
51
  if (value == null) {
@@ -6,7 +6,7 @@ import { StringEncoding } from "./String.js";
6
6
  import { TimestampEncoding } from "./Timestamp.js";
7
7
  export declare const equate: (value1: Value, value2: Value) => boolean;
8
8
  export declare const encode: (value: Value, encoding?: FloatEncoding | IntegerEncoding | TimestampEncoding | StringEncoding) => ArrayBuffer;
9
- export declare const format: (value: Value, radix?: number, separator?: string) => string;
9
+ export declare const format: (value: Value, formatting?: number | string) => string;
10
10
  export declare const funcCoalesce: Constant;
11
11
  export declare const funcEqual: Constant;
12
12
  export declare const funcNotEqual: Constant;
@@ -68,28 +68,28 @@ export const encode = (value, encoding) => value == null
68
68
  : typeof value === "object"
69
69
  ? Object.entries(value).map(([k, v]) => concatBuffers(encode(k, encoding), encode(v, encoding))).reduce((acc, val) => concatBuffers(acc, val))
70
70
  : new Uint8Array(0).buffer;
71
- export const format = (value, radix, separator = "") => value == null
71
+ export const format = (value, formatting) => value == null
72
72
  ? "null"
73
73
  : typeof value === "boolean"
74
74
  ? value.toString()
75
75
  : value instanceof Date
76
- ? formatTimestamp(value, radix ? Number(radix) : undefined)
76
+ ? formatTimestamp(value, String(formatting))
77
77
  : typeof value === "number"
78
- ? formatReal(value, radix ? Number(radix) : undefined)
78
+ ? formatReal(value, formatting ? Number(formatting) : undefined)
79
79
  : typeof value === "bigint"
80
- ? value.toString(radix ? Number(radix) : undefined)
80
+ ? value.toString(formatting ? Number(formatting) : undefined)
81
81
  : value instanceof ArrayBuffer
82
82
  ? formatBuffer(value)
83
83
  : typeof value === "string"
84
84
  ? value
85
85
  : Array.isArray(value)
86
- ? value.map((i) => format(i, radix)).join(separator)
86
+ ? "array"
87
87
  : typeof value === "object"
88
- ? Object.entries(value).map(([k, v]) => `${format(k)}${radix}${format(v)}`).join(separator)
88
+ ? "object"
89
89
  : "function";
90
90
  const typeEquator = Type.functionType(Type.Boolean, [Type.Unknown, Type.Unknown]);
91
91
  export const funcCoalesce = new Constant((value, valueOtherwise) => value ?? valueOtherwise, Type.union(Type.functionType(Type.Unknown, [Type.Unknown, Type.Unknown]), Type.functionType(Type.OptionalFloat, [Type.OptionalFloat, Type.OptionalFloat]), Type.functionType(Type.OptionalBoolean, [Type.OptionalBoolean, Type.OptionalBoolean]), Type.functionType(Type.OptionalTimestamp, [Type.OptionalTimestamp, Type.OptionalTimestamp]), Type.functionType(Type.OptionalInteger, [Type.OptionalInteger, Type.OptionalInteger]), Type.functionType(Type.OptionalBuffer, [Type.OptionalBuffer, Type.OptionalBuffer]), Type.functionType(Type.OptionalString, [Type.OptionalString, Type.OptionalString]), Type.functionType(Type.OptionalArray, [Type.OptionalArray, Type.OptionalArray]), Type.functionType(Type.OptionalObject, [Type.OptionalObject, Type.OptionalObject]), Type.functionType(Type.OptionalFunction, [Type.OptionalFunction, Type.OptionalFunction])));
92
92
  export const funcEqual = new Constant((value1, value2) => equate(value1, value2), typeEquator);
93
93
  export const funcNotEqual = new Constant((value1, value2) => !equate(value1, value2), typeEquator);
94
94
  export const funcEncode = new Constant((value, encoding) => encode(value, encoding), Type.union(Type.functionType(Type.Buffer, [Type.Boolean]), Type.functionType(Type.Buffer, [Type.Timestamp, Type.OptionalString]), Type.functionType(Type.Buffer, [Type.Float, Type.OptionalString]), Type.functionType(Type.Buffer, [Type.Integer, Type.OptionalString]), Type.functionType(Type.Buffer, [Type.String, Type.OptionalString]), Type.functionType(Type.Buffer, [Type.Array, Type.OptionalString]), Type.functionType(Type.Buffer, [Type.Object, Type.OptionalString])));
95
- export const funcFormat = new Constant((value, radix, separator = "") => format(value, radix == null ? undefined : Number(radix), separator), Type.union(Type.functionType(Type.String, [Type.Boolean]), Type.functionType(Type.String, [Type.Timestamp, Type.OptionalInteger]), Type.functionType(Type.String, [Type.Float, Type.OptionalInteger]), Type.functionType(Type.String, [Type.Integer, Type.OptionalInteger]), Type.functionType(Type.String, [Type.Buffer]), Type.functionType(Type.String, [Type.Array, Type.OptionalInteger, Type.OptionalString]), Type.functionType(Type.String, [Type.Object, Type.OptionalInteger, Type.OptionalString])));
95
+ export const funcFormat = new Constant((value, formatting) => format(value, formatting == null ? undefined : typeof formatting === 'string' ? formatting : Number(formatting)), Type.union(Type.functionType(Type.String, [Type.Boolean]), Type.functionType(Type.String, [Type.Timestamp, Type.OptionalString]), Type.functionType(Type.String, [Type.Float, Type.OptionalInteger]), Type.functionType(Type.String, [Type.Integer, Type.OptionalInteger]), Type.functionType(Type.String, [Type.Buffer]), Type.functionType(Type.String, [Type.Array]), Type.functionType(Type.String, [Type.Object]), Type.functionType(Type.String, [Type.Function])));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "affinirum",
3
- "version": "1.2.2",
3
+ "version": "1.2.4",
4
4
  "description": "Affinirum Scripting Language",
5
5
  "main": "dst/cjs/index.js",
6
6
  "module": "dst/index.js",
@@ -56,12 +56,12 @@
56
56
  },
57
57
  "dependencies": {},
58
58
  "devDependencies": {
59
- "@types/jasmine": "~5.1.13",
59
+ "@types/jasmine": "~5.1.15",
60
60
  "copyfiles": "~2.4.1",
61
- "eslint": "~9.39.1",
62
- "jasmine": "~5.12.0",
61
+ "eslint": "~9.39.2",
62
+ "jasmine": "~5.13.0",
63
63
  "rimraf": "~6.1.2",
64
64
  "typescript": "~5.9.3",
65
- "typescript-eslint": "~8.48.0"
65
+ "typescript-eslint": "~8.53.0"
66
66
  }
67
67
  }