@bessemer/cornerstone 0.5.0
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/jest.config.js +3 -0
- package/package.json +39 -0
- package/src/array.ts +142 -0
- package/src/async.ts +114 -0
- package/src/cache.ts +236 -0
- package/src/combinable.ts +40 -0
- package/src/comparator.ts +78 -0
- package/src/content.ts +138 -0
- package/src/context.ts +6 -0
- package/src/crypto.ts +11 -0
- package/src/date.ts +18 -0
- package/src/duration.ts +57 -0
- package/src/either.ts +29 -0
- package/src/entry.ts +21 -0
- package/src/equalitor.ts +12 -0
- package/src/error-event.ts +126 -0
- package/src/error.ts +16 -0
- package/src/expression/array-expression.ts +29 -0
- package/src/expression/expression-evaluator.ts +34 -0
- package/src/expression/expression.ts +188 -0
- package/src/expression/internal.ts +34 -0
- package/src/expression/numeric-expression.ts +182 -0
- package/src/expression/string-expression.ts +38 -0
- package/src/expression.ts +48 -0
- package/src/function.ts +3 -0
- package/src/glob.ts +19 -0
- package/src/global-variable.ts +40 -0
- package/src/hash.ts +28 -0
- package/src/hex-code.ts +6 -0
- package/src/index.ts +82 -0
- package/src/lazy.ts +11 -0
- package/src/logger.ts +144 -0
- package/src/math.ts +132 -0
- package/src/misc.ts +22 -0
- package/src/object.ts +236 -0
- package/src/patch.ts +128 -0
- package/src/precondition.ts +25 -0
- package/src/promise.ts +16 -0
- package/src/property.ts +29 -0
- package/src/reference.ts +68 -0
- package/src/resource.ts +32 -0
- package/src/result.ts +66 -0
- package/src/retry.ts +70 -0
- package/src/rich-text.ts +24 -0
- package/src/set.ts +46 -0
- package/src/signature.ts +20 -0
- package/src/store.ts +91 -0
- package/src/string.ts +173 -0
- package/src/tag.ts +68 -0
- package/src/types.ts +21 -0
- package/src/ulid.ts +28 -0
- package/src/unit.ts +4 -0
- package/src/uri.ts +321 -0
- package/src/url.ts +155 -0
- package/src/uuid.ts +37 -0
- package/src/zod.ts +24 -0
- package/test/comparator.test.ts +1 -0
- package/test/expression.test.ts +12 -0
- package/test/object.test.ts +104 -0
- package/test/patch.test.ts +170 -0
- package/test/set.test.ts +20 -0
- package/test/string.test.ts +22 -0
- package/test/uri.test.ts +111 -0
- package/test/url.test.ts +174 -0
- package/tsconfig.build.json +13 -0
- package/tsup.config.ts +4 -0
@@ -0,0 +1,188 @@
|
|
1
|
+
import { ExpressionEvaluator } from '@bessemer/cornerstone/expression/expression-evaluator'
|
2
|
+
import {
|
3
|
+
ArrayExpressions,
|
4
|
+
EvaluateExpression,
|
5
|
+
Expression,
|
6
|
+
ExpressionContext,
|
7
|
+
ExpressionDefinition,
|
8
|
+
ExpressionReference,
|
9
|
+
ExpressionVariable,
|
10
|
+
NumericExpressions,
|
11
|
+
ParameterizedVariable,
|
12
|
+
StringExpressions,
|
13
|
+
} from '@bessemer/cornerstone/expression'
|
14
|
+
import { Arrays, Objects, Preconditions, Signatures } from '@bessemer/cornerstone'
|
15
|
+
import { Signable } from '@bessemer/cornerstone/signature'
|
16
|
+
import { defineExpression } from '@bessemer/cornerstone/expression/internal'
|
17
|
+
import { UnknownRecord } from 'type-fest'
|
18
|
+
|
19
|
+
export const evaluate = <T>(expression: Expression<T>, context: ExpressionContext): T => {
|
20
|
+
return new ExpressionEvaluator(DEFAULT_EXPRESSION_DEFINITIONS).evaluate(expression, context)
|
21
|
+
}
|
22
|
+
|
23
|
+
export const evaluateDefault = <T>(expression: Expression<T>): T => {
|
24
|
+
return evaluate(expression, defaultContext())
|
25
|
+
}
|
26
|
+
|
27
|
+
export const evaluator = (context: ExpressionContext): EvaluateExpression => {
|
28
|
+
return (it) => evaluate(it, context)
|
29
|
+
}
|
30
|
+
|
31
|
+
export const defaultEvaluator = (): EvaluateExpression => {
|
32
|
+
return evaluator(defaultContext())
|
33
|
+
}
|
34
|
+
|
35
|
+
export const defaultContext = (): ExpressionContext => {
|
36
|
+
return { variables: {} }
|
37
|
+
}
|
38
|
+
|
39
|
+
export const dereference = <ReturnType, ArgumentType extends Array<unknown>>(
|
40
|
+
reference: ExpressionReference<ReturnType, ArgumentType>,
|
41
|
+
...args: ArgumentType
|
42
|
+
): Expression<ReturnType> => {
|
43
|
+
return new ExpressionEvaluator(DEFAULT_EXPRESSION_DEFINITIONS).dereference(reference, ...args)
|
44
|
+
}
|
45
|
+
|
46
|
+
export const parameterizedVariable = <ValueType, ParameterType extends Array<Signable>>(
|
47
|
+
name: string
|
48
|
+
): ParameterizedVariable<ValueType, ParameterType> => {
|
49
|
+
return {
|
50
|
+
apply(...parameters: ParameterType): ExpressionVariable<ValueType> {
|
51
|
+
const parameterString = parameters.map(Signatures.sign).join('.')
|
52
|
+
return variable(`${name}.${parameterString}`)
|
53
|
+
},
|
54
|
+
}
|
55
|
+
}
|
56
|
+
|
57
|
+
export const buildVariable = <T>(variable: ExpressionVariable<T>, value: T): UnknownRecord => {
|
58
|
+
return { [variable.name]: value }
|
59
|
+
}
|
60
|
+
|
61
|
+
export const reference = <ReturnType, ArgumentType extends Array<unknown>, ExpressionType extends Expression<ReturnType>>(
|
62
|
+
expressionDefinition: ExpressionDefinition<ReturnType, ArgumentType, ExpressionType>
|
63
|
+
): ExpressionReference<ReturnType, ArgumentType> => {
|
64
|
+
return { expressionKey: expressionDefinition.expressionKey }
|
65
|
+
}
|
66
|
+
|
67
|
+
export const ValueExpression = defineExpression({
|
68
|
+
expressionKey: 'Value',
|
69
|
+
builder: (value: unknown) => {
|
70
|
+
return { value }
|
71
|
+
},
|
72
|
+
resolver: ({ value }, evaluate, context) => {
|
73
|
+
return value
|
74
|
+
},
|
75
|
+
})
|
76
|
+
|
77
|
+
export const value = <T>(value: T): Expression<T> => ValueExpression.builder(value) as Expression<T>
|
78
|
+
|
79
|
+
export const VariableExpression = defineExpression({
|
80
|
+
expressionKey: 'Variable',
|
81
|
+
builder: (name: string) => {
|
82
|
+
return { name }
|
83
|
+
},
|
84
|
+
resolver: ({ name }, evaluate, context) => {
|
85
|
+
const value = context.variables[name]
|
86
|
+
Preconditions.isPresent(value)
|
87
|
+
return value
|
88
|
+
},
|
89
|
+
})
|
90
|
+
|
91
|
+
export const variable = <T>(name: string): ExpressionVariable<T> => VariableExpression.builder(name) as ExpressionVariable<T>
|
92
|
+
|
93
|
+
export const NotExpression = defineExpression({
|
94
|
+
expressionKey: 'Not',
|
95
|
+
builder: (value: Expression<boolean>) => {
|
96
|
+
return { value }
|
97
|
+
},
|
98
|
+
resolver: (expression, evaluate) => {
|
99
|
+
return !evaluate(expression.value)
|
100
|
+
},
|
101
|
+
})
|
102
|
+
|
103
|
+
export const not = NotExpression.builder
|
104
|
+
|
105
|
+
export const AndExpression = defineExpression({
|
106
|
+
expressionKey: 'And',
|
107
|
+
builder: (operands: Array<Expression<boolean>>) => {
|
108
|
+
return { operands }
|
109
|
+
},
|
110
|
+
resolver: (expression, evaluate) => {
|
111
|
+
const values = expression.operands.map((it) => evaluate(it))
|
112
|
+
const falseValue = values.find((it) => !it)
|
113
|
+
return Objects.isNil(falseValue)
|
114
|
+
},
|
115
|
+
})
|
116
|
+
|
117
|
+
export const and = AndExpression.builder
|
118
|
+
|
119
|
+
export const OrExpression = defineExpression({
|
120
|
+
expressionKey: 'Or',
|
121
|
+
builder: (operands: Array<Expression<boolean>>) => {
|
122
|
+
return { operands }
|
123
|
+
},
|
124
|
+
resolver: (expression, evaluate) => {
|
125
|
+
const values = expression.operands.map((it) => evaluate(it))
|
126
|
+
const trueValue = values.find((it) => it)
|
127
|
+
return Objects.isPresent(trueValue)
|
128
|
+
},
|
129
|
+
})
|
130
|
+
|
131
|
+
export const or = OrExpression.builder
|
132
|
+
|
133
|
+
export const EqualsExpression = defineExpression({
|
134
|
+
expressionKey: 'Equals',
|
135
|
+
builder: (operands: Array<Expression<Signable>>) => {
|
136
|
+
return { operands }
|
137
|
+
},
|
138
|
+
resolver: (expression, evaluate) => {
|
139
|
+
const values = expression.operands.map((it) => evaluate(it)).map(Signatures.sign)
|
140
|
+
|
141
|
+
if (values.length === 0) {
|
142
|
+
return true
|
143
|
+
}
|
144
|
+
|
145
|
+
const first = values[0]
|
146
|
+
return values.every((val) => val === first)
|
147
|
+
},
|
148
|
+
})
|
149
|
+
|
150
|
+
export const equals = EqualsExpression.builder
|
151
|
+
|
152
|
+
export const ContainsExpression = defineExpression({
|
153
|
+
expressionKey: 'Contains',
|
154
|
+
builder: (collection: Expression<Array<Signable>>, operands: Array<Expression<Signable>>) => {
|
155
|
+
return { collection, operands }
|
156
|
+
},
|
157
|
+
resolver: (expression, evaluate) => {
|
158
|
+
const collection = evaluate(expression.collection)
|
159
|
+
const values = expression.operands.map((it) => evaluate(it))
|
160
|
+
return Arrays.containsAll(collection, values)
|
161
|
+
},
|
162
|
+
})
|
163
|
+
|
164
|
+
export const contains = ContainsExpression.builder
|
165
|
+
|
166
|
+
const DEFAULT_EXPRESSION_DEFINITIONS: Array<ExpressionDefinition<unknown, Array<any>, Expression<any>>> = [
|
167
|
+
ValueExpression,
|
168
|
+
VariableExpression,
|
169
|
+
AndExpression,
|
170
|
+
OrExpression,
|
171
|
+
ContainsExpression,
|
172
|
+
EqualsExpression,
|
173
|
+
NumericExpressions.SumExpression,
|
174
|
+
NumericExpressions.MultiplyExpression,
|
175
|
+
NumericExpressions.GreaterThanExpression,
|
176
|
+
NumericExpressions.LessThanExpression,
|
177
|
+
NumericExpressions.FloorExpression,
|
178
|
+
NumericExpressions.CeilingExpression,
|
179
|
+
NumericExpressions.BoundsExpression,
|
180
|
+
NumericExpressions.RoundExpression,
|
181
|
+
NumericExpressions.MaxExpression,
|
182
|
+
NumericExpressions.MinExpression,
|
183
|
+
StringExpressions.ConcatenateExpression,
|
184
|
+
StringExpressions.SubstringExpression,
|
185
|
+
StringExpressions.UppercaseExpression,
|
186
|
+
ArrayExpressions.ConcatenateExpression,
|
187
|
+
ArrayExpressions.FirstExpression,
|
188
|
+
]
|
@@ -0,0 +1,34 @@
|
|
1
|
+
import { EvaluateExpression, Expression, ExpressionContext, ExpressionDefinition, ExpressionKey, IExpression } from '@bessemer/cornerstone/expression'
|
2
|
+
import { Objects } from '@bessemer/cornerstone'
|
3
|
+
import { UnknownRecord } from 'type-fest'
|
4
|
+
|
5
|
+
export const defineExpression = <ReturnType, ArgumentType extends Array<unknown>, PayloadType extends UnknownRecord>(options: {
|
6
|
+
expressionKey: ExpressionKey<ReturnType, ArgumentType>
|
7
|
+
builder: (...parameters: ArgumentType) => PayloadType
|
8
|
+
resolver: (expression: PayloadType, evaluate: EvaluateExpression, context: ExpressionContext) => ReturnType
|
9
|
+
}): ExpressionDefinition<ReturnType, ArgumentType, Expression<ReturnType> & PayloadType> => {
|
10
|
+
return {
|
11
|
+
expressionKey: options.expressionKey,
|
12
|
+
builder: (...parameters) => {
|
13
|
+
return { expressionKey: options.expressionKey, ...options.builder(...parameters) }
|
14
|
+
},
|
15
|
+
resolver: (expression, evaluate, context) => {
|
16
|
+
return options.resolver(expression as any, evaluate, context)
|
17
|
+
},
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
export const isType = <ReturnValue, ArgumentType extends Array<any>, ExpressionType extends Expression<ReturnValue>>(
|
22
|
+
expression: Expression<ReturnValue>,
|
23
|
+
expressionDefinition: ExpressionDefinition<ReturnValue, ArgumentType, ExpressionType>
|
24
|
+
): expression is ReturnType<typeof expressionDefinition['builder']> => {
|
25
|
+
if (!isExpression(expression)) {
|
26
|
+
return false
|
27
|
+
}
|
28
|
+
|
29
|
+
return expression.expressionKey === expressionDefinition.expressionKey
|
30
|
+
}
|
31
|
+
|
32
|
+
export const isExpression = <T>(expression: Expression<any>): expression is IExpression<T> => {
|
33
|
+
return Objects.isObject(expression) && 'expressionKey' in expression
|
34
|
+
}
|
@@ -0,0 +1,182 @@
|
|
1
|
+
import { defineExpression, isType } from '@bessemer/cornerstone/expression/internal'
|
2
|
+
import { Expression } from '@bessemer/cornerstone/expression'
|
3
|
+
import { Maths, Objects } from '@bessemer/cornerstone'
|
4
|
+
import { RoundingMode } from '@bessemer/cornerstone/math'
|
5
|
+
|
6
|
+
export const SumExpression = defineExpression({
|
7
|
+
expressionKey: 'Numeric.Sum',
|
8
|
+
builder: (initialOperands: Array<Expression<number>>) => {
|
9
|
+
const operands: Array<Expression<number>> = initialOperands.flatMap((it) => {
|
10
|
+
if (isType(it, SumExpression)) {
|
11
|
+
return it.operands
|
12
|
+
} else {
|
13
|
+
return [it]
|
14
|
+
}
|
15
|
+
})
|
16
|
+
|
17
|
+
return { operands }
|
18
|
+
},
|
19
|
+
resolver: ({ operands }, evaluate) => {
|
20
|
+
const values = operands.map((it) => evaluate(it))
|
21
|
+
return values.reduce((x, y) => x + y, 0)
|
22
|
+
},
|
23
|
+
})
|
24
|
+
|
25
|
+
export const sum = SumExpression.builder
|
26
|
+
|
27
|
+
export const MultiplyExpression = defineExpression({
|
28
|
+
expressionKey: 'Numeric.Multiply',
|
29
|
+
builder: (initialOperands: Array<Expression<number>>) => {
|
30
|
+
const operands: Array<Expression<number>> = initialOperands.flatMap((it) => {
|
31
|
+
if (isType(it, MultiplyExpression)) {
|
32
|
+
return it.operands
|
33
|
+
} else {
|
34
|
+
return [it]
|
35
|
+
}
|
36
|
+
})
|
37
|
+
|
38
|
+
return { operands }
|
39
|
+
},
|
40
|
+
resolver: ({ operands }, evaluate) => {
|
41
|
+
const values = operands.map((it) => evaluate(it))
|
42
|
+
return values.reduce((x, y) => x * y, 1)
|
43
|
+
},
|
44
|
+
})
|
45
|
+
|
46
|
+
export const multiply = MultiplyExpression.builder
|
47
|
+
|
48
|
+
export const LessThanExpression = defineExpression({
|
49
|
+
expressionKey: 'Numeric.LessThan',
|
50
|
+
builder: (left: Expression<number>, right: Expression<number>) => {
|
51
|
+
return { left, right }
|
52
|
+
},
|
53
|
+
resolver: ({ left, right }, evaluate) => {
|
54
|
+
return evaluate(left) < evaluate(right)
|
55
|
+
},
|
56
|
+
})
|
57
|
+
|
58
|
+
export const lessThan = LessThanExpression.builder
|
59
|
+
|
60
|
+
export const GreaterThanExpression = defineExpression({
|
61
|
+
expressionKey: 'Numeric.GreaterThan',
|
62
|
+
builder: (left: Expression<number>, right: Expression<number>) => {
|
63
|
+
return { left, right }
|
64
|
+
},
|
65
|
+
resolver: ({ left, right }, evaluate) => {
|
66
|
+
return evaluate(left) > evaluate(right)
|
67
|
+
},
|
68
|
+
})
|
69
|
+
|
70
|
+
export const greaterThan = GreaterThanExpression.builder
|
71
|
+
|
72
|
+
export const BoundsExpression = defineExpression({
|
73
|
+
expressionKey: 'Numeric.Bounds',
|
74
|
+
builder: (value: Expression<number>, minimumThreshold: Expression<number> | null, maximumThreshold: Expression<number> | null) => {
|
75
|
+
return { value, minimumThreshold, maximumThreshold }
|
76
|
+
},
|
77
|
+
resolver: (expression, evaluate) => {
|
78
|
+
let value = evaluate(expression.value)
|
79
|
+
const minimumThreshold = Objects.isPresent(expression.minimumThreshold) ? evaluate(expression.minimumThreshold) : null
|
80
|
+
const maximumThreshold = Objects.isPresent(expression.maximumThreshold) ? evaluate(expression.maximumThreshold) : null
|
81
|
+
if (Objects.isPresent(minimumThreshold) && value < minimumThreshold) {
|
82
|
+
value = minimumThreshold
|
83
|
+
}
|
84
|
+
if (Objects.isPresent(maximumThreshold) && value > maximumThreshold) {
|
85
|
+
value = maximumThreshold
|
86
|
+
}
|
87
|
+
|
88
|
+
return value
|
89
|
+
},
|
90
|
+
})
|
91
|
+
|
92
|
+
export const bounds = BoundsExpression.builder
|
93
|
+
|
94
|
+
export const FloorExpression = defineExpression({
|
95
|
+
expressionKey: 'Numeric.Floor',
|
96
|
+
builder: (value: Expression<number>, minimumThreshold: Expression<number> | null) => {
|
97
|
+
return { value, minimumThreshold }
|
98
|
+
},
|
99
|
+
resolver: (expression, evaluate) => {
|
100
|
+
let value = evaluate(expression.value)
|
101
|
+
const minimumThreshold = Objects.isPresent(expression.minimumThreshold) ? evaluate(expression.minimumThreshold) : null
|
102
|
+
if (Objects.isPresent(minimumThreshold) && value < minimumThreshold) {
|
103
|
+
value = minimumThreshold
|
104
|
+
}
|
105
|
+
|
106
|
+
return value
|
107
|
+
},
|
108
|
+
})
|
109
|
+
|
110
|
+
export const floor = FloorExpression.builder
|
111
|
+
|
112
|
+
export const CeilingExpression = defineExpression({
|
113
|
+
expressionKey: 'Numeric.Ceiling',
|
114
|
+
builder: (value: Expression<number>, maximumThreshold: Expression<number> | null) => {
|
115
|
+
return { value, maximumThreshold }
|
116
|
+
},
|
117
|
+
resolver: (expression, evaluate) => {
|
118
|
+
let value = evaluate(expression.value)
|
119
|
+
const maximumThreshold = Objects.isPresent(expression.maximumThreshold) ? evaluate(expression.maximumThreshold) : null
|
120
|
+
if (Objects.isPresent(maximumThreshold) && value > maximumThreshold) {
|
121
|
+
value = maximumThreshold
|
122
|
+
}
|
123
|
+
|
124
|
+
return value
|
125
|
+
},
|
126
|
+
})
|
127
|
+
|
128
|
+
export const ceiling = CeilingExpression.builder
|
129
|
+
|
130
|
+
export const RoundExpression = defineExpression({
|
131
|
+
expressionKey: 'Numeric.Round',
|
132
|
+
builder: (value: Expression<number>, scale: number, roundingMode: RoundingMode) => {
|
133
|
+
return { value, scale, roundingMode }
|
134
|
+
},
|
135
|
+
resolver: ({ value, scale, roundingMode }, evaluate) => {
|
136
|
+
return Maths.round(evaluate(value), scale, roundingMode)
|
137
|
+
},
|
138
|
+
})
|
139
|
+
|
140
|
+
export const round = RoundExpression.builder
|
141
|
+
|
142
|
+
export const MinExpression = defineExpression({
|
143
|
+
expressionKey: 'Numeric.Min',
|
144
|
+
builder: (initialOperands: Array<Expression<number>>) => {
|
145
|
+
const operands: Array<Expression<number>> = initialOperands.flatMap((it) => {
|
146
|
+
if (isType(it, MinExpression)) {
|
147
|
+
return it.operands
|
148
|
+
} else {
|
149
|
+
return [it]
|
150
|
+
}
|
151
|
+
})
|
152
|
+
|
153
|
+
return { operands }
|
154
|
+
},
|
155
|
+
resolver: ({ operands }, evaluate) => {
|
156
|
+
const values = operands.map((it) => evaluate(it))
|
157
|
+
return Math.min(...values)
|
158
|
+
},
|
159
|
+
})
|
160
|
+
|
161
|
+
export const min = MinExpression.builder
|
162
|
+
|
163
|
+
export const MaxExpression = defineExpression({
|
164
|
+
expressionKey: 'Numeric.Max',
|
165
|
+
builder: (initialOperands: Array<Expression<number>>) => {
|
166
|
+
const operands: Array<Expression<number>> = initialOperands.flatMap((it) => {
|
167
|
+
if (isType(it, MaxExpression)) {
|
168
|
+
return it.operands
|
169
|
+
} else {
|
170
|
+
return [it]
|
171
|
+
}
|
172
|
+
})
|
173
|
+
|
174
|
+
return { operands }
|
175
|
+
},
|
176
|
+
resolver: ({ operands }, evaluate) => {
|
177
|
+
const values = operands.map((it) => evaluate(it))
|
178
|
+
return Math.max(...values)
|
179
|
+
},
|
180
|
+
})
|
181
|
+
|
182
|
+
export const max = MaxExpression.builder
|
@@ -0,0 +1,38 @@
|
|
1
|
+
import { defineExpression } from '@bessemer/cornerstone/expression/internal'
|
2
|
+
import { Expression } from '@bessemer/cornerstone/expression'
|
3
|
+
|
4
|
+
export const ConcatenateExpression = defineExpression({
|
5
|
+
expressionKey: 'Concatenate',
|
6
|
+
builder: (first: Expression<string>, second: Expression<string>) => {
|
7
|
+
return { first, second }
|
8
|
+
},
|
9
|
+
resolver: (): string => {
|
10
|
+
throw new Error('Not yet implemented')
|
11
|
+
},
|
12
|
+
})
|
13
|
+
|
14
|
+
export const concatenate = ConcatenateExpression.builder
|
15
|
+
|
16
|
+
export const UppercaseExpression = defineExpression({
|
17
|
+
expressionKey: 'Uppercase',
|
18
|
+
builder: (value: Expression<string>) => {
|
19
|
+
return { value }
|
20
|
+
},
|
21
|
+
resolver: (): string => {
|
22
|
+
throw new Error('Not yet implemented')
|
23
|
+
},
|
24
|
+
})
|
25
|
+
|
26
|
+
export const uppercase = UppercaseExpression.builder
|
27
|
+
|
28
|
+
export const SubstringExpression = defineExpression({
|
29
|
+
expressionKey: 'Substring',
|
30
|
+
builder: (string: Expression<string>, substring: Expression<string>) => {
|
31
|
+
return { string, substring }
|
32
|
+
},
|
33
|
+
resolver: (): boolean => {
|
34
|
+
throw new Error('Not yet implemented')
|
35
|
+
},
|
36
|
+
})
|
37
|
+
|
38
|
+
export const substring = SubstringExpression.builder
|
@@ -0,0 +1,48 @@
|
|
1
|
+
import * as NumericExpressions from '@bessemer/cornerstone/expression/numeric-expression'
|
2
|
+
import * as StringExpressions from '@bessemer/cornerstone/expression/string-expression'
|
3
|
+
import * as ArrayExpressions from '@bessemer/cornerstone/expression/array-expression'
|
4
|
+
import * as Expressions from '@bessemer/cornerstone/expression/expression'
|
5
|
+
import { NominalType } from '@bessemer/cornerstone/types'
|
6
|
+
import { Signable } from '@bessemer/cornerstone/signature'
|
7
|
+
import { UnknownRecord } from 'type-fest'
|
8
|
+
|
9
|
+
export { Expressions, NumericExpressions, StringExpressions, ArrayExpressions }
|
10
|
+
|
11
|
+
export type ExpressionKey<ReturnType, ArgumentType extends Array<unknown>> = NominalType<string, ['ExpressionKey', ReturnType, ArgumentType]>
|
12
|
+
|
13
|
+
export type Expression<ReturnType> = ReturnType | IExpression<ReturnType>
|
14
|
+
|
15
|
+
export interface IExpression<ReturnType> {
|
16
|
+
expressionKey: ExpressionKey<ReturnType, Array<unknown>>
|
17
|
+
}
|
18
|
+
|
19
|
+
export interface ExpressionReference<ReturnType, ArgumentType extends Array<unknown>> {
|
20
|
+
expressionKey: ExpressionKey<ReturnType, ArgumentType>
|
21
|
+
}
|
22
|
+
|
23
|
+
export interface ReducingExpression<ReturnType, ArgumentType> extends ExpressionReference<ReturnType, [Array<Expression<ArgumentType>>]> {}
|
24
|
+
|
25
|
+
export type EvaluateExpression = <T>(expression: Expression<T>) => T
|
26
|
+
|
27
|
+
export type ExpressionDefinition<
|
28
|
+
ReturnType,
|
29
|
+
ArgumentType extends Array<unknown>,
|
30
|
+
ExpressionType extends Expression<ReturnType>
|
31
|
+
> = ExpressionReference<ReturnType, ArgumentType> & {
|
32
|
+
expressionKey: ExpressionKey<ReturnType, ArgumentType>
|
33
|
+
builder: (...parameters: ArgumentType) => ExpressionType
|
34
|
+
resolver: (expression: ExpressionType, evaluate: EvaluateExpression, context: ExpressionContext) => ReturnType
|
35
|
+
}
|
36
|
+
|
37
|
+
export interface ExpressionVariable<T> extends IExpression<T> {
|
38
|
+
expressionKey: 'Variable'
|
39
|
+
name: string
|
40
|
+
}
|
41
|
+
|
42
|
+
export interface ParameterizedVariable<ValueType, ParameterType extends Array<Signable>> {
|
43
|
+
apply(...parameters: ParameterType): ExpressionVariable<ValueType>
|
44
|
+
}
|
45
|
+
|
46
|
+
export type ExpressionContext = {
|
47
|
+
variables: UnknownRecord
|
48
|
+
}
|
package/src/function.ts
ADDED
package/src/glob.ts
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
import { minimatch } from 'minimatch'
|
2
|
+
import { NominalType } from '@bessemer/cornerstone/types'
|
3
|
+
import { Zod } from '@bessemer/cornerstone'
|
4
|
+
import { ZodType } from 'zod'
|
5
|
+
|
6
|
+
export type GlobPattern = NominalType<string, 'GlobPattern'>
|
7
|
+
export const GlobPatternSchema: ZodType<GlobPattern> = Zod.string()
|
8
|
+
|
9
|
+
export const schema = (): ZodType<GlobPattern> => {
|
10
|
+
return Zod.string()
|
11
|
+
}
|
12
|
+
|
13
|
+
export const match = (str: string, pattern: GlobPattern): boolean => {
|
14
|
+
return minimatch(str, pattern)
|
15
|
+
}
|
16
|
+
|
17
|
+
export const anyMatch = (str: string, patterns: Array<GlobPattern>): boolean => {
|
18
|
+
return patterns.some((it) => match(str, it))
|
19
|
+
}
|
@@ -0,0 +1,40 @@
|
|
1
|
+
import { evaluate, LazyValue } from '@bessemer/cornerstone/lazy'
|
2
|
+
import { isUndefined } from '@bessemer/cornerstone/object'
|
3
|
+
import { UnknownRecord } from 'type-fest'
|
4
|
+
|
5
|
+
export type GlobalVariable<T> = {
|
6
|
+
getValue: () => T
|
7
|
+
setValue: (value: T) => void
|
8
|
+
}
|
9
|
+
|
10
|
+
let Global: { BessemerGlobalVariables: UnknownRecord }
|
11
|
+
if (typeof window !== 'undefined') {
|
12
|
+
Global = window as any
|
13
|
+
} else if (typeof global !== 'undefined') {
|
14
|
+
Global = global as any
|
15
|
+
} else {
|
16
|
+
Global = globalThis as any
|
17
|
+
}
|
18
|
+
|
19
|
+
if (isUndefined(Global.BessemerGlobalVariables)) {
|
20
|
+
Global.BessemerGlobalVariables = {}
|
21
|
+
}
|
22
|
+
|
23
|
+
export const createGlobalVariable = <T>(key: string, defaultValue: LazyValue<T>): GlobalVariable<T> => {
|
24
|
+
return {
|
25
|
+
getValue: () => {
|
26
|
+
const value = Global.BessemerGlobalVariables[key] as T | undefined
|
27
|
+
|
28
|
+
if (isUndefined(value)) {
|
29
|
+
const def = evaluate(defaultValue)
|
30
|
+
Global.BessemerGlobalVariables[key] = def
|
31
|
+
return def
|
32
|
+
}
|
33
|
+
|
34
|
+
return value
|
35
|
+
},
|
36
|
+
setValue: (value: T) => {
|
37
|
+
Global.BessemerGlobalVariables[key] = value
|
38
|
+
},
|
39
|
+
}
|
40
|
+
}
|
package/src/hash.ts
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
import { TaggedType } from '@bessemer/cornerstone/types'
|
2
|
+
|
3
|
+
export type Hash = TaggedType<string, 'Hash'>
|
4
|
+
|
5
|
+
export enum HashAlgorithm {
|
6
|
+
SHA1 = 'SHA-1',
|
7
|
+
SHA256 = 'SHA-256',
|
8
|
+
}
|
9
|
+
|
10
|
+
export const asString = (value: Hash): string => {
|
11
|
+
return value
|
12
|
+
}
|
13
|
+
|
14
|
+
export const insecureHash = async (message: string): Promise<Hash> => {
|
15
|
+
return hash(message, HashAlgorithm.SHA1)
|
16
|
+
}
|
17
|
+
|
18
|
+
export const secureHash = async (message: string): Promise<Hash> => {
|
19
|
+
return hash(message, HashAlgorithm.SHA256)
|
20
|
+
}
|
21
|
+
|
22
|
+
export const hash = async (message: string, algorithm: HashAlgorithm): Promise<Hash> => {
|
23
|
+
const msgBuffer = new TextEncoder().encode(message)
|
24
|
+
const hashBuffer = await crypto.subtle.digest(algorithm, msgBuffer)
|
25
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer))
|
26
|
+
const hashHex = hashArray.map((b) => b.toString(16).padStart(2, '0')).join('')
|
27
|
+
return hashHex as Hash
|
28
|
+
}
|
package/src/hex-code.ts
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
import { NominalType } from '@bessemer/cornerstone/types'
|
2
|
+
import { Zod } from '@bessemer/cornerstone/index'
|
3
|
+
import { ZodType } from 'zod'
|
4
|
+
|
5
|
+
export type HexCode = NominalType<string, 'HexCode'>
|
6
|
+
export const HexCodeSchema: ZodType<HexCode> = Zod.string().length(7).startsWith('#').describe('A 6-digit hex code starting a # sign')
|
package/src/index.ts
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
import * as Objects from '@bessemer/cornerstone/object'
|
2
|
+
import * as Functions from '@bessemer/cornerstone/function'
|
3
|
+
import * as Arrays from '@bessemer/cornerstone/array'
|
4
|
+
import * as Strings from '@bessemer/cornerstone/string'
|
5
|
+
import * as Async from '@bessemer/cornerstone/async'
|
6
|
+
import * as Maths from '@bessemer/cornerstone/math'
|
7
|
+
import * as Sets from '@bessemer/cornerstone/set'
|
8
|
+
import * as Dates from '@bessemer/cornerstone/date'
|
9
|
+
import * as Comparators from '@bessemer/cornerstone/comparator'
|
10
|
+
import * as Equalitors from '@bessemer/cornerstone/equalitor'
|
11
|
+
import * as Durations from '@bessemer/cornerstone/duration'
|
12
|
+
import * as Uris from '@bessemer/cornerstone/uri'
|
13
|
+
import * as Urls from '@bessemer/cornerstone/url'
|
14
|
+
import * as Loggers from '@bessemer/cornerstone/logger'
|
15
|
+
import * as Errors from '@bessemer/cornerstone/error'
|
16
|
+
import * as ErrorEvents from '@bessemer/cornerstone/error-event'
|
17
|
+
import * as Preconditions from '@bessemer/cornerstone/precondition'
|
18
|
+
import * as Uuids from '@bessemer/cornerstone/uuid'
|
19
|
+
import * as Ulids from '@bessemer/cornerstone/ulid'
|
20
|
+
import * as Entries from '@bessemer/cornerstone/entry'
|
21
|
+
import * as Hashes from '@bessemer/cornerstone/hash'
|
22
|
+
import * as Crypto from '@bessemer/cornerstone/crypto'
|
23
|
+
import * as Globs from '@bessemer/cornerstone/glob'
|
24
|
+
|
25
|
+
import * as Zod from '@bessemer/cornerstone/zod'
|
26
|
+
import * as Tags from '@bessemer/cornerstone/tag'
|
27
|
+
import * as Promises from '@bessemer/cornerstone/promise'
|
28
|
+
import * as References from '@bessemer/cornerstone/reference'
|
29
|
+
import * as Signatures from '@bessemer/cornerstone/signature'
|
30
|
+
import * as Eithers from '@bessemer/cornerstone/either'
|
31
|
+
import * as Results from '@bessemer/cornerstone/result'
|
32
|
+
import * as Lazy from '@bessemer/cornerstone/lazy'
|
33
|
+
import * as Patches from '@bessemer/cornerstone/patch'
|
34
|
+
import * as Content from '@bessemer/cornerstone/content'
|
35
|
+
import * as Combinables from '@bessemer/cornerstone/combinable'
|
36
|
+
import * as Properties from '@bessemer/cornerstone/property'
|
37
|
+
import * as RichTexts from '@bessemer/cornerstone/rich-text'
|
38
|
+
import * as Retry from '@bessemer/cornerstone/retry'
|
39
|
+
import * as Stores from '@bessemer/cornerstone/store'
|
40
|
+
import * as Misc from '@bessemer/cornerstone/misc'
|
41
|
+
|
42
|
+
export {
|
43
|
+
Objects,
|
44
|
+
Functions,
|
45
|
+
Arrays,
|
46
|
+
Strings,
|
47
|
+
Async,
|
48
|
+
Maths,
|
49
|
+
Sets,
|
50
|
+
Dates,
|
51
|
+
Comparators,
|
52
|
+
Equalitors,
|
53
|
+
Durations,
|
54
|
+
Uris,
|
55
|
+
Urls,
|
56
|
+
Loggers,
|
57
|
+
Errors,
|
58
|
+
ErrorEvents,
|
59
|
+
Preconditions,
|
60
|
+
Uuids,
|
61
|
+
Ulids,
|
62
|
+
Entries,
|
63
|
+
Hashes,
|
64
|
+
Crypto,
|
65
|
+
Globs,
|
66
|
+
Zod,
|
67
|
+
Tags,
|
68
|
+
Promises,
|
69
|
+
References,
|
70
|
+
Signatures,
|
71
|
+
Eithers,
|
72
|
+
Results,
|
73
|
+
Lazy,
|
74
|
+
Patches,
|
75
|
+
Content,
|
76
|
+
Combinables,
|
77
|
+
Properties,
|
78
|
+
RichTexts,
|
79
|
+
Retry,
|
80
|
+
Stores,
|
81
|
+
Misc,
|
82
|
+
}
|
package/src/lazy.ts
ADDED