This commit is contained in:
parent
3c015177a0
commit
6058346808
10 changed files with 337 additions and 279 deletions
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE sites
|
||||||
|
DROP COLUMN default_collection;
|
4
migrations/20230714095746_add-default-collection.up.sql
Normal file
4
migrations/20230714095746_add-default-collection.up.sql
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
ALTER TABLE sites
|
||||||
|
ADD COLUMN default_collection UUID REFERENCES collections (
|
||||||
|
id
|
||||||
|
) ON DELETE SET NULL;
|
486
sqlx-data.json
486
sqlx-data.json
|
@ -1,215 +1,6 @@
|
||||||
{
|
{
|
||||||
"db": "PostgreSQL",
|
"db": "PostgreSQL",
|
||||||
"11e96cfd8c2736f13ce55975ea910dd68640f6f14e38a4b3342d514804e3de27": {
|
"0e52c31f550313507192bd0436e469dc2b01e67bd19ecdd26e663fbb5af8929b": {
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"nullable": [],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Uuid"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"query": "DELETE FROM sessions WHERE id = $1"
|
|
||||||
},
|
|
||||||
"1d21e65cb21ec57986f154395627de9aefbf77f88c892c5e093787ec53d623d3": {
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"ordinal": 0,
|
|
||||||
"type_info": "Uuid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "slug",
|
|
||||||
"ordinal": 1,
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "name",
|
|
||||||
"ordinal": 2,
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "parent",
|
|
||||||
"ordinal": 3,
|
|
||||||
"type_info": "Uuid"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
true
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Uuid"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"query": "SELECT id, slug, name, parent FROM collections WHERE site = $1"
|
|
||||||
},
|
|
||||||
"28ec2833283df836e457161f44f0fbc75ed37dcc0ba63eb09bf285aae2f7a380": {
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"nullable": [],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Uuid",
|
|
||||||
"Uuid",
|
|
||||||
"Varchar",
|
|
||||||
"Varchar"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"query": "INSERT INTO collections (id, site, slug, name)\n VALUES ($1, $2, $3, $4)"
|
|
||||||
},
|
|
||||||
"29e0259def5c6fdc34c6a18345150d2714736b91c1f3040fcb07d77cbe2552e1": {
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"name": "name",
|
|
||||||
"ordinal": 0,
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "owner",
|
|
||||||
"ordinal": 1,
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "owner_display_name",
|
|
||||||
"ordinal": 2,
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "title",
|
|
||||||
"ordinal": 3,
|
|
||||||
"type_info": "Varchar"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "description",
|
|
||||||
"ordinal": 4,
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "created_at",
|
|
||||||
"ordinal": 5,
|
|
||||||
"type_info": "Timestamp"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "collections!: Vec<CollectionNameAndSlug>",
|
|
||||||
"ordinal": 6,
|
|
||||||
"type_info": "RecordArray"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
null,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
null
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Text"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"query": "SELECT\n sites.name,\n users.name as owner,\n COALESCE(users.display_name,users.name) as owner_display_name,\n title,\n description,\n sites.created_at,\n array_agg(row(collections.slug, collections.name)) as \"collections!: Vec<CollectionNameAndSlug>\"\n FROM sites\n JOIN\n users ON sites.owner = users.id\n JOIN\n collections ON collections.site = sites.id\n WHERE\n sites.name = $1\n AND sites.deleted_at IS NULL\n GROUP BY\n sites.name, users.name, users.display_name, title, description, sites.created_at"
|
|
||||||
},
|
|
||||||
"35deaad55b84124dcba02c555718fe815003e3f50b1c8ee2fc7e540009fa5aef": {
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"name": "empty",
|
|
||||||
"ordinal": 0,
|
|
||||||
"type_info": "Bool"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nullable": [
|
|
||||||
null
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"query": "SELECT CASE WHEN EXISTS(SELECT 1 FROM users) THEN false ELSE true END AS empty;"
|
|
||||||
},
|
|
||||||
"39237d1e40ce33ce386320212a53986cb21949dd07014772a150242caf4fa610": {
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"nullable": [],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Uuid",
|
|
||||||
"Uuid",
|
|
||||||
"Uuid",
|
|
||||||
"Varchar",
|
|
||||||
"Varchar",
|
|
||||||
"Text",
|
|
||||||
"VarcharArray",
|
|
||||||
"Jsonb",
|
|
||||||
"UuidArray",
|
|
||||||
"Bool"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"query": "INSERT INTO pages (id, author, site, slug, title, description, tags, blocks, collections, published)\n VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)"
|
|
||||||
},
|
|
||||||
"562254387ad52ad5ee3cf806085873485d6b8a0b372ac59a0796b9f0c8910cf2": {
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"ordinal": 0,
|
|
||||||
"type_info": "Uuid"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"nullable": [
|
|
||||||
false
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Uuid",
|
|
||||||
"Uuid",
|
|
||||||
"Varchar",
|
|
||||||
"Timestamp",
|
|
||||||
"Timestamp"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"query": "INSERT INTO sessions (id, actor, secret, created_at, expires_at) VALUES ($1, $2, $3, $4, $5) RETURNING id"
|
|
||||||
},
|
|
||||||
"61fcf083e6abcfed9480164f3ed4ff2f396c8041a30df002f6e4af920b41f4e4": {
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"nullable": [],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Text",
|
|
||||||
"Uuid"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"query": "UPDATE sites SET deleted_at = NOW() WHERE name = $1 AND owner = $2 AND deleted_at IS NULL"
|
|
||||||
},
|
|
||||||
"742b9eef92ad404b3b1ec285ce8b99e945b1b910f25bff376466c704a79fc9c8": {
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"nullable": [],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Timestamp"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"query": "DELETE FROM sessions WHERE expires_at < $1"
|
|
||||||
},
|
|
||||||
"7aff3e9becb9da6bfba6d50a364fd56f46b739d6e7a5742e5efe1d19858ee427": {
|
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
|
@ -283,14 +74,231 @@
|
||||||
],
|
],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"Left": [
|
"Left": [
|
||||||
"Text",
|
"Uuid",
|
||||||
"Text",
|
"Uuid",
|
||||||
"Timestamp",
|
"Timestamp",
|
||||||
"Int8"
|
"Int8"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"query": "SELECT\n COALESCE(users.display_name,users.name) as author_display_name,\n users.name as author_username,\n pages.slug,\n pages.title,\n pages.description,\n pages.tags,\n pages.blocks as \"blocks!: Json<Vec<PostBlock>>\",\n pages.created_at,\n pages.modified_at,\n pages.published,\n pages.collections\n FROM pages\n JOIN\n users ON author = users.id\n JOIN\n sites ON site = sites.id\n JOIN\n collections ON collections.slug = $2 AND collections.site = sites.id\n WHERE\n sites.name = $1\n AND collections.id = ANY(collections)\n AND pages.deleted_at IS NULL\n AND published = true\n AND pages.created_at <= $3\n ORDER BY created_at DESC\n LIMIT $4\n "
|
"query": "SELECT\n COALESCE(users.display_name,users.name) as author_display_name,\n users.name as author_username,\n pages.slug,\n pages.title,\n pages.description,\n pages.tags,\n pages.blocks as \"blocks!: Json<Vec<PostBlock>>\",\n pages.created_at,\n pages.modified_at,\n pages.published,\n pages.collections\n FROM pages\n JOIN\n users ON author = users.id\n WHERE\n pages.site = $1\n AND $2 = ANY(collections)\n AND pages.deleted_at IS NULL\n AND published = true\n AND pages.created_at <= $3\n ORDER BY created_at DESC\n LIMIT $4\n "
|
||||||
|
},
|
||||||
|
"11e96cfd8c2736f13ce55975ea910dd68640f6f14e38a4b3342d514804e3de27": {
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Uuid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"query": "DELETE FROM sessions WHERE id = $1"
|
||||||
|
},
|
||||||
|
"1d21e65cb21ec57986f154395627de9aefbf77f88c892c5e093787ec53d623d3": {
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "slug",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "parent",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Uuid"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Uuid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"query": "SELECT id, slug, name, parent FROM collections WHERE site = $1"
|
||||||
|
},
|
||||||
|
"35deaad55b84124dcba02c555718fe815003e3f50b1c8ee2fc7e540009fa5aef": {
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "empty",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nullable": [
|
||||||
|
null
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"query": "SELECT CASE WHEN EXISTS(SELECT 1 FROM users) THEN false ELSE true END AS empty;"
|
||||||
|
},
|
||||||
|
"39237d1e40ce33ce386320212a53986cb21949dd07014772a150242caf4fa610": {
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Uuid",
|
||||||
|
"Uuid",
|
||||||
|
"Uuid",
|
||||||
|
"Varchar",
|
||||||
|
"Varchar",
|
||||||
|
"Text",
|
||||||
|
"VarcharArray",
|
||||||
|
"Jsonb",
|
||||||
|
"UuidArray",
|
||||||
|
"Bool"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"query": "INSERT INTO pages (id, author, site, slug, title, description, tags, blocks, collections, published)\n VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)"
|
||||||
|
},
|
||||||
|
"3b27a97c644fda93d0e9b605b606509b4cf77a1877949d0e614a8725666e7e71": {
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "owner",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "owner_display_name",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "title",
|
||||||
|
"ordinal": 3,
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "description",
|
||||||
|
"ordinal": 4,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "created_at",
|
||||||
|
"ordinal": 5,
|
||||||
|
"type_info": "Timestamp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "default_collection",
|
||||||
|
"ordinal": 6,
|
||||||
|
"type_info": "Uuid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "collections!: Vec<CollectionData>",
|
||||||
|
"ordinal": 7,
|
||||||
|
"type_info": "RecordArray"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
null
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Text"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"query": "SELECT\n sites.name,\n users.name as owner,\n COALESCE(users.display_name,users.name) as owner_display_name,\n title,\n description,\n sites.created_at,\n default_collection,\n array_agg(row(collections.id, collections.slug, collections.name, parent)) as \"collections!: Vec<CollectionData>\"\n FROM sites\n JOIN\n users ON sites.owner = users.id\n JOIN\n collections ON collections.site = sites.id\n WHERE\n sites.name = $1\n AND sites.deleted_at IS NULL\n GROUP BY\n sites.name, users.name, users.display_name, title, description, sites.created_at, default_collection"
|
||||||
|
},
|
||||||
|
"562254387ad52ad5ee3cf806085873485d6b8a0b372ac59a0796b9f0c8910cf2": {
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Uuid"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nullable": [
|
||||||
|
false
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Uuid",
|
||||||
|
"Uuid",
|
||||||
|
"Varchar",
|
||||||
|
"Timestamp",
|
||||||
|
"Timestamp"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"query": "INSERT INTO sessions (id, actor, secret, created_at, expires_at) VALUES ($1, $2, $3, $4, $5) RETURNING id"
|
||||||
|
},
|
||||||
|
"61fcf083e6abcfed9480164f3ed4ff2f396c8041a30df002f6e4af920b41f4e4": {
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Text",
|
||||||
|
"Uuid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"query": "UPDATE sites SET deleted_at = NOW() WHERE name = $1 AND owner = $2 AND deleted_at IS NULL"
|
||||||
|
},
|
||||||
|
"6690726421106e317b58513f5d0a2eb0a38f15e1e89eb10695eb00e8bb3076d9": {
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Varchar",
|
||||||
|
"Varchar",
|
||||||
|
"Text",
|
||||||
|
"Uuid",
|
||||||
|
"Text",
|
||||||
|
"Uuid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"query": "UPDATE sites SET\n name = COALESCE($1, name),\n title = COALESCE($2, title),\n description = COALESCE($3, description),\n default_collection = COALESCE($4, default_collection),\n modified_at = NOW()\n WHERE\n name = $5\n AND owner = $6\n AND deleted_at IS NULL"
|
||||||
|
},
|
||||||
|
"742b9eef92ad404b3b1ec285ce8b99e945b1b910f25bff376466c704a79fc9c8": {
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Timestamp"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"query": "DELETE FROM sessions WHERE expires_at < $1"
|
||||||
},
|
},
|
||||||
"7bdb55b060b5e81b50c1bf86cb117215cba7010c91f8384a397efac06a88507d": {
|
"7bdb55b060b5e81b50c1bf86cb117215cba7010c91f8384a397efac06a88507d": {
|
||||||
"describe": {
|
"describe": {
|
||||||
|
@ -382,6 +390,19 @@
|
||||||
},
|
},
|
||||||
"query": "UPDATE sessions SET expires_at = $1 WHERE id = $2 RETURNING id"
|
"query": "UPDATE sessions SET expires_at = $1 WHERE id = $2 RETURNING id"
|
||||||
},
|
},
|
||||||
|
"b85aa5820a73028398878a86ed550ea42daa362a8b0124f9ed626769a22bc047": {
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Uuid",
|
||||||
|
"Uuid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"query": "UPDATE sites\n SET default_collection = $1\n WHERE id = $2"
|
||||||
|
},
|
||||||
"c567d96c92638902bc90f5fc0aa5bbbe0b6d26607767720a87fdbe67335a0180": {
|
"c567d96c92638902bc90f5fc0aa5bbbe0b6d26607767720a87fdbe67335a0180": {
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
|
@ -574,22 +595,6 @@
|
||||||
},
|
},
|
||||||
"query": "DELETE FROM sites WHERE name = $1 AND owner = $2"
|
"query": "DELETE FROM sites WHERE name = $1 AND owner = $2"
|
||||||
},
|
},
|
||||||
"d0005084c0ae3939460c3c727b29899c65a05e53fbc477cdda9665e7f243d5e9": {
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"nullable": [],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Varchar",
|
|
||||||
"Varchar",
|
|
||||||
"Text",
|
|
||||||
"Text",
|
|
||||||
"Uuid"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"query": "UPDATE sites SET\n name = COALESCE($1, name),\n title = COALESCE($2, title),\n description = COALESCE($3, description),\n modified_at = NOW()\n WHERE\n name = $4\n AND owner = $5\n AND deleted_at IS NULL"
|
|
||||||
},
|
|
||||||
"d9649c375db5825adda3b91c52468235fd9c361b827df64350c7e65bca0f00b4": {
|
"d9649c375db5825adda3b91c52468235fd9c361b827df64350c7e65bca0f00b4": {
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
|
@ -628,6 +633,29 @@
|
||||||
},
|
},
|
||||||
"query": "INSERT INTO sites (id, name, owner, title, description)\n VALUES ($1, $2, $3, $4, $5) RETURNING id"
|
"query": "INSERT INTO sites (id, name, owner, title, description)\n VALUES ($1, $2, $3, $4, $5) RETURNING id"
|
||||||
},
|
},
|
||||||
|
"eaf5344fe77b96ba3697e0454989d0e4d2fd074a850e7c8bafeaa9a19c50b71a": {
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Uuid"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nullable": [
|
||||||
|
false
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Uuid",
|
||||||
|
"Uuid",
|
||||||
|
"Varchar",
|
||||||
|
"Varchar"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"query": "INSERT INTO collections (id, site, slug, name)\n VALUES ($1, $2, $3, $4)\n RETURNING id"
|
||||||
|
},
|
||||||
"ecbbf6f400e058cd6e8695354d65a1883f974a39e11ac5ba0f7fba408fcf6b2a": {
|
"ecbbf6f400e058cd6e8695354d65a1883f974a39e11ac5ba0f7fba408fcf6b2a": {
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
|
|
|
@ -7,7 +7,7 @@ use super::Error;
|
||||||
|
|
||||||
pub const DEFAULT_COLLECTIONS: [(&str, &str); 2] = [("blog", "Blog"), ("pages", "Pages")];
|
pub const DEFAULT_COLLECTIONS: [(&str, &str); 2] = [("blog", "Blog"), ("pages", "Pages")];
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, FromRow)]
|
#[derive(Debug, Deserialize, Serialize, FromRow)]
|
||||||
pub struct Collection {
|
pub struct Collection {
|
||||||
/// Collection ID
|
/// Collection ID
|
||||||
pub id: Uuid,
|
pub id: Uuid,
|
||||||
|
@ -25,7 +25,7 @@ pub struct Collection {
|
||||||
pub parent: Option<Uuid>,
|
pub parent: Option<Uuid>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
pub struct CollectionData {
|
pub struct CollectionData {
|
||||||
pub id: Uuid,
|
pub id: Uuid,
|
||||||
pub slug: String,
|
pub slug: String,
|
||||||
|
|
|
@ -135,8 +135,8 @@ pub trait PostRepository {
|
||||||
/// List posts in a collection
|
/// List posts in a collection
|
||||||
async fn list_posts_in_collection(
|
async fn list_posts_in_collection(
|
||||||
&self,
|
&self,
|
||||||
site: &str,
|
site: &Uuid,
|
||||||
collection: &str,
|
collection: &Uuid,
|
||||||
cursor: Option<NaiveDateTime>,
|
cursor: Option<NaiveDateTime>,
|
||||||
limit: i64,
|
limit: i64,
|
||||||
) -> Result<CursorList<PostWithAuthor, NaiveDateTime>, Error>;
|
) -> Result<CursorList<PostWithAuthor, NaiveDateTime>, Error>;
|
||||||
|
|
|
@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
|
||||||
use sqlx::FromRow;
|
use sqlx::FromRow;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use super::Error;
|
use super::{collection::CollectionData, Error};
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, FromRow)]
|
#[derive(Deserialize, Serialize, FromRow)]
|
||||||
pub struct Site {
|
pub struct Site {
|
||||||
|
@ -23,6 +23,9 @@ pub struct Site {
|
||||||
/// Site description (like a user's bio)
|
/// Site description (like a user's bio)
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
|
|
||||||
|
/// Default collection (for homepage)
|
||||||
|
pub default_collection: Option<Uuid>,
|
||||||
|
|
||||||
/// Times
|
/// Times
|
||||||
pub created_at: NaiveDateTime,
|
pub created_at: NaiveDateTime,
|
||||||
pub modified_at: Option<NaiveDateTime>,
|
pub modified_at: Option<NaiveDateTime>,
|
||||||
|
@ -38,13 +41,8 @@ pub struct SiteData {
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
pub created_at: NaiveDateTime,
|
pub created_at: NaiveDateTime,
|
||||||
pub collections: Vec<CollectionNameAndSlug>,
|
pub collections: Vec<CollectionData>,
|
||||||
}
|
pub default_collection: Option<Uuid>,
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
|
||||||
pub struct CollectionNameAndSlug {
|
|
||||||
pub name: String,
|
|
||||||
pub slug: String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Data required to create a new site
|
/// Data required to create a new site
|
||||||
|
@ -61,6 +59,7 @@ pub struct UpdateSiteData {
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
pub title: Option<String>,
|
pub title: Option<String>,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
|
pub default_collection: Option<Uuid>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
use std::vec;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::content::{
|
use crate::content::{
|
||||||
|
@ -23,18 +24,31 @@ impl CollectionRepository for Database {
|
||||||
async fn create_default_collections(&self, site: &Uuid) -> Result<(), Error> {
|
async fn create_default_collections(&self, site: &Uuid) -> Result<(), Error> {
|
||||||
let mut tx = self.pool.begin().await?;
|
let mut tx = self.pool.begin().await?;
|
||||||
|
|
||||||
|
let mut uuids = vec![];
|
||||||
for (slug, name) in DEFAULT_COLLECTIONS {
|
for (slug, name) in DEFAULT_COLLECTIONS {
|
||||||
sqlx::query!(
|
let record = sqlx::query!(
|
||||||
r#"INSERT INTO collections (id, site, slug, name)
|
r#"INSERT INTO collections (id, site, slug, name)
|
||||||
VALUES ($1, $2, $3, $4)"#,
|
VALUES ($1, $2, $3, $4)
|
||||||
|
RETURNING id"#,
|
||||||
Uuid::now_v7(),
|
Uuid::now_v7(),
|
||||||
site,
|
site,
|
||||||
slug,
|
slug,
|
||||||
name
|
name
|
||||||
)
|
)
|
||||||
|
.fetch_one(&mut tx)
|
||||||
|
.await?;
|
||||||
|
uuids.push(record.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlx::query!(
|
||||||
|
r#"UPDATE sites
|
||||||
|
SET default_collection = $1
|
||||||
|
WHERE id = $2"#,
|
||||||
|
uuids[0],
|
||||||
|
site
|
||||||
|
)
|
||||||
.execute(&mut tx)
|
.execute(&mut tx)
|
||||||
.await?;
|
.await?;
|
||||||
}
|
|
||||||
|
|
||||||
tx.commit().await?;
|
tx.commit().await?;
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,8 @@ use super::Database;
|
||||||
impl PostRepository for Database {
|
impl PostRepository for Database {
|
||||||
async fn list_posts_in_collection(
|
async fn list_posts_in_collection(
|
||||||
&self,
|
&self,
|
||||||
site: &str,
|
site: &Uuid,
|
||||||
collection: &str,
|
collection: &Uuid,
|
||||||
from: Option<NaiveDateTime>,
|
from: Option<NaiveDateTime>,
|
||||||
limit: i64,
|
limit: i64,
|
||||||
) -> Result<CursorList<PostWithAuthor, NaiveDateTime>, Error> {
|
) -> Result<CursorList<PostWithAuthor, NaiveDateTime>, Error> {
|
||||||
|
@ -42,13 +42,9 @@ impl PostRepository for Database {
|
||||||
FROM pages
|
FROM pages
|
||||||
JOIN
|
JOIN
|
||||||
users ON author = users.id
|
users ON author = users.id
|
||||||
JOIN
|
|
||||||
sites ON site = sites.id
|
|
||||||
JOIN
|
|
||||||
collections ON collections.slug = $2 AND collections.site = sites.id
|
|
||||||
WHERE
|
WHERE
|
||||||
sites.name = $1
|
pages.site = $1
|
||||||
AND collections.id = ANY(collections)
|
AND $2 = ANY(collections)
|
||||||
AND pages.deleted_at IS NULL
|
AND pages.deleted_at IS NULL
|
||||||
AND published = true
|
AND published = true
|
||||||
AND pages.created_at <= $3
|
AND pages.created_at <= $3
|
||||||
|
|
|
@ -3,33 +3,42 @@ use sqlx::Postgres;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::content::{
|
use crate::content::{
|
||||||
site::{CollectionNameAndSlug, CreateSiteData, SiteData, SiteRepository, UpdateSiteData},
|
collection::CollectionData,
|
||||||
|
site::{CreateSiteData, SiteData, SiteRepository, UpdateSiteData},
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::Database;
|
use super::Database;
|
||||||
|
|
||||||
impl sqlx::Type<Postgres> for CollectionNameAndSlug {
|
impl sqlx::Type<Postgres> for CollectionData {
|
||||||
fn type_info() -> sqlx::postgres::PgTypeInfo {
|
fn type_info() -> sqlx::postgres::PgTypeInfo {
|
||||||
sqlx::postgres::PgTypeInfo::with_name("collection_name_slug")
|
sqlx::postgres::PgTypeInfo::with_name("collection_data")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'r> sqlx::Decode<'r, Postgres> for CollectionNameAndSlug {
|
impl<'r> sqlx::Decode<'r, Postgres> for CollectionData {
|
||||||
fn decode(
|
fn decode(
|
||||||
value: sqlx::postgres::PgValueRef<'r>,
|
value: sqlx::postgres::PgValueRef<'r>,
|
||||||
) -> Result<Self, Box<dyn std::error::Error + 'static + Send + Sync>> {
|
) -> Result<Self, Box<dyn std::error::Error + 'static + Send + Sync>> {
|
||||||
let mut decoder = sqlx::postgres::types::PgRecordDecoder::new(value)?;
|
let mut decoder = sqlx::postgres::types::PgRecordDecoder::new(value)?;
|
||||||
let slug = decoder.try_decode::<String>()?;
|
let id = decoder.try_decode::<Uuid>()?;
|
||||||
let name = decoder.try_decode::<String>()?;
|
let name = decoder.try_decode::<String>()?;
|
||||||
Ok(Self { name, slug })
|
let slug = decoder.try_decode::<String>()?;
|
||||||
|
let parent = decoder.try_decode::<Option<Uuid>>()?;
|
||||||
|
Ok(Self {
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
slug,
|
||||||
|
parent,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl SiteRepository for Database {
|
impl SiteRepository for Database {
|
||||||
async fn get_site_by_name(&self, name: &str) -> Result<SiteData, Error> {
|
async fn get_site_by_name(&self, name: &str) -> Result<SiteData, Error> {
|
||||||
let site = sqlx::query!(
|
let site = sqlx::query_as!(
|
||||||
|
SiteData,
|
||||||
r#"SELECT
|
r#"SELECT
|
||||||
sites.name,
|
sites.name,
|
||||||
users.name as owner,
|
users.name as owner,
|
||||||
|
@ -37,7 +46,8 @@ impl SiteRepository for Database {
|
||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
sites.created_at,
|
sites.created_at,
|
||||||
array_agg(row(collections.slug, collections.name)) as "collections!: Vec<CollectionNameAndSlug>"
|
default_collection,
|
||||||
|
array_agg(row(collections.id, collections.slug, collections.name, parent)) as "collections!: Vec<CollectionData>"
|
||||||
FROM sites
|
FROM sites
|
||||||
JOIN
|
JOIN
|
||||||
users ON sites.owner = users.id
|
users ON sites.owner = users.id
|
||||||
|
@ -47,7 +57,7 @@ impl SiteRepository for Database {
|
||||||
sites.name = $1
|
sites.name = $1
|
||||||
AND sites.deleted_at IS NULL
|
AND sites.deleted_at IS NULL
|
||||||
GROUP BY
|
GROUP BY
|
||||||
sites.name, users.name, users.display_name, title, description, sites.created_at"#,
|
sites.name, users.name, users.display_name, title, description, sites.created_at, default_collection"#,
|
||||||
name
|
name
|
||||||
)
|
)
|
||||||
.fetch_one(&self.pool)
|
.fetch_one(&self.pool)
|
||||||
|
@ -56,15 +66,7 @@ impl SiteRepository for Database {
|
||||||
sqlx::Error::RowNotFound => Error::NotFound,
|
sqlx::Error::RowNotFound => Error::NotFound,
|
||||||
_ => e.into(),
|
_ => e.into(),
|
||||||
})?;
|
})?;
|
||||||
Ok(SiteData {
|
Ok(site)
|
||||||
name: site.name,
|
|
||||||
owner: site.owner,
|
|
||||||
owner_display_name: site.owner_display_name,
|
|
||||||
title: site.title,
|
|
||||||
description: site.description,
|
|
||||||
created_at: site.created_at,
|
|
||||||
collections: site.collections,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_site(&self, owner: &Uuid, options: CreateSiteData) -> Result<Uuid, Error> {
|
async fn create_site(&self, owner: &Uuid, options: CreateSiteData) -> Result<Uuid, Error> {
|
||||||
|
@ -99,14 +101,16 @@ impl SiteRepository for Database {
|
||||||
name = COALESCE($1, name),
|
name = COALESCE($1, name),
|
||||||
title = COALESCE($2, title),
|
title = COALESCE($2, title),
|
||||||
description = COALESCE($3, description),
|
description = COALESCE($3, description),
|
||||||
|
default_collection = COALESCE($4, default_collection),
|
||||||
modified_at = NOW()
|
modified_at = NOW()
|
||||||
WHERE
|
WHERE
|
||||||
name = $4
|
name = $5
|
||||||
AND owner = $5
|
AND owner = $6
|
||||||
AND deleted_at IS NULL"#,
|
AND deleted_at IS NULL"#,
|
||||||
options.name,
|
options.name,
|
||||||
options.title,
|
options.title,
|
||||||
options.description,
|
options.description,
|
||||||
|
options.default_collection,
|
||||||
name,
|
name,
|
||||||
owner,
|
owner,
|
||||||
)
|
)
|
||||||
|
|
|
@ -7,6 +7,7 @@ use axum::{
|
||||||
use chrono::NaiveDateTime;
|
use chrono::NaiveDateTime;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
content::{collection::CollectionRepository, post::PostRepository, site::SiteRepository},
|
content::{collection::CollectionRepository, post::PostRepository, site::SiteRepository},
|
||||||
|
@ -15,6 +16,8 @@ use crate::{
|
||||||
state::AppState,
|
state::AppState,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const DEFAULT_PAGE_SIZE: i64 = 10;
|
||||||
|
|
||||||
async fn create_collection<Repo: CollectionRepository>(repository: Repo) {
|
async fn create_collection<Repo: CollectionRepository>(repository: Repo) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
@ -40,19 +43,27 @@ async fn delete_collection<Repo: CollectionRepository>(repository: Repo) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize, Default)]
|
||||||
struct PaginationQuery {
|
struct PaginationQuery {
|
||||||
before: Option<NaiveDateTime>,
|
before: Option<NaiveDateTime>,
|
||||||
limit: i64,
|
limit: Option<i64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn list_posts_in_collection<Repo: PostRepository>(
|
async fn list_posts_in_collection<Repo: SiteRepository + PostRepository>(
|
||||||
repository: Repo,
|
repository: Repo,
|
||||||
Path((site, slug)): Path<(String, String)>,
|
Path((site, id)): Path<(String, Uuid)>,
|
||||||
query: Query<PaginationQuery>,
|
query: Query<PaginationQuery>,
|
||||||
) -> Result<impl IntoResponse, ApiError<'static>> {
|
) -> Result<impl IntoResponse, ApiError<'static>> {
|
||||||
|
// Resolve site
|
||||||
|
let (site_id, _) = repository.get_site_id_and_owner(&site).await?;
|
||||||
|
|
||||||
let results = repository
|
let results = repository
|
||||||
.list_posts_in_collection(&site, &slug, query.before, query.limit)
|
.list_posts_in_collection(
|
||||||
|
&site_id,
|
||||||
|
&id,
|
||||||
|
query.before,
|
||||||
|
query.limit.unwrap_or(DEFAULT_PAGE_SIZE),
|
||||||
|
)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(Json(results))
|
Ok(Json(results))
|
||||||
}
|
}
|
||||||
|
@ -64,13 +75,13 @@ pub fn router() -> Router<Arc<AppState>> {
|
||||||
get(list_collections_for_site::<Database>).post(create_collection::<Database>),
|
get(list_collections_for_site::<Database>).post(create_collection::<Database>),
|
||||||
)
|
)
|
||||||
.route(
|
.route(
|
||||||
"/:site/:slug",
|
"/:site/:id",
|
||||||
get(get_collection::<Database>)
|
get(get_collection::<Database>)
|
||||||
.put(update_collection::<Database>)
|
.put(update_collection::<Database>)
|
||||||
.delete(delete_collection::<Database>),
|
.delete(delete_collection::<Database>),
|
||||||
)
|
)
|
||||||
.route(
|
.route(
|
||||||
"/:site/:slug/posts",
|
"/:site/:id/posts",
|
||||||
get(list_posts_in_collection::<Database>),
|
get(list_posts_in_collection::<Database>),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue