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
61 changes: 25 additions & 36 deletions packages/crates-io-msw/models/api-token.js
Original file line number Diff line number Diff line change
@@ -1,48 +1,37 @@
import { Collection } from '@msw/data';
import * as v from 'valibot';

import { applyDefault } from '../utils/defaults.js';
import { preCreateExtension } from '../utils/pre-create-extension.js';
import * as counters from '../utils/counters.js';
import { seededRandom } from '../utils/random.js';

const schema = v.object({
id: v.number(),

crateScopes: v.nullable(v.array(v.any())),
createdAt: v.string(),
endpointScopes: v.nullable(v.array(v.any())),
expiredAt: v.nullable(v.string()),
lastUsedAt: v.nullable(v.string()),
name: v.string(),
token: v.string(),
revoked: v.boolean(),

user: v.any(),
});

function preCreate(attrs, counter) {
applyDefault(attrs, 'id', () => counter);
applyDefault(attrs, 'crateScopes', () => null);
applyDefault(attrs, 'createdAt', () => '2017-11-19T17:59:22Z');
applyDefault(attrs, 'endpointScopes', () => null);
applyDefault(attrs, 'expiredAt', () => null);
applyDefault(attrs, 'lastUsedAt', () => null);
applyDefault(attrs, 'name', () => `API Token ${attrs.id}`);
applyDefault(attrs, 'token', () => generateToken(counter));
applyDefault(attrs, 'revoked', () => false);

if (!attrs.user) {
throw new Error('Missing `user` relationship on `api-token`');
}
}
const schema = v.pipe(
v.object({
id: v.optional(v.number()),

crateScopes: v.optional(v.nullable(v.array(v.string())), null),
createdAt: v.optional(v.string(), '2017-11-19T17:59:22Z'),
endpointScopes: v.optional(v.nullable(v.array(v.string())), null),
expiredAt: v.optional(v.nullable(v.string()), null),
lastUsedAt: v.optional(v.nullable(v.string()), null),
name: v.optional(v.string()),
token: v.optional(v.string()),
revoked: v.optional(v.boolean(), false),

user: v.any(),
}),
v.transform(function (input) {
let counter = counters.increment('apiToken');
let id = input.id ?? counter;
let name = input.name ?? `API Token ${id}`;
let token = input.token ?? generateToken(id);
return { ...input, id, name, token };
}),
);

function generateToken(seed) {
return seededRandom(seed).toString().slice(2);
}

const collection = new Collection({
schema,
extensions: [preCreateExtension(preCreate)],
});
const collection = new Collection({ schema });

export default collection;
2 changes: 1 addition & 1 deletion packages/crates-io-msw/models/api-token.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { db } from '../index.js';

test('throws if `user` is not set', async ({ expect }) => {
await expect(() => db.apiToken.create({})).rejects.toThrowErrorMatchingInlineSnapshot(
`[Error: Missing \`user\` relationship on \`api-token\`]`,
`[Error: Failed to create a new record with initial values: does not match the schema. Please see the schema validation errors above.]`,
);
});

Expand Down
43 changes: 20 additions & 23 deletions packages/crates-io-msw/models/category.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,29 @@
import { Collection } from '@msw/data';
import * as v from 'valibot';

import { applyDefault } from '../utils/defaults.js';
import { preCreateExtension } from '../utils/pre-create-extension.js';
import * as counters from '../utils/counters.js';
import { dasherize } from '../utils/strings.js';

const schema = v.object({
id: v.string(),
const schema = v.pipe(
v.object({
id: v.optional(v.string()),

category: v.string(),
slug: v.string(),
description: v.string(),
created_at: v.string(),
crates_cnt: v.nullable(v.number()),
});
category: v.optional(v.string()),
slug: v.optional(v.string()),
description: v.optional(v.string()),
created_at: v.optional(v.string(), '2010-06-16T21:30:45Z'),
crates_cnt: v.optional(v.nullable(v.number()), null),
}),
v.transform(function (input) {
let counter = counters.increment('category');
let category = input.category ?? `Category ${counter}`;
let slug = input.slug ?? dasherize(category);
let id = input.id ?? slug;
let description = input.description ?? `This is the description for the category called "${category}"`;
return { ...input, id, category, slug, description };
}),
);

function preCreate(attrs, counter) {
applyDefault(attrs, 'category', () => `Category ${counter}`);
applyDefault(attrs, 'slug', () => dasherize(attrs.category));
applyDefault(attrs, 'id', () => attrs.slug);
applyDefault(attrs, 'description', () => `This is the description for the category called "${attrs.category}"`);
applyDefault(attrs, 'created_at', () => '2010-06-16T21:30:45Z');
applyDefault(attrs, 'crates_cnt', () => null);
}

const collection = new Collection({
schema,
extensions: [preCreateExtension(preCreate)],
});
const collection = new Collection({ schema });

export default collection;
59 changes: 23 additions & 36 deletions packages/crates-io-msw/models/crate-owner-invitation.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,28 @@
import { Collection } from '@msw/data';
import * as v from 'valibot';

import { applyDefault } from '../utils/defaults.js';
import { preCreateExtension } from '../utils/pre-create-extension.js';

const schema = v.object({
id: v.number(),

createdAt: v.string(),
expiresAt: v.string(),
token: v.string(),

crate: v.any(),
invitee: v.any(),
inviter: v.any(),
});

function preCreate(attrs, counter) {
applyDefault(attrs, 'id', () => counter);
applyDefault(attrs, 'createdAt', () => '2016-12-24T12:34:56Z');
applyDefault(attrs, 'expiresAt', () => '2017-01-24T12:34:56Z');
applyDefault(attrs, 'token', () => `secret-token-${attrs.id}`);

if (!attrs.crate) {
throw new Error(`Missing \`crate\` relationship on \`crate-owner-invitation\``);
}
if (!attrs.invitee) {
throw new Error(`Missing \`invitee\` relationship on \`crate-owner-invitation\``);
}
if (!attrs.inviter) {
throw new Error(`Missing \`inviter\` relationship on \`crate-owner-invitation\``);
}
}

const collection = new Collection({
schema,
extensions: [preCreateExtension(preCreate)],
});
import * as counters from '../utils/counters.js';

const schema = v.pipe(
v.object({
id: v.optional(v.number()),

createdAt: v.optional(v.string(), '2016-12-24T12:34:56Z'),
expiresAt: v.optional(v.string(), '2017-01-24T12:34:56Z'),
token: v.optional(v.string()),

crate: v.any(),
invitee: v.any(),
inviter: v.any(),
}),
v.transform(function (input) {
let counter = counters.increment('crateOwnerInvitation');
let id = input.id ?? counter;
let token = input.token ?? `secret-token-${id}`;
return { ...input, id, token };
}),
);

const collection = new Collection({ schema });

export default collection;
6 changes: 3 additions & 3 deletions packages/crates-io-msw/models/crate-owner-invitation.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,23 @@ test('throws if `crate` is not set', async ({ expect }) => {
let inviter = await db.user.create({});
let invitee = await db.user.create({});
await expect(() => db.crateOwnerInvitation.create({ inviter, invitee })).rejects.toThrowErrorMatchingInlineSnapshot(
`[Error: Missing \`crate\` relationship on \`crate-owner-invitation\`]`,
`[Error: Failed to create a new record with initial values: does not match the schema. Please see the schema validation errors above.]`,
);
});

test('throws if `inviter` is not set', async ({ expect }) => {
let crate = await db.crate.create({});
let invitee = await db.user.create({});
await expect(() => db.crateOwnerInvitation.create({ crate, invitee })).rejects.toThrowErrorMatchingInlineSnapshot(
`[Error: Missing \`inviter\` relationship on \`crate-owner-invitation\`]`,
`[Error: Failed to create a new record with initial values: does not match the schema. Please see the schema validation errors above.]`,
);
});

test('throws if `invitee` is not set', async ({ expect }) => {
let crate = await db.crate.create({});
let inviter = await db.user.create({});
await expect(() => db.crateOwnerInvitation.create({ crate, inviter })).rejects.toThrowErrorMatchingInlineSnapshot(
`[Error: Missing \`invitee\` relationship on \`crate-owner-invitation\`]`,
`[Error: Failed to create a new record with initial values: does not match the schema. Please see the schema validation errors above.]`,
);
});

Expand Down
57 changes: 23 additions & 34 deletions packages/crates-io-msw/models/crate-ownership.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,28 @@
import { Collection } from '@msw/data';
import * as v from 'valibot';

import { applyDefault } from '../utils/defaults.js';
import { preCreateExtension } from '../utils/pre-create-extension.js';

const schema = v.object({
id: v.number(),

emailNotifications: v.boolean(),

crate: v.any(),
team: v.any(),
user: v.any(),
});

function preCreate(attrs, counter) {
applyDefault(attrs, 'id', () => counter);
applyDefault(attrs, 'emailNotifications', () => true);
applyDefault(attrs, 'team', () => null);
applyDefault(attrs, 'user', () => null);

if (!attrs.crate) {
throw new Error('Missing `crate` relationship on `crate-ownership`');
}
if (!attrs.team && !attrs.user) {
throw new Error('Missing `team` or `user` relationship on `crate-ownership`');
}
if (attrs.team && attrs.user) {
throw new Error('`team` and `user` on a `crate-ownership` are mutually exclusive');
}
}

const collection = new Collection({
schema,
extensions: [preCreateExtension(preCreate)],
});
import * as counters from '../utils/counters.js';

const schema = v.pipe(
v.object({
id: v.optional(v.number()),

emailNotifications: v.optional(v.boolean(), true),

crate: v.any(),
team: v.optional(v.nullable(v.any()), null),
user: v.optional(v.nullable(v.any()), null),
}),
v.transform(function (input) {
let counter = counters.increment('crateOwnership');
let id = input.id ?? counter;
return { ...input, id };
}),
v.check(input => input.crate != null, 'Missing `crate` relationship on `crate-ownership`'),
v.check(input => input.team != null || input.user != null, 'Missing `team` or `user` relationship on `crate-ownership`'),
v.check(input => !(input.team != null && input.user != null), '`team` and `user` on a `crate-ownership` are mutually exclusive'),
);

const collection = new Collection({ schema });

export default collection;
6 changes: 3 additions & 3 deletions packages/crates-io-msw/models/crate-ownership.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ import { db } from '../index.js';
test('throws if `crate` is not set', async ({ expect }) => {
let user = await db.user.create({});
await expect(() => db.crateOwnership.create({ user })).rejects.toThrowErrorMatchingInlineSnapshot(
`[Error: Missing \`crate\` relationship on \`crate-ownership\`]`,
`[Error: Failed to create a new record with initial values: does not match the schema. Please see the schema validation errors above.]`,
);
});

test('throws if `team` and `user` are not set', async ({ expect }) => {
let crate = await db.crate.create({});
await expect(() => db.crateOwnership.create({ crate })).rejects.toThrowErrorMatchingInlineSnapshot(
`[Error: Missing \`team\` or \`user\` relationship on \`crate-ownership\`]`,
`[Error: Failed to create a new record with initial values: does not match the schema. Please see the schema validation errors above.]`,
);
});

Expand All @@ -21,7 +21,7 @@ test('throws if `team` and `user` are both set', async ({ expect }) => {
let team = await db.team.create({});
let user = await db.user.create({});
await expect(() => db.crateOwnership.create({ crate, team, user })).rejects.toThrowErrorMatchingInlineSnapshot(
`[Error: \`team\` and \`user\` on a \`crate-ownership\` are mutually exclusive]`,
`[Error: Failed to create a new record with initial values: does not match the schema. Please see the schema validation errors above.]`,
);
});

Expand Down
71 changes: 31 additions & 40 deletions packages/crates-io-msw/models/crate.js
Original file line number Diff line number Diff line change
@@ -1,49 +1,40 @@
import { Collection } from '@msw/data';
import * as v from 'valibot';

import { applyDefault } from '../utils/defaults.js';
import { preCreateExtension } from '../utils/pre-create-extension.js';
import * as counters from '../utils/counters.js';

const schema = v.object({
// `v.string()` is used to support some of our old fixtures that use strings here for some reason
id: v.union([v.number(), v.string()]),
const schema = v.pipe(
v.object({
// `v.string()` is used to support some of our old fixtures that use strings here for some reason
id: v.optional(v.union([v.number(), v.string()])),

name: v.string(),
description: v.string(),
downloads: v.number(),
recent_downloads: v.number(),
documentation: v.nullable(v.string()),
homepage: v.nullable(v.string()),
repository: v.nullable(v.string()),
created_at: v.string(),
updated_at: v.string(),
badges: v.array(v.any()),
_extra_downloads: v.array(v.any()),
trustpubOnly: v.boolean(),
name: v.optional(v.string()),
description: v.optional(v.string()),
downloads: v.optional(v.number()),
recent_downloads: v.optional(v.number()),
documentation: v.optional(v.nullable(v.string()), null),
homepage: v.optional(v.nullable(v.string()), null),
repository: v.optional(v.nullable(v.string()), null),
created_at: v.optional(v.string(), '2010-06-16T21:30:45Z'),
updated_at: v.optional(v.string(), '2017-02-24T12:34:56Z'),
badges: v.optional(v.array(v.any()), []),
_extra_downloads: v.optional(v.array(v.any()), []),
trustpubOnly: v.optional(v.boolean(), false),

categories: v.optional(v.array(v.any()), () => []),
keywords: v.optional(v.array(v.any()), () => []),
});
categories: v.optional(v.array(v.any()), []),
keywords: v.optional(v.array(v.any()), []),
}),
v.transform(function (input) {
let counter = counters.increment('crate');
let id = input.id ?? counter;
let name = input.name ?? `crate-${id}`;
let description = input.description ?? `This is the description for the crate called "${name}"`;
let downloads = input.downloads ?? (((id + 13) * 42) % 13) * 12_345;
let recent_downloads = input.recent_downloads ?? (((id + 7) * 31) % 13) * 321;
return { ...input, id, name, description, downloads, recent_downloads };
}),
);

function preCreate(attrs, counter) {
applyDefault(attrs, 'id', () => counter);
applyDefault(attrs, 'name', () => `crate-${attrs.id}`);
applyDefault(attrs, 'description', () => `This is the description for the crate called "${attrs.name}"`);
applyDefault(attrs, 'downloads', () => (((attrs.id + 13) * 42) % 13) * 12_345);
applyDefault(attrs, 'recent_downloads', () => (((attrs.id + 7) * 31) % 13) * 321);
applyDefault(attrs, 'documentation', () => null);
applyDefault(attrs, 'homepage', () => null);
applyDefault(attrs, 'repository', () => null);
applyDefault(attrs, 'created_at', () => '2010-06-16T21:30:45Z');
applyDefault(attrs, 'updated_at', () => '2017-02-24T12:34:56Z');
applyDefault(attrs, 'badges', () => []);
applyDefault(attrs, '_extra_downloads', () => []);
applyDefault(attrs, 'trustpubOnly', () => false);
}

const collection = new Collection({
schema,
extensions: [preCreateExtension(preCreate)],
});
const collection = new Collection({ schema });

export default collection;
Loading
Loading