Skip to content

Commit

Permalink
feat(util): unassert
Browse files Browse the repository at this point in the history
Signed-off-by: Lexus Drumgold <[email protected]>
  • Loading branch information
unicornware committed Mar 2, 2024
1 parent 1fb494f commit ffff530
Show file tree
Hide file tree
Showing 31 changed files with 738 additions and 35 deletions.
1 change: 1 addition & 0 deletions .commitlintrc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const config: UserConfig = {
'scope-enum': [Severity.Error, 'always', scopes([
'chore',
'handlers',
'util',
'visitors'
])]
}
Expand Down
1 change: 1 addition & 0 deletions .dictionary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,6 @@ shfmt
unassert
unstub
vates
vfile
vitest
yarnrc
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
**/node_modules/
**/tsconfig*temp.json
Brewfile
__fixtures__/modules/*.cjs
yarn.lock

# NEGATED PATTERNS
Expand Down
22 changes: 21 additions & 1 deletion .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,27 @@
*/
const config = {
extends: ['./.eslintrc.base.cjs'],
overrides: [...require('./.eslintrc.base.cjs').overrides],
overrides: [
...require('./.eslintrc.base.cjs').overrides,
{
files: ['__fixtures__/modules/*.mjs'],
rules: {
'@typescript-eslint/no-confusing-void-expression': 0,
'@typescript-eslint/no-unsafe-argument': 0,
'@typescript-eslint/no-unsafe-call': 0,
'@typescript-eslint/no-unsafe-member-access': 0,
'@typescript-eslint/no-unsafe-return': 0,
'@typescript-eslint/require-await': 0,
'@typescript-eslint/restrict-plus-operands': 0,
'@typescript-eslint/restrict-template-expressions': 0,
'@typescript-eslint/strict-boolean-expressions': 0,
'jsdoc/require-file-overview': 0,
'jsdoc/require-jsdoc': 0,
'unicorn/prefer-math-trunc': 0,
'unicorn/prefer-node-protocol': 0
}
}
],
root: true
}

Expand Down
2 changes: 1 addition & 1 deletion .lintstagedrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
"src/**/*.ts": [
"vitest run --changed --coverage",
"yarn build",
"bash -c tsc -p tsconfig.build.json"
"bash -c tsc -p tsconfig.json"
]
}
18 changes: 18 additions & 0 deletions __fixtures__/modules/add.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { deprecate, equal, ok } from 'devlop'

function add(a, b) {
ok(typeof a === 'number', 'expected `a` to be a number')
ok(typeof b === 'number', 'expected `b` to be a number')

if (process.env.NODE_ENV !== 'production') {
equal(Number.isNaN(a), false, 'expected `a` not to equal NaN')
equal(Number.isNaN(b), false, 'expected `b` not to equal NaN')
} else {
ok(!Number.isNaN(a), 'expected `a` not to be NaN')
ok(!Number.isNaN(b), 'expected `b` not to be NaN')
}

return a + b
}

export default deprecate(add)
5 changes: 5 additions & 0 deletions __fixtures__/modules/assert.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
function assert(value, message, ...params) {
return void console.assert(value, message, ...params)
}

export default assert
97 changes: 97 additions & 0 deletions __fixtures__/modules/call-expression.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import {
DOT,
at,
define,
set
} from '@flex-development/tutils'
import { ok, unreachable } from 'devlop'
import { CONTINUE } from 'estree-util-visit'
import { is } from 'unist-util-is'

function CallExpression(node, key, index) {
if (
(
is(node.callee, 'Identifier') &&
this.identifiers.has(node.callee.name)
) ||
(
is(node.callee, 'MemberExpression') &&
is(node.callee.object, 'Identifier') &&
this.identifiers.has(node.callee.object.name)
) ||
(
is(node.callee, 'MemberExpression') &&
is(node.callee.object, 'Identifier') &&
is(node.callee.property, 'Identifier') &&
node.callee.object.name === 'console' &&
node.callee.property.name === 'assert'
)
) {
ok(this.parent, 'expected `parent`')
ok(key, 'expected `key`')
ok(key in this.parent, `expected \`parent.${key}\``)
const zero = { raw: '0', type: 'Literal', value: 0 }
const void0 = {
argument: zero,
operator: 'void',
prefix: true,
type: 'UnaryExpression'
}
switch (this.parent.type) {
case 'ArrayExpression':
case 'CallExpression':
ok(typeof index === 'number', 'expected `index` to be a number')
set(this.parent, key + DOT + index, void0)
break
case 'AssignmentExpression':
if (is(this.grandparent, 'ExpressionStatement')) {
this.trash.add(this.grandparent)
} else {
define(this.parent, key, { value: void0 })
}
break
case 'ArrowFunctionExpression':
case 'AssignmentPattern':
case 'ConditionalExpression':
case 'LogicalExpression':
case 'Property':
define(this.parent, key, { value: void0 })
break
case 'AwaitExpression':
if (is(this.grandparent, 'ExpressionStatement')) {
this.trash.add(this.grandparent)
} else {
define(this.parent, key, { value: void0 })
}
break
case 'ExpressionStatement':
this.trash.add(this.parent)
break
case 'ExportDefaultDeclaration':
define(this.parent, key, { value: at(node.arguments, 0, void0) })
break
case 'ReturnStatement':
case 'YieldExpression':
define(this.parent, key, { value: null })
break
case 'UnaryExpression':
if (is(this.grandparent, 'ExpressionStatement')) {
this.trash.add(this.grandparent)
} else {
define(this.parent, key, {
value: this.parent.operator === 'void' ? zero : void0
})
}
break
default:
console.dir(this.parent, { depth: 10 })
void unreachable(`unexpected parent: ${this.parent.type}`)
}
}
return CONTINUE
}

var call_expression_default = CallExpression
export {
call_expression_default as default
}
10 changes: 10 additions & 0 deletions __fixtures__/modules/century-from-year.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const { ok } = await import('devlop')
const assert = await import('node:assert/strict')

const centuryFromYear = year => {
ok(typeof year === 'number', 'expected `year` to be a number')
assert.notEqual(Number.isNaN(year), true, 'expected `year` not to be NaN')
return Math.ceil(year / 100)
}

export default centuryFromYear
17 changes: 17 additions & 0 deletions __fixtures__/modules/digitize.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { ok } from 'devlop'
import * as assert from 'node:assert/strict'

function digitize(n) {
ok(typeof n === 'number', 'expected `n` to be a number')

if (process.env.NODE_ENV !== 'production') {
assert.notEqual(Number.isNaN(n), true, 'expected `n` not to be NaN')
} else ok(n >= 0, 'expected `n` to be a non-negative number')

if (n <= 9) return [n]
const digits = []
while (n > 0) digits.push(n % 10 | 0) && (n = n / 10 | 0)
return digits
}

export default digitize
13 changes: 13 additions & 0 deletions __fixtures__/modules/divide.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use strict'

let assert = require('assert'), bar = 'BAR', foo = 'FOO'

function divide(a, b) {
assert.equal(typeof a, 'number')
assert(!isNaN(a))
assert.equal(typeof b, 'number')
assert.ok(!isNaN(b))
return a / b
}

module.exports = module.exports.default = divide
25 changes: 25 additions & 0 deletions __fixtures__/modules/gemoji-html.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { ok } from 'devlop'
import { nameToEmoji } from 'gemoji'
import { codes } from 'micromark-util-symbol'
function gemojiHtml() {
return {
enter: {
gemoji() {
return void this.tag('<span>')
}
},
exit: {
gemoji(token) {
const val = this.sliceSerialize(token)
ok(val.codePointAt(0) === codes.colon, 'expected `:` start')
ok(val.codePointAt(val.length - 1) === codes.colon, 'expected `:` end')
this.raw(nameToEmoji[val.slice(1, -1)] ?? val)
return void this.tag('</span>')
}
}
}
}
var html_default = gemojiHtml
export {
html_default as default
}
49 changes: 49 additions & 0 deletions __fixtures__/modules/gemoji-shortcode.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { ok as assert } from 'devlop'
import { asciiAlphanumeric } from 'micromark-util-character'
import { codes } from 'micromark-util-symbol'
function previous(code) {
return code !== codes.backslash && code !== codes.colon
}
var shortcode_default = {
name: 'gemoji',
previous,
tokenize(effects, ok, nok) {
function inside(code) {
switch (true) {
case code === codes.colon:
effects.consume(code)
effects.exit('gemoji')
return ok
case asciiAlphanumeric(code):
case code === codes.dash:
case code === codes.plusSign:
case code === codes.underscore:
effects.consume(code)
return inside
default:
return nok(code)
}
}
function begin(code) {
switch (code) {
case codes.eof:
case codes.colon:
return nok(code)
default:
effects.consume(code)
return inside
}
}
const start = code => {
assert(code === codes.colon, 'expected `:`')
assert(previous.call(this, this.previous), 'expected correct previous')
effects.enter('gemoji')
effects.consume(code)
return begin
}
return start
}
}
export {
shortcode_default as default
}
14 changes: 14 additions & 0 deletions __fixtures__/modules/http-assert.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
'use strict'

const assert = require('http-assert')
const { ok, equal: eq, deepEqual: deq } = require('node:assert')

module.exports = module.exports.default = function(username, check) {
try {
assert(username == check, 401, 'authentication failed')
} catch (err) {
eq(err.status, 401)
deq(err.message, 'authentication failed')
ok(err.expose)
}
}
22 changes: 22 additions & 0 deletions __fixtures__/modules/human-readable.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ok } from 'devlop'
import * as assert from 'node:assert/strict'

async function humanReadable(seconds) {
ok(typeof seconds === 'number', 'expected `seconds` to be a number')
await assert.doesNotReject(async () => seconds.toFixed(2))

return new Promise(resolve => {
let formatted = ''

for (const converter of [3600, 60, 1]) {
const time = seconds / converter | 0
formatted += time < 10 ? `0${time}` : time
if (converter !== 1) formatted += ':'
seconds -= time * converter
}

return resolve(formatted)
})
}

export default humanReadable
13 changes: 13 additions & 0 deletions __fixtures__/modules/multiply.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use strict'

const { strict: assert } = require('assert')

const multiply = function(a, b) {
console.assert(typeof a === 'number')
assert(!isNaN(a))
assert.equal(typeof b, 'number')
assert.ok(!isNaN(b))
return a * b
}

module.exports = module.exports.default = multiply
3 changes: 3 additions & 0 deletions __fixtures__/modules/noop.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { ok } from 'devlop'

export default () => ok(true)
9 changes: 9 additions & 0 deletions __fixtures__/modules/subtract.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import * as assert from 'node:assert'

function subtract(a, b) {
assert.ok(typeof a === 'number', 'expected a to be a number')
assert.ok(typeof b === 'number', 'expected b to be a number')
return a - b
}

export default subtract
Loading

0 comments on commit ffff530

Please sign in to comment.