@jesscss/core 2.0.0-alpha.5 → 2.0.0-alpha.6
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/lib/index.cjs +20159 -0
- package/lib/index.d.cts +5993 -0
- package/lib/index.d.cts.map +1 -0
- package/lib/index.d.ts +5992 -21
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +19926 -22
- package/lib/index.js.map +1 -1
- package/package.json +15 -14
- package/src/__tests__/define-function-record.test.ts +58 -0
- package/src/__tests__/define-function-simple.test.ts +55 -0
- package/src/__tests__/define-function-split-sequence.test.ts +547 -0
- package/src/__tests__/define-function-type-parity.test.ts +9 -0
- package/src/__tests__/define-function.test.ts +763 -0
- package/src/__tests__/num-operations.test.ts +91 -0
- package/src/__tests__/safe-parse.test.ts +374 -0
- package/src/context.ts +896 -0
- package/src/conversions.ts +282 -0
- package/src/debug-log.ts +29 -0
- package/src/define-function.ts +1006 -0
- package/src/deprecation.ts +67 -0
- package/src/globals.d.ts +26 -0
- package/src/index.ts +31 -0
- package/src/jess-error.ts +773 -0
- package/src/logger/deprecation-processing.ts +109 -0
- package/src/logger.ts +31 -0
- package/src/plugin.ts +292 -0
- package/src/tree/LOOKUP_CHAINS.md +35 -0
- package/src/tree/README.md +18 -0
- package/src/tree/__tests__/__snapshots__/extend-eval-integration.test.ts.snap +1455 -0
- package/src/tree/__tests__/ampersand.test.ts +382 -0
- package/src/tree/__tests__/at-rule.test.ts +2047 -0
- package/src/tree/__tests__/basic-render.test.ts +212 -0
- package/src/tree/__tests__/block.test.ts +40 -0
- package/src/tree/__tests__/call.test.ts +346 -0
- package/src/tree/__tests__/color.test.ts +537 -0
- package/src/tree/__tests__/condition.test.ts +186 -0
- package/src/tree/__tests__/control.test.ts +564 -0
- package/src/tree/__tests__/declaration.test.ts +253 -0
- package/src/tree/__tests__/dependency-graph.test.ts +177 -0
- package/src/tree/__tests__/detached-rulesets.test.ts +213 -0
- package/src/tree/__tests__/dimension.test.ts +236 -0
- package/src/tree/__tests__/expression.test.ts +73 -0
- package/src/tree/__tests__/ext-node.test.ts +31 -0
- package/src/tree/__tests__/extend-eval-integration.test.ts +1033 -0
- package/src/tree/__tests__/extend-import-style.test.ts +929 -0
- package/src/tree/__tests__/extend-less-fixtures.test.ts +851 -0
- package/src/tree/__tests__/extend-list.test.ts +31 -0
- package/src/tree/__tests__/extend-roots.test.ts +1045 -0
- package/src/tree/__tests__/extend-rules.test.ts +740 -0
- package/src/tree/__tests__/func.test.ts +171 -0
- package/src/tree/__tests__/import-js.test.ts +33 -0
- package/src/tree/__tests__/import-style-test-helpers.ts +56 -0
- package/src/tree/__tests__/import-style.test.ts +1967 -0
- package/src/tree/__tests__/interpolated-reference.test.ts +44 -0
- package/src/tree/__tests__/interpolated.test.ts +41 -0
- package/src/tree/__tests__/list.test.ts +177 -0
- package/src/tree/__tests__/log.test.ts +83 -0
- package/src/tree/__tests__/mixin-recursion.test.ts +639 -0
- package/src/tree/__tests__/mixin.test.ts +2171 -0
- package/src/tree/__tests__/negative.test.ts +45 -0
- package/src/tree/__tests__/nesting-collapse.test.ts +519 -0
- package/src/tree/__tests__/node-flags-perf.test.ts +195 -0
- package/src/tree/__tests__/node-flags.test.ts +410 -0
- package/src/tree/__tests__/node-graph.test.ts +598 -0
- package/src/tree/__tests__/node-mutation.test.ts +182 -0
- package/src/tree/__tests__/operation.test.ts +18 -0
- package/src/tree/__tests__/paren.test.ts +90 -0
- package/src/tree/__tests__/preserve-mode-output.test.ts +50 -0
- package/src/tree/__tests__/quoted.test.ts +72 -0
- package/src/tree/__tests__/range.test.ts +59 -0
- package/src/tree/__tests__/reference.test.ts +743 -0
- package/src/tree/__tests__/rest.test.ts +29 -0
- package/src/tree/__tests__/rules-raw.test.ts +14 -0
- package/src/tree/__tests__/rules.test.ts +1271 -0
- package/src/tree/__tests__/ruleset.test.ts +597 -0
- package/src/tree/__tests__/selector-attr.test.ts +50 -0
- package/src/tree/__tests__/selector-basic.test.ts +44 -0
- package/src/tree/__tests__/selector-capture.test.ts +22 -0
- package/src/tree/__tests__/selector-complex.test.ts +120 -0
- package/src/tree/__tests__/selector-compound.test.ts +74 -0
- package/src/tree/__tests__/selector-interpolated.test.ts +50 -0
- package/src/tree/__tests__/selector-list.test.ts +59 -0
- package/src/tree/__tests__/selector-pseudo.test.ts +23 -0
- package/src/tree/__tests__/selector.test.ts +182 -0
- package/src/tree/__tests__/sequence.test.ts +226 -0
- package/src/tree/__tests__/serialize-types.test.ts +529 -0
- package/src/tree/__tests__/spaced.test.ts +8 -0
- package/src/tree/__tests__/url.test.ts +72 -0
- package/src/tree/__tests__/var-declaration.test.ts +90 -0
- package/src/tree/ampersand.ts +538 -0
- package/src/tree/any.ts +169 -0
- package/src/tree/at-rule.ts +760 -0
- package/src/tree/block.ts +72 -0
- package/src/tree/bool.ts +46 -0
- package/src/tree/call.ts +593 -0
- package/src/tree/collection.ts +52 -0
- package/src/tree/color.ts +629 -0
- package/src/tree/combinator.ts +30 -0
- package/src/tree/comment.ts +36 -0
- package/src/tree/condition.ts +194 -0
- package/src/tree/control.ts +452 -0
- package/src/tree/declaration-custom.ts +56 -0
- package/src/tree/declaration-var.ts +87 -0
- package/src/tree/declaration.ts +742 -0
- package/src/tree/default-guard.ts +35 -0
- package/src/tree/dimension.ts +392 -0
- package/src/tree/expression.ts +97 -0
- package/src/tree/extend-list.ts +51 -0
- package/src/tree/extend.ts +391 -0
- package/src/tree/function.ts +254 -0
- package/src/tree/import-js.ts +130 -0
- package/src/tree/import-style.ts +875 -0
- package/{lib/tree/index.js → src/tree/index.ts} +49 -22
- package/src/tree/interpolated.ts +346 -0
- package/src/tree/js-array.ts +21 -0
- package/src/tree/js-expr.ts +50 -0
- package/src/tree/js-function.ts +31 -0
- package/src/tree/js-object.ts +22 -0
- package/src/tree/list.ts +415 -0
- package/src/tree/log.ts +89 -0
- package/src/tree/mixin.ts +331 -0
- package/src/tree/negative.ts +58 -0
- package/src/tree/nil.ts +57 -0
- package/src/tree/node-base.ts +1716 -0
- package/src/tree/node-type.ts +122 -0
- package/src/tree/node.ts +118 -0
- package/src/tree/number.ts +54 -0
- package/src/tree/operation.ts +187 -0
- package/src/tree/paren.ts +132 -0
- package/src/tree/query-condition.ts +47 -0
- package/src/tree/quoted.ts +119 -0
- package/src/tree/range.ts +101 -0
- package/src/tree/reference.ts +1099 -0
- package/src/tree/rest.ts +55 -0
- package/src/tree/rules-raw.ts +52 -0
- package/src/tree/rules.ts +2896 -0
- package/src/tree/ruleset.ts +1217 -0
- package/src/tree/selector-attr.ts +172 -0
- package/src/tree/selector-basic.ts +75 -0
- package/src/tree/selector-capture.ts +85 -0
- package/src/tree/selector-complex.ts +189 -0
- package/src/tree/selector-compound.ts +205 -0
- package/src/tree/selector-interpolated.ts +95 -0
- package/src/tree/selector-list.ts +245 -0
- package/src/tree/selector-pseudo.ts +173 -0
- package/src/tree/selector-simple.ts +10 -0
- package/src/tree/selector.ts +152 -0
- package/src/tree/sequence.ts +463 -0
- package/src/tree/tree.ts +130 -0
- package/src/tree/url.ts +95 -0
- package/src/tree/util/EXTEND_ARCHITECTURE_ANALYSIS.md +215 -0
- package/src/tree/util/EXTEND_AUDIT.md +233 -0
- package/src/tree/util/EXTEND_BASELINE.md +64 -0
- package/src/tree/util/EXTEND_CALL_GRAPH_ANALYSIS.md +244 -0
- package/src/tree/util/EXTEND_DOCS.md +24 -0
- package/src/tree/util/EXTEND_FINAL_SUMMARY.md +95 -0
- package/src/tree/util/EXTEND_FUNCTION_AUDIT.md +1433 -0
- package/src/tree/util/EXTEND_OPTIMIZATION_PLAN.md +114 -0
- package/src/tree/util/EXTEND_REFACTORING_SUMMARY.md +152 -0
- package/src/tree/util/EXTEND_RULES.md +74 -0
- package/src/tree/util/EXTEND_UNUSED_FUNCTIONS.md +127 -0
- package/src/tree/util/EXTEND_UNUSED_FUNCTIONS_ANALYSIS.md +227 -0
- package/src/tree/util/NODE_COPY_REDUCTION_PLAN.md +12 -0
- package/src/tree/util/__tests__/EXTEND_TEST_INDEX.md +59 -0
- package/src/tree/util/__tests__/OPTIMIZATION-ANALYSIS.md +130 -0
- package/src/tree/util/__tests__/WALK_AND_CONSUME_DESIGN.md +138 -0
- package/src/tree/util/__tests__/_archive/2026-02-09__OPTIMIZATION-ANALYSIS.md +9 -0
- package/src/tree/util/__tests__/_archive/README.md +4 -0
- package/src/tree/util/__tests__/bitset.test.ts +142 -0
- package/src/tree/util/__tests__/debug-log.ts +50 -0
- package/src/tree/util/__tests__/extend-comment-handling.test.ts +187 -0
- package/src/tree/util/__tests__/extend-core-unit.test.ts +941 -0
- package/src/tree/util/__tests__/extend-pipeline-bench.test.ts +154 -0
- package/src/tree/util/__tests__/extend-pipeline-bench.ts +190 -0
- package/src/tree/util/__tests__/fast-reject.test.ts +377 -0
- package/src/tree/util/__tests__/is-node.test.ts +63 -0
- package/src/tree/util/__tests__/list-like.test.ts +63 -0
- package/src/tree/util/__tests__/outputwriter.test.ts +523 -0
- package/src/tree/util/__tests__/print.test.ts +183 -0
- package/src/tree/util/__tests__/process-extends.test.ts +226 -0
- package/src/tree/util/__tests__/process-leading-is.test.ts +205 -0
- package/src/tree/util/__tests__/recursion-helper.test.ts +184 -0
- package/src/tree/util/__tests__/selector-match-unit.test.ts +1427 -0
- package/src/tree/util/__tests__/sourcemap.test.ts +117 -0
- package/src/tree/util/ampersand-template.ts +9 -0
- package/src/tree/util/bitset.ts +194 -0
- package/src/tree/util/calculate.ts +11 -0
- package/src/tree/util/cast.ts +89 -0
- package/src/tree/util/cloning.ts +8 -0
- package/src/tree/util/collections.ts +299 -0
- package/src/tree/util/compare.ts +90 -0
- package/src/tree/util/cursor.ts +171 -0
- package/src/tree/util/extend-core.ts +2139 -0
- package/src/tree/util/extend-roots.ts +1108 -0
- package/src/tree/util/field-helpers.ts +354 -0
- package/src/tree/util/is-node.ts +43 -0
- package/src/tree/util/list-like.ts +93 -0
- package/src/tree/util/mixin-instance-primitives.ts +2020 -0
- package/src/tree/util/print.ts +303 -0
- package/src/tree/util/process-leading-is.ts +421 -0
- package/src/tree/util/recursion-helper.ts +54 -0
- package/src/tree/util/regex.ts +2 -0
- package/src/tree/util/registry-utils.ts +1953 -0
- package/src/tree/util/ruleset-trace.ts +17 -0
- package/src/tree/util/scoped-body-eval.ts +320 -0
- package/src/tree/util/selector-match-core.ts +2005 -0
- package/src/tree/util/selector-utils.ts +757 -0
- package/src/tree/util/serialize-helper.ts +535 -0
- package/src/tree/util/serialize-types.ts +318 -0
- package/src/tree/util/should-operate.ts +78 -0
- package/src/tree/util/sourcemap.ts +37 -0
- package/src/types/config.ts +247 -0
- package/src/types/index.ts +12 -0
- package/{lib/types/modes.d.ts → src/types/modes.ts} +2 -1
- package/src/types.d.ts +9 -0
- package/src/types.ts +68 -0
- package/src/use-webpack-resolver.ts +56 -0
- package/src/visitor/__tests__/visitor.test.ts +136 -0
- package/src/visitor/index.ts +263 -0
- package/{lib/visitor/less-visitor.js → src/visitor/less-visitor.ts} +3 -2
- package/lib/context.d.ts +0 -352
- package/lib/context.d.ts.map +0 -1
- package/lib/context.js +0 -636
- package/lib/context.js.map +0 -1
- package/lib/conversions.d.ts +0 -73
- package/lib/conversions.d.ts.map +0 -1
- package/lib/conversions.js +0 -253
- package/lib/conversions.js.map +0 -1
- package/lib/debug-log.d.ts +0 -2
- package/lib/debug-log.d.ts.map +0 -1
- package/lib/debug-log.js +0 -27
- package/lib/debug-log.js.map +0 -1
- package/lib/define-function.d.ts +0 -587
- package/lib/define-function.d.ts.map +0 -1
- package/lib/define-function.js +0 -726
- package/lib/define-function.js.map +0 -1
- package/lib/deprecation.d.ts +0 -34
- package/lib/deprecation.d.ts.map +0 -1
- package/lib/deprecation.js +0 -57
- package/lib/deprecation.js.map +0 -1
- package/lib/jess-error.d.ts +0 -343
- package/lib/jess-error.d.ts.map +0 -1
- package/lib/jess-error.js +0 -508
- package/lib/jess-error.js.map +0 -1
- package/lib/logger/deprecation-processing.d.ts +0 -41
- package/lib/logger/deprecation-processing.d.ts.map +0 -1
- package/lib/logger/deprecation-processing.js +0 -81
- package/lib/logger/deprecation-processing.js.map +0 -1
- package/lib/logger.d.ts +0 -10
- package/lib/logger.d.ts.map +0 -1
- package/lib/logger.js +0 -20
- package/lib/logger.js.map +0 -1
- package/lib/plugin.d.ts +0 -94
- package/lib/plugin.d.ts.map +0 -1
- package/lib/plugin.js +0 -174
- package/lib/plugin.js.map +0 -1
- package/lib/tree/ampersand.d.ts +0 -98
- package/lib/tree/ampersand.d.ts.map +0 -1
- package/lib/tree/ampersand.js +0 -319
- package/lib/tree/ampersand.js.map +0 -1
- package/lib/tree/any.d.ts +0 -58
- package/lib/tree/any.d.ts.map +0 -1
- package/lib/tree/any.js +0 -104
- package/lib/tree/any.js.map +0 -1
- package/lib/tree/at-rule.d.ts +0 -53
- package/lib/tree/at-rule.d.ts.map +0 -1
- package/lib/tree/at-rule.js +0 -503
- package/lib/tree/at-rule.js.map +0 -1
- package/lib/tree/block.d.ts +0 -22
- package/lib/tree/block.d.ts.map +0 -1
- package/lib/tree/block.js +0 -24
- package/lib/tree/block.js.map +0 -1
- package/lib/tree/bool.d.ts +0 -18
- package/lib/tree/bool.d.ts.map +0 -1
- package/lib/tree/bool.js +0 -28
- package/lib/tree/bool.js.map +0 -1
- package/lib/tree/call.d.ts +0 -66
- package/lib/tree/call.d.ts.map +0 -1
- package/lib/tree/call.js +0 -306
- package/lib/tree/call.js.map +0 -1
- package/lib/tree/collection.d.ts +0 -30
- package/lib/tree/collection.d.ts.map +0 -1
- package/lib/tree/collection.js +0 -37
- package/lib/tree/collection.js.map +0 -1
- package/lib/tree/color.d.ts +0 -101
- package/lib/tree/color.d.ts.map +0 -1
- package/lib/tree/color.js +0 -513
- package/lib/tree/color.js.map +0 -1
- package/lib/tree/combinator.d.ts +0 -13
- package/lib/tree/combinator.d.ts.map +0 -1
- package/lib/tree/combinator.js +0 -12
- package/lib/tree/combinator.js.map +0 -1
- package/lib/tree/comment.d.ts +0 -20
- package/lib/tree/comment.d.ts.map +0 -1
- package/lib/tree/comment.js +0 -19
- package/lib/tree/comment.js.map +0 -1
- package/lib/tree/condition.d.ts +0 -31
- package/lib/tree/condition.d.ts.map +0 -1
- package/lib/tree/condition.js +0 -103
- package/lib/tree/condition.js.map +0 -1
- package/lib/tree/control.d.ts +0 -104
- package/lib/tree/control.d.ts.map +0 -1
- package/lib/tree/control.js +0 -430
- package/lib/tree/control.js.map +0 -1
- package/lib/tree/declaration-custom.d.ts +0 -18
- package/lib/tree/declaration-custom.d.ts.map +0 -1
- package/lib/tree/declaration-custom.js +0 -24
- package/lib/tree/declaration-custom.js.map +0 -1
- package/lib/tree/declaration-var.d.ts +0 -35
- package/lib/tree/declaration-var.d.ts.map +0 -1
- package/lib/tree/declaration-var.js +0 -63
- package/lib/tree/declaration-var.js.map +0 -1
- package/lib/tree/declaration.d.ts +0 -78
- package/lib/tree/declaration.d.ts.map +0 -1
- package/lib/tree/declaration.js +0 -286
- package/lib/tree/declaration.js.map +0 -1
- package/lib/tree/default-guard.d.ts +0 -15
- package/lib/tree/default-guard.d.ts.map +0 -1
- package/lib/tree/default-guard.js +0 -19
- package/lib/tree/default-guard.js.map +0 -1
- package/lib/tree/dimension.d.ts +0 -34
- package/lib/tree/dimension.d.ts.map +0 -1
- package/lib/tree/dimension.js +0 -294
- package/lib/tree/dimension.js.map +0 -1
- package/lib/tree/expression.d.ts +0 -25
- package/lib/tree/expression.d.ts.map +0 -1
- package/lib/tree/expression.js +0 -32
- package/lib/tree/expression.js.map +0 -1
- package/lib/tree/extend-list.d.ts +0 -23
- package/lib/tree/extend-list.d.ts.map +0 -1
- package/lib/tree/extend-list.js +0 -23
- package/lib/tree/extend-list.js.map +0 -1
- package/lib/tree/extend.d.ts +0 -47
- package/lib/tree/extend.d.ts.map +0 -1
- package/lib/tree/extend.js +0 -296
- package/lib/tree/extend.js.map +0 -1
- package/lib/tree/function.d.ts +0 -48
- package/lib/tree/function.d.ts.map +0 -1
- package/lib/tree/function.js +0 -74
- package/lib/tree/function.js.map +0 -1
- package/lib/tree/import-js.d.ts +0 -35
- package/lib/tree/import-js.d.ts.map +0 -1
- package/lib/tree/import-js.js +0 -45
- package/lib/tree/import-js.js.map +0 -1
- package/lib/tree/import-style.d.ts +0 -156
- package/lib/tree/import-style.d.ts.map +0 -1
- package/lib/tree/import-style.js +0 -566
- package/lib/tree/import-style.js.map +0 -1
- package/lib/tree/index.d.ts +0 -71
- package/lib/tree/index.d.ts.map +0 -1
- package/lib/tree/index.js.map +0 -1
- package/lib/tree/interpolated-reference.d.ts +0 -24
- package/lib/tree/interpolated-reference.d.ts.map +0 -1
- package/lib/tree/interpolated-reference.js +0 -37
- package/lib/tree/interpolated-reference.js.map +0 -1
- package/lib/tree/interpolated.d.ts +0 -62
- package/lib/tree/interpolated.d.ts.map +0 -1
- package/lib/tree/interpolated.js +0 -204
- package/lib/tree/interpolated.js.map +0 -1
- package/lib/tree/js-array.d.ts +0 -10
- package/lib/tree/js-array.d.ts.map +0 -1
- package/lib/tree/js-array.js +0 -10
- package/lib/tree/js-array.js.map +0 -1
- package/lib/tree/js-expr.d.ts +0 -23
- package/lib/tree/js-expr.d.ts.map +0 -1
- package/lib/tree/js-expr.js +0 -28
- package/lib/tree/js-expr.js.map +0 -1
- package/lib/tree/js-function.d.ts +0 -20
- package/lib/tree/js-function.d.ts.map +0 -1
- package/lib/tree/js-function.js +0 -16
- package/lib/tree/js-function.js.map +0 -1
- package/lib/tree/js-object.d.ts +0 -10
- package/lib/tree/js-object.d.ts.map +0 -1
- package/lib/tree/js-object.js +0 -10
- package/lib/tree/js-object.js.map +0 -1
- package/lib/tree/list.d.ts +0 -38
- package/lib/tree/list.d.ts.map +0 -1
- package/lib/tree/list.js +0 -83
- package/lib/tree/list.js.map +0 -1
- package/lib/tree/log.d.ts +0 -29
- package/lib/tree/log.d.ts.map +0 -1
- package/lib/tree/log.js +0 -56
- package/lib/tree/log.js.map +0 -1
- package/lib/tree/mixin.d.ts +0 -87
- package/lib/tree/mixin.d.ts.map +0 -1
- package/lib/tree/mixin.js +0 -112
- package/lib/tree/mixin.js.map +0 -1
- package/lib/tree/negative.d.ts +0 -17
- package/lib/tree/negative.d.ts.map +0 -1
- package/lib/tree/negative.js +0 -22
- package/lib/tree/negative.js.map +0 -1
- package/lib/tree/nil.d.ts +0 -30
- package/lib/tree/nil.d.ts.map +0 -1
- package/lib/tree/nil.js +0 -35
- package/lib/tree/nil.js.map +0 -1
- package/lib/tree/node-base.d.ts +0 -361
- package/lib/tree/node-base.d.ts.map +0 -1
- package/lib/tree/node-base.js +0 -930
- package/lib/tree/node-base.js.map +0 -1
- package/lib/tree/node.d.ts +0 -10
- package/lib/tree/node.d.ts.map +0 -1
- package/lib/tree/node.js +0 -45
- package/lib/tree/node.js.map +0 -1
- package/lib/tree/number.d.ts +0 -21
- package/lib/tree/number.d.ts.map +0 -1
- package/lib/tree/number.js +0 -27
- package/lib/tree/number.js.map +0 -1
- package/lib/tree/operation.d.ts +0 -26
- package/lib/tree/operation.d.ts.map +0 -1
- package/lib/tree/operation.js +0 -103
- package/lib/tree/operation.js.map +0 -1
- package/lib/tree/paren.d.ts +0 -19
- package/lib/tree/paren.d.ts.map +0 -1
- package/lib/tree/paren.js +0 -92
- package/lib/tree/paren.js.map +0 -1
- package/lib/tree/query-condition.d.ts +0 -17
- package/lib/tree/query-condition.d.ts.map +0 -1
- package/lib/tree/query-condition.js +0 -39
- package/lib/tree/query-condition.js.map +0 -1
- package/lib/tree/quoted.d.ts +0 -28
- package/lib/tree/quoted.d.ts.map +0 -1
- package/lib/tree/quoted.js +0 -75
- package/lib/tree/quoted.js.map +0 -1
- package/lib/tree/range.d.ts +0 -33
- package/lib/tree/range.d.ts.map +0 -1
- package/lib/tree/range.js +0 -47
- package/lib/tree/range.js.map +0 -1
- package/lib/tree/reference.d.ts +0 -76
- package/lib/tree/reference.d.ts.map +0 -1
- package/lib/tree/reference.js +0 -521
- package/lib/tree/reference.js.map +0 -1
- package/lib/tree/rest.d.ts +0 -15
- package/lib/tree/rest.d.ts.map +0 -1
- package/lib/tree/rest.js +0 -32
- package/lib/tree/rest.js.map +0 -1
- package/lib/tree/rules-raw.d.ts +0 -17
- package/lib/tree/rules-raw.d.ts.map +0 -1
- package/lib/tree/rules-raw.js +0 -37
- package/lib/tree/rules-raw.js.map +0 -1
- package/lib/tree/rules.d.ts +0 -262
- package/lib/tree/rules.d.ts.map +0 -1
- package/lib/tree/rules.js +0 -2359
- package/lib/tree/rules.js.map +0 -1
- package/lib/tree/ruleset.d.ts +0 -92
- package/lib/tree/ruleset.d.ts.map +0 -1
- package/lib/tree/ruleset.js +0 -528
- package/lib/tree/ruleset.js.map +0 -1
- package/lib/tree/selector-attr.d.ts +0 -31
- package/lib/tree/selector-attr.d.ts.map +0 -1
- package/lib/tree/selector-attr.js +0 -99
- package/lib/tree/selector-attr.js.map +0 -1
- package/lib/tree/selector-basic.d.ts +0 -24
- package/lib/tree/selector-basic.d.ts.map +0 -1
- package/lib/tree/selector-basic.js +0 -38
- package/lib/tree/selector-basic.js.map +0 -1
- package/lib/tree/selector-capture.d.ts +0 -23
- package/lib/tree/selector-capture.d.ts.map +0 -1
- package/lib/tree/selector-capture.js +0 -34
- package/lib/tree/selector-capture.js.map +0 -1
- package/lib/tree/selector-complex.d.ts +0 -40
- package/lib/tree/selector-complex.d.ts.map +0 -1
- package/lib/tree/selector-complex.js +0 -143
- package/lib/tree/selector-complex.js.map +0 -1
- package/lib/tree/selector-compound.d.ts +0 -16
- package/lib/tree/selector-compound.d.ts.map +0 -1
- package/lib/tree/selector-compound.js +0 -114
- package/lib/tree/selector-compound.js.map +0 -1
- package/lib/tree/selector-interpolated.d.ts +0 -23
- package/lib/tree/selector-interpolated.d.ts.map +0 -1
- package/lib/tree/selector-interpolated.js +0 -27
- package/lib/tree/selector-interpolated.js.map +0 -1
- package/lib/tree/selector-list.d.ts +0 -17
- package/lib/tree/selector-list.d.ts.map +0 -1
- package/lib/tree/selector-list.js +0 -174
- package/lib/tree/selector-list.js.map +0 -1
- package/lib/tree/selector-pseudo.d.ts +0 -42
- package/lib/tree/selector-pseudo.d.ts.map +0 -1
- package/lib/tree/selector-pseudo.js +0 -204
- package/lib/tree/selector-pseudo.js.map +0 -1
- package/lib/tree/selector-simple.d.ts +0 -5
- package/lib/tree/selector-simple.d.ts.map +0 -1
- package/lib/tree/selector-simple.js +0 -6
- package/lib/tree/selector-simple.js.map +0 -1
- package/lib/tree/selector.d.ts +0 -43
- package/lib/tree/selector.d.ts.map +0 -1
- package/lib/tree/selector.js +0 -56
- package/lib/tree/selector.js.map +0 -1
- package/lib/tree/sequence.d.ts +0 -43
- package/lib/tree/sequence.d.ts.map +0 -1
- package/lib/tree/sequence.js +0 -151
- package/lib/tree/sequence.js.map +0 -1
- package/lib/tree/tree.d.ts +0 -87
- package/lib/tree/tree.d.ts.map +0 -1
- package/lib/tree/tree.js +0 -2
- package/lib/tree/tree.js.map +0 -1
- package/lib/tree/url.d.ts +0 -18
- package/lib/tree/url.d.ts.map +0 -1
- package/lib/tree/url.js +0 -35
- package/lib/tree/url.js.map +0 -1
- package/lib/tree/util/__tests__/debug-log.d.ts +0 -1
- package/lib/tree/util/__tests__/debug-log.d.ts.map +0 -1
- package/lib/tree/util/__tests__/debug-log.js +0 -36
- package/lib/tree/util/__tests__/debug-log.js.map +0 -1
- package/lib/tree/util/calculate.d.ts +0 -3
- package/lib/tree/util/calculate.d.ts.map +0 -1
- package/lib/tree/util/calculate.js +0 -10
- package/lib/tree/util/calculate.js.map +0 -1
- package/lib/tree/util/cast.d.ts +0 -10
- package/lib/tree/util/cast.d.ts.map +0 -1
- package/lib/tree/util/cast.js +0 -87
- package/lib/tree/util/cast.js.map +0 -1
- package/lib/tree/util/cloning.d.ts +0 -4
- package/lib/tree/util/cloning.d.ts.map +0 -1
- package/lib/tree/util/cloning.js +0 -8
- package/lib/tree/util/cloning.js.map +0 -1
- package/lib/tree/util/collections.d.ts +0 -57
- package/lib/tree/util/collections.d.ts.map +0 -1
- package/lib/tree/util/collections.js +0 -136
- package/lib/tree/util/collections.js.map +0 -1
- package/lib/tree/util/compare.d.ts +0 -11
- package/lib/tree/util/compare.d.ts.map +0 -1
- package/lib/tree/util/compare.js +0 -89
- package/lib/tree/util/compare.js.map +0 -1
- package/lib/tree/util/extend-helpers.d.ts +0 -2
- package/lib/tree/util/extend-helpers.d.ts.map +0 -1
- package/lib/tree/util/extend-helpers.js +0 -2
- package/lib/tree/util/extend-helpers.js.map +0 -1
- package/lib/tree/util/extend-roots.d.ts +0 -37
- package/lib/tree/util/extend-roots.d.ts.map +0 -1
- package/lib/tree/util/extend-roots.js +0 -700
- package/lib/tree/util/extend-roots.js.map +0 -1
- package/lib/tree/util/extend-roots.old.d.ts +0 -132
- package/lib/tree/util/extend-roots.old.d.ts.map +0 -1
- package/lib/tree/util/extend-roots.old.js +0 -2272
- package/lib/tree/util/extend-roots.old.js.map +0 -1
- package/lib/tree/util/extend-trace-debug.d.ts +0 -13
- package/lib/tree/util/extend-trace-debug.d.ts.map +0 -1
- package/lib/tree/util/extend-trace-debug.js +0 -34
- package/lib/tree/util/extend-trace-debug.js.map +0 -1
- package/lib/tree/util/extend-walk.d.ts +0 -53
- package/lib/tree/util/extend-walk.d.ts.map +0 -1
- package/lib/tree/util/extend-walk.js +0 -881
- package/lib/tree/util/extend-walk.js.map +0 -1
- package/lib/tree/util/extend.d.ts +0 -218
- package/lib/tree/util/extend.d.ts.map +0 -1
- package/lib/tree/util/extend.js +0 -3182
- package/lib/tree/util/extend.js.map +0 -1
- package/lib/tree/util/find-extendable-locations.d.ts +0 -2
- package/lib/tree/util/find-extendable-locations.d.ts.map +0 -1
- package/lib/tree/util/find-extendable-locations.js +0 -2
- package/lib/tree/util/find-extendable-locations.js.map +0 -1
- package/lib/tree/util/format.d.ts +0 -20
- package/lib/tree/util/format.d.ts.map +0 -1
- package/lib/tree/util/format.js +0 -67
- package/lib/tree/util/format.js.map +0 -1
- package/lib/tree/util/is-node.d.ts +0 -13
- package/lib/tree/util/is-node.d.ts.map +0 -1
- package/lib/tree/util/is-node.js +0 -43
- package/lib/tree/util/is-node.js.map +0 -1
- package/lib/tree/util/print.d.ts +0 -80
- package/lib/tree/util/print.d.ts.map +0 -1
- package/lib/tree/util/print.js +0 -205
- package/lib/tree/util/print.js.map +0 -1
- package/lib/tree/util/process-leading-is.d.ts +0 -25
- package/lib/tree/util/process-leading-is.d.ts.map +0 -1
- package/lib/tree/util/process-leading-is.js +0 -364
- package/lib/tree/util/process-leading-is.js.map +0 -1
- package/lib/tree/util/recursion-helper.d.ts +0 -15
- package/lib/tree/util/recursion-helper.d.ts.map +0 -1
- package/lib/tree/util/recursion-helper.js +0 -43
- package/lib/tree/util/recursion-helper.js.map +0 -1
- package/lib/tree/util/regex.d.ts +0 -4
- package/lib/tree/util/regex.d.ts.map +0 -1
- package/lib/tree/util/regex.js +0 -4
- package/lib/tree/util/regex.js.map +0 -1
- package/lib/tree/util/registry-utils.d.ts +0 -192
- package/lib/tree/util/registry-utils.d.ts.map +0 -1
- package/lib/tree/util/registry-utils.js +0 -1214
- package/lib/tree/util/registry-utils.js.map +0 -1
- package/lib/tree/util/ruleset-trace.d.ts +0 -4
- package/lib/tree/util/ruleset-trace.d.ts.map +0 -1
- package/lib/tree/util/ruleset-trace.js +0 -14
- package/lib/tree/util/ruleset-trace.js.map +0 -1
- package/lib/tree/util/selector-compare.d.ts +0 -2
- package/lib/tree/util/selector-compare.d.ts.map +0 -1
- package/lib/tree/util/selector-compare.js +0 -2
- package/lib/tree/util/selector-compare.js.map +0 -1
- package/lib/tree/util/selector-match-core.d.ts +0 -184
- package/lib/tree/util/selector-match-core.d.ts.map +0 -1
- package/lib/tree/util/selector-match-core.js +0 -1603
- package/lib/tree/util/selector-match-core.js.map +0 -1
- package/lib/tree/util/selector-utils.d.ts +0 -30
- package/lib/tree/util/selector-utils.d.ts.map +0 -1
- package/lib/tree/util/selector-utils.js +0 -100
- package/lib/tree/util/selector-utils.js.map +0 -1
- package/lib/tree/util/serialize-helper.d.ts +0 -13
- package/lib/tree/util/serialize-helper.d.ts.map +0 -1
- package/lib/tree/util/serialize-helper.js +0 -387
- package/lib/tree/util/serialize-helper.js.map +0 -1
- package/lib/tree/util/serialize-types.d.ts +0 -9
- package/lib/tree/util/serialize-types.d.ts.map +0 -1
- package/lib/tree/util/serialize-types.js +0 -216
- package/lib/tree/util/serialize-types.js.map +0 -1
- package/lib/tree/util/should-operate.d.ts +0 -23
- package/lib/tree/util/should-operate.d.ts.map +0 -1
- package/lib/tree/util/should-operate.js +0 -46
- package/lib/tree/util/should-operate.js.map +0 -1
- package/lib/tree/util/sourcemap.d.ts +0 -7
- package/lib/tree/util/sourcemap.d.ts.map +0 -1
- package/lib/tree/util/sourcemap.js +0 -25
- package/lib/tree/util/sourcemap.js.map +0 -1
- package/lib/types/config.d.ts +0 -205
- package/lib/types/config.d.ts.map +0 -1
- package/lib/types/config.js +0 -2
- package/lib/types/config.js.map +0 -1
- package/lib/types/index.d.ts +0 -15
- package/lib/types/index.d.ts.map +0 -1
- package/lib/types/index.js +0 -3
- package/lib/types/index.js.map +0 -1
- package/lib/types/modes.d.ts.map +0 -1
- package/lib/types/modes.js +0 -2
- package/lib/types/modes.js.map +0 -1
- package/lib/types.d.ts +0 -61
- package/lib/types.d.ts.map +0 -1
- package/lib/types.js +0 -2
- package/lib/types.js.map +0 -1
- package/lib/use-webpack-resolver.d.ts +0 -9
- package/lib/use-webpack-resolver.d.ts.map +0 -1
- package/lib/use-webpack-resolver.js +0 -41
- package/lib/use-webpack-resolver.js.map +0 -1
- package/lib/visitor/index.d.ts +0 -136
- package/lib/visitor/index.d.ts.map +0 -1
- package/lib/visitor/index.js +0 -135
- package/lib/visitor/index.js.map +0 -1
- package/lib/visitor/less-visitor.d.ts +0 -7
- package/lib/visitor/less-visitor.d.ts.map +0 -1
- package/lib/visitor/less-visitor.js.map +0 -1
|
@@ -0,0 +1,763 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { defineFunction, callWithContext } from '../define-function.js';
|
|
3
|
+
import { Context } from '../context.js';
|
|
4
|
+
import { expectTypeOf } from 'vitest';
|
|
5
|
+
import { Color, Dimension } from '../tree/index.js';
|
|
6
|
+
|
|
7
|
+
describe('defineFunction', () => {
|
|
8
|
+
const args = [
|
|
9
|
+
{ name: 'name', type: 'string' },
|
|
10
|
+
{ name: 'value', type: 'number' }
|
|
11
|
+
] as const;
|
|
12
|
+
|
|
13
|
+
const myFunc = defineFunction(
|
|
14
|
+
'test',
|
|
15
|
+
(name: string, value: number) => `${name}: ${value}`,
|
|
16
|
+
{ params: args }
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
describe('positional calls', () => {
|
|
20
|
+
it('should work with valid positional arguments', () => {
|
|
21
|
+
const myFunc = defineFunction(
|
|
22
|
+
'test',
|
|
23
|
+
(name: string, value: number) => `${name}: ${value}`,
|
|
24
|
+
{ params: [
|
|
25
|
+
{ name: 'name', type: 'string' },
|
|
26
|
+
{ name: 'value', type: 'number' }
|
|
27
|
+
] }
|
|
28
|
+
);
|
|
29
|
+
expect(myFunc('hello', 42)).toBe('hello: 42');
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should throw error for invalid first argument type', () => {
|
|
33
|
+
expect(() => {
|
|
34
|
+
(myFunc as any)(1, 42);
|
|
35
|
+
}).toThrow('Argument \'name\' must be of type \'string\'. Got: number');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('should throw error for invalid second argument type', () => {
|
|
39
|
+
expect(() => {
|
|
40
|
+
(myFunc as any)('hello', 'not a number');
|
|
41
|
+
}).toThrow('Argument \'value\' must be of type \'number\'. Got: string');
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('should handle undefined arguments gracefully', () => {
|
|
45
|
+
// With the new validation, undefined arguments for required parameters should throw
|
|
46
|
+
expect(() => {
|
|
47
|
+
myFunc('hello', undefined as any);
|
|
48
|
+
}).toThrow('Required argument \'value\' is missing');
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe('record calls', () => {
|
|
53
|
+
it('should work with valid record arguments', () => {
|
|
54
|
+
expect(myFunc({ name: 'hello', value: 42 })).toBe('hello: 42');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should work with partial record (missing optional parameters)', () => {
|
|
58
|
+
// With the new validation, missing required parameters should throw
|
|
59
|
+
expect(() => {
|
|
60
|
+
(myFunc as any)({ name: 'hello' });
|
|
61
|
+
}).toThrow('Required argument \'value\' is missing');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('should throw error for invalid property type in record', () => {
|
|
65
|
+
expect(() => {
|
|
66
|
+
(myFunc as any)({ name: 123, value: 42 });
|
|
67
|
+
}).toThrow('Argument \'name\' must be of type \'string\'. Got: number');
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('should throw error for invalid second property type in record', () => {
|
|
71
|
+
expect(() => {
|
|
72
|
+
(myFunc as any)({ name: 'hello', value: 'not a number' });
|
|
73
|
+
}).toThrow('Argument \'value\' must be of type \'number\'. Got: string');
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
describe('hybrid calls', () => {
|
|
78
|
+
it('should work with positional + record arguments', () => {
|
|
79
|
+
expect(myFunc('hello', { value: 42 })).toBe('hello: 42');
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('should prioritize record over positional for same parameter', () => {
|
|
83
|
+
// Record takes precedence over positional arguments
|
|
84
|
+
expect(myFunc('ignored', { name: 'hello', value: 42 })).toBe('hello: 42');
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('should handle partial record in hybrid call', () => {
|
|
88
|
+
// Only the value from record, name from positional
|
|
89
|
+
expect(myFunc('hello', { value: 42 })).toBe('hello: 42');
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('should handle record with extra properties', () => {
|
|
93
|
+
// Extra properties in record should be ignored
|
|
94
|
+
(myFunc as any)('hello', { value: 42, extra: 'ignored' });
|
|
95
|
+
// The function should still work correctly despite extra properties
|
|
96
|
+
expect(myFunc('hello', { value: 42 })).toBe('hello: 42');
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('should throw error for invalid positional argument in hybrid call', () => {
|
|
100
|
+
expect(() => {
|
|
101
|
+
(myFunc as any)(123, { value: 42 });
|
|
102
|
+
}).toThrow('Argument \'name\' must be of type \'string\'. Got: number');
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('should throw error for invalid record property in hybrid call', () => {
|
|
106
|
+
expect(() => {
|
|
107
|
+
(myFunc as any)('hello', { value: 'not a number' });
|
|
108
|
+
}).toThrow('Argument \'value\' must be of type \'number\'. Got: string');
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
describe('edge cases', () => {
|
|
113
|
+
it('should handle empty record', () => {
|
|
114
|
+
// With the new validation, empty record should throw for missing required parameters
|
|
115
|
+
expect(() => {
|
|
116
|
+
(myFunc as any)({});
|
|
117
|
+
}).toThrow('Required argument \'name\' is missing');
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('should handle null values', () => {
|
|
121
|
+
expect(() => {
|
|
122
|
+
(myFunc as any)(null, 42);
|
|
123
|
+
}).toThrow('Argument \'name\' must be of type \'string\'. Got: object');
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('should handle boolean values', () => {
|
|
127
|
+
expect(() => {
|
|
128
|
+
(myFunc as any)(true, 42);
|
|
129
|
+
}).toThrow('Argument \'name\' must be of type \'string\'. Got: boolean');
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
describe('type inference', () => {
|
|
134
|
+
it('should provide correct return type', () => {
|
|
135
|
+
const result = myFunc({ name: 'hello', value: 42 });
|
|
136
|
+
expect(typeof result).toBe('string');
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('should maintain function signature for record calls', () => {
|
|
140
|
+
// This should compile without errors
|
|
141
|
+
const testFunc = (fn: typeof myFunc) => {
|
|
142
|
+
fn({ name: 'hello', value: 42 });
|
|
143
|
+
};
|
|
144
|
+
testFunc(myFunc);
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
describe('complex scenarios', () => {
|
|
149
|
+
it('should work with more complex function', () => {
|
|
150
|
+
const complexArgs = [
|
|
151
|
+
{ name: 'name', type: 'string' },
|
|
152
|
+
{ name: 'age', type: 'number' },
|
|
153
|
+
{ name: 'active', type: 'boolean' }
|
|
154
|
+
] as const;
|
|
155
|
+
|
|
156
|
+
const complexFunc = defineFunction(
|
|
157
|
+
'complex',
|
|
158
|
+
(name: string, age: number, active: boolean) =>
|
|
159
|
+
`${name} is ${age} years old and is ${active ? 'active' : 'inactive'}`,
|
|
160
|
+
{ params: complexArgs }
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
expect(complexFunc({ name: 'John', age: 30, active: true })).toBe('John is 30 years old and is active');
|
|
164
|
+
expect(complexFunc({ name: 'Jane', age: 25, active: false })).toBe('Jane is 25 years old and is inactive');
|
|
165
|
+
expect(complexFunc({ name: 'Bob', age: 35, active: true })).toBe('Bob is 35 years old and is active');
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('should handle optional parameters correctly', () => {
|
|
169
|
+
const optionalArgs = [
|
|
170
|
+
{ name: 'required', type: 'string' },
|
|
171
|
+
{ name: 'optional', type: 'number', optional: true }
|
|
172
|
+
] as const;
|
|
173
|
+
|
|
174
|
+
const optionalFunc = defineFunction(
|
|
175
|
+
'optional',
|
|
176
|
+
(required: string, optional?: number) =>
|
|
177
|
+
`${required}${optional ? `: ${optional}` : ''}`,
|
|
178
|
+
{ params: optionalArgs }
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
expect(optionalFunc({ required: 'hello' })).toBe('hello');
|
|
182
|
+
expect(optionalFunc({ required: 'hello', optional: 42 })).toBe('hello: 42');
|
|
183
|
+
expect(optionalFunc({ required: 'world' })).toBe('world');
|
|
184
|
+
expect(optionalFunc({ required: 'world', optional: 123 })).toBe('world: 123');
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('should throw error for missing required parameters', () => {
|
|
188
|
+
const requiredArgs = [
|
|
189
|
+
{ name: 'name', type: 'string' },
|
|
190
|
+
{ name: 'value', type: 'number' }
|
|
191
|
+
] as const;
|
|
192
|
+
|
|
193
|
+
const requiredFunc = defineFunction(
|
|
194
|
+
'required',
|
|
195
|
+
(name: string, value: number) => `${name}: ${value}`,
|
|
196
|
+
{ params: requiredArgs }
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
expect(() => {
|
|
200
|
+
(requiredFunc as any)();
|
|
201
|
+
}).toThrow('Required argument \'name\' is missing');
|
|
202
|
+
|
|
203
|
+
expect(() => {
|
|
204
|
+
(requiredFunc as any)('hello');
|
|
205
|
+
}).toThrow('Required argument \'value\' is missing');
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it('should work with all optional parameters', () => {
|
|
209
|
+
const allOptionalArgs = [
|
|
210
|
+
{ name: 'name', type: 'string', optional: true },
|
|
211
|
+
{ name: 'value', type: 'number', optional: true }
|
|
212
|
+
] as const;
|
|
213
|
+
|
|
214
|
+
const allOptionalFunc = defineFunction(
|
|
215
|
+
'allOptional',
|
|
216
|
+
(name?: string, value?: number) => `${name || 'default'}: ${value || 0}`,
|
|
217
|
+
{ params: allOptionalArgs }
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
// Should work with no arguments
|
|
221
|
+
expect(allOptionalFunc()).toBe('default: 0');
|
|
222
|
+
|
|
223
|
+
// Should work with partial arguments
|
|
224
|
+
expect(allOptionalFunc('hello')).toBe('hello: 0');
|
|
225
|
+
expect(allOptionalFunc(undefined, 42)).toBe('default: 42');
|
|
226
|
+
|
|
227
|
+
// Should work with all arguments
|
|
228
|
+
expect(allOptionalFunc('hello', 42)).toBe('hello: 42');
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
it('should have strong typing for positional arguments', () => {
|
|
232
|
+
const typedArgs = [
|
|
233
|
+
{ name: 'name', type: 'string' },
|
|
234
|
+
{ name: 'value', type: 'number' }
|
|
235
|
+
] as const;
|
|
236
|
+
|
|
237
|
+
const typedFunc = defineFunction(
|
|
238
|
+
'typed',
|
|
239
|
+
(name: string, value: number) => `${name}: ${value}`,
|
|
240
|
+
{ params: typedArgs }
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
// These should have proper type checking
|
|
244
|
+
expect(typedFunc({ name: 'hello', value: 42 })).toBe('hello: 42');
|
|
245
|
+
|
|
246
|
+
// TypeScript should catch these at compile time:
|
|
247
|
+
// typedFunc('hello', 'not-a-number'); // Should be type error
|
|
248
|
+
// typedFunc(123, 42); // Should be type error
|
|
249
|
+
// typedFunc('hello'); // Should be type error (missing required param)
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
it('should preserve parameter names from function signature', () => {
|
|
253
|
+
const args = [
|
|
254
|
+
{ name: 'name', type: 'string' },
|
|
255
|
+
{ name: 'age', type: 'number' },
|
|
256
|
+
{ name: 'active', type: 'boolean' }
|
|
257
|
+
] as const;
|
|
258
|
+
|
|
259
|
+
const func = defineFunction(
|
|
260
|
+
'preserveNames',
|
|
261
|
+
(name: string, age: number, active: boolean) => `${name}: ${age}, ${active}`,
|
|
262
|
+
{ params: args }
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
// The function should have the same parameter names as the original function
|
|
266
|
+
expect(func({ name: 'John', age: 30, active: true })).toBe('John: 30, true');
|
|
267
|
+
expect(func({ name: 'Jane', age: 25, active: false })).toBe('Jane: 25, false');
|
|
268
|
+
|
|
269
|
+
// Test that parameter names are preserved in the type
|
|
270
|
+
expectTypeOf(func).toBeFunction();
|
|
271
|
+
expectTypeOf(func).returns.toBeString();
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
it('should validate that args match function signature', () => {
|
|
275
|
+
// This should work - args match function signature
|
|
276
|
+
const validArgs = [
|
|
277
|
+
{ name: 'name', type: 'string' },
|
|
278
|
+
{ name: 'value', type: 'number' }
|
|
279
|
+
] as const;
|
|
280
|
+
|
|
281
|
+
const validFunc = defineFunction(
|
|
282
|
+
'valid',
|
|
283
|
+
(name: string, value: number) => `${name}: ${value}`,
|
|
284
|
+
{ params: validArgs }
|
|
285
|
+
);
|
|
286
|
+
|
|
287
|
+
expect(validFunc({ name: 'hello', value: 42 })).toBe('hello: 42');
|
|
288
|
+
|
|
289
|
+
// Test that the function signature matches the original
|
|
290
|
+
expectTypeOf(validFunc).toBeFunction();
|
|
291
|
+
expectTypeOf(validFunc).returns.toBeString();
|
|
292
|
+
|
|
293
|
+
// This should cause a type error at compile time if uncommented:
|
|
294
|
+
// const invalidArgs = [
|
|
295
|
+
// { name: 'name', type: 'string' },
|
|
296
|
+
// { name: 'value', type: 'boolean' } // Wrong type!
|
|
297
|
+
// ] as const;
|
|
298
|
+
//
|
|
299
|
+
// const invalidFunc = defineFunction(
|
|
300
|
+
// 'invalid',
|
|
301
|
+
// (name: string, value: number) => `${name}: ${value}`, // Expects number, but args says boolean
|
|
302
|
+
// { params: invalidArgs }
|
|
303
|
+
// );
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
it('should have correct return type', () => {
|
|
307
|
+
const args = [
|
|
308
|
+
{ name: 'name', type: 'string' },
|
|
309
|
+
{ name: 'value', type: 'number' }
|
|
310
|
+
] as const;
|
|
311
|
+
|
|
312
|
+
const func = defineFunction(
|
|
313
|
+
'returnType',
|
|
314
|
+
(name: string, value: number): string => `${name}: ${value}`,
|
|
315
|
+
{ params: args }
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
// Test that return type is preserved
|
|
319
|
+
expectTypeOf(func({ name: 'hello', value: 42 })).toBeString();
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
it('should catch type mismatches between args and function signature', () => {
|
|
323
|
+
// This test demonstrates that TypeScript will catch mismatches
|
|
324
|
+
// Uncomment the following lines to see the type error:
|
|
325
|
+
|
|
326
|
+
// const mismatchedArgs = [
|
|
327
|
+
// { name: 'name', type: 'string' },
|
|
328
|
+
// { name: 'value', type: 'boolean' } // Wrong type!
|
|
329
|
+
// ] as const;
|
|
330
|
+
//
|
|
331
|
+
// const mismatchedFunc = defineFunction(
|
|
332
|
+
// 'mismatched',
|
|
333
|
+
// (name: string, value: number) => `${name}: ${value}`, // Expects number, but args says boolean
|
|
334
|
+
// { params: mismatchedArgs }
|
|
335
|
+
// );
|
|
336
|
+
|
|
337
|
+
// The above should cause a TypeScript error because:
|
|
338
|
+
// - Function expects (name: string, value: number)
|
|
339
|
+
// - Args says value should be boolean
|
|
340
|
+
// - TypeScript should catch this mismatch
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
it('should handle default values correctly', () => {
|
|
344
|
+
const defaultArgs = [
|
|
345
|
+
{ name: 'name', type: 'string', default: 'anonymous' },
|
|
346
|
+
{ name: 'age', type: 'number', default: 18 },
|
|
347
|
+
{ name: 'active', type: 'boolean', default: true }
|
|
348
|
+
] as const;
|
|
349
|
+
|
|
350
|
+
const defaultFunc = defineFunction(
|
|
351
|
+
'defaults',
|
|
352
|
+
(name: string, age: number, active: boolean) => `${name} (${age}) - ${active ? 'active' : 'inactive'}`,
|
|
353
|
+
{ params: defaultArgs }
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
// Should use defaults when no arguments provided
|
|
357
|
+
expect(defaultFunc({})).toBe('anonymous (18) - active');
|
|
358
|
+
|
|
359
|
+
// Should use defaults for missing parameters
|
|
360
|
+
expect(defaultFunc({ name: 'John' })).toBe('John (18) - active');
|
|
361
|
+
expect(defaultFunc({ name: 'Jane', age: 25 })).toBe('Jane (25) - active');
|
|
362
|
+
|
|
363
|
+
// Should override defaults when provided
|
|
364
|
+
expect(defaultFunc({ name: 'Bob', age: 30, active: false })).toBe('Bob (30) - inactive');
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
it('should automatically make parameters optional when they have defaults', () => {
|
|
368
|
+
const autoOptionalArgs = [
|
|
369
|
+
{ name: 'name', type: 'string' }, // Required
|
|
370
|
+
{ name: 'age', type: 'number', default: 18 }, // Auto-optional due to default
|
|
371
|
+
{ name: 'city', type: 'string', default: 'Unknown' } // Auto-optional due to default
|
|
372
|
+
] as const;
|
|
373
|
+
|
|
374
|
+
const autoOptionalFunc = defineFunction(
|
|
375
|
+
'autoOptional',
|
|
376
|
+
(name: string, age: number, city: string) => `${name} (${age}) from ${city}`,
|
|
377
|
+
{ params: autoOptionalArgs }
|
|
378
|
+
);
|
|
379
|
+
|
|
380
|
+
// Should work with just the required parameter
|
|
381
|
+
expect(autoOptionalFunc({ name: 'John' })).toBe('John (18) from Unknown');
|
|
382
|
+
|
|
383
|
+
// Should work with partial parameters
|
|
384
|
+
expect(autoOptionalFunc({ name: 'Jane', age: 25 })).toBe('Jane (25) from Unknown');
|
|
385
|
+
|
|
386
|
+
// Should work with all parameters
|
|
387
|
+
expect(autoOptionalFunc({ name: 'Bob', age: 30, city: 'New York' })).toBe('Bob (30) from New York');
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
it('should not require explicit optional flag when using defaults', () => {
|
|
391
|
+
const implicitOptionalArgs = [
|
|
392
|
+
{ name: 'name', type: 'string' }, // Required
|
|
393
|
+
{ name: 'count', type: 'number', default: 0 }, // Implicitly optional due to default
|
|
394
|
+
{ name: 'enabled', type: 'boolean', default: true } // Implicitly optional due to default
|
|
395
|
+
] as const;
|
|
396
|
+
|
|
397
|
+
const implicitOptionalFunc = defineFunction(
|
|
398
|
+
'implicitOptional',
|
|
399
|
+
(name: string, count: number, enabled: boolean) => `${name}: ${count} items, ${enabled ? 'enabled' : 'disabled'}`,
|
|
400
|
+
{ params: implicitOptionalArgs }
|
|
401
|
+
);
|
|
402
|
+
|
|
403
|
+
// Should work with just required parameter (others use defaults)
|
|
404
|
+
expect(implicitOptionalFunc({ name: 'Widget' })).toBe('Widget: 0 items, enabled');
|
|
405
|
+
|
|
406
|
+
// Should work with partial parameters
|
|
407
|
+
expect(implicitOptionalFunc({ name: 'Gadget', count: 5 })).toBe('Gadget: 5 items, enabled');
|
|
408
|
+
|
|
409
|
+
// Should work with all parameters
|
|
410
|
+
expect(implicitOptionalFunc({ name: 'Tool', count: 10, enabled: false })).toBe('Tool: 10 items, disabled');
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
it('should work with tree node types', () => {
|
|
414
|
+
const treeNodeArgs = [
|
|
415
|
+
{ name: 'color', type: Color },
|
|
416
|
+
{ name: 'dimension', type: Dimension, default: new Dimension({ number: 0, unit: 'px' }) },
|
|
417
|
+
{ name: 'alpha', type: 'number', default: 1 }
|
|
418
|
+
] as const;
|
|
419
|
+
|
|
420
|
+
const treeNodeFunc = defineFunction(
|
|
421
|
+
'treeNodes',
|
|
422
|
+
(color: Color, dimension?: Dimension, alpha?: number) => {
|
|
423
|
+
return {
|
|
424
|
+
colorType: color.type,
|
|
425
|
+
dimensionType: dimension?.type || 'none',
|
|
426
|
+
alpha: alpha || 1
|
|
427
|
+
};
|
|
428
|
+
},
|
|
429
|
+
{ params: treeNodeArgs }
|
|
430
|
+
);
|
|
431
|
+
|
|
432
|
+
const testColor = new Color('#ff0000');
|
|
433
|
+
const testDimension = new Dimension({ number: 10, unit: 'px' });
|
|
434
|
+
|
|
435
|
+
// Test with all parameters
|
|
436
|
+
const result1 = treeNodeFunc(testColor, testDimension, 0.8);
|
|
437
|
+
expect(result1.colorType).toBe('Color');
|
|
438
|
+
expect(result1.dimensionType).toBe('Dimension');
|
|
439
|
+
expect(result1.alpha).toBe(0.8);
|
|
440
|
+
|
|
441
|
+
// Test with missing optional parameter (should use defaults)
|
|
442
|
+
const result2 = treeNodeFunc(testColor);
|
|
443
|
+
expect(result2.colorType).toBe('Color');
|
|
444
|
+
expect(result2.dimensionType).toBe('Dimension'); // Uses default
|
|
445
|
+
expect(result2.alpha).toBe(1); // Uses default
|
|
446
|
+
|
|
447
|
+
// Test that instanceof checks work correctly
|
|
448
|
+
expect(testColor instanceof Color).toBe(true);
|
|
449
|
+
expect(testDimension instanceof Dimension).toBe(true);
|
|
450
|
+
|
|
451
|
+
// Test that runtime validation works with instanceof checks
|
|
452
|
+
expect(() => {
|
|
453
|
+
treeNodeFunc('not a color' as any, testDimension);
|
|
454
|
+
}).toThrow('Argument \'color\' must be of type \'Color\'');
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
it('should support rest parameters and lazy evaluation', async () => {
|
|
458
|
+
const calls: string[] = [];
|
|
459
|
+
class TestNode extends Color {
|
|
460
|
+
override async evalNode(context: any): Promise<any> {
|
|
461
|
+
calls.push(`${(this as any)._nodeValue}`);
|
|
462
|
+
return this;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
const restFunc = defineFunction(
|
|
467
|
+
'rest',
|
|
468
|
+
async (...values: Array<() => Promise<Color>>) => {
|
|
469
|
+
const firstThunk = values[0]!;
|
|
470
|
+
const first = await firstThunk() as TestNode;
|
|
471
|
+
return first;
|
|
472
|
+
},
|
|
473
|
+
{ params: [{ name: 'values', type: Color, rest: true, lazy: true }] }
|
|
474
|
+
);
|
|
475
|
+
|
|
476
|
+
// Call positionally: only first should be evaluated
|
|
477
|
+
const a = new TestNode('#000');
|
|
478
|
+
const b = new TestNode('#111');
|
|
479
|
+
const c = new TestNode('#222');
|
|
480
|
+
const ctx = new Context();
|
|
481
|
+
const result = await callWithContext(ctx, restFunc as any, a, b, c);
|
|
482
|
+
expect(result).toBe(a);
|
|
483
|
+
// Only first element evaluated lazily upon access
|
|
484
|
+
expect(calls).toEqual(['#000']);
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
it('should support lazy evaluation of object parameters', async () => {
|
|
488
|
+
const calls: string[] = [];
|
|
489
|
+
class TestNode extends Color {
|
|
490
|
+
override async evalNode(context: any): Promise<any> {
|
|
491
|
+
calls.push(`${(this as any)._nodeValue}`);
|
|
492
|
+
return this;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
const objFunc = defineFunction(
|
|
497
|
+
'obj',
|
|
498
|
+
async (aThunk: () => Promise<Color>, bThunk: () => Promise<Color>) => {
|
|
499
|
+
const a = await aThunk() as TestNode;
|
|
500
|
+
return a;
|
|
501
|
+
},
|
|
502
|
+
{ params: [
|
|
503
|
+
{ name: 'a', type: Color, lazy: true },
|
|
504
|
+
{ name: 'b', type: Color, lazy: true }
|
|
505
|
+
] }
|
|
506
|
+
);
|
|
507
|
+
|
|
508
|
+
const a = new TestNode('#000');
|
|
509
|
+
const b = new TestNode('#111');
|
|
510
|
+
const ctx = new Context();
|
|
511
|
+
const result = await callWithContext(ctx, objFunc as any, { a, b });
|
|
512
|
+
expect(result).toBe(a);
|
|
513
|
+
expect(calls).toEqual(['#000']);
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
it('should validate lazy parameters when thunk is called, not when function is defined', async () => {
|
|
517
|
+
// This test ensures lazy parameters are validated when the thunk is called,
|
|
518
|
+
// not when the function is initially called. This prevents "Got: function" errors.
|
|
519
|
+
const directFunc = defineFunction(
|
|
520
|
+
'direct',
|
|
521
|
+
async (valueThunk: any) => {
|
|
522
|
+
// When this thunk is called, it should validate the resolved value, not the function
|
|
523
|
+
const value = await valueThunk();
|
|
524
|
+
return value;
|
|
525
|
+
},
|
|
526
|
+
{ params: [
|
|
527
|
+
{ name: 'value', type: Dimension, lazy: true }
|
|
528
|
+
] }
|
|
529
|
+
);
|
|
530
|
+
|
|
531
|
+
// Should throw when function returns wrong type - validation happens when thunk is called
|
|
532
|
+
// This would previously fail with "Got: function" but now correctly validates the resolved value
|
|
533
|
+
await expect(
|
|
534
|
+
directFunc(() => new Color('#000') as any)
|
|
535
|
+
).rejects.toThrow('Argument \'value\' must be of type \'Dimension\'');
|
|
536
|
+
});
|
|
537
|
+
});
|
|
538
|
+
|
|
539
|
+
describe('type checking', () => {
|
|
540
|
+
it('should have strong typing for 1 parameter', () => {
|
|
541
|
+
const singleParamFunc = defineFunction(
|
|
542
|
+
'singleParam',
|
|
543
|
+
(name: string) => `Hello ${name}`,
|
|
544
|
+
{ params: [{ name: 'name', type: 'string' }] }
|
|
545
|
+
);
|
|
546
|
+
|
|
547
|
+
// These should have strong typing
|
|
548
|
+
expectTypeOf(singleParamFunc).toBeFunction();
|
|
549
|
+
expectTypeOf(singleParamFunc).returns.toBeString();
|
|
550
|
+
|
|
551
|
+
// Test that it works
|
|
552
|
+
expect(singleParamFunc('World')).toBe('Hello World');
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
it('should have strong typing for 2 parameters', () => {
|
|
556
|
+
const twoParamFunc = defineFunction(
|
|
557
|
+
'twoParam',
|
|
558
|
+
(name: string, age: number) => `${name} is ${age} years old`,
|
|
559
|
+
{ params: [
|
|
560
|
+
{ name: 'name', type: 'string' },
|
|
561
|
+
{ name: 'age', type: 'number' }
|
|
562
|
+
] }
|
|
563
|
+
);
|
|
564
|
+
|
|
565
|
+
// These should have strong typing
|
|
566
|
+
expectTypeOf(twoParamFunc).toBeFunction();
|
|
567
|
+
expectTypeOf(twoParamFunc).returns.toBeString();
|
|
568
|
+
|
|
569
|
+
// Test that it works
|
|
570
|
+
expect(twoParamFunc('Alice', 25)).toBe('Alice is 25 years old');
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
it('should have strong typing for 3 parameters', () => {
|
|
574
|
+
const threeParamFunc = defineFunction(
|
|
575
|
+
'threeParam',
|
|
576
|
+
(name: string, age: number, city: string) => `${name} is ${age} from ${city}`,
|
|
577
|
+
{ params: [
|
|
578
|
+
{ name: 'name', type: 'string' },
|
|
579
|
+
{ name: 'age', type: 'number' },
|
|
580
|
+
{ name: 'city', type: 'string' }
|
|
581
|
+
] }
|
|
582
|
+
);
|
|
583
|
+
|
|
584
|
+
// These should have strong typing
|
|
585
|
+
expectTypeOf(threeParamFunc).toBeFunction();
|
|
586
|
+
expectTypeOf(threeParamFunc).returns.toBeString();
|
|
587
|
+
|
|
588
|
+
// Test that it works
|
|
589
|
+
expect(threeParamFunc('Bob', 30, 'New York')).toBe('Bob is 30 from New York');
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
it('should have strong typing for 4 parameters', () => {
|
|
593
|
+
const fourParamFunc = defineFunction(
|
|
594
|
+
'fourParam',
|
|
595
|
+
(name: string, age: number, city: string, active: boolean) =>
|
|
596
|
+
`${name} is ${age} from ${city}, ${active ? 'active' : 'inactive'}`,
|
|
597
|
+
{ params: [
|
|
598
|
+
{ name: 'name', type: 'string' },
|
|
599
|
+
{ name: 'age', type: 'number' },
|
|
600
|
+
{ name: 'city', type: 'string' },
|
|
601
|
+
{ name: 'active', type: 'boolean' }
|
|
602
|
+
] }
|
|
603
|
+
);
|
|
604
|
+
|
|
605
|
+
// These should have strong typing
|
|
606
|
+
expectTypeOf(fourParamFunc).toBeFunction();
|
|
607
|
+
expectTypeOf(fourParamFunc).returns.toBeString();
|
|
608
|
+
|
|
609
|
+
// Test that it works
|
|
610
|
+
expect(fourParamFunc('Charlie', 35, 'London', true)).toBe('Charlie is 35 from London, active');
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
it('should have strong typing for 5 parameters', () => {
|
|
614
|
+
const fiveParamFunc = defineFunction(
|
|
615
|
+
'fiveParam',
|
|
616
|
+
(name: string, age: number, city: string, active: boolean, score: number) =>
|
|
617
|
+
`${name} is ${age} from ${city}, ${active ? 'active' : 'inactive'}, score: ${score}`,
|
|
618
|
+
{ params: [
|
|
619
|
+
{ name: 'name', type: 'string' },
|
|
620
|
+
{ name: 'age', type: 'number' },
|
|
621
|
+
{ name: 'city', type: 'string' },
|
|
622
|
+
{ name: 'active', type: 'boolean' },
|
|
623
|
+
{ name: 'score', type: 'number' }
|
|
624
|
+
] }
|
|
625
|
+
);
|
|
626
|
+
|
|
627
|
+
// These should have strong typing
|
|
628
|
+
expectTypeOf(fiveParamFunc).toBeFunction();
|
|
629
|
+
expectTypeOf(fiveParamFunc).returns.toBeString();
|
|
630
|
+
|
|
631
|
+
// Test that it works
|
|
632
|
+
expect(fiveParamFunc('David', 40, 'Paris', false, 85)).toBe('David is 40 from Paris, inactive, score: 85');
|
|
633
|
+
});
|
|
634
|
+
|
|
635
|
+
it('should work with 6+ parameters (fallback typing)', () => {
|
|
636
|
+
const sixParamFunc = defineFunction(
|
|
637
|
+
'sixParam',
|
|
638
|
+
(name: string, age: number, city: string, active: boolean, score: number, level: string) =>
|
|
639
|
+
`${name} is ${age} from ${city}, ${active ? 'active' : 'inactive'}, score: ${score}, level: ${level}`,
|
|
640
|
+
{ params: [
|
|
641
|
+
{ name: 'name', type: 'string' },
|
|
642
|
+
{ name: 'age', type: 'number' },
|
|
643
|
+
{ name: 'city', type: 'string' },
|
|
644
|
+
{ name: 'active', type: 'boolean' },
|
|
645
|
+
{ name: 'score', type: 'number' },
|
|
646
|
+
{ name: 'level', type: 'string' }
|
|
647
|
+
] }
|
|
648
|
+
);
|
|
649
|
+
|
|
650
|
+
// Should still be a function, but without specific overloads
|
|
651
|
+
expectTypeOf(sixParamFunc).toBeFunction();
|
|
652
|
+
expectTypeOf(sixParamFunc).returns.toBeString();
|
|
653
|
+
|
|
654
|
+
// Test that it works
|
|
655
|
+
expect(sixParamFunc('Eve', 45, 'Tokyo', true, 92, 'expert')).toBe('Eve is 45 from Tokyo, active, score: 92, level: expert');
|
|
656
|
+
});
|
|
657
|
+
|
|
658
|
+
it('should work with 7+ parameters (fallback typing)', () => {
|
|
659
|
+
const sevenParamFunc = defineFunction(
|
|
660
|
+
'sevenParam',
|
|
661
|
+
(name: string, age: number, city: string, active: boolean, score: number, level: string, rank: number) =>
|
|
662
|
+
`${name} is ${age} from ${city}, ${active ? 'active' : 'inactive'}, score: ${score}, level: ${level}, rank: ${rank}`,
|
|
663
|
+
{ params: [
|
|
664
|
+
{ name: 'name', type: 'string' },
|
|
665
|
+
{ name: 'age', type: 'number' },
|
|
666
|
+
{ name: 'city', type: 'string' },
|
|
667
|
+
{ name: 'active', type: 'boolean' },
|
|
668
|
+
{ name: 'score', type: 'number' },
|
|
669
|
+
{ name: 'level', type: 'string' },
|
|
670
|
+
{ name: 'rank', type: 'number' }
|
|
671
|
+
] }
|
|
672
|
+
);
|
|
673
|
+
|
|
674
|
+
// Should still be a function, but without specific overloads
|
|
675
|
+
expectTypeOf(sevenParamFunc).toBeFunction();
|
|
676
|
+
expectTypeOf(sevenParamFunc).returns.toBeString();
|
|
677
|
+
|
|
678
|
+
// Test that it works
|
|
679
|
+
expect(sevenParamFunc('Frank', 50, 'Berlin', false, 78, 'intermediate', 3)).toBe('Frank is 50 from Berlin, inactive, score: 78, level: intermediate, rank: 3');
|
|
680
|
+
});
|
|
681
|
+
|
|
682
|
+
it('should demonstrate parameter name preservation in strong typing', () => {
|
|
683
|
+
const preservedFunc = defineFunction(
|
|
684
|
+
'preserved',
|
|
685
|
+
(firstName: string, lastName: string, age: number) => `${firstName} ${lastName} is ${age}`,
|
|
686
|
+
{ params: [
|
|
687
|
+
{ name: 'firstName', type: 'string' },
|
|
688
|
+
{ name: 'lastName', type: 'string' },
|
|
689
|
+
{ name: 'age', type: 'number' }
|
|
690
|
+
] }
|
|
691
|
+
);
|
|
692
|
+
|
|
693
|
+
// The function should preserve parameter names in the type signature
|
|
694
|
+
expectTypeOf(preservedFunc).toBeFunction();
|
|
695
|
+
expectTypeOf(preservedFunc).returns.toBeString();
|
|
696
|
+
|
|
697
|
+
// Test that it works
|
|
698
|
+
expect(preservedFunc('John', 'Doe', 30)).toBe('John Doe is 30');
|
|
699
|
+
});
|
|
700
|
+
|
|
701
|
+
it('should demonstrate optional parameters in strong typing', () => {
|
|
702
|
+
const optionalFunc = defineFunction(
|
|
703
|
+
'optional',
|
|
704
|
+
(name: string, age?: number, city?: string) => `${name}${age ? ` is ${age}` : ''}${city ? ` from ${city}` : ''}`,
|
|
705
|
+
{ params: [
|
|
706
|
+
{ name: 'name', type: 'string' },
|
|
707
|
+
{ name: 'age', type: 'number', optional: true },
|
|
708
|
+
{ name: 'city', type: 'string', optional: true }
|
|
709
|
+
] }
|
|
710
|
+
);
|
|
711
|
+
|
|
712
|
+
// Should have strong typing for optional parameters
|
|
713
|
+
expectTypeOf(optionalFunc).toBeFunction();
|
|
714
|
+
expectTypeOf(optionalFunc).returns.toBeString();
|
|
715
|
+
|
|
716
|
+
// Test various combinations
|
|
717
|
+
expect(optionalFunc('Alice')).toBe('Alice');
|
|
718
|
+
expect(optionalFunc('Bob', 25)).toBe('Bob is 25');
|
|
719
|
+
expect(optionalFunc('Charlie', 30, 'London')).toBe('Charlie is 30 from London');
|
|
720
|
+
});
|
|
721
|
+
|
|
722
|
+
it('should demonstrate default values in strong typing', () => {
|
|
723
|
+
const defaultFunc = defineFunction(
|
|
724
|
+
'default',
|
|
725
|
+
(name: string, age: number, city: string) => `${name} is ${age} from ${city}`,
|
|
726
|
+
{ params: [
|
|
727
|
+
{ name: 'name', type: 'string' },
|
|
728
|
+
{ name: 'age', type: 'number', default: 25 },
|
|
729
|
+
{ name: 'city', type: 'string', default: 'Unknown' }
|
|
730
|
+
] }
|
|
731
|
+
);
|
|
732
|
+
|
|
733
|
+
// Should have strong typing with defaults
|
|
734
|
+
expectTypeOf(defaultFunc).toBeFunction();
|
|
735
|
+
expectTypeOf(defaultFunc).returns.toBeString();
|
|
736
|
+
|
|
737
|
+
// Test that defaults work
|
|
738
|
+
expect(defaultFunc('David')).toBe('David is 25 from Unknown');
|
|
739
|
+
expect(defaultFunc('Eve', 30)).toBe('Eve is 30 from Unknown');
|
|
740
|
+
expect(defaultFunc('Frank', 35, 'Paris')).toBe('Frank is 35 from Paris');
|
|
741
|
+
});
|
|
742
|
+
});
|
|
743
|
+
|
|
744
|
+
describe('error messages', () => {
|
|
745
|
+
it('should provide descriptive error messages', () => {
|
|
746
|
+
try {
|
|
747
|
+
(myFunc as any)(123, 'invalid');
|
|
748
|
+
} catch (error) {
|
|
749
|
+
expect((error as Error).message).toContain('Argument \'name\' must be of type \'string\'');
|
|
750
|
+
expect((error as Error).message).toContain('Got: number');
|
|
751
|
+
}
|
|
752
|
+
});
|
|
753
|
+
|
|
754
|
+
it('should provide error messages for record calls', () => {
|
|
755
|
+
try {
|
|
756
|
+
(myFunc as any)({ name: 456, value: 'invalid' });
|
|
757
|
+
} catch (error) {
|
|
758
|
+
expect((error as Error).message).toContain('Argument \'name\' must be of type \'string\'');
|
|
759
|
+
expect((error as Error).message).toContain('Got: number');
|
|
760
|
+
}
|
|
761
|
+
});
|
|
762
|
+
});
|
|
763
|
+
});
|