Skip to content

Commit

Permalink
some more json sqlite fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
goto-bus-stop committed Aug 27, 2024
1 parent b87a71b commit 7592cd2
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 22 deletions.
2 changes: 1 addition & 1 deletion src/Source.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class ImportContext extends SourceContext {
* @returns {Promise<Playlist>} Playlist model.
*/
async createPlaylist(name, itemOrItems) {
const playlist = await this.uw.playlists.createPlaylist(this.user, { name });
const { playlist } = await this.uw.playlists.createPlaylist(this.user, { name });

const rawItems = Array.isArray(itemOrItems) ? itemOrItems : [itemOrItems];
const items = this.source.addSourceType(rawItems);
Expand Down
3 changes: 2 additions & 1 deletion src/controllers/authenticate.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import sendEmail from '../email.js';
import beautifyDuplicateKeyError from '../utils/beautifyDuplicateKeyError.js';
import toItemResponse from '../utils/toItemResponse.js';
import toListResponse from '../utils/toListResponse.js';
import { serializeUser } from '../utils/serialize.js';

const { BadRequest } = httpErrors;

Expand Down Expand Up @@ -48,7 +49,7 @@ function seconds(str) {
* @type {import('../types.js').Controller}
*/
async function getCurrentUser(req) {
return toItemResponse(req.user ?? null, {
return toItemResponse(req.user != null ? serializeUser(req.user) : null, {

Check failure on line 52 in src/controllers/authenticate.js

View workflow job for this annotation

GitHub Actions / Types

Argument of type 'User & { id: UserID; username: string; slug: string; avatar: string | null; activePlaylistID: PlaylistID | null; pendingActivation: boolean; createdAt: Date; updatedAt: Date; }' is not assignable to parameter of type 'Pick<{ id: UserID; username: string; slug: string; avatar: string | null; activePlaylistID: PlaylistID | null; pendingActivation: boolean; createdAt: Date; updatedAt: Date; }, "id" | ... 6 more ... | "lastSeenAt">'.
url: req.fullUrl,
});
}
Expand Down
4 changes: 2 additions & 2 deletions src/controllers/playlists.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,15 @@ async function createPlaylist(req) {
const { name } = req.body;
const { playlists } = req.uwave;

const playlist = await playlists.createPlaylist(user, {
const { playlist, active } = await playlists.createPlaylist(user, {
name,
});

return toItemResponse(
serializePlaylist(playlist),
{
url: req.fullUrl,
meta: { active: user.activePlaylistID === playlist.id },
meta: { active },
},
);
}
Expand Down
24 changes: 12 additions & 12 deletions src/plugins/configStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ import fs from 'node:fs';
import EventEmitter from 'node:events';
import Ajv from 'ajv/dist/2019.js';
import formats from 'ajv-formats';
import lodash from 'lodash';
import jsonMergePatch from 'json-merge-patch';
import sjson from 'secure-json-parse';
import ValidationError from '../errors/ValidationError.js';

const { omit } = lodash;
import { sql } from 'kysely';
import { jsonb } from '../utils/sqlite.js';

/**
* @typedef {import('type-fest').JsonObject} JsonObject
Expand Down Expand Up @@ -113,16 +112,16 @@ class ConfigStore {

const previous = await db.transaction().execute(async (tx) => {
const row = await tx.selectFrom('configuration')
.select('value')
.select(sql`json(value)`.as('value'))
.where('name', '=', name)
.executeTakeFirst();

await tx.insertInto('configuration')
.values({ name, value })
.onConflict((oc) => oc.column('name').doUpdateSet({ value }))
.values({ name, value: jsonb(value) })
.onConflict((oc) => oc.column('name').doUpdateSet({ value: jsonb(value) }))
.execute();

return row?.value ?? null;
return row?.value != null ? JSON.parse(/** @type {string} */ (row.value)) : null;
});

return previous;
Expand All @@ -136,14 +135,14 @@ class ConfigStore {
const { db } = this.#uw;

const row = await db.selectFrom('configuration')
.select(['value'])
.select(sql`json(value)`.as('value'))
.where('name', '=', key)
.executeTakeFirst();
if (!row) {
return null;
}

return row.value;
return JSON.parse(/** @type {string} */ (row.value));
}

/**
Expand Down Expand Up @@ -217,15 +216,16 @@ class ConfigStore {
const { db } = this.#uw;

const results = await db.selectFrom('configuration')
.select(['name', 'value'])
.select(['name', sql`json(value)`.as('value')])
.execute();

const configs = Object.create(null);
for (const [key, validate] of this.#validators.entries()) {
const row = results.find((m) => m.name === key);
if (row) {
validate(row.value);
configs[key] = row.value;
const value = JSON.parse(/** @type {string} */ (row.value));
validate(value);
configs[key] = value;
} else {
configs[key] = {};
}
Expand Down
35 changes: 31 additions & 4 deletions src/plugins/playlists.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,20 +188,30 @@ class PlaylistsRepository {
id,
name,
userID: user.id,
items: jsonb([]),
})
.returningAll()
.returning([
'id',
'userID',
'name',
(eb) => jsonLength(eb.ref('items')).as('size'),
'createdAt',
'updatedAt',
])
.executeTakeFirstOrThrow();

let active = false;
// If this is the user's first playlist, immediately activate it.
if (user.activePlaylistID == null) {
this.#logger.info({ userId: user.id, playlistId: playlist.id }, 'activating first playlist');
await db.updateTable('users')
.where('users.id', '=', user.id)
.set({ activePlaylistID: playlist.id })
.execute();
active = true;
}

return playlist;
return { playlist, active };
}

/**
Expand All @@ -214,9 +224,11 @@ class PlaylistsRepository {
.where('userID', '=', user.id)
.select([
'id',
'userID',
'name',
(eb) => jsonLength(eb.ref('items')).as('size'),
'createdAt',
'updatedAt',
])
.execute();

Expand Down Expand Up @@ -411,7 +423,14 @@ class PlaylistsRepository {
const { db } = this.#uw;

let query = db.selectFrom('playlists')
.select(['playlists.id', 'playlists.name', 'playlists.createdAt'])
.select([
'playlists.id',
'playlists.userID',
'playlists.name',
(eb) => jsonLength(eb.ref('playlists.items')).as('size'),
'playlists.createdAt',
'playlists.updatedAt',
])
.innerJoin('playlistItems', 'playlists.id', 'playlistItems.playlistID')
.where('playlistItems.mediaID', '=', mediaID)
.groupBy('playlistItems.playlistID')
Expand Down Expand Up @@ -440,7 +459,15 @@ class PlaylistsRepository {

let query = db.selectFrom('playlists')
.innerJoin('playlistItems', 'playlists.id', 'playlistItems.playlistID')
.select(['playlists.id', 'playlists.name', 'playlists.createdAt', 'playlistItems.mediaID'])
.select([
'playlists.id',
'playlists.userID',
'playlists.name',
(eb) => jsonLength(eb.ref('playlists.items')).as('size'),
'playlists.createdAt',
'playlists.updatedAt',
'playlistItems.mediaID',
])
.where('playlistItems.mediaID', 'in', mediaIDs);
if (options.author) {
query = query.where('playlists.userID', '=', options.author)
Expand Down
1 change: 1 addition & 0 deletions src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export interface UserTable {
email: string | null,
password: string | null,
slug: string,
avatar: string | null,
activePlaylistID: PlaylistID | null,
pendingActivation: boolean,
createdAt: Generated<Date>,
Expand Down
2 changes: 1 addition & 1 deletion src/utils/serialize.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* @param {import('../schema.js').Playlist} model
* @param {import('../schema.js').Playlist & { size: number }} model
*/
export function serializePlaylist(model) {
return {
Expand Down
3 changes: 2 additions & 1 deletion test/authenticate.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ describe('Authentication', () => {
sinon.assert.match(res.body.data, {
_id: user.id,
username: user.username,
avatar: user.avatar,
// TODO: sql avatars
// avatar: user.avatar,
slug: user.slug,
});
});
Expand Down

0 comments on commit 7592cd2

Please sign in to comment.