@elaraai/east-node-std 0.0.1-beta.9 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLA.md +1 -1
- package/CONTRIBUTING.md +3 -3
- package/LICENSE.md +31 -0
- package/README.md +55 -19
- package/dist/src/console.d.ts.map +1 -0
- package/dist/{console.js → src/console.js} +3 -3
- package/dist/src/console.js.map +1 -0
- package/dist/src/crypto.d.ts.map +1 -0
- package/dist/{crypto.js → src/crypto.js} +4 -4
- package/dist/src/crypto.js.map +1 -0
- package/dist/{fetch.d.ts → src/fetch.d.ts} +129 -79
- package/dist/src/fetch.d.ts.map +1 -0
- package/dist/{fetch.js → src/fetch.js} +76 -6
- package/dist/src/fetch.js.map +1 -0
- package/dist/src/fs.d.ts.map +1 -0
- package/dist/{fs.js → src/fs.js} +8 -8
- package/dist/src/fs.js.map +1 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/path.d.ts.map +1 -0
- package/dist/{path.js → src/path.js} +5 -5
- package/dist/src/path.js.map +1 -0
- package/dist/src/platform.d.ts.map +1 -0
- package/dist/src/platform.js.map +1 -0
- package/dist/src/random/crypto-rng.d.ts.map +1 -0
- package/dist/src/random/crypto-rng.js.map +1 -0
- package/dist/src/random/distributions/bates.d.ts.map +1 -0
- package/dist/src/random/distributions/bates.js.map +1 -0
- package/dist/src/random/distributions/bernoulli.d.ts.map +1 -0
- package/dist/src/random/distributions/bernoulli.js.map +1 -0
- package/dist/src/random/distributions/binomial.d.ts.map +1 -0
- package/dist/src/random/distributions/binomial.js.map +1 -0
- package/dist/src/random/distributions/exponential.d.ts.map +1 -0
- package/dist/src/random/distributions/exponential.js.map +1 -0
- package/dist/src/random/distributions/geometric.d.ts.map +1 -0
- package/dist/src/random/distributions/geometric.js.map +1 -0
- package/dist/src/random/distributions/irwin-hall.d.ts.map +1 -0
- package/dist/src/random/distributions/irwin-hall.js.map +1 -0
- package/dist/src/random/distributions/log-normal.d.ts.map +1 -0
- package/dist/src/random/distributions/log-normal.js.map +1 -0
- package/dist/src/random/distributions/normal.d.ts.map +1 -0
- package/dist/src/random/distributions/normal.js.map +1 -0
- package/dist/src/random/distributions/pareto.d.ts.map +1 -0
- package/dist/src/random/distributions/pareto.js.map +1 -0
- package/dist/src/random/distributions/poisson.d.ts.map +1 -0
- package/dist/src/random/distributions/poisson.js.map +1 -0
- package/dist/src/random/distributions/uniform-int.d.ts.map +1 -0
- package/dist/src/random/distributions/uniform-int.js.map +1 -0
- package/dist/src/random/distributions/uniform.d.ts.map +1 -0
- package/dist/src/random/distributions/uniform.js.map +1 -0
- package/dist/src/random/rng.d.ts.map +1 -0
- package/dist/src/random/rng.js.map +1 -0
- package/dist/src/random/xorshift128.d.ts.map +1 -0
- package/dist/src/random/xorshift128.js.map +1 -0
- package/dist/{random.d.ts → src/random.d.ts} +2 -1
- package/dist/src/random.d.ts.map +1 -0
- package/dist/{random.js → src/random.js} +13 -13
- package/dist/src/random.js.map +1 -0
- package/dist/{test.d.ts → src/test.d.ts} +8 -1
- package/dist/src/test.d.ts.map +1 -0
- package/dist/src/test.js +364 -0
- package/dist/src/test.js.map +1 -0
- package/dist/{time.d.ts → src/time.d.ts} +50 -2
- package/dist/src/time.d.ts.map +1 -0
- package/dist/{time.js → src/time.js} +100 -4
- package/dist/src/time.js.map +1 -0
- package/package.json +24 -47
- package/dist/console.d.ts.map +0 -1
- package/dist/console.js.map +0 -1
- package/dist/crypto.d.ts.map +0 -1
- package/dist/crypto.js.map +0 -1
- package/dist/fetch.d.ts.map +0 -1
- package/dist/fetch.js.map +0 -1
- package/dist/fs.d.ts.map +0 -1
- package/dist/fs.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/path.d.ts.map +0 -1
- package/dist/path.js.map +0 -1
- package/dist/platform.d.ts.map +0 -1
- package/dist/platform.js.map +0 -1
- package/dist/random/crypto-rng.d.ts.map +0 -1
- package/dist/random/crypto-rng.js.map +0 -1
- package/dist/random/distributions/bates.d.ts.map +0 -1
- package/dist/random/distributions/bates.js.map +0 -1
- package/dist/random/distributions/bernoulli.d.ts.map +0 -1
- package/dist/random/distributions/bernoulli.js.map +0 -1
- package/dist/random/distributions/binomial.d.ts.map +0 -1
- package/dist/random/distributions/binomial.js.map +0 -1
- package/dist/random/distributions/exponential.d.ts.map +0 -1
- package/dist/random/distributions/exponential.js.map +0 -1
- package/dist/random/distributions/geometric.d.ts.map +0 -1
- package/dist/random/distributions/geometric.js.map +0 -1
- package/dist/random/distributions/irwin-hall.d.ts.map +0 -1
- package/dist/random/distributions/irwin-hall.js.map +0 -1
- package/dist/random/distributions/log-normal.d.ts.map +0 -1
- package/dist/random/distributions/log-normal.js.map +0 -1
- package/dist/random/distributions/normal.d.ts.map +0 -1
- package/dist/random/distributions/normal.js.map +0 -1
- package/dist/random/distributions/pareto.d.ts.map +0 -1
- package/dist/random/distributions/pareto.js.map +0 -1
- package/dist/random/distributions/poisson.d.ts.map +0 -1
- package/dist/random/distributions/poisson.js.map +0 -1
- package/dist/random/distributions/uniform-int.d.ts.map +0 -1
- package/dist/random/distributions/uniform-int.js.map +0 -1
- package/dist/random/distributions/uniform.d.ts.map +0 -1
- package/dist/random/distributions/uniform.js.map +0 -1
- package/dist/random/rng.d.ts.map +0 -1
- package/dist/random/rng.js.map +0 -1
- package/dist/random/xorshift128.d.ts.map +0 -1
- package/dist/random/xorshift128.js.map +0 -1
- package/dist/random.d.ts.map +0 -1
- package/dist/random.js.map +0 -1
- package/dist/test.d.ts.map +0 -1
- package/dist/test.js +0 -828
- package/dist/test.js.map +0 -1
- package/dist/time.d.ts.map +0 -1
- package/dist/time.js.map +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1
- /package/dist/{console.d.ts → src/console.d.ts} +0 -0
- /package/dist/{crypto.d.ts → src/crypto.d.ts} +0 -0
- /package/dist/{fs.d.ts → src/fs.d.ts} +0 -0
- /package/dist/{index.d.ts → src/index.d.ts} +0 -0
- /package/dist/{index.js → src/index.js} +0 -0
- /package/dist/{path.d.ts → src/path.d.ts} +0 -0
- /package/dist/{platform.d.ts → src/platform.d.ts} +0 -0
- /package/dist/{platform.js → src/platform.js} +0 -0
- /package/dist/{random → src/random}/crypto-rng.d.ts +0 -0
- /package/dist/{random → src/random}/crypto-rng.js +0 -0
- /package/dist/{random → src/random}/distributions/bates.d.ts +0 -0
- /package/dist/{random → src/random}/distributions/bates.js +0 -0
- /package/dist/{random → src/random}/distributions/bernoulli.d.ts +0 -0
- /package/dist/{random → src/random}/distributions/bernoulli.js +0 -0
- /package/dist/{random → src/random}/distributions/binomial.d.ts +0 -0
- /package/dist/{random → src/random}/distributions/binomial.js +0 -0
- /package/dist/{random → src/random}/distributions/exponential.d.ts +0 -0
- /package/dist/{random → src/random}/distributions/exponential.js +0 -0
- /package/dist/{random → src/random}/distributions/geometric.d.ts +0 -0
- /package/dist/{random → src/random}/distributions/geometric.js +0 -0
- /package/dist/{random → src/random}/distributions/irwin-hall.d.ts +0 -0
- /package/dist/{random → src/random}/distributions/irwin-hall.js +0 -0
- /package/dist/{random → src/random}/distributions/log-normal.d.ts +0 -0
- /package/dist/{random → src/random}/distributions/log-normal.js +0 -0
- /package/dist/{random → src/random}/distributions/normal.d.ts +0 -0
- /package/dist/{random → src/random}/distributions/normal.js +0 -0
- /package/dist/{random → src/random}/distributions/pareto.d.ts +0 -0
- /package/dist/{random → src/random}/distributions/pareto.js +0 -0
- /package/dist/{random → src/random}/distributions/poisson.d.ts +0 -0
- /package/dist/{random → src/random}/distributions/poisson.js +0 -0
- /package/dist/{random → src/random}/distributions/uniform-int.d.ts +0 -0
- /package/dist/{random → src/random}/distributions/uniform-int.js +0 -0
- /package/dist/{random → src/random}/distributions/uniform.d.ts +0 -0
- /package/dist/{random → src/random}/distributions/uniform.js +0 -0
- /package/dist/{random → src/random}/rng.d.ts +0 -0
- /package/dist/{random → src/random}/rng.js +0 -0
- /package/dist/{random → src/random}/xorshift128.d.ts +0 -0
- /package/dist/{random → src/random}/xorshift128.js +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Expr, NullType, StringType, type SubtypeExprOrValue } from "@elaraai/east";
|
|
1
|
+
import { Expr, NullType, StringType, type SubtypeExprOrValue, type ExampleDef } from "@elaraai/east";
|
|
2
2
|
import type { BlockBuilder, PlatformFunction, TypeSymbol } from "@elaraai/east/internal";
|
|
3
3
|
/**
|
|
4
4
|
* Creates a test platform that uses Node.js assertions.
|
|
@@ -169,5 +169,12 @@ export declare const Assert: {
|
|
|
169
169
|
* @returns An East expression that unconditionally fails the test
|
|
170
170
|
*/
|
|
171
171
|
fail(message: SubtypeExprOrValue<StringType>): import("@elaraai/east").NullExpr;
|
|
172
|
+
/**
|
|
173
|
+
* Runs all examples as tests, calling each with its inputs and asserting the result equals returns.
|
|
174
|
+
*
|
|
175
|
+
* @param test - The test function from describeEast's builder
|
|
176
|
+
* @param examples - A record of named ExampleDef exports (e.g. `import * as examples from "./array.examples.js"`)
|
|
177
|
+
*/
|
|
178
|
+
examples(test: (name: string, body: ($: BlockBuilder<NullType>) => void) => void, examples: Record<string, ExampleDef>): void;
|
|
172
179
|
};
|
|
173
180
|
//# sourceMappingURL=test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../src/test.ts"],"names":[],"mappings":"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"}
|
package/dist/src/test.js
ADDED
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
import assert from "node:assert/strict";
|
|
6
|
+
import util from "node:util";
|
|
7
|
+
import { test as testNode, describe as describeNode } from "node:test";
|
|
8
|
+
import { writeFileSync, mkdirSync } from "node:fs";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
import { AsyncFunctionType, East, Expr, get_location, IRType, NullType, printLocations, StringType, toJSONFor, ArrayType, IntegerType, StructType } from "@elaraai/east";
|
|
11
|
+
const { str } = East;
|
|
12
|
+
// Force node test to show full stack traces for easier debugging
|
|
13
|
+
Error.stackTraceLimit = Infinity;
|
|
14
|
+
// Force node to print full objects in console.log output
|
|
15
|
+
util.inspect.defaultOptions.depth = null;
|
|
16
|
+
/**
|
|
17
|
+
* Platform function that indicates a test assertion passed.
|
|
18
|
+
*
|
|
19
|
+
* This is used by East test code to signal successful assertions.
|
|
20
|
+
* When running in Node.js, this does nothing. Other platforms may log or track passes.
|
|
21
|
+
*/
|
|
22
|
+
const testPass = East.platform("testPass", [], NullType);
|
|
23
|
+
/**
|
|
24
|
+
* Platform function that indicates a test assertion failed.
|
|
25
|
+
*
|
|
26
|
+
* This is used by East test code to signal failed assertions.
|
|
27
|
+
* When running in Node.js, this throws an assertion error.
|
|
28
|
+
*
|
|
29
|
+
* @param message - The error message describing the assertion failure
|
|
30
|
+
*/
|
|
31
|
+
const testFail = East.platform("testFail", [StringType], NullType);
|
|
32
|
+
/**
|
|
33
|
+
* Platform function that defines a single test case.
|
|
34
|
+
*
|
|
35
|
+
* This is used by East test code to define individual tests.
|
|
36
|
+
* When running in Node.js, this runs the test using Node's test runner.
|
|
37
|
+
*
|
|
38
|
+
* @param name - The name of the test
|
|
39
|
+
* @param body - The test body function
|
|
40
|
+
*/
|
|
41
|
+
const test = East.asyncPlatform("test", [StringType, AsyncFunctionType([], NullType)], NullType);
|
|
42
|
+
/**
|
|
43
|
+
* Platform function that defines a test suite.
|
|
44
|
+
*
|
|
45
|
+
* This is used by East test code to group related tests.
|
|
46
|
+
* When running in Node.js, this runs the suite using Node's describe.
|
|
47
|
+
*
|
|
48
|
+
* @param name - The name of the test suite
|
|
49
|
+
* @param body - A function that calls test() to define tests
|
|
50
|
+
*/
|
|
51
|
+
const describe = East.asyncPlatform("describe", [StringType, AsyncFunctionType([], NullType)], NullType);
|
|
52
|
+
/**
|
|
53
|
+
* Creates a test platform that uses Node.js assertions.
|
|
54
|
+
*
|
|
55
|
+
* @returns A platform object with `testPass`, `testFail`, `test`, and `describe` functions
|
|
56
|
+
*/
|
|
57
|
+
export const TestImpl = [
|
|
58
|
+
testPass.implement(() => { }), // Assertion passed - do nothing (test continues)
|
|
59
|
+
testFail.implement((message) => {
|
|
60
|
+
// Assertion failed - throw to fail the test
|
|
61
|
+
assert.fail(message);
|
|
62
|
+
}),
|
|
63
|
+
test.implement((name, body) => testNode(name, async () => { await body(); })),
|
|
64
|
+
describe.implement((name, body) => describeNode(name, async () => { await body(); })),
|
|
65
|
+
];
|
|
66
|
+
/* Type-directed JSON serialization for the test IR export format:
|
|
67
|
+
* StructType({ ir: IRType, source_map: StructType({ stacks: Array(Array(Struct({column,filename,line}))) }) })
|
|
68
|
+
* Note: struct fields are sorted alphabetically in East's structural type system. */
|
|
69
|
+
const LocationType = StructType({ column: IntegerType, filename: StringType, line: IntegerType });
|
|
70
|
+
const SourceMapType = StructType({ stacks: ArrayType(ArrayType(LocationType)) });
|
|
71
|
+
const ExportWrapperType = StructType({ ir: IRType, source_map: SourceMapType });
|
|
72
|
+
const exportToJSON = toJSONFor(ExportWrapperType);
|
|
73
|
+
/**
|
|
74
|
+
* Defines and runs an East test suite using platform functions.
|
|
75
|
+
*
|
|
76
|
+
* This creates a single East function that calls `describe` and `test` platform functions.
|
|
77
|
+
* The entire suite can be exported as IR and run on any East implementation that provides
|
|
78
|
+
* the test platform (testPass, testFail, test, describe).
|
|
79
|
+
*
|
|
80
|
+
* When the `EXPORT_TEST_IR` environment variable is set to a directory path, the IR for
|
|
81
|
+
* each test suite is exported to `<path>/<suite_name>.json`.
|
|
82
|
+
*
|
|
83
|
+
* @param suiteName - The name of the test suite
|
|
84
|
+
* @param builder - A function that receives a `test` function for defining tests
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```ts
|
|
88
|
+
* describeEast("Array tests", (test) => {
|
|
89
|
+
* test("addition", $ => {
|
|
90
|
+
* $(assertEast.equal(East.value(1n).add(1n), 2n));
|
|
91
|
+
* });
|
|
92
|
+
* test("subtraction", $ => {
|
|
93
|
+
* $(assertEast.equal(East.value(2n).subtract(1n), 1n));
|
|
94
|
+
* });
|
|
95
|
+
* });
|
|
96
|
+
* ```
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```bash
|
|
100
|
+
* # Export test IR to a directory
|
|
101
|
+
* EXPORT_TEST_IR=./test-ir npm test
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
export function describeEast(suiteName, builder, options) {
|
|
105
|
+
const tests = [];
|
|
106
|
+
// Collect all test names and bodies
|
|
107
|
+
builder((name, body) => {
|
|
108
|
+
tests.push({ name, body });
|
|
109
|
+
});
|
|
110
|
+
// Create a single East function that uses describe/test platform functions
|
|
111
|
+
const suiteFunction = East.asyncFunction([], NullType, $ => {
|
|
112
|
+
$(describe.call($, suiteName, East.asyncFunction([], NullType, $ => {
|
|
113
|
+
// beforeAll hook
|
|
114
|
+
if (options?.beforeAll) {
|
|
115
|
+
options.beforeAll($);
|
|
116
|
+
}
|
|
117
|
+
for (const { name, body } of tests) {
|
|
118
|
+
$(test.call($, name, East.asyncFunction([], NullType, $test => {
|
|
119
|
+
// beforeEach hook (inside test body)
|
|
120
|
+
if (options?.beforeEach) {
|
|
121
|
+
options.beforeEach($test);
|
|
122
|
+
}
|
|
123
|
+
// Wrap test body in try-finally so afterEach runs even on failure
|
|
124
|
+
if (options?.afterEach) {
|
|
125
|
+
$test.try(body)
|
|
126
|
+
.catch(($catch, message) => {
|
|
127
|
+
// Re-throw the error after finally runs
|
|
128
|
+
$catch.error(message);
|
|
129
|
+
})
|
|
130
|
+
.finally(options.afterEach);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
body($test);
|
|
134
|
+
}
|
|
135
|
+
})));
|
|
136
|
+
}
|
|
137
|
+
// afterAll hook
|
|
138
|
+
if (options?.afterAll) {
|
|
139
|
+
options.afterAll($);
|
|
140
|
+
}
|
|
141
|
+
})));
|
|
142
|
+
});
|
|
143
|
+
// Auto-export test IR if EXPORT_TEST_IR environment variable is set to a path
|
|
144
|
+
if (process.env.EXPORT_TEST_IR) {
|
|
145
|
+
const outputDir = process.env.EXPORT_TEST_IR;
|
|
146
|
+
try {
|
|
147
|
+
mkdirSync(outputDir, { recursive: true });
|
|
148
|
+
const ir = suiteFunction.toIR();
|
|
149
|
+
const stacks = (ir.source_map?.entries() ?? [[]]).map(stack => stack.map(frame => ({ column: frame.column, filename: frame.filename, line: frame.line })));
|
|
150
|
+
const wrapperValue = { ir: ir.ir, source_map: { stacks } };
|
|
151
|
+
const wrapperJSON = exportToJSON(wrapperValue);
|
|
152
|
+
const filename = join(outputDir, `${suiteName.replace(/[^a-zA-Z0-9]/g, '_')}.json`);
|
|
153
|
+
writeFileSync(filename, JSON.stringify(wrapperJSON, null, 2));
|
|
154
|
+
console.log(`✓ Exported test IR: ${filename}`);
|
|
155
|
+
}
|
|
156
|
+
catch (err) {
|
|
157
|
+
console.error(`✗ Failed to export test IR for "${suiteName}":`, err);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (options?.exportOnly !== true) {
|
|
161
|
+
// Run the test suite using the Node.js platform implementation
|
|
162
|
+
const compiled = suiteFunction.toIR().compile([...(options?.platformFns ?? [])]);
|
|
163
|
+
return compiled();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* East assertion functions that match Node.js assert API naming.
|
|
168
|
+
*
|
|
169
|
+
* These functions generate East expressions that perform runtime assertions
|
|
170
|
+
* using platform functions, enabling testing of East code.
|
|
171
|
+
*/
|
|
172
|
+
export const Assert = {
|
|
173
|
+
/**
|
|
174
|
+
* Asserts that two values are the same reference (meaning if one is mutated, the other reflects the change - and they are always equal).
|
|
175
|
+
*
|
|
176
|
+
* @typeParam E - The type of the actual expression
|
|
177
|
+
* @param actual - The actual value to test
|
|
178
|
+
* @param expected - The expected value to compare against
|
|
179
|
+
* @returns An East expression that performs the equality check
|
|
180
|
+
*/
|
|
181
|
+
is(actual, expected) {
|
|
182
|
+
const location = get_location();
|
|
183
|
+
const expected_expr = Expr.from(expected, Expr.type(actual));
|
|
184
|
+
return Expr.tryCatch(Expr.block($ => {
|
|
185
|
+
const act = $.let(actual);
|
|
186
|
+
const exp = $.let(expected_expr);
|
|
187
|
+
return East.is(act, exp).ifElse(_$ => testPass(), _$ => testFail(str `Expected ${act} to be ${exp} (${printLocations(location)})`));
|
|
188
|
+
}), (_$, message, stack) => testFail(East.String.printError(message, stack)));
|
|
189
|
+
},
|
|
190
|
+
/**
|
|
191
|
+
* Asserts that two values are equal.
|
|
192
|
+
*
|
|
193
|
+
* @typeParam E - The type of the actual expression
|
|
194
|
+
* @param actual - The actual value to test
|
|
195
|
+
* @param expected - The expected value to compare against
|
|
196
|
+
* @returns An East expression that performs the equality check
|
|
197
|
+
*/
|
|
198
|
+
equal(actual, expected) {
|
|
199
|
+
const location = get_location();
|
|
200
|
+
const expected_expr = Expr.from(expected, Expr.type(actual));
|
|
201
|
+
return Expr.tryCatch(Expr.block($ => {
|
|
202
|
+
const act = $.let(actual);
|
|
203
|
+
const exp = $.let(expected_expr);
|
|
204
|
+
return East.equal(act, exp).ifElse(_$ => testPass(), _$ => testFail(str `Expected ${act} to equal ${exp} (${printLocations(location)})`));
|
|
205
|
+
}), (_$, message, stack) => testFail(East.String.printError(message, stack)));
|
|
206
|
+
},
|
|
207
|
+
/**
|
|
208
|
+
* Asserts that two values are not equal.
|
|
209
|
+
*
|
|
210
|
+
* @typeParam E - The type of the actual expression
|
|
211
|
+
* @param actual - The actual value to test
|
|
212
|
+
* @param expected - The value that should not be equal
|
|
213
|
+
* @returns An East expression that performs the inequality check
|
|
214
|
+
*/
|
|
215
|
+
notEqual(actual, expected) {
|
|
216
|
+
const location = get_location();
|
|
217
|
+
const expected_expr = Expr.from(expected, Expr.type(actual));
|
|
218
|
+
return Expr.tryCatch(Expr.block($ => {
|
|
219
|
+
const act = $.let(actual);
|
|
220
|
+
const exp = $.let(expected_expr);
|
|
221
|
+
return East.notEqual(act, exp).ifElse(_$ => testPass(), _$ => testFail(str `Expected ${act} to not equal ${exp} (${printLocations(location)})`));
|
|
222
|
+
}), (_$, message, stack) => testFail(East.String.printError(message, stack)));
|
|
223
|
+
},
|
|
224
|
+
/**
|
|
225
|
+
* Asserts that actual is less than expected.
|
|
226
|
+
*
|
|
227
|
+
* @typeParam E - The type of the actual expression
|
|
228
|
+
* @param actual - The actual value to test
|
|
229
|
+
* @param expected - The value that actual should be less than
|
|
230
|
+
* @returns An East expression that performs the less-than check
|
|
231
|
+
*/
|
|
232
|
+
less(actual, expected) {
|
|
233
|
+
const location = get_location();
|
|
234
|
+
const expected_expr = Expr.from(expected, Expr.type(actual));
|
|
235
|
+
return Expr.tryCatch(Expr.block($ => {
|
|
236
|
+
const act = $.let(actual);
|
|
237
|
+
const exp = $.let(expected_expr);
|
|
238
|
+
return East.less(act, exp).ifElse(_$ => testPass(), _$ => testFail(str `Expected ${act} to be less than ${exp} (${printLocations(location)})`));
|
|
239
|
+
}), (_$, message, stack) => testFail(East.String.printError(message, stack)));
|
|
240
|
+
},
|
|
241
|
+
/**
|
|
242
|
+
* Asserts that actual is less than or equal to expected.
|
|
243
|
+
*
|
|
244
|
+
* @typeParam E - The type of the actual expression
|
|
245
|
+
* @param actual - The actual value to test
|
|
246
|
+
* @param expected - The value that actual should be less than or equal to
|
|
247
|
+
* @returns An East expression that performs the less-than-or-equal check
|
|
248
|
+
*/
|
|
249
|
+
lessEqual(actual, expected) {
|
|
250
|
+
const location = get_location();
|
|
251
|
+
const expected_expr = Expr.from(expected, Expr.type(actual));
|
|
252
|
+
return Expr.tryCatch(Expr.block($ => {
|
|
253
|
+
const act = $.let(actual);
|
|
254
|
+
const exp = $.let(expected_expr);
|
|
255
|
+
return East.lessEqual(act, exp).ifElse(_$ => testPass(), _$ => testFail(str `Expected ${act} to be less than or equal to ${exp} (${printLocations(location)})`));
|
|
256
|
+
}), (_$, message, stack) => testFail(East.String.printError(message, stack)));
|
|
257
|
+
},
|
|
258
|
+
/**
|
|
259
|
+
* Asserts that actual is greater than expected.
|
|
260
|
+
*
|
|
261
|
+
* @typeParam E - The type of the actual expression
|
|
262
|
+
* @param actual - The actual value to test
|
|
263
|
+
* @param expected - The value that actual should be greater than
|
|
264
|
+
* @returns An East expression that performs the greater-than check
|
|
265
|
+
*/
|
|
266
|
+
greater(actual, expected) {
|
|
267
|
+
const location = get_location();
|
|
268
|
+
const expected_expr = Expr.from(expected, Expr.type(actual));
|
|
269
|
+
return Expr.tryCatch(Expr.block($ => {
|
|
270
|
+
const act = $.let(actual);
|
|
271
|
+
const exp = $.let(expected_expr);
|
|
272
|
+
return East.greater(act, exp).ifElse(_$ => testPass(), _$ => testFail(str `Expected ${act} to be greater than ${exp} (${printLocations(location)})`));
|
|
273
|
+
}), (_$, message, stack) => testFail(East.String.printError(message, stack)));
|
|
274
|
+
},
|
|
275
|
+
/**
|
|
276
|
+
* Asserts that actual is greater than or equal to expected.
|
|
277
|
+
*
|
|
278
|
+
* @typeParam E - The type of the actual expression
|
|
279
|
+
* @param actual - The actual value to test
|
|
280
|
+
* @param expected - The value that actual should be greater than or equal to
|
|
281
|
+
* @returns An East expression that performs the greater-than-or-equal check
|
|
282
|
+
*/
|
|
283
|
+
greaterEqual(actual, expected) {
|
|
284
|
+
const location = get_location();
|
|
285
|
+
const expected_expr = Expr.from(expected, Expr.type(actual));
|
|
286
|
+
return Expr.tryCatch(Expr.block($ => {
|
|
287
|
+
const act = $.let(actual);
|
|
288
|
+
const exp = $.let(expected_expr);
|
|
289
|
+
return East.greaterEqual(act, exp).ifElse(_$ => testPass(), _$ => testFail(str `Expected ${act} to be greater than or equal to ${exp} (${printLocations(location)})`));
|
|
290
|
+
}), (_$, message, stack) => testFail(East.String.printError(message, stack)));
|
|
291
|
+
},
|
|
292
|
+
/**
|
|
293
|
+
* Asserts that actual is between min and max (inclusive).
|
|
294
|
+
*
|
|
295
|
+
* @typeParam E - The type of the actual expression
|
|
296
|
+
* @param actual - The actual value to test
|
|
297
|
+
* @param min - The minimum value (inclusive)
|
|
298
|
+
* @param max - The maximum value (inclusive)
|
|
299
|
+
* @returns An East expression that performs the range check
|
|
300
|
+
*/
|
|
301
|
+
between(actual, min, max) {
|
|
302
|
+
const location = get_location();
|
|
303
|
+
const min_expr = Expr.from(min, Expr.type(actual));
|
|
304
|
+
const max_expr = Expr.from(max, Expr.type(actual));
|
|
305
|
+
return Expr.tryCatch(East.greaterEqual(actual, min_expr).ifElse(_$ => East.lessEqual(actual, max_expr).ifElse(_$ => testPass(), _$ => testFail(str `Expected ${actual} to be less than or equal to ${max_expr} (${printLocations(location)})`)), _$ => testFail(str `Expected ${actual} to be greater than or equal to ${min_expr}`)), (_$, message, stack) => testFail(East.String.printError(message, stack)));
|
|
306
|
+
},
|
|
307
|
+
/**
|
|
308
|
+
* Asserts that an expression throws an error.
|
|
309
|
+
*
|
|
310
|
+
* @param fn - The expression that should throw an error when evaluated
|
|
311
|
+
* @param pattern - Optional regex pattern to match against the error message
|
|
312
|
+
* @returns An East expression that verifies an error is thrown
|
|
313
|
+
*/
|
|
314
|
+
throws(fn, pattern) {
|
|
315
|
+
const location = get_location();
|
|
316
|
+
return Expr.tryCatch(Expr.block($ => {
|
|
317
|
+
const result = $.let(fn);
|
|
318
|
+
$(testFail(str `Expected error, got ${result} (${printLocations(location)})`));
|
|
319
|
+
return null;
|
|
320
|
+
}), ($, message, stack) => {
|
|
321
|
+
if (pattern) {
|
|
322
|
+
// Validate error message matches the pattern
|
|
323
|
+
return message.contains(pattern).ifElse(_$ => testPass(), _$ => testFail(str `Expected error message to match ${East.value(pattern.source)}, but got: ${East.String.printError(message, stack)}`));
|
|
324
|
+
}
|
|
325
|
+
else {
|
|
326
|
+
// Just verify it threw
|
|
327
|
+
return testPass();
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
},
|
|
331
|
+
/**
|
|
332
|
+
* Fails a test with the given message.
|
|
333
|
+
*
|
|
334
|
+
* @param message
|
|
335
|
+
* @returns An East expression that unconditionally fails the test
|
|
336
|
+
*/
|
|
337
|
+
fail(message) {
|
|
338
|
+
const location = get_location();
|
|
339
|
+
const message_expr = Expr.from(message, StringType);
|
|
340
|
+
return testFail(str `${message_expr} (${printLocations(location)})`);
|
|
341
|
+
},
|
|
342
|
+
/**
|
|
343
|
+
* Runs all examples as tests, calling each with its inputs and asserting the result equals returns.
|
|
344
|
+
*
|
|
345
|
+
* @param test - The test function from describeEast's builder
|
|
346
|
+
* @param examples - A record of named ExampleDef exports (e.g. `import * as examples from "./array.examples.js"`)
|
|
347
|
+
*/
|
|
348
|
+
examples(test, examples) {
|
|
349
|
+
for (const ex of Object.values(examples)) {
|
|
350
|
+
if (ex.returns !== undefined) {
|
|
351
|
+
test(ex.description, $ => {
|
|
352
|
+
const result = $.let(ex.fn(...ex.inputs));
|
|
353
|
+
$(Assert.equal(result, ex.returns));
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
else {
|
|
357
|
+
test(ex.description, $ => {
|
|
358
|
+
$.let(ex.fn(...ex.inputs));
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
},
|
|
363
|
+
};
|
|
364
|
+
//# sourceMappingURL=test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test.js","sourceRoot":"","sources":["../../src/test.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
3
|
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
4
|
*/
|
|
5
|
-
import { IntegerType, NullType } from "@elaraai/east";
|
|
5
|
+
import { IntegerType, NullType, DateTimeType, StringType } from "@elaraai/east";
|
|
6
6
|
import type { PlatformFunction } from "@elaraai/east/internal";
|
|
7
7
|
/**
|
|
8
8
|
* Gets the current Unix timestamp in milliseconds.
|
|
@@ -50,6 +50,33 @@ export declare const time_now: import("@elaraai/east").PlatformDefinition<[], In
|
|
|
50
50
|
* ```
|
|
51
51
|
*/
|
|
52
52
|
export declare const time_sleep: import("@elaraai/east").AsyncPlatformDefinition<[IntegerType], NullType>;
|
|
53
|
+
/**
|
|
54
|
+
* Gets the UTC offset in minutes for an IANA timezone at a given UTC datetime.
|
|
55
|
+
*
|
|
56
|
+
* Returns the number of minutes that the given timezone is ahead of (positive)
|
|
57
|
+
* or behind (negative) UTC at the specified instant. This accounts for DST
|
|
58
|
+
* transitions — the same timezone can return different offsets depending on
|
|
59
|
+
* the datetime.
|
|
60
|
+
*
|
|
61
|
+
* The timezone must be a valid IANA timezone name (e.g., "Australia/Sydney",
|
|
62
|
+
* "America/New_York", "Europe/London", "Asia/Tokyo"). See the IANA Time Zone
|
|
63
|
+
* Database for the full list of valid names.
|
|
64
|
+
*
|
|
65
|
+
* @param datetime - A UTC datetime to compute the offset for
|
|
66
|
+
* @param zone - An IANA timezone name (e.g., "Australia/Sydney")
|
|
67
|
+
* @returns UTC offset in minutes (e.g., 660 for Sydney in summer, 600 in winter)
|
|
68
|
+
*
|
|
69
|
+
* @throws {EastError} When the timezone name is not a valid IANA timezone
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```ts
|
|
73
|
+
* const toSydneyTime = East.function([DateTimeType], DateTimeType, ($, dt) => {
|
|
74
|
+
* const offset = $.let(Time.getTimezoneOffset(dt, "Australia/Sydney"));
|
|
75
|
+
* $.return(dt.addMinutes(offset));
|
|
76
|
+
* });
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export declare const time_get_timezone_offset: import("@elaraai/east").PlatformDefinition<[DateTimeType, StringType], IntegerType>;
|
|
53
80
|
/**
|
|
54
81
|
* Node.js implementation of time platform functions.
|
|
55
82
|
*
|
|
@@ -59,7 +86,7 @@ declare const TimeImpl: PlatformFunction[];
|
|
|
59
86
|
/**
|
|
60
87
|
* Grouped time platform functions.
|
|
61
88
|
*
|
|
62
|
-
* Provides time and
|
|
89
|
+
* Provides time, sleep, and timezone operations for East programs.
|
|
63
90
|
*
|
|
64
91
|
* @example
|
|
65
92
|
* ```ts
|
|
@@ -119,6 +146,27 @@ export declare const Time: {
|
|
|
119
146
|
* ```
|
|
120
147
|
*/
|
|
121
148
|
readonly sleep: import("@elaraai/east").AsyncPlatformDefinition<[IntegerType], NullType>;
|
|
149
|
+
/**
|
|
150
|
+
* Gets the UTC offset in minutes for an IANA timezone at a given UTC datetime.
|
|
151
|
+
*
|
|
152
|
+
* Accounts for DST — the same timezone returns different offsets depending
|
|
153
|
+
* on the datetime. Use the result with `addMinutes` to convert a UTC datetime
|
|
154
|
+
* to local time.
|
|
155
|
+
*
|
|
156
|
+
* @param datetime - A UTC datetime
|
|
157
|
+
* @param zone - An IANA timezone name (e.g., "Australia/Sydney")
|
|
158
|
+
* @returns UTC offset in minutes
|
|
159
|
+
* @throws {EastError} When the timezone name is invalid
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* ```ts
|
|
163
|
+
* const toSydneyTime = East.function([DateTimeType], DateTimeType, ($, dt) => {
|
|
164
|
+
* const offset = $.let(Time.getTimezoneOffset(dt, "Australia/Sydney"));
|
|
165
|
+
* $.return(dt.addMinutes(offset));
|
|
166
|
+
* });
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
169
|
+
readonly getTimezoneOffset: import("@elaraai/east").PlatformDefinition<[DateTimeType, StringType], IntegerType>;
|
|
122
170
|
/**
|
|
123
171
|
* Node.js implementation of time platform functions.
|
|
124
172
|
*
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time.d.ts","sourceRoot":"","sources":["../../src/time.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAQ,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACtF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAoC/D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,QAAQ,6DAA6C,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,UAAU,0EAA4D,CAAC;AAEpF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,wBAAwB,qFAIpC,CAAC;AAEF;;;;GAIG;AACH,QAAA,MAAM,QAAQ,EAAE,gBAAgB,EAyC/B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,IAAI;IACb;;;;;;;;;;;;;;;;;OAiBG;;IAGH;;;;;;;;;;;;;;;;;;;;;OAqBG;;IAGH;;;;;;;;;;;;;;;;;;;OAmBG;;IAGH;;;;OAIG;;CAEG,CAAC;AAGX,OAAO,EAAE,QAAQ,EAAE,CAAC"}
|
|
@@ -2,8 +2,37 @@
|
|
|
2
2
|
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
3
|
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
4
|
*/
|
|
5
|
-
import { East, IntegerType, NullType } from "@elaraai/east";
|
|
5
|
+
import { East, IntegerType, NullType, DateTimeType, StringType } from "@elaraai/east";
|
|
6
6
|
import { EastError } from "@elaraai/east/internal";
|
|
7
|
+
/**
|
|
8
|
+
* Computes the UTC offset in minutes for an IANA timezone at a given instant.
|
|
9
|
+
*
|
|
10
|
+
* Uses Intl.DateTimeFormat to format the datetime in both UTC and the target
|
|
11
|
+
* timezone, then computes the difference. This is reliable across all Node.js
|
|
12
|
+
* versions — it only depends on the date component formatting, not abbreviations.
|
|
13
|
+
*/
|
|
14
|
+
function computeUtcOffsetMinutes(datetime, zone) {
|
|
15
|
+
const formatParts = (tz) => {
|
|
16
|
+
const fmt = new Intl.DateTimeFormat("en-US", {
|
|
17
|
+
timeZone: tz,
|
|
18
|
+
year: "numeric",
|
|
19
|
+
month: "2-digit",
|
|
20
|
+
day: "2-digit",
|
|
21
|
+
hour: "2-digit",
|
|
22
|
+
minute: "2-digit",
|
|
23
|
+
second: "2-digit",
|
|
24
|
+
hour12: false,
|
|
25
|
+
});
|
|
26
|
+
const parts = fmt.formatToParts(datetime);
|
|
27
|
+
const get = (type) => parseInt(parts.find(p => p.type === type).value);
|
|
28
|
+
return { year: get("year"), month: get("month"), day: get("day"), hour: get("hour"), minute: get("minute"), second: get("second") };
|
|
29
|
+
};
|
|
30
|
+
const utc = formatParts("UTC");
|
|
31
|
+
const local = formatParts(zone);
|
|
32
|
+
const utcMs = Date.UTC(utc.year, utc.month - 1, utc.day, utc.hour, utc.minute, utc.second);
|
|
33
|
+
const localMs = Date.UTC(local.year, local.month - 1, local.day, local.hour, local.minute, local.second);
|
|
34
|
+
return (localMs - utcMs) / 60000;
|
|
35
|
+
}
|
|
7
36
|
/**
|
|
8
37
|
* Gets the current Unix timestamp in milliseconds.
|
|
9
38
|
*
|
|
@@ -50,6 +79,33 @@ export const time_now = East.platform("time_now", [], IntegerType);
|
|
|
50
79
|
* ```
|
|
51
80
|
*/
|
|
52
81
|
export const time_sleep = East.asyncPlatform("time_sleep", [IntegerType], NullType);
|
|
82
|
+
/**
|
|
83
|
+
* Gets the UTC offset in minutes for an IANA timezone at a given UTC datetime.
|
|
84
|
+
*
|
|
85
|
+
* Returns the number of minutes that the given timezone is ahead of (positive)
|
|
86
|
+
* or behind (negative) UTC at the specified instant. This accounts for DST
|
|
87
|
+
* transitions — the same timezone can return different offsets depending on
|
|
88
|
+
* the datetime.
|
|
89
|
+
*
|
|
90
|
+
* The timezone must be a valid IANA timezone name (e.g., "Australia/Sydney",
|
|
91
|
+
* "America/New_York", "Europe/London", "Asia/Tokyo"). See the IANA Time Zone
|
|
92
|
+
* Database for the full list of valid names.
|
|
93
|
+
*
|
|
94
|
+
* @param datetime - A UTC datetime to compute the offset for
|
|
95
|
+
* @param zone - An IANA timezone name (e.g., "Australia/Sydney")
|
|
96
|
+
* @returns UTC offset in minutes (e.g., 660 for Sydney in summer, 600 in winter)
|
|
97
|
+
*
|
|
98
|
+
* @throws {EastError} When the timezone name is not a valid IANA timezone
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```ts
|
|
102
|
+
* const toSydneyTime = East.function([DateTimeType], DateTimeType, ($, dt) => {
|
|
103
|
+
* const offset = $.let(Time.getTimezoneOffset(dt, "Australia/Sydney"));
|
|
104
|
+
* $.return(dt.addMinutes(offset));
|
|
105
|
+
* });
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
export const time_get_timezone_offset = East.platform("time_get_timezone_offset", [DateTimeType, StringType], IntegerType);
|
|
53
109
|
/**
|
|
54
110
|
* Node.js implementation of time platform functions.
|
|
55
111
|
*
|
|
@@ -62,7 +118,7 @@ const TimeImpl = [
|
|
|
62
118
|
}
|
|
63
119
|
catch (err) {
|
|
64
120
|
throw new EastError(`Failed to get current time: ${err.message}`, {
|
|
65
|
-
location: { filename: "time_now", line: 0n, column: 0n },
|
|
121
|
+
location: [{ filename: "time_now", line: 0n, column: 0n }],
|
|
66
122
|
cause: err
|
|
67
123
|
});
|
|
68
124
|
}
|
|
@@ -73,7 +129,26 @@ const TimeImpl = [
|
|
|
73
129
|
}
|
|
74
130
|
catch (err) {
|
|
75
131
|
throw new EastError(`Failed to sleep: ${err.message}`, {
|
|
76
|
-
location: { filename: "time_sleep", line: 0n, column: 0n },
|
|
132
|
+
location: [{ filename: "time_sleep", line: 0n, column: 0n }],
|
|
133
|
+
cause: err
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}),
|
|
137
|
+
time_get_timezone_offset.implement((datetime, zone) => {
|
|
138
|
+
try {
|
|
139
|
+
const offset = computeUtcOffsetMinutes(datetime, zone);
|
|
140
|
+
return BigInt(offset);
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
if (err instanceof RangeError) {
|
|
144
|
+
throw new EastError(`Invalid IANA timezone: "${zone}". ` +
|
|
145
|
+
`Use a valid IANA timezone name such as "Australia/Sydney", "America/New_York", or "Europe/London". ` +
|
|
146
|
+
`See https://en.wikipedia.org/wiki/List_of_tz_database_time_zones for the full list.`, { location: [{ filename: "time_get_timezone_offset", line: 0n, column: 0n }], cause: err });
|
|
147
|
+
}
|
|
148
|
+
if (err instanceof EastError)
|
|
149
|
+
throw err;
|
|
150
|
+
throw new EastError(`Failed to get timezone offset for "${zone}": ${err.message}`, {
|
|
151
|
+
location: [{ filename: "time_get_timezone_offset", line: 0n, column: 0n }],
|
|
77
152
|
cause: err
|
|
78
153
|
});
|
|
79
154
|
}
|
|
@@ -82,7 +157,7 @@ const TimeImpl = [
|
|
|
82
157
|
/**
|
|
83
158
|
* Grouped time platform functions.
|
|
84
159
|
*
|
|
85
|
-
* Provides time and
|
|
160
|
+
* Provides time, sleep, and timezone operations for East programs.
|
|
86
161
|
*
|
|
87
162
|
* @example
|
|
88
163
|
* ```ts
|
|
@@ -142,6 +217,27 @@ export const Time = {
|
|
|
142
217
|
* ```
|
|
143
218
|
*/
|
|
144
219
|
sleep: time_sleep,
|
|
220
|
+
/**
|
|
221
|
+
* Gets the UTC offset in minutes for an IANA timezone at a given UTC datetime.
|
|
222
|
+
*
|
|
223
|
+
* Accounts for DST — the same timezone returns different offsets depending
|
|
224
|
+
* on the datetime. Use the result with `addMinutes` to convert a UTC datetime
|
|
225
|
+
* to local time.
|
|
226
|
+
*
|
|
227
|
+
* @param datetime - A UTC datetime
|
|
228
|
+
* @param zone - An IANA timezone name (e.g., "Australia/Sydney")
|
|
229
|
+
* @returns UTC offset in minutes
|
|
230
|
+
* @throws {EastError} When the timezone name is invalid
|
|
231
|
+
*
|
|
232
|
+
* @example
|
|
233
|
+
* ```ts
|
|
234
|
+
* const toSydneyTime = East.function([DateTimeType], DateTimeType, ($, dt) => {
|
|
235
|
+
* const offset = $.let(Time.getTimezoneOffset(dt, "Australia/Sydney"));
|
|
236
|
+
* $.return(dt.addMinutes(offset));
|
|
237
|
+
* });
|
|
238
|
+
* ```
|
|
239
|
+
*/
|
|
240
|
+
getTimezoneOffset: time_get_timezone_offset,
|
|
145
241
|
/**
|
|
146
242
|
* Node.js implementation of time platform functions.
|
|
147
243
|
*
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time.js","sourceRoot":"","sources":["../../src/time.ts"],"names":[],"mappings":"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"}
|