Implement complete collection persistence with database-backed survival across server restarts

• Add full multi-table schema for collections with normalized design (collections, collection_templates, collection_items, collection_item_versions)
• Implement collection detection and processing in enhancement pipeline for .insertr-add elements
• Add template extraction and storage from existing HTML children with multi-variant support
• Enable collection reconstruction from database on server restart with proper DOM rebuilding
• Extend ContentClient interface with collection operations and full database integration
• Update enhance command to use engine.DatabaseClient for collection persistence support
This commit is contained in:
2025-09-22 18:29:58 +02:00
parent b25663f76b
commit 2315ba4750
36 changed files with 4356 additions and 46 deletions

View File

@@ -0,0 +1,197 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
// source: collection_item_versions.sql
package sqlite
import (
"context"
"database/sql"
)
const createCollectionItemVersion = `-- name: CreateCollectionItemVersion :exec
INSERT INTO collection_item_versions (item_id, collection_id, site_id, html_content, template_id, position, created_by)
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)
`
type CreateCollectionItemVersionParams struct {
ItemID string `json:"item_id"`
CollectionID string `json:"collection_id"`
SiteID string `json:"site_id"`
HtmlContent string `json:"html_content"`
TemplateID int64 `json:"template_id"`
Position int64 `json:"position"`
CreatedBy string `json:"created_by"`
}
// Collection item versions table queries
func (q *Queries) CreateCollectionItemVersion(ctx context.Context, arg CreateCollectionItemVersionParams) error {
_, err := q.db.ExecContext(ctx, createCollectionItemVersion,
arg.ItemID,
arg.CollectionID,
arg.SiteID,
arg.HtmlContent,
arg.TemplateID,
arg.Position,
arg.CreatedBy,
)
return err
}
const deleteOldCollectionItemVersions = `-- name: DeleteOldCollectionItemVersions :exec
DELETE FROM collection_item_versions
WHERE created_at < ?1 AND site_id = ?2
`
type DeleteOldCollectionItemVersionsParams struct {
CreatedBefore int64 `json:"created_before"`
SiteID string `json:"site_id"`
}
func (q *Queries) DeleteOldCollectionItemVersions(ctx context.Context, arg DeleteOldCollectionItemVersionsParams) error {
_, err := q.db.ExecContext(ctx, deleteOldCollectionItemVersions, arg.CreatedBefore, arg.SiteID)
return err
}
const getAllCollectionItemVersionsForSite = `-- name: GetAllCollectionItemVersionsForSite :many
SELECT
civ.version_id, civ.item_id, civ.collection_id, civ.site_id, civ.html_content, civ.template_id, civ.position, civ.created_at, civ.created_by,
ci.html_content as current_html_content, ci.position as current_position
FROM collection_item_versions civ
LEFT JOIN collection_items ci ON civ.item_id = ci.item_id AND civ.collection_id = ci.collection_id AND civ.site_id = ci.site_id
WHERE civ.site_id = ?1
ORDER BY civ.created_at DESC
LIMIT ?2
`
type GetAllCollectionItemVersionsForSiteParams struct {
SiteID string `json:"site_id"`
LimitCount int64 `json:"limit_count"`
}
type GetAllCollectionItemVersionsForSiteRow struct {
VersionID int64 `json:"version_id"`
ItemID string `json:"item_id"`
CollectionID string `json:"collection_id"`
SiteID string `json:"site_id"`
HtmlContent string `json:"html_content"`
TemplateID int64 `json:"template_id"`
Position int64 `json:"position"`
CreatedAt int64 `json:"created_at"`
CreatedBy string `json:"created_by"`
CurrentHtmlContent sql.NullString `json:"current_html_content"`
CurrentPosition sql.NullInt64 `json:"current_position"`
}
func (q *Queries) GetAllCollectionItemVersionsForSite(ctx context.Context, arg GetAllCollectionItemVersionsForSiteParams) ([]GetAllCollectionItemVersionsForSiteRow, error) {
rows, err := q.db.QueryContext(ctx, getAllCollectionItemVersionsForSite, arg.SiteID, arg.LimitCount)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetAllCollectionItemVersionsForSiteRow
for rows.Next() {
var i GetAllCollectionItemVersionsForSiteRow
if err := rows.Scan(
&i.VersionID,
&i.ItemID,
&i.CollectionID,
&i.SiteID,
&i.HtmlContent,
&i.TemplateID,
&i.Position,
&i.CreatedAt,
&i.CreatedBy,
&i.CurrentHtmlContent,
&i.CurrentPosition,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getCollectionItemVersion = `-- name: GetCollectionItemVersion :one
SELECT version_id, item_id, collection_id, site_id, html_content, template_id, position, created_at, created_by
FROM collection_item_versions
WHERE version_id = ?1
`
func (q *Queries) GetCollectionItemVersion(ctx context.Context, versionID int64) (CollectionItemVersion, error) {
row := q.db.QueryRowContext(ctx, getCollectionItemVersion, versionID)
var i CollectionItemVersion
err := row.Scan(
&i.VersionID,
&i.ItemID,
&i.CollectionID,
&i.SiteID,
&i.HtmlContent,
&i.TemplateID,
&i.Position,
&i.CreatedAt,
&i.CreatedBy,
)
return i, err
}
const getCollectionItemVersionHistory = `-- name: GetCollectionItemVersionHistory :many
SELECT version_id, item_id, collection_id, site_id, html_content, template_id, position, created_at, created_by
FROM collection_item_versions
WHERE item_id = ?1 AND collection_id = ?2 AND site_id = ?3
ORDER BY created_at DESC
LIMIT ?4
`
type GetCollectionItemVersionHistoryParams struct {
ItemID string `json:"item_id"`
CollectionID string `json:"collection_id"`
SiteID string `json:"site_id"`
LimitCount int64 `json:"limit_count"`
}
func (q *Queries) GetCollectionItemVersionHistory(ctx context.Context, arg GetCollectionItemVersionHistoryParams) ([]CollectionItemVersion, error) {
rows, err := q.db.QueryContext(ctx, getCollectionItemVersionHistory,
arg.ItemID,
arg.CollectionID,
arg.SiteID,
arg.LimitCount,
)
if err != nil {
return nil, err
}
defer rows.Close()
var items []CollectionItemVersion
for rows.Next() {
var i CollectionItemVersion
if err := rows.Scan(
&i.VersionID,
&i.ItemID,
&i.CollectionID,
&i.SiteID,
&i.HtmlContent,
&i.TemplateID,
&i.Position,
&i.CreatedAt,
&i.CreatedBy,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}

View File

@@ -0,0 +1,327 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
// source: collection_items.sql
package sqlite
import (
"context"
)
const createCollectionItem = `-- name: CreateCollectionItem :one
INSERT INTO collection_items (item_id, collection_id, site_id, template_id, html_content, position, last_edited_by)
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)
RETURNING item_id, collection_id, site_id, template_id, html_content, position, created_at, updated_at, last_edited_by
`
type CreateCollectionItemParams struct {
ItemID string `json:"item_id"`
CollectionID string `json:"collection_id"`
SiteID string `json:"site_id"`
TemplateID int64 `json:"template_id"`
HtmlContent string `json:"html_content"`
Position int64 `json:"position"`
LastEditedBy string `json:"last_edited_by"`
}
func (q *Queries) CreateCollectionItem(ctx context.Context, arg CreateCollectionItemParams) (CollectionItem, error) {
row := q.db.QueryRowContext(ctx, createCollectionItem,
arg.ItemID,
arg.CollectionID,
arg.SiteID,
arg.TemplateID,
arg.HtmlContent,
arg.Position,
arg.LastEditedBy,
)
var i CollectionItem
err := row.Scan(
&i.ItemID,
&i.CollectionID,
&i.SiteID,
&i.TemplateID,
&i.HtmlContent,
&i.Position,
&i.CreatedAt,
&i.UpdatedAt,
&i.LastEditedBy,
)
return i, err
}
const deleteCollectionItem = `-- name: DeleteCollectionItem :exec
DELETE FROM collection_items
WHERE item_id = ?1 AND collection_id = ?2 AND site_id = ?3
`
type DeleteCollectionItemParams struct {
ItemID string `json:"item_id"`
CollectionID string `json:"collection_id"`
SiteID string `json:"site_id"`
}
func (q *Queries) DeleteCollectionItem(ctx context.Context, arg DeleteCollectionItemParams) error {
_, err := q.db.ExecContext(ctx, deleteCollectionItem, arg.ItemID, arg.CollectionID, arg.SiteID)
return err
}
const deleteCollectionItems = `-- name: DeleteCollectionItems :exec
DELETE FROM collection_items
WHERE collection_id = ?1 AND site_id = ?2
`
type DeleteCollectionItemsParams struct {
CollectionID string `json:"collection_id"`
SiteID string `json:"site_id"`
}
func (q *Queries) DeleteCollectionItems(ctx context.Context, arg DeleteCollectionItemsParams) error {
_, err := q.db.ExecContext(ctx, deleteCollectionItems, arg.CollectionID, arg.SiteID)
return err
}
const getCollectionItem = `-- name: GetCollectionItem :one
SELECT item_id, collection_id, site_id, template_id, html_content, position, created_at, updated_at, last_edited_by
FROM collection_items
WHERE item_id = ?1 AND collection_id = ?2 AND site_id = ?3
`
type GetCollectionItemParams struct {
ItemID string `json:"item_id"`
CollectionID string `json:"collection_id"`
SiteID string `json:"site_id"`
}
// Collection items table queries
func (q *Queries) GetCollectionItem(ctx context.Context, arg GetCollectionItemParams) (CollectionItem, error) {
row := q.db.QueryRowContext(ctx, getCollectionItem, arg.ItemID, arg.CollectionID, arg.SiteID)
var i CollectionItem
err := row.Scan(
&i.ItemID,
&i.CollectionID,
&i.SiteID,
&i.TemplateID,
&i.HtmlContent,
&i.Position,
&i.CreatedAt,
&i.UpdatedAt,
&i.LastEditedBy,
)
return i, err
}
const getCollectionItems = `-- name: GetCollectionItems :many
SELECT item_id, collection_id, site_id, template_id, html_content, position, created_at, updated_at, last_edited_by
FROM collection_items
WHERE collection_id = ?1 AND site_id = ?2
ORDER BY position ASC
`
type GetCollectionItemsParams struct {
CollectionID string `json:"collection_id"`
SiteID string `json:"site_id"`
}
func (q *Queries) GetCollectionItems(ctx context.Context, arg GetCollectionItemsParams) ([]CollectionItem, error) {
rows, err := q.db.QueryContext(ctx, getCollectionItems, arg.CollectionID, arg.SiteID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []CollectionItem
for rows.Next() {
var i CollectionItem
if err := rows.Scan(
&i.ItemID,
&i.CollectionID,
&i.SiteID,
&i.TemplateID,
&i.HtmlContent,
&i.Position,
&i.CreatedAt,
&i.UpdatedAt,
&i.LastEditedBy,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getCollectionItemsWithTemplate = `-- name: GetCollectionItemsWithTemplate :many
SELECT
ci.item_id, ci.collection_id, ci.site_id, ci.template_id, ci.html_content, ci.position, ci.created_at, ci.updated_at, ci.last_edited_by,
ct.name as template_name, ct.html_template, ct.is_default
FROM collection_items ci
JOIN collection_templates ct ON ci.template_id = ct.template_id
WHERE ci.collection_id = ?1 AND ci.site_id = ?2
ORDER BY ci.position ASC
`
type GetCollectionItemsWithTemplateParams struct {
CollectionID string `json:"collection_id"`
SiteID string `json:"site_id"`
}
type GetCollectionItemsWithTemplateRow struct {
ItemID string `json:"item_id"`
CollectionID string `json:"collection_id"`
SiteID string `json:"site_id"`
TemplateID int64 `json:"template_id"`
HtmlContent string `json:"html_content"`
Position int64 `json:"position"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
LastEditedBy string `json:"last_edited_by"`
TemplateName string `json:"template_name"`
HtmlTemplate string `json:"html_template"`
IsDefault int64 `json:"is_default"`
}
func (q *Queries) GetCollectionItemsWithTemplate(ctx context.Context, arg GetCollectionItemsWithTemplateParams) ([]GetCollectionItemsWithTemplateRow, error) {
rows, err := q.db.QueryContext(ctx, getCollectionItemsWithTemplate, arg.CollectionID, arg.SiteID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetCollectionItemsWithTemplateRow
for rows.Next() {
var i GetCollectionItemsWithTemplateRow
if err := rows.Scan(
&i.ItemID,
&i.CollectionID,
&i.SiteID,
&i.TemplateID,
&i.HtmlContent,
&i.Position,
&i.CreatedAt,
&i.UpdatedAt,
&i.LastEditedBy,
&i.TemplateName,
&i.HtmlTemplate,
&i.IsDefault,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getMaxPosition = `-- name: GetMaxPosition :one
SELECT COALESCE(MAX(position), 0) as max_position
FROM collection_items
WHERE collection_id = ?1 AND site_id = ?2
`
type GetMaxPositionParams struct {
CollectionID string `json:"collection_id"`
SiteID string `json:"site_id"`
}
func (q *Queries) GetMaxPosition(ctx context.Context, arg GetMaxPositionParams) (interface{}, error) {
row := q.db.QueryRowContext(ctx, getMaxPosition, arg.CollectionID, arg.SiteID)
var max_position interface{}
err := row.Scan(&max_position)
return max_position, err
}
const reorderCollectionItems = `-- name: ReorderCollectionItems :exec
UPDATE collection_items
SET position = position + ?1
WHERE collection_id = ?2 AND site_id = ?3
AND position >= ?4
`
type ReorderCollectionItemsParams struct {
PositionDelta int64 `json:"position_delta"`
CollectionID string `json:"collection_id"`
SiteID string `json:"site_id"`
StartPosition int64 `json:"start_position"`
}
func (q *Queries) ReorderCollectionItems(ctx context.Context, arg ReorderCollectionItemsParams) error {
_, err := q.db.ExecContext(ctx, reorderCollectionItems,
arg.PositionDelta,
arg.CollectionID,
arg.SiteID,
arg.StartPosition,
)
return err
}
const updateCollectionItem = `-- name: UpdateCollectionItem :one
UPDATE collection_items
SET html_content = ?1, last_edited_by = ?2
WHERE item_id = ?3 AND collection_id = ?4 AND site_id = ?5
RETURNING item_id, collection_id, site_id, template_id, html_content, position, created_at, updated_at, last_edited_by
`
type UpdateCollectionItemParams struct {
HtmlContent string `json:"html_content"`
LastEditedBy string `json:"last_edited_by"`
ItemID string `json:"item_id"`
CollectionID string `json:"collection_id"`
SiteID string `json:"site_id"`
}
func (q *Queries) UpdateCollectionItem(ctx context.Context, arg UpdateCollectionItemParams) (CollectionItem, error) {
row := q.db.QueryRowContext(ctx, updateCollectionItem,
arg.HtmlContent,
arg.LastEditedBy,
arg.ItemID,
arg.CollectionID,
arg.SiteID,
)
var i CollectionItem
err := row.Scan(
&i.ItemID,
&i.CollectionID,
&i.SiteID,
&i.TemplateID,
&i.HtmlContent,
&i.Position,
&i.CreatedAt,
&i.UpdatedAt,
&i.LastEditedBy,
)
return i, err
}
const updateCollectionItemPosition = `-- name: UpdateCollectionItemPosition :exec
UPDATE collection_items
SET position = ?1
WHERE item_id = ?2 AND collection_id = ?3 AND site_id = ?4
`
type UpdateCollectionItemPositionParams struct {
Position int64 `json:"position"`
ItemID string `json:"item_id"`
CollectionID string `json:"collection_id"`
SiteID string `json:"site_id"`
}
func (q *Queries) UpdateCollectionItemPosition(ctx context.Context, arg UpdateCollectionItemPositionParams) error {
_, err := q.db.ExecContext(ctx, updateCollectionItemPosition,
arg.Position,
arg.ItemID,
arg.CollectionID,
arg.SiteID,
)
return err
}

View File

@@ -0,0 +1,217 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
// source: collection_templates.sql
package sqlite
import (
"context"
)
const createCollectionTemplate = `-- name: CreateCollectionTemplate :one
INSERT INTO collection_templates (collection_id, site_id, name, html_template, is_default)
VALUES (?1, ?2, ?3, ?4, ?5)
RETURNING template_id, collection_id, site_id, name, html_template, is_default, created_at
`
type CreateCollectionTemplateParams struct {
CollectionID string `json:"collection_id"`
SiteID string `json:"site_id"`
Name string `json:"name"`
HtmlTemplate string `json:"html_template"`
IsDefault int64 `json:"is_default"`
}
func (q *Queries) CreateCollectionTemplate(ctx context.Context, arg CreateCollectionTemplateParams) (CollectionTemplate, error) {
row := q.db.QueryRowContext(ctx, createCollectionTemplate,
arg.CollectionID,
arg.SiteID,
arg.Name,
arg.HtmlTemplate,
arg.IsDefault,
)
var i CollectionTemplate
err := row.Scan(
&i.TemplateID,
&i.CollectionID,
&i.SiteID,
&i.Name,
&i.HtmlTemplate,
&i.IsDefault,
&i.CreatedAt,
)
return i, err
}
const deleteCollectionTemplate = `-- name: DeleteCollectionTemplate :exec
DELETE FROM collection_templates
WHERE template_id = ?1
`
func (q *Queries) DeleteCollectionTemplate(ctx context.Context, templateID int64) error {
_, err := q.db.ExecContext(ctx, deleteCollectionTemplate, templateID)
return err
}
const deleteCollectionTemplates = `-- name: DeleteCollectionTemplates :exec
DELETE FROM collection_templates
WHERE collection_id = ?1 AND site_id = ?2
`
type DeleteCollectionTemplatesParams struct {
CollectionID string `json:"collection_id"`
SiteID string `json:"site_id"`
}
func (q *Queries) DeleteCollectionTemplates(ctx context.Context, arg DeleteCollectionTemplatesParams) error {
_, err := q.db.ExecContext(ctx, deleteCollectionTemplates, arg.CollectionID, arg.SiteID)
return err
}
const getCollectionTemplate = `-- name: GetCollectionTemplate :one
SELECT template_id, collection_id, site_id, name, html_template, is_default, created_at
FROM collection_templates
WHERE template_id = ?1
`
// Collection templates table queries
func (q *Queries) GetCollectionTemplate(ctx context.Context, templateID int64) (CollectionTemplate, error) {
row := q.db.QueryRowContext(ctx, getCollectionTemplate, templateID)
var i CollectionTemplate
err := row.Scan(
&i.TemplateID,
&i.CollectionID,
&i.SiteID,
&i.Name,
&i.HtmlTemplate,
&i.IsDefault,
&i.CreatedAt,
)
return i, err
}
const getCollectionTemplates = `-- name: GetCollectionTemplates :many
SELECT template_id, collection_id, site_id, name, html_template, is_default, created_at
FROM collection_templates
WHERE collection_id = ?1 AND site_id = ?2
ORDER BY is_default DESC, created_at ASC
`
type GetCollectionTemplatesParams struct {
CollectionID string `json:"collection_id"`
SiteID string `json:"site_id"`
}
func (q *Queries) GetCollectionTemplates(ctx context.Context, arg GetCollectionTemplatesParams) ([]CollectionTemplate, error) {
rows, err := q.db.QueryContext(ctx, getCollectionTemplates, arg.CollectionID, arg.SiteID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []CollectionTemplate
for rows.Next() {
var i CollectionTemplate
if err := rows.Scan(
&i.TemplateID,
&i.CollectionID,
&i.SiteID,
&i.Name,
&i.HtmlTemplate,
&i.IsDefault,
&i.CreatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getDefaultTemplate = `-- name: GetDefaultTemplate :one
SELECT template_id, collection_id, site_id, name, html_template, is_default, created_at
FROM collection_templates
WHERE collection_id = ?1 AND site_id = ?2 AND is_default = TRUE
LIMIT 1
`
type GetDefaultTemplateParams struct {
CollectionID string `json:"collection_id"`
SiteID string `json:"site_id"`
}
func (q *Queries) GetDefaultTemplate(ctx context.Context, arg GetDefaultTemplateParams) (CollectionTemplate, error) {
row := q.db.QueryRowContext(ctx, getDefaultTemplate, arg.CollectionID, arg.SiteID)
var i CollectionTemplate
err := row.Scan(
&i.TemplateID,
&i.CollectionID,
&i.SiteID,
&i.Name,
&i.HtmlTemplate,
&i.IsDefault,
&i.CreatedAt,
)
return i, err
}
const setTemplateAsDefault = `-- name: SetTemplateAsDefault :exec
UPDATE collection_templates
SET is_default = CASE
WHEN template_id = ?1 THEN TRUE
ELSE FALSE
END
WHERE collection_id = ?2 AND site_id = ?3
`
type SetTemplateAsDefaultParams struct {
TemplateID int64 `json:"template_id"`
CollectionID string `json:"collection_id"`
SiteID string `json:"site_id"`
}
func (q *Queries) SetTemplateAsDefault(ctx context.Context, arg SetTemplateAsDefaultParams) error {
_, err := q.db.ExecContext(ctx, setTemplateAsDefault, arg.TemplateID, arg.CollectionID, arg.SiteID)
return err
}
const updateCollectionTemplate = `-- name: UpdateCollectionTemplate :one
UPDATE collection_templates
SET name = ?1, html_template = ?2, is_default = ?3
WHERE template_id = ?4
RETURNING template_id, collection_id, site_id, name, html_template, is_default, created_at
`
type UpdateCollectionTemplateParams struct {
Name string `json:"name"`
HtmlTemplate string `json:"html_template"`
IsDefault int64 `json:"is_default"`
TemplateID int64 `json:"template_id"`
}
func (q *Queries) UpdateCollectionTemplate(ctx context.Context, arg UpdateCollectionTemplateParams) (CollectionTemplate, error) {
row := q.db.QueryRowContext(ctx, updateCollectionTemplate,
arg.Name,
arg.HtmlTemplate,
arg.IsDefault,
arg.TemplateID,
)
var i CollectionTemplate
err := row.Scan(
&i.TemplateID,
&i.CollectionID,
&i.SiteID,
&i.Name,
&i.HtmlTemplate,
&i.IsDefault,
&i.CreatedAt,
)
return i, err
}

View File

@@ -0,0 +1,199 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
// source: collections.sql
package sqlite
import (
"context"
)
const createCollection = `-- name: CreateCollection :one
INSERT INTO collections (id, site_id, container_html, last_edited_by)
VALUES (?1, ?2, ?3, ?4)
RETURNING id, site_id, container_html, created_at, updated_at, last_edited_by
`
type CreateCollectionParams struct {
ID string `json:"id"`
SiteID string `json:"site_id"`
ContainerHtml string `json:"container_html"`
LastEditedBy string `json:"last_edited_by"`
}
func (q *Queries) CreateCollection(ctx context.Context, arg CreateCollectionParams) (Collection, error) {
row := q.db.QueryRowContext(ctx, createCollection,
arg.ID,
arg.SiteID,
arg.ContainerHtml,
arg.LastEditedBy,
)
var i Collection
err := row.Scan(
&i.ID,
&i.SiteID,
&i.ContainerHtml,
&i.CreatedAt,
&i.UpdatedAt,
&i.LastEditedBy,
)
return i, err
}
const deleteAllSiteCollections = `-- name: DeleteAllSiteCollections :exec
DELETE FROM collections
WHERE site_id = ?1
`
func (q *Queries) DeleteAllSiteCollections(ctx context.Context, siteID string) error {
_, err := q.db.ExecContext(ctx, deleteAllSiteCollections, siteID)
return err
}
const deleteCollection = `-- name: DeleteCollection :exec
DELETE FROM collections
WHERE id = ?1 AND site_id = ?2
`
type DeleteCollectionParams struct {
ID string `json:"id"`
SiteID string `json:"site_id"`
}
func (q *Queries) DeleteCollection(ctx context.Context, arg DeleteCollectionParams) error {
_, err := q.db.ExecContext(ctx, deleteCollection, arg.ID, arg.SiteID)
return err
}
const getAllCollections = `-- name: GetAllCollections :many
SELECT id, site_id, container_html, created_at, updated_at, last_edited_by
FROM collections
WHERE site_id = ?1
ORDER BY updated_at DESC
`
func (q *Queries) GetAllCollections(ctx context.Context, siteID string) ([]Collection, error) {
rows, err := q.db.QueryContext(ctx, getAllCollections, siteID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Collection
for rows.Next() {
var i Collection
if err := rows.Scan(
&i.ID,
&i.SiteID,
&i.ContainerHtml,
&i.CreatedAt,
&i.UpdatedAt,
&i.LastEditedBy,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getCollection = `-- name: GetCollection :one
SELECT id, site_id, container_html, created_at, updated_at, last_edited_by
FROM collections
WHERE id = ?1 AND site_id = ?2
`
type GetCollectionParams struct {
ID string `json:"id"`
SiteID string `json:"site_id"`
}
// Collections table queries
func (q *Queries) GetCollection(ctx context.Context, arg GetCollectionParams) (Collection, error) {
row := q.db.QueryRowContext(ctx, getCollection, arg.ID, arg.SiteID)
var i Collection
err := row.Scan(
&i.ID,
&i.SiteID,
&i.ContainerHtml,
&i.CreatedAt,
&i.UpdatedAt,
&i.LastEditedBy,
)
return i, err
}
const updateCollection = `-- name: UpdateCollection :one
UPDATE collections
SET container_html = ?1, last_edited_by = ?2
WHERE id = ?3 AND site_id = ?4
RETURNING id, site_id, container_html, created_at, updated_at, last_edited_by
`
type UpdateCollectionParams struct {
ContainerHtml string `json:"container_html"`
LastEditedBy string `json:"last_edited_by"`
ID string `json:"id"`
SiteID string `json:"site_id"`
}
func (q *Queries) UpdateCollection(ctx context.Context, arg UpdateCollectionParams) (Collection, error) {
row := q.db.QueryRowContext(ctx, updateCollection,
arg.ContainerHtml,
arg.LastEditedBy,
arg.ID,
arg.SiteID,
)
var i Collection
err := row.Scan(
&i.ID,
&i.SiteID,
&i.ContainerHtml,
&i.CreatedAt,
&i.UpdatedAt,
&i.LastEditedBy,
)
return i, err
}
const upsertCollection = `-- name: UpsertCollection :one
INSERT INTO collections (id, site_id, container_html, last_edited_by)
VALUES (?1, ?2, ?3, ?4)
ON CONFLICT(id, site_id) DO UPDATE SET
container_html = EXCLUDED.container_html,
last_edited_by = EXCLUDED.last_edited_by
RETURNING id, site_id, container_html, created_at, updated_at, last_edited_by
`
type UpsertCollectionParams struct {
ID string `json:"id"`
SiteID string `json:"site_id"`
ContainerHtml string `json:"container_html"`
LastEditedBy string `json:"last_edited_by"`
}
func (q *Queries) UpsertCollection(ctx context.Context, arg UpsertCollectionParams) (Collection, error) {
row := q.db.QueryRowContext(ctx, upsertCollection,
arg.ID,
arg.SiteID,
arg.ContainerHtml,
arg.LastEditedBy,
)
var i Collection
err := row.Scan(
&i.ID,
&i.SiteID,
&i.ContainerHtml,
&i.CreatedAt,
&i.UpdatedAt,
&i.LastEditedBy,
)
return i, err
}

View File

@@ -8,6 +8,49 @@ import (
"database/sql"
)
type Collection struct {
ID string `json:"id"`
SiteID string `json:"site_id"`
ContainerHtml string `json:"container_html"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
LastEditedBy string `json:"last_edited_by"`
}
type CollectionItem struct {
ItemID string `json:"item_id"`
CollectionID string `json:"collection_id"`
SiteID string `json:"site_id"`
TemplateID int64 `json:"template_id"`
HtmlContent string `json:"html_content"`
Position int64 `json:"position"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
LastEditedBy string `json:"last_edited_by"`
}
type CollectionItemVersion struct {
VersionID int64 `json:"version_id"`
ItemID string `json:"item_id"`
CollectionID string `json:"collection_id"`
SiteID string `json:"site_id"`
HtmlContent string `json:"html_content"`
TemplateID int64 `json:"template_id"`
Position int64 `json:"position"`
CreatedAt int64 `json:"created_at"`
CreatedBy string `json:"created_by"`
}
type CollectionTemplate struct {
TemplateID int64 `json:"template_id"`
CollectionID string `json:"collection_id"`
SiteID string `json:"site_id"`
Name string `json:"name"`
HtmlTemplate string `json:"html_template"`
IsDefault int64 `json:"is_default"`
CreatedAt int64 `json:"created_at"`
}
type Content struct {
ID string `json:"id"`
SiteID string `json:"site_id"`

View File

@@ -9,20 +9,58 @@ import (
)
type Querier interface {
CreateCollection(ctx context.Context, arg CreateCollectionParams) (Collection, error)
CreateCollectionItem(ctx context.Context, arg CreateCollectionItemParams) (CollectionItem, error)
// Collection item versions table queries
CreateCollectionItemVersion(ctx context.Context, arg CreateCollectionItemVersionParams) error
CreateCollectionTemplate(ctx context.Context, arg CreateCollectionTemplateParams) (CollectionTemplate, error)
CreateContent(ctx context.Context, arg CreateContentParams) (Content, error)
CreateContentVersion(ctx context.Context, arg CreateContentVersionParams) error
DeleteAllSiteCollections(ctx context.Context, siteID string) error
DeleteAllSiteContent(ctx context.Context, siteID string) error
DeleteCollection(ctx context.Context, arg DeleteCollectionParams) error
DeleteCollectionItem(ctx context.Context, arg DeleteCollectionItemParams) error
DeleteCollectionItems(ctx context.Context, arg DeleteCollectionItemsParams) error
DeleteCollectionTemplate(ctx context.Context, templateID int64) error
DeleteCollectionTemplates(ctx context.Context, arg DeleteCollectionTemplatesParams) error
DeleteContent(ctx context.Context, arg DeleteContentParams) error
DeleteOldCollectionItemVersions(ctx context.Context, arg DeleteOldCollectionItemVersionsParams) error
DeleteOldVersions(ctx context.Context, arg DeleteOldVersionsParams) error
GetAllCollectionItemVersionsForSite(ctx context.Context, arg GetAllCollectionItemVersionsForSiteParams) ([]GetAllCollectionItemVersionsForSiteRow, error)
GetAllCollections(ctx context.Context, siteID string) ([]Collection, error)
GetAllContent(ctx context.Context, siteID string) ([]Content, error)
GetAllVersionsForSite(ctx context.Context, arg GetAllVersionsForSiteParams) ([]GetAllVersionsForSiteRow, error)
GetBulkContent(ctx context.Context, arg GetBulkContentParams) ([]Content, error)
// Collections table queries
GetCollection(ctx context.Context, arg GetCollectionParams) (Collection, error)
// Collection items table queries
GetCollectionItem(ctx context.Context, arg GetCollectionItemParams) (CollectionItem, error)
GetCollectionItemVersion(ctx context.Context, versionID int64) (CollectionItemVersion, error)
GetCollectionItemVersionHistory(ctx context.Context, arg GetCollectionItemVersionHistoryParams) ([]CollectionItemVersion, error)
GetCollectionItems(ctx context.Context, arg GetCollectionItemsParams) ([]CollectionItem, error)
GetCollectionItemsWithTemplate(ctx context.Context, arg GetCollectionItemsWithTemplateParams) ([]GetCollectionItemsWithTemplateRow, error)
// Collection templates table queries
GetCollectionTemplate(ctx context.Context, templateID int64) (CollectionTemplate, error)
GetCollectionTemplates(ctx context.Context, arg GetCollectionTemplatesParams) ([]CollectionTemplate, error)
GetContent(ctx context.Context, arg GetContentParams) (Content, error)
GetContentVersion(ctx context.Context, versionID int64) (ContentVersion, error)
GetContentVersionHistory(ctx context.Context, arg GetContentVersionHistoryParams) ([]ContentVersion, error)
GetDefaultTemplate(ctx context.Context, arg GetDefaultTemplateParams) (CollectionTemplate, error)
GetMaxPosition(ctx context.Context, arg GetMaxPositionParams) (interface{}, error)
InitializeCollectionItemVersionsTable(ctx context.Context) error
InitializeCollectionItemsTable(ctx context.Context) error
InitializeCollectionTemplatesTable(ctx context.Context) error
InitializeCollectionsTable(ctx context.Context) error
InitializeSchema(ctx context.Context) error
InitializeVersionsTable(ctx context.Context) error
ReorderCollectionItems(ctx context.Context, arg ReorderCollectionItemsParams) error
SetTemplateAsDefault(ctx context.Context, arg SetTemplateAsDefaultParams) error
UpdateCollection(ctx context.Context, arg UpdateCollectionParams) (Collection, error)
UpdateCollectionItem(ctx context.Context, arg UpdateCollectionItemParams) (CollectionItem, error)
UpdateCollectionItemPosition(ctx context.Context, arg UpdateCollectionItemPositionParams) error
UpdateCollectionTemplate(ctx context.Context, arg UpdateCollectionTemplateParams) (CollectionTemplate, error)
UpdateContent(ctx context.Context, arg UpdateContentParams) (Content, error)
UpsertCollection(ctx context.Context, arg UpsertCollectionParams) (Collection, error)
UpsertContent(ctx context.Context, arg UpsertContentParams) (Content, error)
}

View File

@@ -22,15 +22,97 @@ CREATE TABLE content_versions (
created_by TEXT DEFAULT 'system' NOT NULL
);
-- Collections table - manages .insertr-add containers
CREATE TABLE collections (
id TEXT NOT NULL,
site_id TEXT NOT NULL,
container_html TEXT NOT NULL,
created_at INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
updated_at INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
last_edited_by TEXT DEFAULT 'system' NOT NULL,
PRIMARY KEY (id, site_id)
);
-- Collection templates - multiple template variants per collection
CREATE TABLE collection_templates (
template_id INTEGER PRIMARY KEY AUTOINCREMENT,
collection_id TEXT NOT NULL,
site_id TEXT NOT NULL,
name TEXT NOT NULL,
html_template TEXT NOT NULL,
is_default INTEGER DEFAULT 0 NOT NULL,
created_at INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
FOREIGN KEY (collection_id, site_id) REFERENCES collections(id, site_id) ON DELETE CASCADE
);
-- Collection items - individual items within collections
CREATE TABLE collection_items (
item_id TEXT NOT NULL,
collection_id TEXT NOT NULL,
site_id TEXT NOT NULL,
template_id INTEGER NOT NULL,
html_content TEXT NOT NULL,
position INTEGER NOT NULL,
created_at INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
updated_at INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
last_edited_by TEXT DEFAULT 'system' NOT NULL,
PRIMARY KEY (item_id, collection_id, site_id),
FOREIGN KEY (collection_id, site_id) REFERENCES collections(id, site_id) ON DELETE CASCADE,
FOREIGN KEY (template_id) REFERENCES collection_templates(template_id) ON DELETE RESTRICT
);
-- Collection item version history
CREATE TABLE collection_item_versions (
version_id INTEGER PRIMARY KEY AUTOINCREMENT,
item_id TEXT NOT NULL,
collection_id TEXT NOT NULL,
site_id TEXT NOT NULL,
html_content TEXT NOT NULL,
template_id INTEGER NOT NULL,
position INTEGER NOT NULL,
created_at INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
created_by TEXT DEFAULT 'system' NOT NULL,
FOREIGN KEY (item_id, collection_id, site_id) REFERENCES collection_items(item_id, collection_id, site_id) ON DELETE CASCADE
);
-- Indexes for performance
CREATE INDEX IF NOT EXISTS idx_content_site_id ON content(site_id);
CREATE INDEX IF NOT EXISTS idx_content_updated_at ON content(updated_at);
CREATE INDEX IF NOT EXISTS idx_content_versions_lookup ON content_versions(content_id, site_id, created_at DESC);
-- Collection indexes for performance
CREATE INDEX IF NOT EXISTS idx_collections_site_id ON collections(site_id);
CREATE INDEX IF NOT EXISTS idx_collections_updated_at ON collections(updated_at);
CREATE INDEX IF NOT EXISTS idx_collection_templates_lookup ON collection_templates(collection_id, site_id);
CREATE INDEX IF NOT EXISTS idx_collection_templates_default ON collection_templates(collection_id, site_id, is_default DESC);
CREATE INDEX IF NOT EXISTS idx_collection_items_lookup ON collection_items(collection_id, site_id, position);
CREATE INDEX IF NOT EXISTS idx_collection_items_template ON collection_items(template_id);
CREATE INDEX IF NOT EXISTS idx_collection_item_versions_lookup ON collection_item_versions(item_id, collection_id, site_id, created_at DESC);
-- Constraint to ensure only one default template per collection
CREATE UNIQUE INDEX IF NOT EXISTS idx_collection_templates_one_default
ON collection_templates(collection_id, site_id)
WHERE is_default = 1;
-- Trigger to automatically update updated_at timestamp
CREATE TRIGGER IF NOT EXISTS update_content_updated_at
AFTER UPDATE ON content
FOR EACH ROW
BEGIN
UPDATE content SET updated_at = strftime('%s', 'now') WHERE id = NEW.id AND site_id = NEW.site_id;
END;
-- Triggers for collection timestamps
CREATE TRIGGER IF NOT EXISTS update_collections_updated_at
AFTER UPDATE ON collections
FOR EACH ROW
BEGIN
UPDATE collections SET updated_at = strftime('%s', 'now') WHERE id = NEW.id AND site_id = NEW.site_id;
END;
CREATE TRIGGER IF NOT EXISTS update_collection_items_updated_at
AFTER UPDATE ON collection_items
FOR EACH ROW
BEGIN
UPDATE collection_items SET updated_at = strftime('%s', 'now') WHERE item_id = NEW.item_id AND collection_id = NEW.collection_id AND site_id = NEW.site_id;
END;

View File

@@ -21,6 +21,59 @@ CREATE TABLE IF NOT EXISTS content_versions (
created_by TEXT DEFAULT 'system' NOT NULL
);
-- name: InitializeCollectionsTable :exec
CREATE TABLE IF NOT EXISTS collections (
id TEXT NOT NULL,
site_id TEXT NOT NULL,
container_html TEXT NOT NULL,
created_at INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
updated_at INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
last_edited_by TEXT DEFAULT 'system' NOT NULL,
PRIMARY KEY (id, site_id)
);
-- name: InitializeCollectionTemplatesTable :exec
CREATE TABLE IF NOT EXISTS collection_templates (
template_id INTEGER PRIMARY KEY AUTOINCREMENT,
collection_id TEXT NOT NULL,
site_id TEXT NOT NULL,
name TEXT NOT NULL,
html_template TEXT NOT NULL,
is_default INTEGER DEFAULT 0 NOT NULL,
created_at INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
FOREIGN KEY (collection_id, site_id) REFERENCES collections(id, site_id) ON DELETE CASCADE
);
-- name: InitializeCollectionItemsTable :exec
CREATE TABLE IF NOT EXISTS collection_items (
item_id TEXT NOT NULL,
collection_id TEXT NOT NULL,
site_id TEXT NOT NULL,
template_id INTEGER NOT NULL,
html_content TEXT NOT NULL,
position INTEGER NOT NULL,
created_at INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
updated_at INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
last_edited_by TEXT DEFAULT 'system' NOT NULL,
PRIMARY KEY (item_id, collection_id, site_id),
FOREIGN KEY (collection_id, site_id) REFERENCES collections(id, site_id) ON DELETE CASCADE,
FOREIGN KEY (template_id) REFERENCES collection_templates(template_id) ON DELETE RESTRICT
);
-- name: InitializeCollectionItemVersionsTable :exec
CREATE TABLE IF NOT EXISTS collection_item_versions (
version_id INTEGER PRIMARY KEY AUTOINCREMENT,
item_id TEXT NOT NULL,
collection_id TEXT NOT NULL,
site_id TEXT NOT NULL,
html_content TEXT NOT NULL,
template_id INTEGER NOT NULL,
position INTEGER NOT NULL,
created_at INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
created_by TEXT DEFAULT 'system' NOT NULL,
FOREIGN KEY (item_id, collection_id, site_id) REFERENCES collection_items(item_id, collection_id, site_id) ON DELETE CASCADE
);
-- name: CreateContentSiteIndex :exec
CREATE INDEX IF NOT EXISTS idx_content_site_id ON content(site_id);
@@ -30,10 +83,52 @@ CREATE INDEX IF NOT EXISTS idx_content_updated_at ON content(updated_at);
-- name: CreateVersionsLookupIndex :exec
CREATE INDEX IF NOT EXISTS idx_content_versions_lookup ON content_versions(content_id, site_id, created_at DESC);
-- name: CreateCollectionsSiteIndex :exec
CREATE INDEX IF NOT EXISTS idx_collections_site_id ON collections(site_id);
-- name: CreateCollectionsUpdatedAtIndex :exec
CREATE INDEX IF NOT EXISTS idx_collections_updated_at ON collections(updated_at);
-- name: CreateCollectionTemplatesLookupIndex :exec
CREATE INDEX IF NOT EXISTS idx_collection_templates_lookup ON collection_templates(collection_id, site_id);
-- name: CreateCollectionTemplatesDefaultIndex :exec
CREATE INDEX IF NOT EXISTS idx_collection_templates_default ON collection_templates(collection_id, site_id, is_default DESC);
-- name: CreateCollectionItemsLookupIndex :exec
CREATE INDEX IF NOT EXISTS idx_collection_items_lookup ON collection_items(collection_id, site_id, position);
-- name: CreateCollectionItemsTemplateIndex :exec
CREATE INDEX IF NOT EXISTS idx_collection_items_template ON collection_items(template_id);
-- name: CreateCollectionItemVersionsLookupIndex :exec
CREATE INDEX IF NOT EXISTS idx_collection_item_versions_lookup ON collection_item_versions(item_id, collection_id, site_id, created_at DESC);
-- name: CreateCollectionTemplatesOneDefaultIndex :exec
CREATE UNIQUE INDEX IF NOT EXISTS idx_collection_templates_one_default
ON collection_templates(collection_id, site_id)
WHERE is_default = 1;
-- name: CreateUpdateTrigger :exec
CREATE TRIGGER IF NOT EXISTS update_content_updated_at
AFTER UPDATE ON content
FOR EACH ROW
BEGIN
UPDATE content SET updated_at = strftime('%s', 'now') WHERE id = NEW.id AND site_id = NEW.site_id;
END;
-- name: CreateCollectionsUpdateTrigger :exec
CREATE TRIGGER IF NOT EXISTS update_collections_updated_at
AFTER UPDATE ON collections
FOR EACH ROW
BEGIN
UPDATE collections SET updated_at = strftime('%s', 'now') WHERE id = NEW.id AND site_id = NEW.site_id;
END;
-- name: CreateCollectionItemsUpdateTrigger :exec
CREATE TRIGGER IF NOT EXISTS update_collection_items_updated_at
AFTER UPDATE ON collection_items
FOR EACH ROW
BEGIN
UPDATE collection_items SET updated_at = strftime('%s', 'now') WHERE item_id = NEW.item_id AND collection_id = NEW.collection_id AND site_id = NEW.site_id;
END;

View File

@@ -9,6 +9,83 @@ import (
"context"
)
const initializeCollectionItemVersionsTable = `-- name: InitializeCollectionItemVersionsTable :exec
CREATE TABLE IF NOT EXISTS collection_item_versions (
version_id INTEGER PRIMARY KEY AUTOINCREMENT,
item_id TEXT NOT NULL,
collection_id TEXT NOT NULL,
site_id TEXT NOT NULL,
html_content TEXT NOT NULL,
template_id INTEGER NOT NULL,
position INTEGER NOT NULL,
created_at INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
created_by TEXT DEFAULT 'system' NOT NULL,
FOREIGN KEY (item_id, collection_id, site_id) REFERENCES collection_items(item_id, collection_id, site_id) ON DELETE CASCADE
)
`
func (q *Queries) InitializeCollectionItemVersionsTable(ctx context.Context) error {
_, err := q.db.ExecContext(ctx, initializeCollectionItemVersionsTable)
return err
}
const initializeCollectionItemsTable = `-- name: InitializeCollectionItemsTable :exec
CREATE TABLE IF NOT EXISTS collection_items (
item_id TEXT NOT NULL,
collection_id TEXT NOT NULL,
site_id TEXT NOT NULL,
template_id INTEGER NOT NULL,
html_content TEXT NOT NULL,
position INTEGER NOT NULL,
created_at INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
updated_at INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
last_edited_by TEXT DEFAULT 'system' NOT NULL,
PRIMARY KEY (item_id, collection_id, site_id),
FOREIGN KEY (collection_id, site_id) REFERENCES collections(id, site_id) ON DELETE CASCADE,
FOREIGN KEY (template_id) REFERENCES collection_templates(template_id) ON DELETE RESTRICT
)
`
func (q *Queries) InitializeCollectionItemsTable(ctx context.Context) error {
_, err := q.db.ExecContext(ctx, initializeCollectionItemsTable)
return err
}
const initializeCollectionTemplatesTable = `-- name: InitializeCollectionTemplatesTable :exec
CREATE TABLE IF NOT EXISTS collection_templates (
template_id INTEGER PRIMARY KEY AUTOINCREMENT,
collection_id TEXT NOT NULL,
site_id TEXT NOT NULL,
name TEXT NOT NULL,
html_template TEXT NOT NULL,
is_default INTEGER DEFAULT 0 NOT NULL,
created_at INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
FOREIGN KEY (collection_id, site_id) REFERENCES collections(id, site_id) ON DELETE CASCADE
)
`
func (q *Queries) InitializeCollectionTemplatesTable(ctx context.Context) error {
_, err := q.db.ExecContext(ctx, initializeCollectionTemplatesTable)
return err
}
const initializeCollectionsTable = `-- name: InitializeCollectionsTable :exec
CREATE TABLE IF NOT EXISTS collections (
id TEXT NOT NULL,
site_id TEXT NOT NULL,
container_html TEXT NOT NULL,
created_at INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
updated_at INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL,
last_edited_by TEXT DEFAULT 'system' NOT NULL,
PRIMARY KEY (id, site_id)
)
`
func (q *Queries) InitializeCollectionsTable(ctx context.Context) error {
_, err := q.db.ExecContext(ctx, initializeCollectionsTable)
return err
}
const initializeSchema = `-- name: InitializeSchema :exec
CREATE TABLE IF NOT EXISTS content (
id TEXT NOT NULL,