Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/arktype-upgrade.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@jhecht/arktype-utils': major
---

Updated to ArkType 2.0.4

This moves off of the old 1.x beta and into 2, which marks a major update to ArkType and
is therefore a major move for the utils.
5 changes: 4 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,8 @@
"extends": [
"plugin:@jhecht/recommended",
"plugin:@typescript-eslint/recommended"
]
],
"rules": {
"arrow-parens": ["error", "as-needed"]
}
}
2 changes: 1 addition & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
"singleQuote": true,
"tabWidth": 2,
"semi": true,
"arrowParens": "avoid",
"arrowParens": "always",
"endOfLine": "lf"
}
3 changes: 2 additions & 1 deletion packages/arktype-utils/.eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"plugin:@typescript-eslint/recommended"
],
"rules": {
"arrow-parens": ["warn", "always"]
"arrow-parens": ["warn", "always"],
"@jhecht/max-static-destructure-depth": ["error", 3]
}
}
4 changes: 2 additions & 2 deletions packages/arktype-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@
"@jhecht/typescript-config": "workspace:*",
"@vitest/browser": "^1.2.0",
"@vitest/coverage-v8": "^1.2.2",
"arktype": "^1.0.28-alpha",
"arktype": "^2.0.4",
"eslint": "^7.11.0",
"jsdom": "^24.0.0",
"tsup": "^8.0.1",
"typescript": "^5.3.3",
"vitest": "^1.1.3"
},
"peerDependencies": {
"arktype": "^1.0.28-alpha"
"arktype": "^2.0.4"
}
}
25 changes: 24 additions & 1 deletion packages/arktype-utils/src/formData.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,29 @@ describe('formDataToObject', () => {
});
});

it('Should work with specified keys in arrays', () => {
const fd = new FormData();
fd.append('names[0]', 'bob');
fd.append('names[2]', 'joe');
fd.append('names[1]', 'rob');
expect(formDataToObject(fd)).toStrictEqual({
names: ['bob', 'rob', 'joe'],
});
});

it('Should work with objects', () => {
const fd = new FormData();
fd.append('locations[london]', '24');
fd.append('locations[new_york]', '77');

expect(formDataToObject(fd)).toStrictEqual({
locations: {
london: 24,
new_york: 77,
},
});
});

it('Should work with File objects', () => {
const fd = new FormData();
fd.set('file', new File([], 'testing.txt'));
Expand Down Expand Up @@ -130,7 +153,7 @@ describe('validateFormData', () => {
fd.append('file-upload', f);

const passSchema = type({
emails: 'email[]',
emails: 'string.email[]',
something: 'boolean',
'something-else': 'bigint',
'file-upload': fileType,
Expand Down
57 changes: 45 additions & 12 deletions packages/arktype-utils/src/formData.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import type { Problems, Type } from 'arktype';
import type { Type } from 'arktype';
import { type } from 'arktype';

type EntriesTouple = [string, FormDataEntryValue];

Expand Down Expand Up @@ -85,7 +86,7 @@ export function formDataToObject(
iterator = iterator.slice(0, iterator.indexOf('['));

// Set the iterator value on returned object
ret[iterator] = all.map(v =>
ret[iterator] = all.map((v) =>
typeof v === 'string' ? stringToJSValue(v) : v,
);
} else {
Expand All @@ -105,13 +106,7 @@ export function formDataToObject(
info.set(name, magic);
}

// If the index is '', it means we were given something like `name[]`, or `age[]`
if (index === '') {
// Get all the values for this iterator
const all = fd.getAll(iterator);
// Loop over
for (const a of all) magic.add('', a as string);
} else magic.add(index, value);
magic.add(index, value);
}
}

Expand Down Expand Up @@ -159,9 +154,47 @@ export function validateFormData<T extends Type<any>>(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
): T extends Type<infer R> ? R : any {
const fdo = formDataToObject(fd, filterFn);
const { data, problems } = obj(fdo);
const data = obj(fdo);

if (data) return data;
if (data instanceof type.errors) throw data;

throw problems;
return data;
}

// This section is here because i don't want to publish the makeMagicObject function
// But I should still test it
if (import.meta.vitest) {
const { it, expect, describe } = import.meta.vitest;
describe('makeMagicObject', () => {
it('Correctly interprets arrays without keys', () => {
const obj = makeMagicObject();
obj.add('', 'bob');
obj.add('', 'jon');

expect(obj.type).toBe('array');
expect(obj.toJS()).toStrictEqual(['bob', 'jon']);
});

it('Correctly interprets arrays with keys', () => {
const obj = makeMagicObject();
obj.add('0', 'bob');
obj.add('2', 'jon');
obj.add('4', 'dave');

expect(obj.type).toBe('array');
expect(obj.toJS()).toEqual(['bob', undefined, 'jon', undefined, 'dave']);
});

it('Correctly interprets objects', () => {
const obj = makeMagicObject([
['1', 'jim'],
['fred', 'and george'],
]);
expect(obj.type).toBe('object');
expect(obj.toJS()).toEqual({
'1': 'jim',
fred: 'and george',
});
});
});
}
23 changes: 12 additions & 11 deletions packages/arktype-utils/src/strToObjects.test.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
import { describe, expect, it } from 'vitest';
import { strToObject } from './strToObject.js';
// import { strToObject } from './strToObject.js';

describe('strToObjects', () => {
it('does a thing', () => {
const a = strToObject('a[4]', 3);
expect(a.a[4]).toBe(3);
expect(a.a).toHaveLength(5);
expect(a.a.slice(0, 3).every(f => f === undefined)).toBeTruthy();
expect(1).toBe(1);
// const a = strToObject('a[4]', 3);
// expect(a.a[4]).toBe(3);
// expect(a.a).toHaveLength(5);
// expect(a.a.slice(0, 3).every(f => f === undefined)).toBeTruthy();
// expect(1).toBe(1);

const b = strToObject('b[]', 7);
expect(b.b).toHaveLength(1);
expect(b.b[0]).toBe(7);
// const b = strToObject('b[]', 7);
// expect(b.b).toHaveLength(1);
// expect(b.b[0]).toBe(7);

expect(strToObject('a', 3)).toStrictEqual({
a: 3,
});
// expect(strToObject('a', 3)).toStrictEqual({
// a: 3,
// });
// const a = strToObject('a.b', 3);
// expect(a).toStrictEqual({
// a: {
Expand Down
5 changes: 3 additions & 2 deletions packages/arktype-utils/src/validator.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import type { Type } from 'arktype';
import { type } from 'arktype';

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function validateObject<T extends Type<any>>(
obj: unknown,
validator: T,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
): T extends Type<infer R> ? R : any {
const { data, problems } = validator(obj);
const data = validator(obj);

if (problems) throw problems;
if (data instanceof type.errors) throw data;

return data;
}
5 changes: 4 additions & 1 deletion packages/arktype-utils/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
"extends": "@jhecht/typescript-config/base.json",
"compilerOptions": {
"esModuleInterop": true,
"target": "es2020"
"target": "es2020",
"types": [
"vitest/importMeta"
]
}
}
1 change: 1 addition & 0 deletions packages/arktype-utils/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ export default defineConfig({
test: {
// Need this to use File in the tests
environment: 'jsdom',
includeSource: ['src/**/*.ts'],
},
});
2 changes: 1 addition & 1 deletion packages/design-tokens/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"access": "public"
},
"scripts": {
"test": "vitest --coverage",
"test": "vitest run --coverage",
"test:ci": "vitest run --changed --coverage --reporter=html",
"build": "tsup src/index.ts"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/design-tokens/src/generate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ describe('Generate functions', () => {

expect(parsed.first.nodes).toHaveLength(5);

parsed.first.nodes.forEach(node => {
parsed.first.nodes.forEach((node) => {
expect(node.type).toBe('decl');
if (node.type !== 'decl') throw new Error('Node is wrong type');
switch (node.prop) {
Expand Down
6 changes: 3 additions & 3 deletions packages/design-tokens/src/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export async function build({

const fileName = resolve(import.meta.dirname, configFile);

const rawFile = await import(fileName).then(r => r.default);
const rawFile = await import(fileName).then((r) => r.default);
const stylesheet = await buildStylesheet(rawFile);

const output = stylesheet.build();
Expand All @@ -37,7 +37,7 @@ export async function build({
writeFile(resolve(dirname(fileName), 'tokens.scss'), output.scss),
]);

return resp.every(r => r.status === 'fulfilled');
return resp.every((r) => r.status === 'fulfilled');
}

/**
Expand Down Expand Up @@ -91,7 +91,7 @@ export async function buildStylesheet(config: Config): Promise<Stylesheet> {
// parses the values into tokens.
const tokens = parseKeyValuePairs(values);
// Iterate over the tokens, adding each one to the MediaQuery
tokens.forEach(token => {
tokens.forEach((token) => {
mq.addToken(token);
baseStylesheet.addResolveRef(token);
});
Expand Down
6 changes: 3 additions & 3 deletions packages/design-tokens/src/stylesheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export class Stylesheet implements TokenConsumer {
}

addSelectors(...args: Selector[]) {
args.forEach(sel => this.addSelector(sel));
args.forEach((sel) => this.addSelector(sel));
return this;
}

Expand Down Expand Up @@ -66,7 +66,7 @@ export class Stylesheet implements TokenConsumer {

addTokens(selector: Selector = this.#root, ...tokens: Token[]) {
if (!this.selectors.has(selector)) this.selectors.add(selector);
tokens.forEach(token => {
tokens.forEach((token) => {
this.addToken(token, selector);
// console.info(token);
// selector.addToken(token);
Expand All @@ -85,7 +85,7 @@ export class Stylesheet implements TokenConsumer {
for (const [ref, tokens] of this.needsResolving.entries()) {
if (this.tokenRefs.has(ref)) {
const token = this.tokenRefs.get(ref);
tokens.forEach(t => (t.value = token));
tokens.forEach((t) => (t.value = token));
this.needsResolving.delete(ref);
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/design-tokens/src/token.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe('Tokens class', () => {
});

it('Works for nested tokens', () => {
const [blueToken, redToken] = ['blue', 'red'].map(t => new Token(t, t));
const [blueToken, redToken] = ['blue', 'red'].map((t) => new Token(t, t));
expect(blueToken.getCssKey()).toBe('--blue');
expect(blueToken.toCssValue()).toBe('blue');
expect(redToken.getCssKey()).toBe('--red');
Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"access": "public"
},
"scripts": {
"test": "vitest",
"test": "vitest run",
"prelint": "pnpm build",
"lint": "eslint **/*.ts",
"build": "tsup",
Expand Down
2 changes: 1 addition & 1 deletion packages/vite-plugin-design-tokens/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default function designTokenPlugin(): Plugin {
if ([virtualModuleCss, virtualModuleJs].includes(id)) return '\0' + id;
},
load(id) {
if ([virtualModuleCss, virtualModuleJs].map(v => '\0' + v).includes(id))
if ([virtualModuleCss, virtualModuleJs].map((v) => '\0' + v).includes(id))
return 'export const msg = "hello, from the virtual module!"; ';
},
transform(code, id) {
Expand Down
21 changes: 17 additions & 4 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.