create-smoodly-app 0.0.45 → 0.0.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -10
- package/dist/index.js +75 -33
- package/package.json +2 -2
- package/templates/astro-blank/AGENTS.md +55 -0
- package/templates/astro-blank/CLAUDE.md +1 -0
- package/templates/astro-blank/README.md +88 -0
- package/templates/astro-blank/_gitignore +5 -0
- package/templates/astro-blank/astro.config.ts +15 -0
- package/templates/astro-blank/package.json +24 -0
- package/templates/astro-blank/scripts/seed.ts +80 -0
- package/templates/astro-blank/src/components/LocaleNav.astro +15 -0
- package/templates/astro-blank/src/components/elements/Button.schema.ts +22 -0
- package/templates/astro-blank/src/components/pages/Home.schema.ts +17 -0
- package/templates/astro-blank/src/components/pages/Page.schema.ts +14 -0
- package/templates/astro-blank/src/components/sections/Text.schema.ts +24 -0
- package/templates/astro-blank/src/elements/button.astro +10 -0
- package/templates/astro-blank/src/entry-pages/posts.astro +23 -0
- package/templates/astro-blank/src/layouts/Layout.astro +25 -0
- package/templates/astro-blank/src/live.config.ts +13 -0
- package/templates/astro-blank/src/page-types/home.astro +15 -0
- package/templates/astro-blank/src/page-types/page.astro +15 -0
- package/templates/astro-blank/src/pages/404.astro +7 -0
- package/templates/astro-blank/src/sections/text.astro +18 -0
- package/templates/astro-blank/src/smoodly/collections.ts +24 -0
- package/templates/astro-blank/src/smoodly/config.ts +28 -0
- package/templates/astro-blank/src/smoodly/elements.ts +5 -0
- package/templates/astro-blank/src/smoodly/globals.ts +18 -0
- package/templates/astro-blank/src/smoodly/sections.ts +5 -0
- package/templates/astro-blank/src/smoodly/toolsets.ts +14 -0
- package/templates/astro-blank/src/styles/global.css +57 -0
- package/templates/astro-blank/supabase/migrations/20260926120000_smoodly_v1.sql +535 -0
- package/templates/astro-blank/supabase/migrations/20260926130000_smoodly_v2.sql +26 -0
- package/templates/astro-blank/supabase/migrations/20260926140000_smoodly_v3.sql +38 -0
- package/templates/astro-blank/supabase/migrations/20260926150000_smoodly_v4.sql +41 -0
- package/templates/astro-blank/supabase/migrations/20260929120000_smoodly_v5.sql +56 -0
- package/templates/astro-blank/supabase/migrations/20260929135523_smoodly_v6.sql +200 -0
- package/templates/astro-blank/supabase/migrations/20260930040956_smoodly_v7.sql +84 -0
- package/templates/astro-blank/supabase/migrations/20261007120000_smoodly_v8.sql +154 -0
- package/templates/astro-blank/supabase/migrations/20261007200000_smoodly_v9.sql +30 -0
- package/templates/astro-blank/supabase/migrations/20261008120000_smoodly_v10.sql +47 -0
- package/templates/{blank/supabase/migrations/20260930041056_smoodly_views.sql → astro-blank/supabase/migrations/20261008120100_smoodly_views.sql} +1 -1
- package/templates/astro-blank/tsconfig.json +17 -0
- package/templates/astro-blank-intl/AGENTS.md +55 -0
- package/templates/astro-blank-intl/CLAUDE.md +1 -0
- package/templates/astro-blank-intl/README.md +89 -0
- package/templates/astro-blank-intl/_gitignore +5 -0
- package/templates/astro-blank-intl/astro.config.ts +17 -0
- package/templates/astro-blank-intl/package.json +24 -0
- package/templates/astro-blank-intl/scripts/seed.ts +80 -0
- package/templates/astro-blank-intl/src/components/LocaleNav.astro +15 -0
- package/templates/astro-blank-intl/src/components/elements/Button.schema.ts +22 -0
- package/templates/astro-blank-intl/src/components/pages/Home.schema.ts +17 -0
- package/templates/astro-blank-intl/src/components/pages/Page.schema.ts +14 -0
- package/templates/astro-blank-intl/src/components/sections/Text.schema.ts +24 -0
- package/templates/astro-blank-intl/src/elements/button.astro +10 -0
- package/templates/astro-blank-intl/src/entry-pages/posts.astro +23 -0
- package/templates/astro-blank-intl/src/layouts/Layout.astro +25 -0
- package/templates/astro-blank-intl/src/live.config.ts +13 -0
- package/templates/astro-blank-intl/src/page-types/home.astro +15 -0
- package/templates/astro-blank-intl/src/page-types/page.astro +15 -0
- package/templates/astro-blank-intl/src/pages/404.astro +7 -0
- package/templates/astro-blank-intl/src/sections/text.astro +18 -0
- package/templates/astro-blank-intl/src/smoodly/collections.ts +24 -0
- package/templates/astro-blank-intl/src/smoodly/config.ts +29 -0
- package/templates/astro-blank-intl/src/smoodly/elements.ts +5 -0
- package/templates/astro-blank-intl/src/smoodly/globals.ts +18 -0
- package/templates/astro-blank-intl/src/smoodly/sections.ts +5 -0
- package/templates/astro-blank-intl/src/smoodly/toolsets.ts +14 -0
- package/templates/astro-blank-intl/src/styles/global.css +57 -0
- package/templates/astro-blank-intl/supabase/migrations/20260926120000_smoodly_v1.sql +535 -0
- package/templates/astro-blank-intl/supabase/migrations/20260926130000_smoodly_v2.sql +26 -0
- package/templates/astro-blank-intl/supabase/migrations/20260926140000_smoodly_v3.sql +38 -0
- package/templates/astro-blank-intl/supabase/migrations/20260926150000_smoodly_v4.sql +41 -0
- package/templates/astro-blank-intl/supabase/migrations/20260929120000_smoodly_v5.sql +56 -0
- package/templates/astro-blank-intl/supabase/migrations/20260929135523_smoodly_v6.sql +200 -0
- package/templates/astro-blank-intl/supabase/migrations/20260930040956_smoodly_v7.sql +84 -0
- package/templates/astro-blank-intl/supabase/migrations/20261007120000_smoodly_v8.sql +154 -0
- package/templates/astro-blank-intl/supabase/migrations/20261007200000_smoodly_v9.sql +30 -0
- package/templates/astro-blank-intl/supabase/migrations/20261008120000_smoodly_v10.sql +47 -0
- package/templates/{blank-intl/supabase/migrations/20260930041056_smoodly_views.sql → astro-blank-intl/supabase/migrations/20261008120100_smoodly_views.sql} +1 -1
- package/templates/astro-blank-intl/tsconfig.json +17 -0
- package/templates/astro-blank-intl.tsconfig.json +24 -0
- package/templates/astro-blank.tsconfig.json +24 -0
- package/templates/astro-lorem/AGENTS.md +55 -0
- package/templates/astro-lorem/CLAUDE.md +1 -0
- package/templates/astro-lorem/README.md +60 -0
- package/templates/astro-lorem/_gitignore +5 -0
- package/templates/astro-lorem/astro.config.ts +15 -0
- package/templates/astro-lorem/package.json +24 -0
- package/templates/astro-lorem/public/images/about_main.jpg +0 -0
- package/templates/astro-lorem/public/images/article_photo.jpg +0 -0
- package/templates/astro-lorem/public/images/hero_image.jpg +0 -0
- package/templates/astro-lorem/public/images/home_section_2.jpg +0 -0
- package/templates/astro-lorem/scripts/seed.ts +405 -0
- package/templates/astro-lorem/src/components/ArticleCard.astro +19 -0
- package/templates/astro-lorem/src/components/articles.ts +42 -0
- package/templates/astro-lorem/src/components/elements/Callout.schema.ts +24 -0
- package/templates/astro-lorem/src/components/elements/Cta.schema.ts +21 -0
- package/templates/astro-lorem/src/components/news.ts +13 -0
- package/templates/astro-lorem/src/components/pages/Articles.schema.ts +20 -0
- package/templates/astro-lorem/src/components/pages/Home.schema.ts +26 -0
- package/templates/astro-lorem/src/components/pages/News.schema.ts +17 -0
- package/templates/astro-lorem/src/components/pages/Page.schema.ts +24 -0
- package/templates/astro-lorem/src/components/sections/FavouriteArticles.schema.ts +17 -0
- package/templates/astro-lorem/src/components/sections/Footer.schema.ts +31 -0
- package/templates/astro-lorem/src/components/sections/Header.schema.ts +21 -0
- package/templates/astro-lorem/src/components/sections/Hero.schema.ts +24 -0
- package/templates/astro-lorem/src/components/sections/ImageText.schema.ts +30 -0
- package/templates/astro-lorem/src/components/sections/PageHero.schema.ts +21 -0
- package/templates/astro-lorem/src/components/sections/People.schema.ts +15 -0
- package/templates/astro-lorem/src/components/sections/Points.schema.ts +21 -0
- package/templates/astro-lorem/src/components/sections/Quote.schema.ts +23 -0
- package/templates/astro-lorem/src/elements/callout.astro +13 -0
- package/templates/astro-lorem/src/elements/cta.astro +15 -0
- package/templates/astro-lorem/src/entry-pages/articles.astro +71 -0
- package/templates/astro-lorem/src/entry-pages/news.astro +29 -0
- package/templates/astro-lorem/src/layouts/Layout.astro +39 -0
- package/templates/astro-lorem/src/live.config.ts +20 -0
- package/templates/astro-lorem/src/messages/en.json +7 -0
- package/templates/astro-lorem/src/messages/fi.json +7 -0
- package/templates/astro-lorem/src/page-types/articlesIndex.astro +24 -0
- package/templates/astro-lorem/src/page-types/home.astro +14 -0
- package/templates/astro-lorem/src/page-types/newsIndex.astro +28 -0
- package/templates/astro-lorem/src/page-types/page.astro +27 -0
- package/templates/astro-lorem/src/pages/404.astro +7 -0
- package/templates/astro-lorem/src/sections/favouriteArticles.astro +26 -0
- package/templates/astro-lorem/src/sections/footer.astro +37 -0
- package/templates/astro-lorem/src/sections/header.astro +27 -0
- package/templates/astro-lorem/src/sections/hero.astro +28 -0
- package/templates/astro-lorem/src/sections/imageText.astro +22 -0
- package/templates/astro-lorem/src/sections/pageHero.astro +20 -0
- package/templates/astro-lorem/src/sections/peopleSection.astro +24 -0
- package/templates/astro-lorem/src/sections/points.astro +32 -0
- package/templates/astro-lorem/src/sections/quote.astro +16 -0
- package/templates/astro-lorem/src/smoodly/collections.ts +63 -0
- package/templates/astro-lorem/src/smoodly/config.ts +48 -0
- package/templates/astro-lorem/src/smoodly/elements.ts +6 -0
- package/templates/astro-lorem/src/smoodly/globals.ts +29 -0
- package/templates/astro-lorem/src/smoodly/sections.ts +18 -0
- package/templates/astro-lorem/src/smoodly/toolsets.ts +16 -0
- package/templates/astro-lorem/src/strings.ts +17 -0
- package/templates/astro-lorem/src/styles/global.css +228 -0
- package/templates/astro-lorem/supabase/migrations/20260926120000_smoodly_v1.sql +535 -0
- package/templates/astro-lorem/supabase/migrations/20260926130000_smoodly_v2.sql +26 -0
- package/templates/astro-lorem/supabase/migrations/20260926140000_smoodly_v3.sql +38 -0
- package/templates/astro-lorem/supabase/migrations/20260926150000_smoodly_v4.sql +41 -0
- package/templates/astro-lorem/supabase/migrations/20260929120000_smoodly_v5.sql +56 -0
- package/templates/astro-lorem/supabase/migrations/20260929135523_smoodly_v6.sql +200 -0
- package/templates/astro-lorem/supabase/migrations/20260930040956_smoodly_v7.sql +84 -0
- package/templates/astro-lorem/supabase/migrations/20261007120000_smoodly_v8.sql +154 -0
- package/templates/astro-lorem/supabase/migrations/20261007200000_smoodly_v9.sql +30 -0
- package/templates/astro-lorem/supabase/migrations/20261008120000_smoodly_v10.sql +47 -0
- package/templates/{lorem/supabase/migrations/20260930041056_smoodly_views.sql → astro-lorem/supabase/migrations/20261008120100_smoodly_views.sql} +1 -1
- package/templates/astro-lorem/tsconfig.json +17 -0
- package/templates/astro-lorem-intl/AGENTS.md +55 -0
- package/templates/astro-lorem-intl/CLAUDE.md +1 -0
- package/templates/astro-lorem-intl/README.md +62 -0
- package/templates/astro-lorem-intl/_gitignore +5 -0
- package/templates/astro-lorem-intl/astro.config.ts +17 -0
- package/templates/astro-lorem-intl/package.json +24 -0
- package/templates/astro-lorem-intl/public/images/about_main.jpg +0 -0
- package/templates/astro-lorem-intl/public/images/article_photo.jpg +0 -0
- package/templates/astro-lorem-intl/public/images/hero_image.jpg +0 -0
- package/templates/astro-lorem-intl/public/images/home_section_2.jpg +0 -0
- package/templates/astro-lorem-intl/scripts/seed.ts +405 -0
- package/templates/astro-lorem-intl/src/components/ArticleCard.astro +19 -0
- package/templates/astro-lorem-intl/src/components/articles.ts +42 -0
- package/templates/astro-lorem-intl/src/components/elements/Callout.schema.ts +24 -0
- package/templates/astro-lorem-intl/src/components/elements/Cta.schema.ts +21 -0
- package/templates/astro-lorem-intl/src/components/news.ts +13 -0
- package/templates/astro-lorem-intl/src/components/pages/Articles.schema.ts +20 -0
- package/templates/astro-lorem-intl/src/components/pages/Home.schema.ts +26 -0
- package/templates/astro-lorem-intl/src/components/pages/News.schema.ts +17 -0
- package/templates/astro-lorem-intl/src/components/pages/Page.schema.ts +24 -0
- package/templates/astro-lorem-intl/src/components/sections/FavouriteArticles.schema.ts +17 -0
- package/templates/astro-lorem-intl/src/components/sections/Footer.schema.ts +31 -0
- package/templates/astro-lorem-intl/src/components/sections/Header.schema.ts +21 -0
- package/templates/astro-lorem-intl/src/components/sections/Hero.schema.ts +24 -0
- package/templates/astro-lorem-intl/src/components/sections/ImageText.schema.ts +30 -0
- package/templates/astro-lorem-intl/src/components/sections/PageHero.schema.ts +21 -0
- package/templates/astro-lorem-intl/src/components/sections/People.schema.ts +15 -0
- package/templates/astro-lorem-intl/src/components/sections/Points.schema.ts +21 -0
- package/templates/astro-lorem-intl/src/components/sections/Quote.schema.ts +23 -0
- package/templates/astro-lorem-intl/src/elements/callout.astro +13 -0
- package/templates/astro-lorem-intl/src/elements/cta.astro +15 -0
- package/templates/astro-lorem-intl/src/entry-pages/articles.astro +71 -0
- package/templates/astro-lorem-intl/src/entry-pages/news.astro +29 -0
- package/templates/astro-lorem-intl/src/layouts/Layout.astro +39 -0
- package/templates/astro-lorem-intl/src/live.config.ts +20 -0
- package/templates/astro-lorem-intl/src/messages/en.json +7 -0
- package/templates/astro-lorem-intl/src/messages/fi.json +7 -0
- package/templates/astro-lorem-intl/src/page-types/articlesIndex.astro +24 -0
- package/templates/astro-lorem-intl/src/page-types/home.astro +14 -0
- package/templates/astro-lorem-intl/src/page-types/newsIndex.astro +28 -0
- package/templates/astro-lorem-intl/src/page-types/page.astro +27 -0
- package/templates/astro-lorem-intl/src/pages/404.astro +7 -0
- package/templates/astro-lorem-intl/src/sections/favouriteArticles.astro +26 -0
- package/templates/astro-lorem-intl/src/sections/footer.astro +37 -0
- package/templates/astro-lorem-intl/src/sections/header.astro +27 -0
- package/templates/astro-lorem-intl/src/sections/hero.astro +28 -0
- package/templates/astro-lorem-intl/src/sections/imageText.astro +22 -0
- package/templates/astro-lorem-intl/src/sections/pageHero.astro +20 -0
- package/templates/astro-lorem-intl/src/sections/peopleSection.astro +24 -0
- package/templates/astro-lorem-intl/src/sections/points.astro +32 -0
- package/templates/astro-lorem-intl/src/sections/quote.astro +16 -0
- package/templates/astro-lorem-intl/src/smoodly/collections.ts +63 -0
- package/templates/astro-lorem-intl/src/smoodly/config.ts +48 -0
- package/templates/astro-lorem-intl/src/smoodly/elements.ts +6 -0
- package/templates/astro-lorem-intl/src/smoodly/globals.ts +29 -0
- package/templates/astro-lorem-intl/src/smoodly/sections.ts +18 -0
- package/templates/astro-lorem-intl/src/smoodly/toolsets.ts +16 -0
- package/templates/astro-lorem-intl/src/strings.ts +17 -0
- package/templates/astro-lorem-intl/src/styles/global.css +228 -0
- package/templates/astro-lorem-intl/supabase/migrations/20260926120000_smoodly_v1.sql +535 -0
- package/templates/astro-lorem-intl/supabase/migrations/20260926130000_smoodly_v2.sql +26 -0
- package/templates/astro-lorem-intl/supabase/migrations/20260926140000_smoodly_v3.sql +38 -0
- package/templates/astro-lorem-intl/supabase/migrations/20260926150000_smoodly_v4.sql +41 -0
- package/templates/astro-lorem-intl/supabase/migrations/20260929120000_smoodly_v5.sql +56 -0
- package/templates/astro-lorem-intl/supabase/migrations/20260929135523_smoodly_v6.sql +200 -0
- package/templates/astro-lorem-intl/supabase/migrations/20260930040956_smoodly_v7.sql +84 -0
- package/templates/astro-lorem-intl/supabase/migrations/20261007120000_smoodly_v8.sql +154 -0
- package/templates/astro-lorem-intl/supabase/migrations/20261007200000_smoodly_v9.sql +30 -0
- package/templates/astro-lorem-intl/supabase/migrations/20261008120000_smoodly_v10.sql +47 -0
- package/templates/{lorem-intl/supabase/migrations/20260930041056_smoodly_views.sql → astro-lorem-intl/supabase/migrations/20261008120100_smoodly_views.sql} +1 -1
- package/templates/astro-lorem-intl/tsconfig.json +17 -0
- package/templates/astro-lorem-intl.tsconfig.json +24 -0
- package/templates/astro-lorem.tsconfig.json +24 -0
- package/templates/blank/AGENTS.md +23 -16
- package/templates/blank/README.md +20 -15
- package/templates/blank/app/(smoodly)/admin/[[...segments]]/route.ts +8 -0
- package/templates/blank/components/elements/Button.schema.ts +22 -0
- package/templates/blank/components/elements/Button.tsx +2 -20
- package/templates/blank/components/pages/Home.schema.ts +17 -0
- package/templates/blank/components/pages/Home.tsx +2 -16
- package/templates/blank/components/pages/Page.schema.ts +14 -0
- package/templates/blank/components/pages/Page.tsx +2 -14
- package/templates/blank/components/pages/Post.tsx +5 -4
- package/templates/blank/components/sections/Text.schema.ts +24 -0
- package/templates/blank/components/sections/Text.tsx +7 -27
- package/templates/blank/package.json +1 -1
- package/templates/blank/scripts/seed.ts +2 -2
- package/templates/blank/smoodly/config.ts +8 -7
- package/templates/blank/smoodly/elements.ts +4 -4
- package/templates/blank/smoodly/globals.ts +4 -2
- package/templates/blank/smoodly/richtext.tsx +4 -5
- package/templates/blank/smoodly/sections.ts +4 -4
- package/templates/blank/smoodly/server.ts +22 -44
- package/templates/blank/smoodly/toolsets.ts +2 -2
- package/templates/blank/smoodly/views.ts +15 -0
- package/templates/blank/supabase/migrations/20261007120000_smoodly_v8.sql +154 -0
- package/templates/blank/supabase/migrations/20261007200000_smoodly_v9.sql +30 -0
- package/templates/blank/supabase/migrations/20261008120000_smoodly_v10.sql +47 -0
- package/templates/blank/supabase/migrations/20261008120100_smoodly_views.sql +20 -0
- package/templates/blank-intl/AGENTS.md +23 -16
- package/templates/blank-intl/README.md +20 -15
- package/templates/blank-intl/app/(smoodly)/admin/[[...segments]]/route.ts +8 -0
- package/templates/blank-intl/components/elements/Button.schema.ts +22 -0
- package/templates/blank-intl/components/elements/Button.tsx +2 -20
- package/templates/blank-intl/components/pages/Home.schema.ts +17 -0
- package/templates/blank-intl/components/pages/Home.tsx +2 -16
- package/templates/blank-intl/components/pages/Page.schema.ts +14 -0
- package/templates/blank-intl/components/pages/Page.tsx +2 -14
- package/templates/blank-intl/components/pages/Post.tsx +5 -4
- package/templates/blank-intl/components/sections/Text.schema.ts +24 -0
- package/templates/blank-intl/components/sections/Text.tsx +7 -27
- package/templates/blank-intl/package.json +1 -1
- package/templates/blank-intl/scripts/seed.ts +2 -2
- package/templates/blank-intl/smoodly/config.ts +8 -7
- package/templates/blank-intl/smoodly/elements.ts +4 -4
- package/templates/blank-intl/smoodly/globals.ts +4 -2
- package/templates/blank-intl/smoodly/richtext.tsx +4 -5
- package/templates/blank-intl/smoodly/sections.ts +4 -4
- package/templates/blank-intl/smoodly/server.ts +22 -44
- package/templates/blank-intl/smoodly/toolsets.ts +2 -2
- package/templates/blank-intl/smoodly/views.ts +15 -0
- package/templates/blank-intl/supabase/migrations/20261007120000_smoodly_v8.sql +154 -0
- package/templates/blank-intl/supabase/migrations/20261007200000_smoodly_v9.sql +30 -0
- package/templates/blank-intl/supabase/migrations/20261008120000_smoodly_v10.sql +47 -0
- package/templates/blank-intl/supabase/migrations/20261008120100_smoodly_views.sql +20 -0
- package/templates/lorem/AGENTS.md +23 -16
- package/templates/lorem/README.md +3 -3
- package/templates/lorem/app/(smoodly)/admin/[[...segments]]/route.ts +8 -0
- package/templates/lorem/components/elements/Callout.schema.ts +24 -0
- package/templates/lorem/components/elements/Callout.tsx +2 -24
- package/templates/lorem/components/elements/Cta.schema.ts +21 -0
- package/templates/lorem/components/elements/Cta.tsx +2 -21
- package/templates/lorem/components/pages/Article.tsx +1 -1
- package/templates/lorem/components/pages/Articles.schema.ts +20 -0
- package/templates/lorem/components/pages/Articles.tsx +2 -20
- package/templates/lorem/components/pages/Home.schema.ts +26 -0
- package/templates/lorem/components/pages/Home.tsx +2 -26
- package/templates/lorem/components/pages/News.schema.ts +17 -0
- package/templates/lorem/components/pages/News.tsx +2 -17
- package/templates/lorem/components/pages/NewsPost.tsx +1 -1
- package/templates/lorem/components/pages/Page.schema.ts +24 -0
- package/templates/lorem/components/pages/Page.tsx +2 -24
- package/templates/lorem/components/sections/FavouriteArticles.schema.ts +17 -0
- package/templates/lorem/components/sections/FavouriteArticles.tsx +2 -17
- package/templates/lorem/components/sections/Footer.schema.ts +31 -0
- package/templates/lorem/components/sections/Footer.tsx +4 -32
- package/templates/lorem/components/sections/Header.schema.ts +21 -0
- package/templates/lorem/components/sections/Header.tsx +2 -21
- package/templates/lorem/components/sections/Hero.schema.ts +24 -0
- package/templates/lorem/components/sections/Hero.tsx +2 -24
- package/templates/lorem/components/sections/ImageText.schema.ts +30 -0
- package/templates/lorem/components/sections/ImageText.tsx +2 -30
- package/templates/lorem/components/sections/PageHero.schema.ts +21 -0
- package/templates/lorem/components/sections/PageHero.tsx +2 -21
- package/templates/lorem/components/sections/People.schema.ts +15 -0
- package/templates/lorem/components/sections/People.tsx +2 -14
- package/templates/lorem/components/sections/Points.schema.ts +21 -0
- package/templates/lorem/components/sections/Points.tsx +2 -21
- package/templates/lorem/components/sections/Quote.schema.ts +23 -0
- package/templates/lorem/components/sections/Quote.tsx +2 -23
- package/templates/lorem/package.json +1 -1
- package/templates/lorem/scripts/seed.ts +18 -18
- package/templates/lorem/smoodly/collections.ts +2 -2
- package/templates/lorem/smoodly/config.ts +14 -15
- package/templates/lorem/smoodly/elements.ts +5 -5
- package/templates/lorem/smoodly/globals.ts +10 -7
- package/templates/lorem/smoodly/richtext.tsx +5 -5
- package/templates/lorem/smoodly/sections.ts +12 -13
- package/templates/lorem/smoodly/server.ts +22 -44
- package/templates/lorem/smoodly/toolsets.ts +3 -3
- package/templates/lorem/smoodly/views.ts +33 -0
- package/templates/lorem/supabase/migrations/20261007120000_smoodly_v8.sql +154 -0
- package/templates/lorem/supabase/migrations/20261007200000_smoodly_v9.sql +30 -0
- package/templates/lorem/supabase/migrations/20261008120000_smoodly_v10.sql +47 -0
- package/templates/lorem/supabase/migrations/20261008120100_smoodly_views.sql +58 -0
- package/templates/lorem-intl/AGENTS.md +23 -16
- package/templates/lorem-intl/README.md +3 -3
- package/templates/lorem-intl/app/(smoodly)/admin/[[...segments]]/route.ts +8 -0
- package/templates/lorem-intl/components/elements/Callout.schema.ts +24 -0
- package/templates/lorem-intl/components/elements/Callout.tsx +2 -24
- package/templates/lorem-intl/components/elements/Cta.schema.ts +21 -0
- package/templates/lorem-intl/components/elements/Cta.tsx +2 -21
- package/templates/lorem-intl/components/pages/Article.tsx +1 -1
- package/templates/lorem-intl/components/pages/Articles.schema.ts +20 -0
- package/templates/lorem-intl/components/pages/Articles.tsx +2 -20
- package/templates/lorem-intl/components/pages/Home.schema.ts +26 -0
- package/templates/lorem-intl/components/pages/Home.tsx +2 -26
- package/templates/lorem-intl/components/pages/News.schema.ts +17 -0
- package/templates/lorem-intl/components/pages/News.tsx +2 -17
- package/templates/lorem-intl/components/pages/NewsPost.tsx +1 -1
- package/templates/lorem-intl/components/pages/Page.schema.ts +24 -0
- package/templates/lorem-intl/components/pages/Page.tsx +2 -24
- package/templates/lorem-intl/components/sections/FavouriteArticles.schema.ts +17 -0
- package/templates/lorem-intl/components/sections/FavouriteArticles.tsx +2 -17
- package/templates/lorem-intl/components/sections/Footer.schema.ts +31 -0
- package/templates/lorem-intl/components/sections/Footer.tsx +4 -32
- package/templates/lorem-intl/components/sections/Header.schema.ts +21 -0
- package/templates/lorem-intl/components/sections/Header.tsx +2 -21
- package/templates/lorem-intl/components/sections/Hero.schema.ts +24 -0
- package/templates/lorem-intl/components/sections/Hero.tsx +2 -24
- package/templates/lorem-intl/components/sections/ImageText.schema.ts +30 -0
- package/templates/lorem-intl/components/sections/ImageText.tsx +2 -30
- package/templates/lorem-intl/components/sections/PageHero.schema.ts +21 -0
- package/templates/lorem-intl/components/sections/PageHero.tsx +2 -21
- package/templates/lorem-intl/components/sections/People.schema.ts +15 -0
- package/templates/lorem-intl/components/sections/People.tsx +2 -14
- package/templates/lorem-intl/components/sections/Points.schema.ts +21 -0
- package/templates/lorem-intl/components/sections/Points.tsx +2 -21
- package/templates/lorem-intl/components/sections/Quote.schema.ts +23 -0
- package/templates/lorem-intl/components/sections/Quote.tsx +2 -23
- package/templates/lorem-intl/package.json +1 -1
- package/templates/lorem-intl/scripts/seed.ts +18 -18
- package/templates/lorem-intl/smoodly/collections.ts +2 -2
- package/templates/lorem-intl/smoodly/config.ts +14 -15
- package/templates/lorem-intl/smoodly/elements.ts +5 -5
- package/templates/lorem-intl/smoodly/globals.ts +10 -7
- package/templates/lorem-intl/smoodly/richtext.tsx +5 -5
- package/templates/lorem-intl/smoodly/sections.ts +12 -13
- package/templates/lorem-intl/smoodly/server.ts +22 -44
- package/templates/lorem-intl/smoodly/toolsets.ts +3 -3
- package/templates/lorem-intl/smoodly/views.ts +33 -0
- package/templates/lorem-intl/supabase/migrations/20261007120000_smoodly_v8.sql +154 -0
- package/templates/lorem-intl/supabase/migrations/20261007200000_smoodly_v9.sql +30 -0
- package/templates/lorem-intl/supabase/migrations/20261008120000_smoodly_v10.sql +47 -0
- package/templates/lorem-intl/supabase/migrations/20261008120100_smoodly_views.sql +58 -0
- package/templates/blank/app/(smoodly)/admin/[[...segments]]/page.tsx +0 -1
- package/templates/blank/app/(smoodly)/admin/layout.tsx +0 -15
- package/templates/blank/smoodly/admin.tsx +0 -6
- package/templates/blank/smoodly/ops.ts +0 -11
- package/templates/blank-intl/app/(smoodly)/admin/[[...segments]]/page.tsx +0 -1
- package/templates/blank-intl/app/(smoodly)/admin/layout.tsx +0 -15
- package/templates/blank-intl/smoodly/admin.tsx +0 -6
- package/templates/blank-intl/smoodly/ops.ts +0 -11
- package/templates/lorem/app/(smoodly)/admin/[[...segments]]/page.tsx +0 -1
- package/templates/lorem/app/(smoodly)/admin/layout.tsx +0 -15
- package/templates/lorem/smoodly/admin.tsx +0 -6
- package/templates/lorem/smoodly/ops.ts +0 -11
- package/templates/lorem-intl/app/(smoodly)/admin/[[...segments]]/page.tsx +0 -1
- package/templates/lorem-intl/app/(smoodly)/admin/layout.tsx +0 -15
- package/templates/lorem-intl/smoodly/admin.tsx +0 -6
- package/templates/lorem-intl/smoodly/ops.ts +0 -11
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
-- Smoodly core schema, version 5 (docs/superpowers/specs/2026-09-29-nested-collection-paths-design.md,
|
|
2
|
+
-- docs/superpowers/specs/2026-09-29-anchored-paths-design.md).
|
|
3
|
+
-- Shipped in the smoodly package; `npx smoodly migrate` copies it into supabase/migrations/.
|
|
4
|
+
-- Never edit a published file: the next change is the next file.
|
|
5
|
+
-- The delta over version 4: `pages.fixed` names the registration that owns a
|
|
6
|
+
-- code-owned record, unique per space; `paths.anchor` names the code address
|
|
7
|
+
-- a URL row hangs under, and the row keeps only the part editors made.
|
|
8
|
+
-- No backfill: a record without `fixed` is an editor's page, a row without
|
|
9
|
+
-- an anchor is the editors' tree.
|
|
10
|
+
|
|
11
|
+
set client_min_messages = warning;
|
|
12
|
+
|
|
13
|
+
alter table "pages" add column if not exists "fixed" text;
|
|
14
|
+
|
|
15
|
+
create unique index if not exists "pages_fixed_idx"
|
|
16
|
+
on "pages" ("space_id", "fixed") where "fixed" is not null;
|
|
17
|
+
|
|
18
|
+
alter table "paths" add column if not exists "anchor" text not null default '';
|
|
19
|
+
alter table "paths" drop constraint if exists "paths_pkey";
|
|
20
|
+
alter table "paths" add constraint "paths_pkey" primary key ("space_id", "locale", "anchor", "path");
|
|
21
|
+
|
|
22
|
+
create or replace function "smoodly_rewrite_paths"(p_targets jsonb, p_rows jsonb) returns void language sql set search_path = public as $$
|
|
23
|
+
delete from "paths" p
|
|
24
|
+
using jsonb_to_recordset(p_rows) as r(locale text, anchor text, path text, kind text, id uuid, keys jsonb)
|
|
25
|
+
where p."redirect" and p."locale" = r.locale
|
|
26
|
+
and exists (select 1 from jsonb_to_recordset(r.keys) as k(anchor text, path text) where k.anchor = p."anchor" and k.path = p."path")
|
|
27
|
+
and p."space_id" = "smoodly_current_space"();
|
|
28
|
+
update "paths" p set "redirect" = true
|
|
29
|
+
from jsonb_to_recordset(p_targets) as t(kind text, id uuid, redirect_locales text[])
|
|
30
|
+
where not p."redirect" and p."kind" = t.kind and p."target_id" = t.id
|
|
31
|
+
and p."locale" = any (coalesce(t.redirect_locales, '{}'::text[]))
|
|
32
|
+
and not exists (select 1 from jsonb_to_recordset(p_rows) as r(locale text, anchor text, path text, kind text, id uuid, keys jsonb)
|
|
33
|
+
cross join lateral jsonb_to_recordset(r.keys) as k(anchor text, path text)
|
|
34
|
+
where r.locale = p."locale" and k.anchor = p."anchor" and k.path = p."path")
|
|
35
|
+
and p."space_id" = "smoodly_current_space"();
|
|
36
|
+
delete from "paths" p
|
|
37
|
+
using jsonb_to_recordset(p_targets) as t(kind text, id uuid, redirect_locales text[])
|
|
38
|
+
where p."kind" = t.kind and p."target_id" = t.id
|
|
39
|
+
and (not p."redirect" or not exists (select 1 from jsonb_to_recordset(p_rows) as r(locale text, anchor text, path text, kind text, id uuid)
|
|
40
|
+
where r.kind = p."kind" and r.id = p."target_id" and r.locale = p."locale"))
|
|
41
|
+
and p."space_id" = "smoodly_current_space"();
|
|
42
|
+
insert into "paths" ("locale", "anchor", "path", "kind", "target_id")
|
|
43
|
+
select r.locale, r.anchor, r.path, r.kind, r.id
|
|
44
|
+
from jsonb_to_recordset(p_rows) as r(locale text, anchor text, path text, kind text, id uuid);
|
|
45
|
+
$$;
|
|
46
|
+
|
|
47
|
+
revoke execute on function "smoodly_rewrite_paths"(jsonb, jsonb) from public, anon;
|
|
48
|
+
|
|
49
|
+
create or replace function "smoodly_resolve_path"(p_locale text, p_keys jsonb) returns setof "paths" language sql stable set search_path = public as $$
|
|
50
|
+
select p.* from "paths" p
|
|
51
|
+
join jsonb_to_recordset(p_keys) as k(anchor text, path text) on p."anchor" = k.anchor and p."path" = k.path
|
|
52
|
+
where p."locale" = p_locale;
|
|
53
|
+
$$;
|
|
54
|
+
|
|
55
|
+
insert into "smoodly_meta" ("key", "value") values ('schema_version', '5')
|
|
56
|
+
on conflict ("key") do update set "value" = excluded."value";
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
-- Smoodly core schema, version 6 (docs/superpowers/specs/2026-09-29-pre-install-fixes-design.md §3).
|
|
2
|
+
-- Shipped in the smoodly package; `npx smoodly migrate` copies it into supabase/migrations/.
|
|
3
|
+
-- Never edit a published file: the next change is the next file.
|
|
4
|
+
-- The delta over version 5: one permissive policy per table and action (the
|
|
5
|
+
-- write key reads through smoodly_read; smoodly_write splits into insert,
|
|
6
|
+
-- update and delete where a public read exists; the media pair the same),
|
|
7
|
+
-- indexes on the foreign keys without one, and no anon call of the row cap.
|
|
8
|
+
-- Access is unchanged.
|
|
9
|
+
|
|
10
|
+
set client_min_messages = warning;
|
|
11
|
+
|
|
12
|
+
create index if not exists "page_locales_draft_version_idx" on "page_locales" ("draft_version_id");
|
|
13
|
+
create index if not exists "entry_locales_draft_version_idx" on "entry_locales" ("draft_version_id");
|
|
14
|
+
create index if not exists "page_locales_published_version_idx" on "page_locales" ("published_version_id");
|
|
15
|
+
create index if not exists "entry_locales_published_version_idx" on "entry_locales" ("published_version_id");
|
|
16
|
+
create index if not exists "pages_parent_id_idx" on "pages" ("parent_id");
|
|
17
|
+
create index if not exists "entries_parent_id_idx" on "entries" ("parent_id");
|
|
18
|
+
create index if not exists "assets_poster_idx" on "assets" ("poster_id");
|
|
19
|
+
|
|
20
|
+
drop policy if exists "smoodly_write" on "pages";
|
|
21
|
+
|
|
22
|
+
drop policy if exists "smoodly_insert" on "pages";
|
|
23
|
+
create policy "smoodly_insert" on "pages" for insert
|
|
24
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
25
|
+
|
|
26
|
+
drop policy if exists "smoodly_update" on "pages";
|
|
27
|
+
create policy "smoodly_update" on "pages" for update
|
|
28
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write')
|
|
29
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
30
|
+
|
|
31
|
+
drop policy if exists "smoodly_delete" on "pages";
|
|
32
|
+
create policy "smoodly_delete" on "pages" for delete
|
|
33
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
34
|
+
|
|
35
|
+
drop policy if exists "smoodly_read" on "pages";
|
|
36
|
+
create policy "smoodly_read" on "pages" for select
|
|
37
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and ((select "smoodly_key_kind"()) = 'write' or exists (select 1 from "page_locales" l where l."page_id" = "pages"."id" and l."status" = 'published')));
|
|
38
|
+
|
|
39
|
+
drop policy if exists "smoodly_write" on "page_locales";
|
|
40
|
+
|
|
41
|
+
drop policy if exists "smoodly_insert" on "page_locales";
|
|
42
|
+
create policy "smoodly_insert" on "page_locales" for insert
|
|
43
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
44
|
+
|
|
45
|
+
drop policy if exists "smoodly_update" on "page_locales";
|
|
46
|
+
create policy "smoodly_update" on "page_locales" for update
|
|
47
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write')
|
|
48
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
49
|
+
|
|
50
|
+
drop policy if exists "smoodly_delete" on "page_locales";
|
|
51
|
+
create policy "smoodly_delete" on "page_locales" for delete
|
|
52
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
53
|
+
|
|
54
|
+
drop policy if exists "smoodly_read" on "page_locales";
|
|
55
|
+
create policy "smoodly_read" on "page_locales" for select
|
|
56
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and ((select "smoodly_key_kind"()) = 'write' or "status" = 'published'));
|
|
57
|
+
|
|
58
|
+
drop policy if exists "smoodly_write" on "page_versions";
|
|
59
|
+
|
|
60
|
+
drop policy if exists "smoodly_insert" on "page_versions";
|
|
61
|
+
create policy "smoodly_insert" on "page_versions" for insert
|
|
62
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
63
|
+
|
|
64
|
+
drop policy if exists "smoodly_update" on "page_versions";
|
|
65
|
+
create policy "smoodly_update" on "page_versions" for update
|
|
66
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write')
|
|
67
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
68
|
+
|
|
69
|
+
drop policy if exists "smoodly_delete" on "page_versions";
|
|
70
|
+
create policy "smoodly_delete" on "page_versions" for delete
|
|
71
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
72
|
+
|
|
73
|
+
drop policy if exists "smoodly_read" on "page_versions";
|
|
74
|
+
create policy "smoodly_read" on "page_versions" for select
|
|
75
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and ((select "smoodly_key_kind"()) = 'write' or exists (select 1 from "page_locales" l where l."published_version_id" = "page_versions"."id")));
|
|
76
|
+
|
|
77
|
+
drop policy if exists "smoodly_write" on "entries";
|
|
78
|
+
|
|
79
|
+
drop policy if exists "smoodly_insert" on "entries";
|
|
80
|
+
create policy "smoodly_insert" on "entries" for insert
|
|
81
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
82
|
+
|
|
83
|
+
drop policy if exists "smoodly_update" on "entries";
|
|
84
|
+
create policy "smoodly_update" on "entries" for update
|
|
85
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write')
|
|
86
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
87
|
+
|
|
88
|
+
drop policy if exists "smoodly_delete" on "entries";
|
|
89
|
+
create policy "smoodly_delete" on "entries" for delete
|
|
90
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
91
|
+
|
|
92
|
+
drop policy if exists "smoodly_read" on "entries";
|
|
93
|
+
create policy "smoodly_read" on "entries" for select
|
|
94
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and ((select "smoodly_key_kind"()) = 'write' or exists (select 1 from "entry_locales" l where l."entry_id" = "entries"."id" and l."status" = 'published')));
|
|
95
|
+
|
|
96
|
+
drop policy if exists "smoodly_write" on "entry_locales";
|
|
97
|
+
|
|
98
|
+
drop policy if exists "smoodly_insert" on "entry_locales";
|
|
99
|
+
create policy "smoodly_insert" on "entry_locales" for insert
|
|
100
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
101
|
+
|
|
102
|
+
drop policy if exists "smoodly_update" on "entry_locales";
|
|
103
|
+
create policy "smoodly_update" on "entry_locales" for update
|
|
104
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write')
|
|
105
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
106
|
+
|
|
107
|
+
drop policy if exists "smoodly_delete" on "entry_locales";
|
|
108
|
+
create policy "smoodly_delete" on "entry_locales" for delete
|
|
109
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
110
|
+
|
|
111
|
+
drop policy if exists "smoodly_read" on "entry_locales";
|
|
112
|
+
create policy "smoodly_read" on "entry_locales" for select
|
|
113
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and ((select "smoodly_key_kind"()) = 'write' or "status" = 'published'));
|
|
114
|
+
|
|
115
|
+
drop policy if exists "smoodly_write" on "entry_versions";
|
|
116
|
+
|
|
117
|
+
drop policy if exists "smoodly_insert" on "entry_versions";
|
|
118
|
+
create policy "smoodly_insert" on "entry_versions" for insert
|
|
119
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
120
|
+
|
|
121
|
+
drop policy if exists "smoodly_update" on "entry_versions";
|
|
122
|
+
create policy "smoodly_update" on "entry_versions" for update
|
|
123
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write')
|
|
124
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
125
|
+
|
|
126
|
+
drop policy if exists "smoodly_delete" on "entry_versions";
|
|
127
|
+
create policy "smoodly_delete" on "entry_versions" for delete
|
|
128
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
129
|
+
|
|
130
|
+
drop policy if exists "smoodly_read" on "entry_versions";
|
|
131
|
+
create policy "smoodly_read" on "entry_versions" for select
|
|
132
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and ((select "smoodly_key_kind"()) = 'write' or exists (select 1 from "entry_locales" l where l."published_version_id" = "entry_versions"."id")));
|
|
133
|
+
|
|
134
|
+
drop policy if exists "smoodly_write" on "refs";
|
|
135
|
+
create policy "smoodly_write" on "refs" for all
|
|
136
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write')
|
|
137
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
138
|
+
|
|
139
|
+
drop policy if exists "smoodly_write" on "paths";
|
|
140
|
+
|
|
141
|
+
drop policy if exists "smoodly_insert" on "paths";
|
|
142
|
+
create policy "smoodly_insert" on "paths" for insert
|
|
143
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
144
|
+
|
|
145
|
+
drop policy if exists "smoodly_update" on "paths";
|
|
146
|
+
create policy "smoodly_update" on "paths" for update
|
|
147
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write')
|
|
148
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
149
|
+
|
|
150
|
+
drop policy if exists "smoodly_delete" on "paths";
|
|
151
|
+
create policy "smoodly_delete" on "paths" for delete
|
|
152
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
153
|
+
|
|
154
|
+
drop policy if exists "smoodly_read" on "paths";
|
|
155
|
+
create policy "smoodly_read" on "paths" for select
|
|
156
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and ((select "smoodly_key_kind"()) = 'write' or (("kind" = 'page' and exists (select 1 from "page_locales" l where l."page_id" = "paths"."target_id" and l."locale" = "paths"."locale" and l."status" = 'published')) or ("kind" = 'entry' and exists (select 1 from "entry_locales" l where l."entry_id" = "paths"."target_id" and l."locale" = "paths"."locale" and l."status" = 'published')))));
|
|
157
|
+
|
|
158
|
+
drop policy if exists "smoodly_write" on "assets";
|
|
159
|
+
|
|
160
|
+
drop policy if exists "smoodly_insert" on "assets";
|
|
161
|
+
create policy "smoodly_insert" on "assets" for insert
|
|
162
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
163
|
+
|
|
164
|
+
drop policy if exists "smoodly_update" on "assets";
|
|
165
|
+
create policy "smoodly_update" on "assets" for update
|
|
166
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write')
|
|
167
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
168
|
+
|
|
169
|
+
drop policy if exists "smoodly_delete" on "assets";
|
|
170
|
+
create policy "smoodly_delete" on "assets" for delete
|
|
171
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
172
|
+
|
|
173
|
+
drop policy if exists "smoodly_read" on "assets";
|
|
174
|
+
create policy "smoodly_read" on "assets" for select
|
|
175
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and ((select "smoodly_key_kind"()) = 'write' or "status" = 'ready'));
|
|
176
|
+
|
|
177
|
+
drop policy if exists "smoodly_write" on "members";
|
|
178
|
+
create policy "smoodly_write" on "members" for all
|
|
179
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write')
|
|
180
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
181
|
+
|
|
182
|
+
drop policy if exists "smoodly_media_write" on storage.objects;
|
|
183
|
+
|
|
184
|
+
drop policy if exists "smoodly_media_insert" on storage.objects;
|
|
185
|
+
create policy "smoodly_media_insert" on storage.objects for insert
|
|
186
|
+
with check ("bucket_id" = 'media' and (select public."smoodly_key_kind"()) = 'write' and not (select public."smoodly_space_key_revoked"()) and split_part("name", '/', 1) = (select public."smoodly_current_space"())::text);
|
|
187
|
+
|
|
188
|
+
drop policy if exists "smoodly_media_update" on storage.objects;
|
|
189
|
+
create policy "smoodly_media_update" on storage.objects for update
|
|
190
|
+
using ("bucket_id" = 'media' and (select public."smoodly_key_kind"()) = 'write' and not (select public."smoodly_space_key_revoked"()) and split_part("name", '/', 1) = (select public."smoodly_current_space"())::text)
|
|
191
|
+
with check ("bucket_id" = 'media' and (select public."smoodly_key_kind"()) = 'write' and not (select public."smoodly_space_key_revoked"()) and split_part("name", '/', 1) = (select public."smoodly_current_space"())::text);
|
|
192
|
+
|
|
193
|
+
drop policy if exists "smoodly_media_delete" on storage.objects;
|
|
194
|
+
create policy "smoodly_media_delete" on storage.objects for delete
|
|
195
|
+
using ("bucket_id" = 'media' and (select public."smoodly_key_kind"()) = 'write' and not (select public."smoodly_space_key_revoked"()) and split_part("name", '/', 1) = (select public."smoodly_current_space"())::text);
|
|
196
|
+
|
|
197
|
+
revoke execute on function "smoodly_space_row_cap"() from public, anon;
|
|
198
|
+
|
|
199
|
+
insert into "smoodly_meta" ("key", "value") values ('schema_version', '6')
|
|
200
|
+
on conflict ("key") do update set "value" = excluded."value";
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
-- Smoodly core schema, version 7 (docs/superpowers/specs/2026-09-29-content-api-contract-design.md §5).
|
|
2
|
+
-- Shipped in the smoodly package; `npx smoodly migrate` copies it into supabase/migrations/.
|
|
3
|
+
-- Never edit a published file: the next change is the next file.
|
|
4
|
+
-- The delta over version 6: smoodly_list_entries, which filters, orders and
|
|
5
|
+
-- limits a collection over the snapshot the reader is shown, and the read
|
|
6
|
+
-- policies of every content table admit a write key only (§8).
|
|
7
|
+
|
|
8
|
+
-- The shown snapshot of one collection's entries in a locale, filtered,
|
|
9
|
+
-- ordered and limited in one query (spec 2026-09-29 content API contract
|
|
10
|
+
-- §5): the published snapshot, or the live merge in preview. Invoker
|
|
11
|
+
-- rights, so RLS decides what a key sees; a preview read needs the
|
|
12
|
+
-- service role or a write key, anything else reads published.
|
|
13
|
+
create or replace function "smoodly_list_entries"(
|
|
14
|
+
p_collection text, p_locale text, p_draft boolean, p_where jsonb, p_order jsonb,
|
|
15
|
+
p_limit integer, p_parent uuid, p_has_parent boolean, p_ids uuid[]
|
|
16
|
+
) returns table ("id" uuid, "fields" jsonb) language sql stable set search_path = public as $$
|
|
17
|
+
with mode as (
|
|
18
|
+
select p_draft and (current_user = 'service_role' or "smoodly_key_kind"() = 'write') as draft
|
|
19
|
+
), shown as (
|
|
20
|
+
select e."id", e."sort", e."created_at", l."updated_at",
|
|
21
|
+
case when (select draft from mode) then e."fields" || l."fields" || jsonb_build_object('slug', l."slug")
|
|
22
|
+
else coalesce(v."fields", e."fields" || l."fields" || jsonb_build_object('slug', l."slug")) end as "fields"
|
|
23
|
+
from "entries" e
|
|
24
|
+
join "entry_locales" l on l."entry_id" = e."id" and l."locale" = p_locale
|
|
25
|
+
left join "entry_versions" v on v."id" = l."published_version_id"
|
|
26
|
+
where e."collection" = p_collection
|
|
27
|
+
and ((select draft from mode) or l."status" = 'published')
|
|
28
|
+
and (not p_has_parent or e."parent_id" is not distinct from p_parent)
|
|
29
|
+
and (p_ids is null or e."id" = any(p_ids))
|
|
30
|
+
)
|
|
31
|
+
select s."id", s."fields" from shown s
|
|
32
|
+
where not exists (
|
|
33
|
+
select 1 from jsonb_each(coalesce(p_where, '{}'::jsonb)) w
|
|
34
|
+
where not (case when w.value ? 'in'
|
|
35
|
+
then (s."fields" ->> w.key) = any (select jsonb_array_elements_text(w.value -> 'in'))
|
|
36
|
+
else s."fields" @> jsonb_build_object(w.key, w.value -> 'contains') end))
|
|
37
|
+
order by
|
|
38
|
+
case when p_order ->> 'by' = 'manual' then s."sort" end asc nulls last,
|
|
39
|
+
case when p_order ->> 'direction' = 'asc' then
|
|
40
|
+
case p_order ->> 'by' when 'createdAt' then to_jsonb(s."created_at") when 'updatedAt' then to_jsonb(s."updated_at")
|
|
41
|
+
when 'manual' then null else nullif(nullif(s."fields" -> (p_order ->> 'by'), 'null'::jsonb), '""'::jsonb) end end asc nulls last,
|
|
42
|
+
case when p_order ->> 'direction' = 'desc' then
|
|
43
|
+
case p_order ->> 'by' when 'createdAt' then to_jsonb(s."created_at") when 'updatedAt' then to_jsonb(s."updated_at")
|
|
44
|
+
when 'manual' then null else nullif(nullif(s."fields" -> (p_order ->> 'by'), 'null'::jsonb), '""'::jsonb) end end desc nulls last,
|
|
45
|
+
s."created_at" asc, s."id" asc
|
|
46
|
+
limit p_limit;
|
|
47
|
+
$$;
|
|
48
|
+
|
|
49
|
+
-- No public content reads (spec 2026-09-29 content API contract §8): the
|
|
50
|
+
-- publishable key and a read key read nothing; a write key reads its own space.
|
|
51
|
+
drop policy if exists "smoodly_read" on "pages";
|
|
52
|
+
create policy "smoodly_read" on "pages" for select
|
|
53
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
54
|
+
|
|
55
|
+
drop policy if exists "smoodly_read" on "page_locales";
|
|
56
|
+
create policy "smoodly_read" on "page_locales" for select
|
|
57
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
58
|
+
|
|
59
|
+
drop policy if exists "smoodly_read" on "page_versions";
|
|
60
|
+
create policy "smoodly_read" on "page_versions" for select
|
|
61
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
62
|
+
|
|
63
|
+
drop policy if exists "smoodly_read" on "entries";
|
|
64
|
+
create policy "smoodly_read" on "entries" for select
|
|
65
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
66
|
+
|
|
67
|
+
drop policy if exists "smoodly_read" on "entry_locales";
|
|
68
|
+
create policy "smoodly_read" on "entry_locales" for select
|
|
69
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
70
|
+
|
|
71
|
+
drop policy if exists "smoodly_read" on "entry_versions";
|
|
72
|
+
create policy "smoodly_read" on "entry_versions" for select
|
|
73
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
74
|
+
|
|
75
|
+
drop policy if exists "smoodly_read" on "paths";
|
|
76
|
+
create policy "smoodly_read" on "paths" for select
|
|
77
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
78
|
+
|
|
79
|
+
drop policy if exists "smoodly_read" on "assets";
|
|
80
|
+
create policy "smoodly_read" on "assets" for select
|
|
81
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
82
|
+
|
|
83
|
+
insert into "smoodly_meta" ("key", "value") values ('schema_version', '7')
|
|
84
|
+
on conflict ("key") do update set "value" = excluded."value";
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
-- Smoodly core schema, version 8 (docs/superpowers/specs/2026-10-07-delivery-model-design.md).
|
|
2
|
+
-- Shipped in the smoodly package; `npx smoodly migrate` copies it into supabase/migrations/.
|
|
3
|
+
-- Never edit a published file: the next change is the next file.
|
|
4
|
+
-- The delta over version 7: the delivery model's two derived tables,
|
|
5
|
+
-- published_pages and published_entries, with the space trigger and the
|
|
6
|
+
-- write-key-only policies every content table has (no row cap: they are
|
|
7
|
+
-- derived), smoodly_list_published over the raw published snapshot, and
|
|
8
|
+
-- the published_routes view, one lookup for any address.
|
|
9
|
+
|
|
10
|
+
set client_min_messages = warning;
|
|
11
|
+
|
|
12
|
+
-- The delivery model (spec 2026-10-07): Publish writes the finished document of a page, an entry
|
|
13
|
+
-- or a global here; a live read is one lookup. Derived and rebuildable from the editing tables.
|
|
14
|
+
create table if not exists "published_pages" (
|
|
15
|
+
"space_id" uuid not null default '00000000-0000-0000-0000-000000000000',
|
|
16
|
+
"page_id" uuid not null references "pages" ("id") on delete cascade,
|
|
17
|
+
"locale" text not null,
|
|
18
|
+
"parent_id" uuid,
|
|
19
|
+
"sort" numeric,
|
|
20
|
+
"path" text,
|
|
21
|
+
"title" text not null,
|
|
22
|
+
"has_page" boolean not null,
|
|
23
|
+
"link_fields" jsonb not null default '{}'::jsonb,
|
|
24
|
+
"document" jsonb,
|
|
25
|
+
"tags" text[] not null default '{}',
|
|
26
|
+
"model" text not null,
|
|
27
|
+
"stale" boolean not null default false,
|
|
28
|
+
"published_at" timestamptz not null default now(),
|
|
29
|
+
primary key ("page_id", "locale")
|
|
30
|
+
);
|
|
31
|
+
create unique index if not exists "published_pages_address_idx"
|
|
32
|
+
on "published_pages" ("space_id", "locale", "path") where "path" is not null;
|
|
33
|
+
create index if not exists "published_pages_tree_idx"
|
|
34
|
+
on "published_pages" ("space_id", "locale", "parent_id", "sort");
|
|
35
|
+
|
|
36
|
+
create table if not exists "published_entries" (
|
|
37
|
+
"space_id" uuid not null default '00000000-0000-0000-0000-000000000000',
|
|
38
|
+
"entry_id" uuid not null references "entries" ("id") on delete cascade,
|
|
39
|
+
"locale" text not null,
|
|
40
|
+
"collection" text not null,
|
|
41
|
+
"parent_id" uuid,
|
|
42
|
+
"sort" numeric,
|
|
43
|
+
"slug" text,
|
|
44
|
+
"path" text,
|
|
45
|
+
"created_at" timestamptz not null,
|
|
46
|
+
"updated_at" timestamptz not null,
|
|
47
|
+
"fields" jsonb not null,
|
|
48
|
+
"document" jsonb not null,
|
|
49
|
+
"tags" text[] not null default '{}',
|
|
50
|
+
"model" text not null,
|
|
51
|
+
"stale" boolean not null default false,
|
|
52
|
+
"published_at" timestamptz not null default now(),
|
|
53
|
+
primary key ("entry_id", "locale")
|
|
54
|
+
);
|
|
55
|
+
create index if not exists "published_entries_list_idx"
|
|
56
|
+
on "published_entries" ("space_id", "collection", "locale");
|
|
57
|
+
create unique index if not exists "published_entries_address_idx"
|
|
58
|
+
on "published_entries" ("space_id", "locale", "path") where "path" is not null;
|
|
59
|
+
create index if not exists "published_entries_fields_idx"
|
|
60
|
+
on "published_entries" using gin ("fields");
|
|
61
|
+
|
|
62
|
+
alter table "published_pages" enable row level security;
|
|
63
|
+
alter table "published_entries" enable row level security;
|
|
64
|
+
|
|
65
|
+
-- smoodly_list_entries without the draft branch, over the delivery table (spec 2026-10-07 §3):
|
|
66
|
+
-- `where` and `order` read the raw published snapshot, the row answers with its document.
|
|
67
|
+
-- Invoker rights, so RLS decides what a key sees.
|
|
68
|
+
create or replace function "smoodly_list_published"(
|
|
69
|
+
p_collection text, p_locale text, p_where jsonb, p_order jsonb,
|
|
70
|
+
p_limit integer, p_parent uuid, p_has_parent boolean, p_ids uuid[]
|
|
71
|
+
) returns table ("id" uuid, "document" jsonb, "model" text, "stale" boolean) language sql stable set search_path = public as $$
|
|
72
|
+
with shown as (
|
|
73
|
+
select p."entry_id" as "id", p."sort", p."created_at", p."updated_at", p."fields", p."document", p."model", p."stale"
|
|
74
|
+
from "published_entries" p
|
|
75
|
+
where p."collection" = p_collection and p."locale" = p_locale
|
|
76
|
+
and (not p_has_parent or p."parent_id" is not distinct from p_parent)
|
|
77
|
+
and (p_ids is null or p."entry_id" = any(p_ids))
|
|
78
|
+
)
|
|
79
|
+
select s."id", s."document", s."model", s."stale" from shown s
|
|
80
|
+
where not exists (
|
|
81
|
+
select 1 from jsonb_each(coalesce(p_where, '{}'::jsonb)) w
|
|
82
|
+
where not (case when w.value ? 'in'
|
|
83
|
+
then (s."fields" ->> w.key) = any (select jsonb_array_elements_text(w.value -> 'in'))
|
|
84
|
+
else s."fields" @> jsonb_build_object(w.key, w.value -> 'contains') end))
|
|
85
|
+
order by
|
|
86
|
+
case when p_order ->> 'by' = 'manual' then s."sort" end asc nulls last,
|
|
87
|
+
case when p_order ->> 'direction' = 'asc' then
|
|
88
|
+
case p_order ->> 'by' when 'createdAt' then to_jsonb(s."created_at") when 'updatedAt' then to_jsonb(s."updated_at")
|
|
89
|
+
when 'manual' then null else nullif(nullif(s."fields" -> (p_order ->> 'by'), 'null'::jsonb), '""'::jsonb) end end asc nulls last,
|
|
90
|
+
case when p_order ->> 'direction' = 'desc' then
|
|
91
|
+
case p_order ->> 'by' when 'createdAt' then to_jsonb(s."created_at") when 'updatedAt' then to_jsonb(s."updated_at")
|
|
92
|
+
when 'manual' then null else nullif(nullif(s."fields" -> (p_order ->> 'by'), 'null'::jsonb), '""'::jsonb) end end desc nulls last,
|
|
93
|
+
s."created_at" asc, s."id" asc
|
|
94
|
+
limit p_limit;
|
|
95
|
+
$$;
|
|
96
|
+
|
|
97
|
+
-- One lookup for any address (spec 2026-10-07 §3): a page or an entry, under the caller's own policies.
|
|
98
|
+
create or replace view "published_routes" with (security_invoker = true) as
|
|
99
|
+
select "space_id", "locale", "path", 'page' as "kind", "page_id" as "id", "document", "model", "stale", "tags", null::text as "collection"
|
|
100
|
+
from "published_pages" where "path" is not null and "has_page"
|
|
101
|
+
union all
|
|
102
|
+
select "space_id", "locale", "path", 'entry' as "kind", "entry_id" as "id", "document", "model", "stale", "tags", "collection"
|
|
103
|
+
from "published_entries" where "path" is not null;
|
|
104
|
+
|
|
105
|
+
-- Stamped with the caller's space on insert, as every content table.
|
|
106
|
+
drop trigger if exists "smoodly_a_set_space" on "published_pages";
|
|
107
|
+
create trigger "smoodly_a_set_space" before insert on "published_pages"
|
|
108
|
+
for each row execute function "smoodly_set_space"();
|
|
109
|
+
|
|
110
|
+
drop trigger if exists "smoodly_a_set_space" on "published_entries";
|
|
111
|
+
create trigger "smoodly_a_set_space" before insert on "published_entries"
|
|
112
|
+
for each row execute function "smoodly_set_space"();
|
|
113
|
+
|
|
114
|
+
-- A write key reads and writes its own space; no other key reads (spec 2026-09-29 content API contract §8).
|
|
115
|
+
drop policy if exists "smoodly_write" on "published_pages";
|
|
116
|
+
|
|
117
|
+
drop policy if exists "smoodly_insert" on "published_pages";
|
|
118
|
+
create policy "smoodly_insert" on "published_pages" for insert
|
|
119
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
120
|
+
|
|
121
|
+
drop policy if exists "smoodly_update" on "published_pages";
|
|
122
|
+
create policy "smoodly_update" on "published_pages" for update
|
|
123
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write')
|
|
124
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
125
|
+
|
|
126
|
+
drop policy if exists "smoodly_delete" on "published_pages";
|
|
127
|
+
create policy "smoodly_delete" on "published_pages" for delete
|
|
128
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
129
|
+
|
|
130
|
+
drop policy if exists "smoodly_read" on "published_pages";
|
|
131
|
+
create policy "smoodly_read" on "published_pages" for select
|
|
132
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
133
|
+
|
|
134
|
+
drop policy if exists "smoodly_write" on "published_entries";
|
|
135
|
+
|
|
136
|
+
drop policy if exists "smoodly_insert" on "published_entries";
|
|
137
|
+
create policy "smoodly_insert" on "published_entries" for insert
|
|
138
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
139
|
+
|
|
140
|
+
drop policy if exists "smoodly_update" on "published_entries";
|
|
141
|
+
create policy "smoodly_update" on "published_entries" for update
|
|
142
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write')
|
|
143
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
144
|
+
|
|
145
|
+
drop policy if exists "smoodly_delete" on "published_entries";
|
|
146
|
+
create policy "smoodly_delete" on "published_entries" for delete
|
|
147
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
148
|
+
|
|
149
|
+
drop policy if exists "smoodly_read" on "published_entries";
|
|
150
|
+
create policy "smoodly_read" on "published_entries" for select
|
|
151
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
152
|
+
|
|
153
|
+
insert into "smoodly_meta" ("key", "value") values ('schema_version', '8')
|
|
154
|
+
on conflict ("key") do update set "value" = excluded."value";
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
-- Smoodly core schema, version 9 (packages/smoodly/MAINTAINERS.md, register 2026-10-07: what the delivery model left).
|
|
2
|
+
-- Shipped in the smoodly package; `npx smoodly migrate` copies it into supabase/migrations/.
|
|
3
|
+
-- Never edit a published file: the next change is the next file.
|
|
4
|
+
-- The delta over version 8: smoodly_lookup_address, the route row and the
|
|
5
|
+
-- locale's global items in one call, so a live page is one database call
|
|
6
|
+
-- instead of the page then its layout's globals.
|
|
7
|
+
|
|
8
|
+
set client_min_messages = warning;
|
|
9
|
+
|
|
10
|
+
-- The address and the locale's global items in one call (schema v9; register 2026-10-07: a miss was two
|
|
11
|
+
-- rounds, the page then the layout's globals). The route row first, kind 'page' or 'entry'; then one row per
|
|
12
|
+
-- named global, kind 'global', the collection its name. A miss answers nothing: the globals ride with a page
|
|
13
|
+
-- only. Invoker rights, so RLS decides what a key sees.
|
|
14
|
+
create or replace function "smoodly_lookup_address"(p_locale text, p_path text, p_globals text[])
|
|
15
|
+
returns table ("kind" text, "id" uuid, "collection" text, "document" jsonb, "model" text, "stale" boolean, "tags" text[])
|
|
16
|
+
language sql stable set search_path = public as $$
|
|
17
|
+
with route as (
|
|
18
|
+
select r."kind", r."id", r."collection", r."document", r."model", r."stale", r."tags"
|
|
19
|
+
from "published_routes" r where r."locale" = p_locale and r."path" = p_path limit 1
|
|
20
|
+
)
|
|
21
|
+
select * from route
|
|
22
|
+
union all
|
|
23
|
+
select 'global' as "kind", e."entry_id", e."collection", e."document", e."model", e."stale", e."tags"
|
|
24
|
+
from "published_entries" e
|
|
25
|
+
where e."locale" = p_locale and e."collection" = any(coalesce(p_globals, '{}'::text[]))
|
|
26
|
+
and exists (select 1 from route);
|
|
27
|
+
$$;
|
|
28
|
+
|
|
29
|
+
insert into "smoodly_meta" ("key", "value") values ('schema_version', '9')
|
|
30
|
+
on conflict ("key") do update set "value" = excluded."value";
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
-- Smoodly core schema, version 10 (DESIGN §3, the document stamp, decided 2026-10-08).
|
|
2
|
+
-- Shipped in the smoodly package; `npx smoodly migrate` copies it into supabase/migrations/.
|
|
3
|
+
-- Never edit a published file: the next change is the next file.
|
|
4
|
+
-- The delta over version 9: published_models, one row per space holding the
|
|
5
|
+
-- document stamp the space recorded as current, so only the deployment at that
|
|
6
|
+
-- stamp rewrites delivery rows (a preview deployment on a newer package serves
|
|
7
|
+
-- assembled documents and writes nothing). Additive: no function changes.
|
|
8
|
+
|
|
9
|
+
set client_min_messages = warning;
|
|
10
|
+
|
|
11
|
+
-- The document stamp a space recorded as current: set by `npx smoodly rebuild` and by the first writer
|
|
12
|
+
-- into an empty record; only a reader at this stamp rewrites published_pages and published_entries.
|
|
13
|
+
create table if not exists "published_models" (
|
|
14
|
+
"space_id" uuid primary key default '00000000-0000-0000-0000-000000000000',
|
|
15
|
+
"model" text not null,
|
|
16
|
+
"recorded_at" timestamptz not null default now()
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
alter table "published_models" enable row level security;
|
|
20
|
+
|
|
21
|
+
-- Stamped with the caller's space on insert, as every content table.
|
|
22
|
+
drop trigger if exists "smoodly_a_set_space" on "published_models";
|
|
23
|
+
create trigger "smoodly_a_set_space" before insert on "published_models"
|
|
24
|
+
for each row execute function "smoodly_set_space"();
|
|
25
|
+
|
|
26
|
+
-- A write key reads and writes its own space's record; no other key reads (spec 2026-09-29 content API contract §8).
|
|
27
|
+
drop policy if exists "smoodly_write" on "published_models";
|
|
28
|
+
|
|
29
|
+
drop policy if exists "smoodly_insert" on "published_models";
|
|
30
|
+
create policy "smoodly_insert" on "published_models" for insert
|
|
31
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
32
|
+
|
|
33
|
+
drop policy if exists "smoodly_update" on "published_models";
|
|
34
|
+
create policy "smoodly_update" on "published_models" for update
|
|
35
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write')
|
|
36
|
+
with check ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
37
|
+
|
|
38
|
+
drop policy if exists "smoodly_delete" on "published_models";
|
|
39
|
+
create policy "smoodly_delete" on "published_models" for delete
|
|
40
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
41
|
+
|
|
42
|
+
drop policy if exists "smoodly_read" on "published_models";
|
|
43
|
+
create policy "smoodly_read" on "published_models" for select
|
|
44
|
+
using ("space_id" = (select "smoodly_current_space"()) and not (select "smoodly_space_key_revoked"()) and (select "smoodly_key_kind"()) = 'write');
|
|
45
|
+
|
|
46
|
+
insert into "smoodly_meta" ("key", "value") values ('schema_version', '10')
|
|
47
|
+
on conflict ("key") do update set "value" = excluded."value";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
-- Smoodly: read views for this app's collections, written by `npx smoodly migrate`
|
|
2
|
-
-- (2026-
|
|
2
|
+
-- (2026-10-08T12:01:00.000Z). One block per collection; the marker's hash is the block's SQL, compared on the next run.
|
|
3
3
|
-- Never edit a written file: change the collection and run migrate again.
|
|
4
4
|
|
|
5
5
|
-- smoodly:collection posts sha256:38ba2918f83ab367
|