@sablier/devkit 1.6.1 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/biome/base.jsonc +30 -7
- package/biome/ui.jsonc +11 -50
- package/just/csv.just +102 -0
- package/just/tsv.just +7 -72
- package/package.json +2 -1
- package/vitest/base.js +1 -1
package/biome/base.jsonc
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// which files to lint and format. For example:
|
|
7
7
|
//
|
|
8
8
|
// {
|
|
9
|
-
// "extends": ["@sablier/devkit/biome"],
|
|
9
|
+
// "extends": ["@sablier/devkit/biome/base"],
|
|
10
10
|
// "files": {
|
|
11
11
|
// "includes": ["**/*.{css,js,jsx,json,ts,tsx}", "!node_modules"]
|
|
12
12
|
// }
|
|
@@ -38,23 +38,41 @@
|
|
|
38
38
|
"linter": {
|
|
39
39
|
"enabled": true,
|
|
40
40
|
"rules": {
|
|
41
|
+
"recommended": true,
|
|
42
|
+
"complexity": {
|
|
43
|
+
"noImplicitCoercions": "error", // forbid `!!foo`, allow `Boolean(foo)`
|
|
44
|
+
"noVoid": "off" // void is useful in some cases e.g. `useEffect` callbacks
|
|
45
|
+
},
|
|
41
46
|
"correctness": {
|
|
42
|
-
"noUnusedImports": "off",
|
|
43
|
-
"noUnusedVariables": "error"
|
|
44
|
-
"useExhaustiveDependencies": "error"
|
|
47
|
+
"noUnusedImports": "off", // allow unused imports during development
|
|
48
|
+
"noUnusedVariables": "error"
|
|
45
49
|
},
|
|
46
50
|
"nursery": {
|
|
47
|
-
"noFloatingPromises": "error"
|
|
51
|
+
"noFloatingPromises": "error", // floating promises can lead to bugs
|
|
52
|
+
"noUselessUndefined": "off" // we want explicit undefined return values
|
|
53
|
+
},
|
|
54
|
+
"performance": {
|
|
55
|
+
"noBarrelFile": "off", // barrel exports lead to cleaner imports
|
|
56
|
+
"noDelete": "off", // disabled due to https://github.com/biomejs/biome/issues/4093
|
|
57
|
+
"noNamespaceImport": "off" // namespaces are cool
|
|
48
58
|
},
|
|
49
|
-
"recommended": true,
|
|
50
59
|
"style": {
|
|
60
|
+
"noNamespace": "off", // namespaces are cool
|
|
61
|
+
"useDefaultSwitchClause": "off", // already handled by TypeScript
|
|
62
|
+
"useFilenamingConvention": {
|
|
63
|
+
"level": "error",
|
|
64
|
+
"options": {
|
|
65
|
+
"filenameCases": ["kebab-case", "camelCase", "PascalCase", "export"]
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
// disabled due to https://github.com/biomejs/biome/issues/8450
|
|
51
69
|
"useImportType": {
|
|
52
70
|
"level": "warn",
|
|
53
71
|
"options": {
|
|
54
72
|
"style": "separatedType"
|
|
55
73
|
}
|
|
56
74
|
},
|
|
57
|
-
"useTemplate": "off"
|
|
75
|
+
"useTemplate": "off" // allow string concatenation using `+`
|
|
58
76
|
}
|
|
59
77
|
}
|
|
60
78
|
},
|
|
@@ -70,6 +88,11 @@
|
|
|
70
88
|
"includes": ["**/*.{json,json5,jsonc}"]
|
|
71
89
|
}
|
|
72
90
|
],
|
|
91
|
+
"json": {
|
|
92
|
+
"formatter": {
|
|
93
|
+
"lineWidth": 100
|
|
94
|
+
}
|
|
95
|
+
},
|
|
73
96
|
"vcs": {
|
|
74
97
|
"clientKind": "git",
|
|
75
98
|
"enabled": true,
|
package/biome/ui.jsonc
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// Sablier Devkit UI configuration for Biome v2
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
3
|
+
// Extends base configuration with UI-specific rules for accessibility,
|
|
4
|
+
// Tailwind CSS class sorting, and CSS modules support.
|
|
5
5
|
//
|
|
6
|
-
// IMPORTANT: Consumers must
|
|
7
|
-
//
|
|
6
|
+
// IMPORTANT: Consumers must extend BOTH configs and add their own
|
|
7
|
+
// `files.includes` patterns. For example:
|
|
8
8
|
//
|
|
9
9
|
// {
|
|
10
|
-
// "extends": ["@sablier/devkit/biome/ui"],
|
|
10
|
+
// "extends": ["@sablier/devkit/biome/base", "@sablier/devkit/biome/ui"],
|
|
11
11
|
// "files": {
|
|
12
12
|
// "includes": ["**/*.{css,js,jsx,json,ts,tsx}", "!node_modules"]
|
|
13
13
|
// }
|
|
@@ -18,40 +18,28 @@
|
|
|
18
18
|
"enabled": true,
|
|
19
19
|
"actions": {
|
|
20
20
|
"source": {
|
|
21
|
-
"
|
|
22
|
-
"useSortedKeys": "on"
|
|
21
|
+
"useSortedAttributes": "on"
|
|
23
22
|
}
|
|
24
23
|
}
|
|
25
24
|
},
|
|
26
25
|
"css": {
|
|
26
|
+
"formatter": {
|
|
27
|
+
"lineWidth": 100
|
|
28
|
+
},
|
|
27
29
|
"parser": {
|
|
28
30
|
"cssModules": true,
|
|
29
31
|
"tailwindDirectives": true
|
|
30
32
|
}
|
|
31
33
|
},
|
|
32
|
-
"files": {
|
|
33
|
-
"maxSize": 5242880 // 5MB
|
|
34
|
-
},
|
|
35
|
-
"formatter": {
|
|
36
|
-
"enabled": true,
|
|
37
|
-
"formatWithErrors": true,
|
|
38
|
-
"indentStyle": "space",
|
|
39
|
-
"lineWidth": 100
|
|
40
|
-
},
|
|
41
34
|
"linter": {
|
|
42
|
-
"enabled": true,
|
|
43
35
|
"rules": {
|
|
44
36
|
"a11y": {
|
|
45
37
|
"noSvgWithoutTitle": "off",
|
|
46
38
|
"useKeyWithClickEvents": "off"
|
|
47
39
|
},
|
|
48
|
-
"correctness": {
|
|
49
|
-
"noUnusedImports": "off",
|
|
50
|
-
"noUnusedVariables": "error",
|
|
51
|
-
"useExhaustiveDependencies": "error"
|
|
52
|
-
},
|
|
53
40
|
"nursery": {
|
|
54
|
-
|
|
41
|
+
// Sort Tailwind CSS classes alphabetically
|
|
42
|
+
// See https://github.com/biomejs/biome/issues/1274#issuecomment-3490774696
|
|
55
43
|
"useSortedClasses": {
|
|
56
44
|
"fix": "safe",
|
|
57
45
|
"level": "warn",
|
|
@@ -60,34 +48,7 @@
|
|
|
60
48
|
"functions": ["clsx", "cva", "cn", "tv", "tw", "tw.*"]
|
|
61
49
|
}
|
|
62
50
|
}
|
|
63
|
-
},
|
|
64
|
-
"recommended": true,
|
|
65
|
-
"style": {
|
|
66
|
-
"useImportType": {
|
|
67
|
-
"level": "warn",
|
|
68
|
-
"options": {
|
|
69
|
-
"style": "separatedType"
|
|
70
|
-
}
|
|
71
|
-
},
|
|
72
|
-
"useTemplate": "off"
|
|
73
51
|
}
|
|
74
52
|
}
|
|
75
|
-
},
|
|
76
|
-
"overrides": [
|
|
77
|
-
{
|
|
78
|
-
"assist": {
|
|
79
|
-
"actions": {
|
|
80
|
-
"source": {
|
|
81
|
-
"useSortedKeys": "off"
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
},
|
|
85
|
-
"includes": ["**/*.{json,json5,jsonc}"]
|
|
86
|
-
}
|
|
87
|
-
],
|
|
88
|
-
"vcs": {
|
|
89
|
-
"clientKind": "git",
|
|
90
|
-
"enabled": true,
|
|
91
|
-
"useIgnoreFile": true
|
|
92
53
|
}
|
|
93
54
|
}
|
package/just/csv.just
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import "./settings.just"
|
|
2
|
+
|
|
3
|
+
# ---------------------------------------------------------------------------- #
|
|
4
|
+
# SCRIPTS #
|
|
5
|
+
# ---------------------------------------------------------------------------- #
|
|
6
|
+
|
|
7
|
+
# Check CSV/TSV files using qsv: https://github.com/dathere/qsv
|
|
8
|
+
[group("checks"), script("python3")]
|
|
9
|
+
_csv-check globs="data/*/*.csv" ext="CSV" schema="" ignore="*.csv.invalid|*.csv.valid|*validation-errors.csv":
|
|
10
|
+
import fnmatch
|
|
11
|
+
import glob as globmod
|
|
12
|
+
import subprocess
|
|
13
|
+
import sys
|
|
14
|
+
|
|
15
|
+
# Check qsv is available
|
|
16
|
+
if subprocess.run(["which", "qsv"], capture_output=True).returncode != 0:
|
|
17
|
+
print("✗ qsv CLI not found")
|
|
18
|
+
print("Install it: https://github.com/dathere/qsv")
|
|
19
|
+
sys.exit(1)
|
|
20
|
+
|
|
21
|
+
ext = "{{ ext }}" or "CSV"
|
|
22
|
+
ignore_patterns = "{{ ignore }}".split("|") if "{{ ignore }}" else []
|
|
23
|
+
schema = "{{ schema }}" or None
|
|
24
|
+
globs = "{{ globs }}"
|
|
25
|
+
|
|
26
|
+
print(f"Validating {ext} files...")
|
|
27
|
+
files = globmod.glob(globs)
|
|
28
|
+
|
|
29
|
+
# Filter ignored files
|
|
30
|
+
files = [f for f in files if not any(fnmatch.fnmatch(f, p) for p in ignore_patterns)]
|
|
31
|
+
|
|
32
|
+
if not files:
|
|
33
|
+
print(f"ℹ️ No {ext} files found to validate")
|
|
34
|
+
sys.exit(0)
|
|
35
|
+
|
|
36
|
+
for file in files:
|
|
37
|
+
cmd = ["qsv", "validate", file]
|
|
38
|
+
if schema:
|
|
39
|
+
cmd.append(schema)
|
|
40
|
+
result = subprocess.run(cmd, capture_output=True)
|
|
41
|
+
if result.returncode != 0:
|
|
42
|
+
print(f"❌ Validation failed for: {file}")
|
|
43
|
+
subprocess.run(["just", "_csv-show-errors", file, ext])
|
|
44
|
+
sys.exit(1)
|
|
45
|
+
|
|
46
|
+
print(f"✅ All {ext} files are valid")
|
|
47
|
+
|
|
48
|
+
# Show validation errors for a CSV/TSV file
|
|
49
|
+
[group("checks"), script("python3")]
|
|
50
|
+
_csv-show-errors file ext="CSV":
|
|
51
|
+
import os
|
|
52
|
+
import subprocess
|
|
53
|
+
import sys
|
|
54
|
+
|
|
55
|
+
file = "{{ file }}"
|
|
56
|
+
error_file = f"{file}.validation-errors.tsv"
|
|
57
|
+
|
|
58
|
+
if not os.path.exists(error_file):
|
|
59
|
+
print(f"Error file not found: {error_file}")
|
|
60
|
+
sys.exit(0)
|
|
61
|
+
|
|
62
|
+
# Count errors (qsv auto-detects .tsv delimiter)
|
|
63
|
+
result = subprocess.run(["qsv", "count", error_file], capture_output=True, text=True)
|
|
64
|
+
try:
|
|
65
|
+
total = int(result.stdout.strip()) if result.returncode == 0 and result.stdout.strip() else 0
|
|
66
|
+
except ValueError:
|
|
67
|
+
total = 0
|
|
68
|
+
|
|
69
|
+
print()
|
|
70
|
+
if total > 0:
|
|
71
|
+
print(f"First 20 validation errors ({total} total):")
|
|
72
|
+
else:
|
|
73
|
+
print("Validation errors:")
|
|
74
|
+
print()
|
|
75
|
+
|
|
76
|
+
# Try qsv table for nice formatting, fall back to reading file directly
|
|
77
|
+
slice_result = subprocess.run(
|
|
78
|
+
["qsv", "slice", "--start", "0", "--len", "21", error_file],
|
|
79
|
+
capture_output=True, text=True
|
|
80
|
+
)
|
|
81
|
+
if slice_result.returncode == 0:
|
|
82
|
+
table_result = subprocess.run(
|
|
83
|
+
["qsv", "table"],
|
|
84
|
+
input=slice_result.stdout,
|
|
85
|
+
capture_output=True, text=True
|
|
86
|
+
)
|
|
87
|
+
if table_result.returncode == 0:
|
|
88
|
+
print(table_result.stdout)
|
|
89
|
+
else:
|
|
90
|
+
print(slice_result.stdout)
|
|
91
|
+
else:
|
|
92
|
+
with open(error_file) as f:
|
|
93
|
+
for i, line in enumerate(f):
|
|
94
|
+
if i >= 21:
|
|
95
|
+
break
|
|
96
|
+
print(line, end="")
|
|
97
|
+
|
|
98
|
+
if total > 20:
|
|
99
|
+
print()
|
|
100
|
+
print(f"... and {total - 20} more errors")
|
|
101
|
+
print()
|
|
102
|
+
print(f"Full details: {error_file}")
|
package/just/tsv.just
CHANGED
|
@@ -1,80 +1,15 @@
|
|
|
1
|
-
import "./
|
|
1
|
+
import "./csv.just"
|
|
2
2
|
|
|
3
3
|
# ---------------------------------------------------------------------------- #
|
|
4
|
-
#
|
|
4
|
+
# TSV WRAPPERS #
|
|
5
5
|
# ---------------------------------------------------------------------------- #
|
|
6
6
|
|
|
7
7
|
# Check TSV files using qsv: https://github.com/dathere/qsv
|
|
8
|
-
[group("checks")
|
|
9
|
-
_tsv-check globs="data/*/*.tsv" schema="" ignore="*.tsv.invalid|*.tsv.valid|*validation-errors.tsv":
|
|
10
|
-
|
|
11
|
-
echo "✗ qsv CLI not found"
|
|
12
|
-
echo "Install it: https://github.com/dathere/qsv"
|
|
13
|
-
exit 1
|
|
14
|
-
fi
|
|
15
|
-
|
|
16
|
-
echo "Validating TSV files..."
|
|
17
|
-
found=0
|
|
18
|
-
for file in {{ globs }}; do
|
|
19
|
-
# Skip validation artifact files
|
|
20
|
-
case "$file" in
|
|
21
|
-
{{ ignore }})
|
|
22
|
-
continue
|
|
23
|
-
;;
|
|
24
|
-
esac
|
|
25
|
-
|
|
26
|
-
# Skip if no files match the pattern
|
|
27
|
-
[ -e "$file" ] || continue
|
|
28
|
-
|
|
29
|
-
found=$((found + 1))
|
|
30
|
-
schema_arg="{{ schema }}"
|
|
31
|
-
if ! qsv validate "$file" ${schema_arg:+"$schema_arg"} > /dev/null 2>&1; then
|
|
32
|
-
echo "❌ Validation failed for: $file"
|
|
33
|
-
just _tsv-show-errors "$file"
|
|
34
|
-
exit 1
|
|
35
|
-
fi
|
|
36
|
-
done
|
|
37
|
-
|
|
38
|
-
if [ "$found" -eq 0 ]; then
|
|
39
|
-
echo "ℹ️ No TSV files found to validate"
|
|
40
|
-
else
|
|
41
|
-
echo "✅ All TSV files are valid"
|
|
42
|
-
fi
|
|
8
|
+
[group("checks")]
|
|
9
|
+
_tsv-check globs="data/*/*.tsv" ext="TSV" schema="" ignore="*.tsv.invalid|*.tsv.valid|*validation-errors.tsv":
|
|
10
|
+
@just _csv-check "{{ globs }}" "{{ ext }}" "{{ schema }}" "{{ ignore }}"
|
|
43
11
|
|
|
44
12
|
# Show validation errors for a TSV file
|
|
45
|
-
[group("checks")
|
|
13
|
+
[group("checks")]
|
|
46
14
|
_tsv-show-errors file:
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
if [ ! -f "$error_file" ]; then
|
|
50
|
-
echo "Error file not found: $error_file"
|
|
51
|
-
exit 0
|
|
52
|
-
fi
|
|
53
|
-
|
|
54
|
-
# Try to count total errors (subtract 1 for header row)
|
|
55
|
-
total_errors=$(qsv count "$error_file" 2>/dev/null || echo "0")
|
|
56
|
-
if [ "$total_errors" != "0" ]; then
|
|
57
|
-
total_errors=$((total_errors - 1))
|
|
58
|
-
fi
|
|
59
|
-
|
|
60
|
-
echo ""
|
|
61
|
-
if [ "$total_errors" != "0" ] && [ "$total_errors" -gt 0 ]; then
|
|
62
|
-
echo "First 20 validation errors (${total_errors} total):"
|
|
63
|
-
else
|
|
64
|
-
echo "Validation errors:"
|
|
65
|
-
fi
|
|
66
|
-
echo ""
|
|
67
|
-
|
|
68
|
-
# Try to use qsv table for nice formatting, fall back to basic display
|
|
69
|
-
if qsv slice --start 0 --len 21 "$error_file" 2>/dev/null | qsv table 2>/dev/null; then
|
|
70
|
-
: # Success, output already shown
|
|
71
|
-
else
|
|
72
|
-
head -n 21 "$error_file"
|
|
73
|
-
fi
|
|
74
|
-
|
|
75
|
-
if [ "$total_errors" != "0" ] && [ "$total_errors" -gt 20 ]; then
|
|
76
|
-
echo ""
|
|
77
|
-
echo "... and $((total_errors - 20)) more errors"
|
|
78
|
-
fi
|
|
79
|
-
echo ""
|
|
80
|
-
echo "Full details: $error_file"
|
|
15
|
+
@just _csv-show-errors "{{ file }}" "TSV"
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Configuration files and reusable scripts for Sablier repositories",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"version": "1.
|
|
6
|
+
"version": "1.8.0",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "Sablier Labs Ltd",
|
|
9
9
|
"url": "https://sablier.com"
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
},
|
|
27
27
|
"exports": {
|
|
28
28
|
"./biome": "./biome/base.jsonc",
|
|
29
|
+
"./biome/base": "./biome/base.jsonc",
|
|
29
30
|
"./biome/ui": "./biome/ui.jsonc",
|
|
30
31
|
"./prettier": "./.prettierrc.json",
|
|
31
32
|
"./tsconfig/base": "./tsconfig/base.json",
|
package/vitest/base.js
CHANGED
|
@@ -11,7 +11,7 @@ import { defineConfig, mergeConfig } from "vitest/config";
|
|
|
11
11
|
* @param {DevkitVitestOptions} [options]
|
|
12
12
|
*/
|
|
13
13
|
export function defineDevkitConfig(options = {}) {
|
|
14
|
-
const isCI =
|
|
14
|
+
const isCI = Boolean(process.env.CI);
|
|
15
15
|
|
|
16
16
|
const baseConfig = {
|
|
17
17
|
test: {
|