Add opt-in SQL root-level projected columns for repository stores - #763

Draft
patroza with Copilot wants to merge 12 commits into
mainfrom
copilot/plan-relational-database-adoption
Draft

Add opt-in SQL root-level projected columns for repository stores#763
patroza with Copilot wants to merge 12 commits into
mainfrom
copilot/plan-relational-database-adoption

Conversation

CopilotAI commented May 22, 2026

Copy link
Copy Markdown
Contributor

This splits the storage evolution into the first track only: keep the current document model and JSON-based nested semantics, while allowing SQLite/PostgreSQL repositories to switch root-level fields to real columns. The new mode is opt-in per repository or adapter via rootLevelFieldsWhenAvailable.

  • What changed

    • Added rootLevelFieldsWhenAvailable?: boolean to repository/store config, with adapter-level default support in SQL storage config.
    • Kept the existing non-relational model intact.
    • When projection is enabled, projected root fields are stored in dedicated columns and are no longer duplicated in data.
    • Corrected the flag semantics so this is an exclusive mode switch:
      • false / omitted: reads, writes, and queries use data
      • true: derived root fields are read, written, and queried via dedicated root columns
  • Schema-derived projected columns

    • Derive projected root-level fields from the encoded repository schema.
    • Root scalar fields use typed SQL columns when possible:
      • string
      • number
      • boolean
      • nullable forms of the above
      • encoded date-like fields that serialize to root strings
    • Complex root fields are also projected:
      • nested objects
      • arrays
      • other non-scalar encoded root fields
    • Complex projected fields use JSON / JSONB columns.
  • SQLite / PostgreSQL store behavior

    • On fresh table setup, include projected root columns when the mode is enabled.
    • On writes in projected mode, persist:
      • non-projected fields into data
      • projected root fields into dedicated columns
    • On reads in projected mode, reconstruct projected fields from dedicated columns only.
    • Removed runtime fallback/backfill behavior:
      • no COALESCE(...) fallback from projected columns back to data
      • no on-the-fly backfill of projected columns from existing data
      • no runtime ALTER TABLE / migration behavior for existing rows
    • Existing schema/data migration for switching modes is expected to happen offline.
  • Query planning

    • In projected mode, root-level filters, ordering, and scalar selection resolve to projected columns directly.
    • Nested paths under projected JSON root fields resolve against the projected JSON/JSONB columns directly.
    • Root-level relation-style array queries continue to work when those arrays are projected into JSON/JSONB columns.
    • When the mode is disabled, queries continue to use the data column.
  • Tests

    • Added coverage for:
      • projected-field metadata derivation from schema, including complex root fields
      • SQL generation using projected scalar and projected JSON columns
      • exclusive projected-mode behavior without JSON fallback
      • row parsing from projected columns without falling back to stale JSON payloads
      • omitting projected fields from data

Example:

constrepo=yield*makeRepo("User",User,{config: {rootLevelFieldsWhenAvailable: true}})

With that enabled, root-level fields are stored in dedicated SQL columns when available. Scalars use typed columns where possible, while complex root fields use JSON/JSONB columns. Projected fields are not duplicated into data, and projected-mode reads/writes/queries use the root columns instead of falling back to data.

CopilotAIand others added 4 commits May 22, 2026 18:54
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
@pkg-pr-new

pkg-pr-newBot commented May 22, 2026

Copy link
Copy Markdown

Open in StackBlitz

@effect-app/cli

npm i https://pkg.pr.new/effect-app/libs/@effect-app/cli@763

effect-app

npm i https://pkg.pr.new/effect-app/libs/effect-app@763

@effect-app/eslint-codegen-model

npm i https://pkg.pr.new/effect-app/libs/@effect-app/eslint-codegen-model@763

@effect-app/eslint-shared-config

npm i https://pkg.pr.new/effect-app/libs/@effect-app/eslint-shared-config@763

@effect-app/infra

npm i https://pkg.pr.new/effect-app/libs/@effect-app/infra@763

@effect-app/vue

npm i https://pkg.pr.new/effect-app/libs/@effect-app/vue@763

@effect-app/vue-components

npm i https://pkg.pr.new/effect-app/libs/@effect-app/vue-components@763

commit: bcaf8e2

@patroza

Copy link
Copy Markdown
Member

@copilot document the plan for next step; relational fields

Agent-Logs-Url: https://github.com/effect-app/libs/sessions/ffdbe97c-c62f-4ae1-8a79-57e8f539221a
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>

CopilotAI commented May 22, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot document the plan for next step; relational fields

Added the Phase 2 relational follow-up plan to the config docs so it’s documented next to rootLevelFieldsWhenAvailable and the repository config surface. Addressed in 24782ef.

CopilotAI requested a review from patrozaMay 22, 2026 19:36
@patroza

Copy link
Copy Markdown
Member

@copilot don't write the separate fields also to data. and support any field type, including complex types, which should simply be json fields, like data is.

CopilotAIand others added 3 commits May 22, 2026 19:45
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/2c26dc3a-b352-4999-b5d5-98349e52640c
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/2c26dc3a-b352-4999-b5d5-98349e52640c
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>

CopilotAI commented May 22, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot don't write the separate fields also to data. and support any field type, including complex types, which should simply be json fields, like data is.

Addressed in 93db22d. Projected root fields are no longer duplicated into data, and root projection now covers any root field type by using JSON/JSONB columns for complex fields while keeping nested filters and root-array relation queries working.

@patroza

Copy link
Copy Markdown
Member

@copilot you misunderstood rootLevelFieldsWhenAvailable setting; the when available is about when database adapters usually use data column, when the setting is enabled you should switch to using root level columns and do migrations when there are schema changes.

you should not support both at the same time, with fallbacks. A migration of data should also happen offline, not on the fly. Queries and writes should either be to data column when setting is omitted/false, and to columns when true

CopilotAIand others added 2 commits May 23, 2026 05:17
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/18e97927-7b93-4bc4-aefc-a0461aa0331e
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>

CopilotAI commented May 23, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot you misunderstood rootLevelFieldsWhenAvailable setting; the when available is about when database adapters usually use data column, when the setting is enabled you should switch to using root...

Addressed in 34fb23e, with cleanup in 0b3b0b9. rootLevelFieldsWhenAvailable now switches SQL repos into an exclusive root-column mode: projected fields no longer fall back to data, runtime backfill/ALTER behavior was removed, and the docs/tests now reflect that existing schema/data migration is expected offline.

@patroza

Copy link
Copy Markdown
Member

@copilot update to latest main

…plan-relational-database-adoption
# Conflicts:
#	packages/effect-app/src/Model/Repository/internal/internal.ts
#	packages/effect-app/src/Store.ts
#	packages/infra/src/Store/SQL.ts
#	packages/infra/src/Store/SQL/Pg.ts
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@patroza
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Add opt-in SQL root-level projected columns for repository stores - #763

Draft
patroza with Copilot wants to merge 12 commits into
mainfrom
copilot/plan-relational-database-adoption
Draft

Add opt-in SQL root-level projected columns for repository stores#763
patroza with Copilot wants to merge 12 commits into
mainfrom
copilot/plan-relational-database-adoption

Conversation

CopilotAI commented May 22, 2026

Copy link
Copy Markdown
Contributor

This splits the storage evolution into the first track only: keep the current document model and JSON-based nested semantics, while allowing SQLite/PostgreSQL repositories to switch root-level fields to real columns. The new mode is opt-in per repository or adapter via rootLevelFieldsWhenAvailable.

  • What changed

    • Added rootLevelFieldsWhenAvailable?: boolean to repository/store config, with adapter-level default support in SQL storage config.
    • Kept the existing non-relational model intact.
    • When projection is enabled, projected root fields are stored in dedicated columns and are no longer duplicated in data.
    • Corrected the flag semantics so this is an exclusive mode switch:
      • false / omitted: reads, writes, and queries use data
      • true: derived root fields are read, written, and queried via dedicated root columns
  • Schema-derived projected columns

    • Derive projected root-level fields from the encoded repository schema.
    • Root scalar fields use typed SQL columns when possible:
      • string
      • number
      • boolean
      • nullable forms of the above
      • encoded date-like fields that serialize to root strings
    • Complex root fields are also projected:
      • nested objects
      • arrays
      • other non-scalar encoded root fields
    • Complex projected fields use JSON / JSONB columns.
  • SQLite / PostgreSQL store behavior

    • On fresh table setup, include projected root columns when the mode is enabled.
    • On writes in projected mode, persist:
      • non-projected fields into data
      • projected root fields into dedicated columns
    • On reads in projected mode, reconstruct projected fields from dedicated columns only.
    • Removed runtime fallback/backfill behavior:
      • no COALESCE(...) fallback from projected columns back to data
      • no on-the-fly backfill of projected columns from existing data
      • no runtime ALTER TABLE / migration behavior for existing rows
    • Existing schema/data migration for switching modes is expected to happen offline.
  • Query planning

    • In projected mode, root-level filters, ordering, and scalar selection resolve to projected columns directly.
    • Nested paths under projected JSON root fields resolve against the projected JSON/JSONB columns directly.
    • Root-level relation-style array queries continue to work when those arrays are projected into JSON/JSONB columns.
    • When the mode is disabled, queries continue to use the data column.
  • Tests

    • Added coverage for:
      • projected-field metadata derivation from schema, including complex root fields
      • SQL generation using projected scalar and projected JSON columns
      • exclusive projected-mode behavior without JSON fallback
      • row parsing from projected columns without falling back to stale JSON payloads
      • omitting projected fields from data

Example:

constrepo=yield*makeRepo("User",User,{config: {rootLevelFieldsWhenAvailable: true}})

With that enabled, root-level fields are stored in dedicated SQL columns when available. Scalars use typed columns where possible, while complex root fields use JSON/JSONB columns. Projected fields are not duplicated into data, and projected-mode reads/writes/queries use the root columns instead of falling back to data.

CopilotAIand others added 4 commits May 22, 2026 18:54
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
@pkg-pr-new

pkg-pr-newBot commented May 22, 2026

Copy link
Copy Markdown

Open in StackBlitz

@effect-app/cli

npm i https://pkg.pr.new/effect-app/libs/@effect-app/cli@763

effect-app

npm i https://pkg.pr.new/effect-app/libs/effect-app@763

@effect-app/eslint-codegen-model

npm i https://pkg.pr.new/effect-app/libs/@effect-app/eslint-codegen-model@763

@effect-app/eslint-shared-config

npm i https://pkg.pr.new/effect-app/libs/@effect-app/eslint-shared-config@763

@effect-app/infra

npm i https://pkg.pr.new/effect-app/libs/@effect-app/infra@763

@effect-app/vue

npm i https://pkg.pr.new/effect-app/libs/@effect-app/vue@763

@effect-app/vue-components

npm i https://pkg.pr.new/effect-app/libs/@effect-app/vue-components@763

commit: bcaf8e2

@patroza

Copy link
Copy Markdown
Member

@copilot document the plan for next step; relational fields

Agent-Logs-Url: https://github.com/effect-app/libs/sessions/ffdbe97c-c62f-4ae1-8a79-57e8f539221a
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>

CopilotAI commented May 22, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot document the plan for next step; relational fields

Added the Phase 2 relational follow-up plan to the config docs so it’s documented next to rootLevelFieldsWhenAvailable and the repository config surface. Addressed in 24782ef.

CopilotAI requested a review from patrozaMay 22, 2026 19:36
@patroza

Copy link
Copy Markdown
Member

@copilot don't write the separate fields also to data. and support any field type, including complex types, which should simply be json fields, like data is.

CopilotAIand others added 3 commits May 22, 2026 19:45
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/2c26dc3a-b352-4999-b5d5-98349e52640c
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/2c26dc3a-b352-4999-b5d5-98349e52640c
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>

CopilotAI commented May 22, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot don't write the separate fields also to data. and support any field type, including complex types, which should simply be json fields, like data is.

Addressed in 93db22d. Projected root fields are no longer duplicated into data, and root projection now covers any root field type by using JSON/JSONB columns for complex fields while keeping nested filters and root-array relation queries working.

@patroza

Copy link
Copy Markdown
Member

@copilot you misunderstood rootLevelFieldsWhenAvailable setting; the when available is about when database adapters usually use data column, when the setting is enabled you should switch to using root level columns and do migrations when there are schema changes.

you should not support both at the same time, with fallbacks. A migration of data should also happen offline, not on the fly. Queries and writes should either be to data column when setting is omitted/false, and to columns when true

CopilotAIand others added 2 commits May 23, 2026 05:17
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/18e97927-7b93-4bc4-aefc-a0461aa0331e
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>

CopilotAI commented May 23, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot you misunderstood rootLevelFieldsWhenAvailable setting; the when available is about when database adapters usually use data column, when the setting is enabled you should switch to using root...

Addressed in 34fb23e, with cleanup in 0b3b0b9. rootLevelFieldsWhenAvailable now switches SQL repos into an exclusive root-column mode: projected fields no longer fall back to data, runtime backfill/ALTER behavior was removed, and the docs/tests now reflect that existing schema/data migration is expected offline.

@patroza

Copy link
Copy Markdown
Member

@copilot update to latest main

…plan-relational-database-adoption
# Conflicts:
#	packages/effect-app/src/Model/Repository/internal/internal.ts
#	packages/effect-app/src/Store.ts
#	packages/infra/src/Store/SQL.ts
#	packages/infra/src/Store/SQL/Pg.ts
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@patroza
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add opt-in SQL root-level projected columns for repository stores - #763

Draft
patroza with Copilot wants to merge 12 commits into
mainfrom
copilot/plan-relational-database-adoption
Draft

Add opt-in SQL root-level projected columns for repository stores#763
patroza with Copilot wants to merge 12 commits into
mainfrom
copilot/plan-relational-database-adoption

Conversation

CopilotAI commented May 22, 2026

Copy link
Copy Markdown
Contributor

This splits the storage evolution into the first track only: keep the current document model and JSON-based nested semantics, while allowing SQLite/PostgreSQL repositories to switch root-level fields to real columns. The new mode is opt-in per repository or adapter via rootLevelFieldsWhenAvailable.

  • What changed

    • Added rootLevelFieldsWhenAvailable?: boolean to repository/store config, with adapter-level default support in SQL storage config.
    • Kept the existing non-relational model intact.
    • When projection is enabled, projected root fields are stored in dedicated columns and are no longer duplicated in data.
    • Corrected the flag semantics so this is an exclusive mode switch:
      • false / omitted: reads, writes, and queries use data
      • true: derived root fields are read, written, and queried via dedicated root columns
  • Schema-derived projected columns

    • Derive projected root-level fields from the encoded repository schema.
    • Root scalar fields use typed SQL columns when possible:
      • string
      • number
      • boolean
      • nullable forms of the above
      • encoded date-like fields that serialize to root strings
    • Complex root fields are also projected:
      • nested objects
      • arrays
      • other non-scalar encoded root fields
    • Complex projected fields use JSON / JSONB columns.
  • SQLite / PostgreSQL store behavior

    • On fresh table setup, include projected root columns when the mode is enabled.
    • On writes in projected mode, persist:
      • non-projected fields into data
      • projected root fields into dedicated columns
    • On reads in projected mode, reconstruct projected fields from dedicated columns only.
    • Removed runtime fallback/backfill behavior:
      • no COALESCE(...) fallback from projected columns back to data
      • no on-the-fly backfill of projected columns from existing data
      • no runtime ALTER TABLE / migration behavior for existing rows
    • Existing schema/data migration for switching modes is expected to happen offline.
  • Query planning

    • In projected mode, root-level filters, ordering, and scalar selection resolve to projected columns directly.
    • Nested paths under projected JSON root fields resolve against the projected JSON/JSONB columns directly.
    • Root-level relation-style array queries continue to work when those arrays are projected into JSON/JSONB columns.
    • When the mode is disabled, queries continue to use the data column.
  • Tests

    • Added coverage for:
      • projected-field metadata derivation from schema, including complex root fields
      • SQL generation using projected scalar and projected JSON columns
      • exclusive projected-mode behavior without JSON fallback
      • row parsing from projected columns without falling back to stale JSON payloads
      • omitting projected fields from data

Example:

constrepo=yield*makeRepo("User",User,{config: {rootLevelFieldsWhenAvailable: true}})

With that enabled, root-level fields are stored in dedicated SQL columns when available. Scalars use typed columns where possible, while complex root fields use JSON/JSONB columns. Projected fields are not duplicated into data, and projected-mode reads/writes/queries use the root columns instead of falling back to data.

CopilotAIand others added 4 commits May 22, 2026 18:54
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
@pkg-pr-new

pkg-pr-newBot commented May 22, 2026

Copy link
Copy Markdown

Open in StackBlitz

@effect-app/cli

npm i https://pkg.pr.new/effect-app/libs/@effect-app/cli@763

effect-app

npm i https://pkg.pr.new/effect-app/libs/effect-app@763

@effect-app/eslint-codegen-model

npm i https://pkg.pr.new/effect-app/libs/@effect-app/eslint-codegen-model@763

@effect-app/eslint-shared-config

npm i https://pkg.pr.new/effect-app/libs/@effect-app/eslint-shared-config@763

@effect-app/infra

npm i https://pkg.pr.new/effect-app/libs/@effect-app/infra@763

@effect-app/vue

npm i https://pkg.pr.new/effect-app/libs/@effect-app/vue@763

@effect-app/vue-components

npm i https://pkg.pr.new/effect-app/libs/@effect-app/vue-components@763

commit: bcaf8e2

@patroza

Copy link
Copy Markdown
Member

@copilot document the plan for next step; relational fields

Agent-Logs-Url: https://github.com/effect-app/libs/sessions/ffdbe97c-c62f-4ae1-8a79-57e8f539221a
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>

CopilotAI commented May 22, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot document the plan for next step; relational fields

Added the Phase 2 relational follow-up plan to the config docs so it’s documented next to rootLevelFieldsWhenAvailable and the repository config surface. Addressed in 24782ef.

CopilotAI requested a review from patrozaMay 22, 2026 19:36
@patroza

Copy link
Copy Markdown
Member

@copilot don't write the separate fields also to data. and support any field type, including complex types, which should simply be json fields, like data is.

CopilotAIand others added 3 commits May 22, 2026 19:45
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/2c26dc3a-b352-4999-b5d5-98349e52640c
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/2c26dc3a-b352-4999-b5d5-98349e52640c
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>

CopilotAI commented May 22, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot don't write the separate fields also to data. and support any field type, including complex types, which should simply be json fields, like data is.

Addressed in 93db22d. Projected root fields are no longer duplicated into data, and root projection now covers any root field type by using JSON/JSONB columns for complex fields while keeping nested filters and root-array relation queries working.

@patroza

Copy link
Copy Markdown
Member

@copilot you misunderstood rootLevelFieldsWhenAvailable setting; the when available is about when database adapters usually use data column, when the setting is enabled you should switch to using root level columns and do migrations when there are schema changes.

you should not support both at the same time, with fallbacks. A migration of data should also happen offline, not on the fly. Queries and writes should either be to data column when setting is omitted/false, and to columns when true

CopilotAIand others added 2 commits May 23, 2026 05:17
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/18e97927-7b93-4bc4-aefc-a0461aa0331e
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>

CopilotAI commented May 23, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot you misunderstood rootLevelFieldsWhenAvailable setting; the when available is about when database adapters usually use data column, when the setting is enabled you should switch to using root...

Addressed in 34fb23e, with cleanup in 0b3b0b9. rootLevelFieldsWhenAvailable now switches SQL repos into an exclusive root-column mode: projected fields no longer fall back to data, runtime backfill/ALTER behavior was removed, and the docs/tests now reflect that existing schema/data migration is expected offline.

@patroza

Copy link
Copy Markdown
Member

@copilot update to latest main

…plan-relational-database-adoption
# Conflicts:
#	packages/effect-app/src/Model/Repository/internal/internal.ts
#	packages/effect-app/src/Store.ts
#	packages/infra/src/Store/SQL.ts
#	packages/infra/src/Store/SQL/Pg.ts
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@patroza
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add opt-in SQL root-level projected columns for repository stores - #763

Draft
patroza with Copilot wants to merge 12 commits into
mainfrom
copilot/plan-relational-database-adoption
Draft

Add opt-in SQL root-level projected columns for repository stores#763
patroza with Copilot wants to merge 12 commits into
mainfrom
copilot/plan-relational-database-adoption

Conversation

CopilotAI commented May 22, 2026

Copy link
Copy Markdown
Contributor

This splits the storage evolution into the first track only: keep the current document model and JSON-based nested semantics, while allowing SQLite/PostgreSQL repositories to switch root-level fields to real columns. The new mode is opt-in per repository or adapter via rootLevelFieldsWhenAvailable.

  • What changed

    • Added rootLevelFieldsWhenAvailable?: boolean to repository/store config, with adapter-level default support in SQL storage config.
    • Kept the existing non-relational model intact.
    • When projection is enabled, projected root fields are stored in dedicated columns and are no longer duplicated in data.
    • Corrected the flag semantics so this is an exclusive mode switch:
      • false / omitted: reads, writes, and queries use data
      • true: derived root fields are read, written, and queried via dedicated root columns
  • Schema-derived projected columns

    • Derive projected root-level fields from the encoded repository schema.
    • Root scalar fields use typed SQL columns when possible:
      • string
      • number
      • boolean
      • nullable forms of the above
      • encoded date-like fields that serialize to root strings
    • Complex root fields are also projected:
      • nested objects
      • arrays
      • other non-scalar encoded root fields
    • Complex projected fields use JSON / JSONB columns.
  • SQLite / PostgreSQL store behavior

    • On fresh table setup, include projected root columns when the mode is enabled.
    • On writes in projected mode, persist:
      • non-projected fields into data
      • projected root fields into dedicated columns
    • On reads in projected mode, reconstruct projected fields from dedicated columns only.
    • Removed runtime fallback/backfill behavior:
      • no COALESCE(...) fallback from projected columns back to data
      • no on-the-fly backfill of projected columns from existing data
      • no runtime ALTER TABLE / migration behavior for existing rows
    • Existing schema/data migration for switching modes is expected to happen offline.
  • Query planning

    • In projected mode, root-level filters, ordering, and scalar selection resolve to projected columns directly.
    • Nested paths under projected JSON root fields resolve against the projected JSON/JSONB columns directly.
    • Root-level relation-style array queries continue to work when those arrays are projected into JSON/JSONB columns.
    • When the mode is disabled, queries continue to use the data column.
  • Tests

    • Added coverage for:
      • projected-field metadata derivation from schema, including complex root fields
      • SQL generation using projected scalar and projected JSON columns
      • exclusive projected-mode behavior without JSON fallback
      • row parsing from projected columns without falling back to stale JSON payloads
      • omitting projected fields from data

Example:

constrepo=yield*makeRepo("User",User,{config: {rootLevelFieldsWhenAvailable: true}})

With that enabled, root-level fields are stored in dedicated SQL columns when available. Scalars use typed columns where possible, while complex root fields use JSON/JSONB columns. Projected fields are not duplicated into data, and projected-mode reads/writes/queries use the root columns instead of falling back to data.

CopilotAIand others added 4 commits May 22, 2026 18:54
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
@pkg-pr-new

pkg-pr-newBot commented May 22, 2026

Copy link
Copy Markdown

Open in StackBlitz

@effect-app/cli

npm i https://pkg.pr.new/effect-app/libs/@effect-app/cli@763

effect-app

npm i https://pkg.pr.new/effect-app/libs/effect-app@763

@effect-app/eslint-codegen-model

npm i https://pkg.pr.new/effect-app/libs/@effect-app/eslint-codegen-model@763

@effect-app/eslint-shared-config

npm i https://pkg.pr.new/effect-app/libs/@effect-app/eslint-shared-config@763

@effect-app/infra

npm i https://pkg.pr.new/effect-app/libs/@effect-app/infra@763

@effect-app/vue

npm i https://pkg.pr.new/effect-app/libs/@effect-app/vue@763

@effect-app/vue-components

npm i https://pkg.pr.new/effect-app/libs/@effect-app/vue-components@763

commit: bcaf8e2

@patroza

Copy link
Copy Markdown
Member

@copilot document the plan for next step; relational fields

Agent-Logs-Url: https://github.com/effect-app/libs/sessions/ffdbe97c-c62f-4ae1-8a79-57e8f539221a
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>

CopilotAI commented May 22, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot document the plan for next step; relational fields

Added the Phase 2 relational follow-up plan to the config docs so it’s documented next to rootLevelFieldsWhenAvailable and the repository config surface. Addressed in 24782ef.

CopilotAI requested a review from patrozaMay 22, 2026 19:36
@patroza

Copy link
Copy Markdown
Member

@copilot don't write the separate fields also to data. and support any field type, including complex types, which should simply be json fields, like data is.

CopilotAIand others added 3 commits May 22, 2026 19:45
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/2c26dc3a-b352-4999-b5d5-98349e52640c
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/2c26dc3a-b352-4999-b5d5-98349e52640c
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>

CopilotAI commented May 22, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot don't write the separate fields also to data. and support any field type, including complex types, which should simply be json fields, like data is.

Addressed in 93db22d. Projected root fields are no longer duplicated into data, and root projection now covers any root field type by using JSON/JSONB columns for complex fields while keeping nested filters and root-array relation queries working.

@patroza

Copy link
Copy Markdown
Member

@copilot you misunderstood rootLevelFieldsWhenAvailable setting; the when available is about when database adapters usually use data column, when the setting is enabled you should switch to using root level columns and do migrations when there are schema changes.

you should not support both at the same time, with fallbacks. A migration of data should also happen offline, not on the fly. Queries and writes should either be to data column when setting is omitted/false, and to columns when true

CopilotAIand others added 2 commits May 23, 2026 05:17
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/18e97927-7b93-4bc4-aefc-a0461aa0331e
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>

CopilotAI commented May 23, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot you misunderstood rootLevelFieldsWhenAvailable setting; the when available is about when database adapters usually use data column, when the setting is enabled you should switch to using root...

Addressed in 34fb23e, with cleanup in 0b3b0b9. rootLevelFieldsWhenAvailable now switches SQL repos into an exclusive root-column mode: projected fields no longer fall back to data, runtime backfill/ALTER behavior was removed, and the docs/tests now reflect that existing schema/data migration is expected offline.

@patroza

Copy link
Copy Markdown
Member

@copilot update to latest main

…plan-relational-database-adoption
# Conflicts:
#	packages/effect-app/src/Model/Repository/internal/internal.ts
#	packages/effect-app/src/Store.ts
#	packages/infra/src/Store/SQL.ts
#	packages/infra/src/Store/SQL/Pg.ts
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@patroza
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Add opt-in SQL root-level projected columns for repository stores - #763

Draft
patroza with Copilot wants to merge 12 commits into
mainfrom
copilot/plan-relational-database-adoption
Draft

Add opt-in SQL root-level projected columns for repository stores#763
patroza with Copilot wants to merge 12 commits into
mainfrom
copilot/plan-relational-database-adoption

Conversation

CopilotAI commented May 22, 2026

Copy link
Copy Markdown
Contributor

This splits the storage evolution into the first track only: keep the current document model and JSON-based nested semantics, while allowing SQLite/PostgreSQL repositories to switch root-level fields to real columns. The new mode is opt-in per repository or adapter via rootLevelFieldsWhenAvailable.

  • What changed

    • Added rootLevelFieldsWhenAvailable?: boolean to repository/store config, with adapter-level default support in SQL storage config.
    • Kept the existing non-relational model intact.
    • When projection is enabled, projected root fields are stored in dedicated columns and are no longer duplicated in data.
    • Corrected the flag semantics so this is an exclusive mode switch:
      • false / omitted: reads, writes, and queries use data
      • true: derived root fields are read, written, and queried via dedicated root columns
  • Schema-derived projected columns

    • Derive projected root-level fields from the encoded repository schema.
    • Root scalar fields use typed SQL columns when possible:
      • string
      • number
      • boolean
      • nullable forms of the above
      • encoded date-like fields that serialize to root strings
    • Complex root fields are also projected:
      • nested objects
      • arrays
      • other non-scalar encoded root fields
    • Complex projected fields use JSON / JSONB columns.
  • SQLite / PostgreSQL store behavior

    • On fresh table setup, include projected root columns when the mode is enabled.
    • On writes in projected mode, persist:
      • non-projected fields into data
      • projected root fields into dedicated columns
    • On reads in projected mode, reconstruct projected fields from dedicated columns only.
    • Removed runtime fallback/backfill behavior:
      • no COALESCE(...) fallback from projected columns back to data
      • no on-the-fly backfill of projected columns from existing data
      • no runtime ALTER TABLE / migration behavior for existing rows
    • Existing schema/data migration for switching modes is expected to happen offline.
  • Query planning

    • In projected mode, root-level filters, ordering, and scalar selection resolve to projected columns directly.
    • Nested paths under projected JSON root fields resolve against the projected JSON/JSONB columns directly.
    • Root-level relation-style array queries continue to work when those arrays are projected into JSON/JSONB columns.
    • When the mode is disabled, queries continue to use the data column.
  • Tests

    • Added coverage for:
      • projected-field metadata derivation from schema, including complex root fields
      • SQL generation using projected scalar and projected JSON columns
      • exclusive projected-mode behavior without JSON fallback
      • row parsing from projected columns without falling back to stale JSON payloads
      • omitting projected fields from data

Example:

constrepo=yield*makeRepo("User",User,{config: {rootLevelFieldsWhenAvailable: true}})

With that enabled, root-level fields are stored in dedicated SQL columns when available. Scalars use typed columns where possible, while complex root fields use JSON/JSONB columns. Projected fields are not duplicated into data, and projected-mode reads/writes/queries use the root columns instead of falling back to data.

CopilotAIand others added 4 commits May 22, 2026 18:54
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
@pkg-pr-new

pkg-pr-newBot commented May 22, 2026

Copy link
Copy Markdown

Open in StackBlitz

@effect-app/cli

npm i https://pkg.pr.new/effect-app/libs/@effect-app/cli@763

effect-app

npm i https://pkg.pr.new/effect-app/libs/effect-app@763

@effect-app/eslint-codegen-model

npm i https://pkg.pr.new/effect-app/libs/@effect-app/eslint-codegen-model@763

@effect-app/eslint-shared-config

npm i https://pkg.pr.new/effect-app/libs/@effect-app/eslint-shared-config@763

@effect-app/infra

npm i https://pkg.pr.new/effect-app/libs/@effect-app/infra@763

@effect-app/vue

npm i https://pkg.pr.new/effect-app/libs/@effect-app/vue@763

@effect-app/vue-components

npm i https://pkg.pr.new/effect-app/libs/@effect-app/vue-components@763

commit: bcaf8e2

@patroza

Copy link
Copy Markdown
Member

@copilot document the plan for next step; relational fields

Agent-Logs-Url: https://github.com/effect-app/libs/sessions/ffdbe97c-c62f-4ae1-8a79-57e8f539221a
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>

CopilotAI commented May 22, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot document the plan for next step; relational fields

Added the Phase 2 relational follow-up plan to the config docs so it’s documented next to rootLevelFieldsWhenAvailable and the repository config surface. Addressed in 24782ef.

CopilotAI requested a review from patrozaMay 22, 2026 19:36
@patroza

Copy link
Copy Markdown
Member

@copilot don't write the separate fields also to data. and support any field type, including complex types, which should simply be json fields, like data is.

CopilotAIand others added 3 commits May 22, 2026 19:45
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/2c26dc3a-b352-4999-b5d5-98349e52640c
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/2c26dc3a-b352-4999-b5d5-98349e52640c
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>

CopilotAI commented May 22, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot don't write the separate fields also to data. and support any field type, including complex types, which should simply be json fields, like data is.

Addressed in 93db22d. Projected root fields are no longer duplicated into data, and root projection now covers any root field type by using JSON/JSONB columns for complex fields while keeping nested filters and root-array relation queries working.

@patroza

Copy link
Copy Markdown
Member

@copilot you misunderstood rootLevelFieldsWhenAvailable setting; the when available is about when database adapters usually use data column, when the setting is enabled you should switch to using root level columns and do migrations when there are schema changes.

you should not support both at the same time, with fallbacks. A migration of data should also happen offline, not on the fly. Queries and writes should either be to data column when setting is omitted/false, and to columns when true

CopilotAIand others added 2 commits May 23, 2026 05:17
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/18e97927-7b93-4bc4-aefc-a0461aa0331e
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>

CopilotAI commented May 23, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot you misunderstood rootLevelFieldsWhenAvailable setting; the when available is about when database adapters usually use data column, when the setting is enabled you should switch to using root...

Addressed in 34fb23e, with cleanup in 0b3b0b9. rootLevelFieldsWhenAvailable now switches SQL repos into an exclusive root-column mode: projected fields no longer fall back to data, runtime backfill/ALTER behavior was removed, and the docs/tests now reflect that existing schema/data migration is expected offline.

@patroza

Copy link
Copy Markdown
Member

@copilot update to latest main

…plan-relational-database-adoption
# Conflicts:
#	packages/effect-app/src/Model/Repository/internal/internal.ts
#	packages/effect-app/src/Store.ts
#	packages/infra/src/Store/SQL.ts
#	packages/infra/src/Store/SQL/Pg.ts
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@patroza
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add opt-in SQL root-level projected columns for repository stores - #763

Draft
patroza with Copilot wants to merge 12 commits into
mainfrom
copilot/plan-relational-database-adoption
Draft

Add opt-in SQL root-level projected columns for repository stores#763
patroza with Copilot wants to merge 12 commits into
mainfrom
copilot/plan-relational-database-adoption

Conversation

CopilotAI commented May 22, 2026

Copy link
Copy Markdown
Contributor

This splits the storage evolution into the first track only: keep the current document model and JSON-based nested semantics, while allowing SQLite/PostgreSQL repositories to switch root-level fields to real columns. The new mode is opt-in per repository or adapter via rootLevelFieldsWhenAvailable.

  • What changed

    • Added rootLevelFieldsWhenAvailable?: boolean to repository/store config, with adapter-level default support in SQL storage config.
    • Kept the existing non-relational model intact.
    • When projection is enabled, projected root fields are stored in dedicated columns and are no longer duplicated in data.
    • Corrected the flag semantics so this is an exclusive mode switch:
      • false / omitted: reads, writes, and queries use data
      • true: derived root fields are read, written, and queried via dedicated root columns
  • Schema-derived projected columns

    • Derive projected root-level fields from the encoded repository schema.
    • Root scalar fields use typed SQL columns when possible:
      • string
      • number
      • boolean
      • nullable forms of the above
      • encoded date-like fields that serialize to root strings
    • Complex root fields are also projected:
      • nested objects
      • arrays
      • other non-scalar encoded root fields
    • Complex projected fields use JSON / JSONB columns.
  • SQLite / PostgreSQL store behavior

    • On fresh table setup, include projected root columns when the mode is enabled.
    • On writes in projected mode, persist:
      • non-projected fields into data
      • projected root fields into dedicated columns
    • On reads in projected mode, reconstruct projected fields from dedicated columns only.
    • Removed runtime fallback/backfill behavior:
      • no COALESCE(...) fallback from projected columns back to data
      • no on-the-fly backfill of projected columns from existing data
      • no runtime ALTER TABLE / migration behavior for existing rows
    • Existing schema/data migration for switching modes is expected to happen offline.
  • Query planning

    • In projected mode, root-level filters, ordering, and scalar selection resolve to projected columns directly.
    • Nested paths under projected JSON root fields resolve against the projected JSON/JSONB columns directly.
    • Root-level relation-style array queries continue to work when those arrays are projected into JSON/JSONB columns.
    • When the mode is disabled, queries continue to use the data column.
  • Tests

    • Added coverage for:
      • projected-field metadata derivation from schema, including complex root fields
      • SQL generation using projected scalar and projected JSON columns
      • exclusive projected-mode behavior without JSON fallback
      • row parsing from projected columns without falling back to stale JSON payloads
      • omitting projected fields from data

Example:

constrepo=yield*makeRepo("User",User,{config: {rootLevelFieldsWhenAvailable: true}})

With that enabled, root-level fields are stored in dedicated SQL columns when available. Scalars use typed columns where possible, while complex root fields use JSON/JSONB columns. Projected fields are not duplicated into data, and projected-mode reads/writes/queries use the root columns instead of falling back to data.

CopilotAIand others added 4 commits May 22, 2026 18:54
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
@pkg-pr-new

pkg-pr-newBot commented May 22, 2026

Copy link
Copy Markdown

Open in StackBlitz

@effect-app/cli

npm i https://pkg.pr.new/effect-app/libs/@effect-app/cli@763

effect-app

npm i https://pkg.pr.new/effect-app/libs/effect-app@763

@effect-app/eslint-codegen-model

npm i https://pkg.pr.new/effect-app/libs/@effect-app/eslint-codegen-model@763

@effect-app/eslint-shared-config

npm i https://pkg.pr.new/effect-app/libs/@effect-app/eslint-shared-config@763

@effect-app/infra

npm i https://pkg.pr.new/effect-app/libs/@effect-app/infra@763

@effect-app/vue

npm i https://pkg.pr.new/effect-app/libs/@effect-app/vue@763

@effect-app/vue-components

npm i https://pkg.pr.new/effect-app/libs/@effect-app/vue-components@763

commit: bcaf8e2

@patroza

Copy link
Copy Markdown
Member

@copilot document the plan for next step; relational fields

Agent-Logs-Url: https://github.com/effect-app/libs/sessions/ffdbe97c-c62f-4ae1-8a79-57e8f539221a
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>

CopilotAI commented May 22, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot document the plan for next step; relational fields

Added the Phase 2 relational follow-up plan to the config docs so it’s documented next to rootLevelFieldsWhenAvailable and the repository config surface. Addressed in 24782ef.

CopilotAI requested a review from patrozaMay 22, 2026 19:36
@patroza

Copy link
Copy Markdown
Member

@copilot don't write the separate fields also to data. and support any field type, including complex types, which should simply be json fields, like data is.

CopilotAIand others added 3 commits May 22, 2026 19:45
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/2c26dc3a-b352-4999-b5d5-98349e52640c
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/2c26dc3a-b352-4999-b5d5-98349e52640c
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>

CopilotAI commented May 22, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot don't write the separate fields also to data. and support any field type, including complex types, which should simply be json fields, like data is.

Addressed in 93db22d. Projected root fields are no longer duplicated into data, and root projection now covers any root field type by using JSON/JSONB columns for complex fields while keeping nested filters and root-array relation queries working.

@patroza

Copy link
Copy Markdown
Member

@copilot you misunderstood rootLevelFieldsWhenAvailable setting; the when available is about when database adapters usually use data column, when the setting is enabled you should switch to using root level columns and do migrations when there are schema changes.

you should not support both at the same time, with fallbacks. A migration of data should also happen offline, not on the fly. Queries and writes should either be to data column when setting is omitted/false, and to columns when true

CopilotAIand others added 2 commits May 23, 2026 05:17
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/18e97927-7b93-4bc4-aefc-a0461aa0331e
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>

CopilotAI commented May 23, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot you misunderstood rootLevelFieldsWhenAvailable setting; the when available is about when database adapters usually use data column, when the setting is enabled you should switch to using root...

Addressed in 34fb23e, with cleanup in 0b3b0b9. rootLevelFieldsWhenAvailable now switches SQL repos into an exclusive root-column mode: projected fields no longer fall back to data, runtime backfill/ALTER behavior was removed, and the docs/tests now reflect that existing schema/data migration is expected offline.

@patroza

Copy link
Copy Markdown
Member

@copilot update to latest main

…plan-relational-database-adoption
# Conflicts:
#	packages/effect-app/src/Model/Repository/internal/internal.ts
#	packages/effect-app/src/Store.ts
#	packages/infra/src/Store/SQL.ts
#	packages/infra/src/Store/SQL/Pg.ts
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@patroza
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add opt-in SQL root-level projected columns for repository stores - #763

Draft
patroza with Copilot wants to merge 12 commits into
mainfrom
copilot/plan-relational-database-adoption
Draft

Add opt-in SQL root-level projected columns for repository stores#763
patroza with Copilot wants to merge 12 commits into
mainfrom
copilot/plan-relational-database-adoption

Conversation

CopilotAI commented May 22, 2026

Copy link
Copy Markdown
Contributor

This splits the storage evolution into the first track only: keep the current document model and JSON-based nested semantics, while allowing SQLite/PostgreSQL repositories to switch root-level fields to real columns. The new mode is opt-in per repository or adapter via rootLevelFieldsWhenAvailable.

  • What changed

    • Added rootLevelFieldsWhenAvailable?: boolean to repository/store config, with adapter-level default support in SQL storage config.
    • Kept the existing non-relational model intact.
    • When projection is enabled, projected root fields are stored in dedicated columns and are no longer duplicated in data.
    • Corrected the flag semantics so this is an exclusive mode switch:
      • false / omitted: reads, writes, and queries use data
      • true: derived root fields are read, written, and queried via dedicated root columns
  • Schema-derived projected columns

    • Derive projected root-level fields from the encoded repository schema.
    • Root scalar fields use typed SQL columns when possible:
      • string
      • number
      • boolean
      • nullable forms of the above
      • encoded date-like fields that serialize to root strings
    • Complex root fields are also projected:
      • nested objects
      • arrays
      • other non-scalar encoded root fields
    • Complex projected fields use JSON / JSONB columns.
  • SQLite / PostgreSQL store behavior

    • On fresh table setup, include projected root columns when the mode is enabled.
    • On writes in projected mode, persist:
      • non-projected fields into data
      • projected root fields into dedicated columns
    • On reads in projected mode, reconstruct projected fields from dedicated columns only.
    • Removed runtime fallback/backfill behavior:
      • no COALESCE(...) fallback from projected columns back to data
      • no on-the-fly backfill of projected columns from existing data
      • no runtime ALTER TABLE / migration behavior for existing rows
    • Existing schema/data migration for switching modes is expected to happen offline.
  • Query planning

    • In projected mode, root-level filters, ordering, and scalar selection resolve to projected columns directly.
    • Nested paths under projected JSON root fields resolve against the projected JSON/JSONB columns directly.
    • Root-level relation-style array queries continue to work when those arrays are projected into JSON/JSONB columns.
    • When the mode is disabled, queries continue to use the data column.
  • Tests

    • Added coverage for:
      • projected-field metadata derivation from schema, including complex root fields
      • SQL generation using projected scalar and projected JSON columns
      • exclusive projected-mode behavior without JSON fallback
      • row parsing from projected columns without falling back to stale JSON payloads
      • omitting projected fields from data

Example:

constrepo=yield*makeRepo("User",User,{config: {rootLevelFieldsWhenAvailable: true}})

With that enabled, root-level fields are stored in dedicated SQL columns when available. Scalars use typed columns where possible, while complex root fields use JSON/JSONB columns. Projected fields are not duplicated into data, and projected-mode reads/writes/queries use the root columns instead of falling back to data.

CopilotAIand others added 4 commits May 22, 2026 18:54
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
@pkg-pr-new

pkg-pr-newBot commented May 22, 2026

Copy link
Copy Markdown

Open in StackBlitz

@effect-app/cli

npm i https://pkg.pr.new/effect-app/libs/@effect-app/cli@763

effect-app

npm i https://pkg.pr.new/effect-app/libs/effect-app@763

@effect-app/eslint-codegen-model

npm i https://pkg.pr.new/effect-app/libs/@effect-app/eslint-codegen-model@763

@effect-app/eslint-shared-config

npm i https://pkg.pr.new/effect-app/libs/@effect-app/eslint-shared-config@763

@effect-app/infra

npm i https://pkg.pr.new/effect-app/libs/@effect-app/infra@763

@effect-app/vue

npm i https://pkg.pr.new/effect-app/libs/@effect-app/vue@763

@effect-app/vue-components

npm i https://pkg.pr.new/effect-app/libs/@effect-app/vue-components@763

commit: bcaf8e2

@patroza

Copy link
Copy Markdown
Member

@copilot document the plan for next step; relational fields

Agent-Logs-Url: https://github.com/effect-app/libs/sessions/ffdbe97c-c62f-4ae1-8a79-57e8f539221a
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>

CopilotAI commented May 22, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot document the plan for next step; relational fields

Added the Phase 2 relational follow-up plan to the config docs so it’s documented next to rootLevelFieldsWhenAvailable and the repository config surface. Addressed in 24782ef.

CopilotAI requested a review from patrozaMay 22, 2026 19:36
@patroza

Copy link
Copy Markdown
Member

@copilot don't write the separate fields also to data. and support any field type, including complex types, which should simply be json fields, like data is.

CopilotAIand others added 3 commits May 22, 2026 19:45
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/2c26dc3a-b352-4999-b5d5-98349e52640c
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/2c26dc3a-b352-4999-b5d5-98349e52640c
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>

CopilotAI commented May 22, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot don't write the separate fields also to data. and support any field type, including complex types, which should simply be json fields, like data is.

Addressed in 93db22d. Projected root fields are no longer duplicated into data, and root projection now covers any root field type by using JSON/JSONB columns for complex fields while keeping nested filters and root-array relation queries working.

@patroza

Copy link
Copy Markdown
Member

@copilot you misunderstood rootLevelFieldsWhenAvailable setting; the when available is about when database adapters usually use data column, when the setting is enabled you should switch to using root level columns and do migrations when there are schema changes.

you should not support both at the same time, with fallbacks. A migration of data should also happen offline, not on the fly. Queries and writes should either be to data column when setting is omitted/false, and to columns when true

CopilotAIand others added 2 commits May 23, 2026 05:17
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/18e97927-7b93-4bc4-aefc-a0461aa0331e
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>

CopilotAI commented May 23, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot you misunderstood rootLevelFieldsWhenAvailable setting; the when available is about when database adapters usually use data column, when the setting is enabled you should switch to using root...

Addressed in 34fb23e, with cleanup in 0b3b0b9. rootLevelFieldsWhenAvailable now switches SQL repos into an exclusive root-column mode: projected fields no longer fall back to data, runtime backfill/ALTER behavior was removed, and the docs/tests now reflect that existing schema/data migration is expected offline.

@patroza

Copy link
Copy Markdown
Member

@copilot update to latest main

…plan-relational-database-adoption
# Conflicts:
#	packages/effect-app/src/Model/Repository/internal/internal.ts
#	packages/effect-app/src/Store.ts
#	packages/infra/src/Store/SQL.ts
#	packages/infra/src/Store/SQL/Pg.ts
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@patroza
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Add opt-in SQL root-level projected columns for repository stores - #763

Draft
patroza with Copilot wants to merge 12 commits into
mainfrom
copilot/plan-relational-database-adoption
Draft

Add opt-in SQL root-level projected columns for repository stores#763
patroza with Copilot wants to merge 12 commits into
mainfrom
copilot/plan-relational-database-adoption

Conversation

CopilotAI commented May 22, 2026

Copy link
Copy Markdown
Contributor

This splits the storage evolution into the first track only: keep the current document model and JSON-based nested semantics, while allowing SQLite/PostgreSQL repositories to switch root-level fields to real columns. The new mode is opt-in per repository or adapter via rootLevelFieldsWhenAvailable.

  • What changed

    • Added rootLevelFieldsWhenAvailable?: boolean to repository/store config, with adapter-level default support in SQL storage config.
    • Kept the existing non-relational model intact.
    • When projection is enabled, projected root fields are stored in dedicated columns and are no longer duplicated in data.
    • Corrected the flag semantics so this is an exclusive mode switch:
      • false / omitted: reads, writes, and queries use data
      • true: derived root fields are read, written, and queried via dedicated root columns
  • Schema-derived projected columns

    • Derive projected root-level fields from the encoded repository schema.
    • Root scalar fields use typed SQL columns when possible:
      • string
      • number
      • boolean
      • nullable forms of the above
      • encoded date-like fields that serialize to root strings
    • Complex root fields are also projected:
      • nested objects
      • arrays
      • other non-scalar encoded root fields
    • Complex projected fields use JSON / JSONB columns.
  • SQLite / PostgreSQL store behavior

    • On fresh table setup, include projected root columns when the mode is enabled.
    • On writes in projected mode, persist:
      • non-projected fields into data
      • projected root fields into dedicated columns
    • On reads in projected mode, reconstruct projected fields from dedicated columns only.
    • Removed runtime fallback/backfill behavior:
      • no COALESCE(...) fallback from projected columns back to data
      • no on-the-fly backfill of projected columns from existing data
      • no runtime ALTER TABLE / migration behavior for existing rows
    • Existing schema/data migration for switching modes is expected to happen offline.
  • Query planning

    • In projected mode, root-level filters, ordering, and scalar selection resolve to projected columns directly.
    • Nested paths under projected JSON root fields resolve against the projected JSON/JSONB columns directly.
    • Root-level relation-style array queries continue to work when those arrays are projected into JSON/JSONB columns.
    • When the mode is disabled, queries continue to use the data column.
  • Tests

    • Added coverage for:
      • projected-field metadata derivation from schema, including complex root fields
      • SQL generation using projected scalar and projected JSON columns
      • exclusive projected-mode behavior without JSON fallback
      • row parsing from projected columns without falling back to stale JSON payloads
      • omitting projected fields from data

Example:

constrepo=yield*makeRepo("User",User,{config: {rootLevelFieldsWhenAvailable: true}})

With that enabled, root-level fields are stored in dedicated SQL columns when available. Scalars use typed columns where possible, while complex root fields use JSON/JSONB columns. Projected fields are not duplicated into data, and projected-mode reads/writes/queries use the root columns instead of falling back to data.

CopilotAIand others added 4 commits May 22, 2026 18:54
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/f324ecdc-fbb7-4471-9947-241bf85170ff
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
@pkg-pr-new

pkg-pr-newBot commented May 22, 2026

Copy link
Copy Markdown

Open in StackBlitz

@effect-app/cli

npm i https://pkg.pr.new/effect-app/libs/@effect-app/cli@763

effect-app

npm i https://pkg.pr.new/effect-app/libs/effect-app@763

@effect-app/eslint-codegen-model

npm i https://pkg.pr.new/effect-app/libs/@effect-app/eslint-codegen-model@763

@effect-app/eslint-shared-config

npm i https://pkg.pr.new/effect-app/libs/@effect-app/eslint-shared-config@763

@effect-app/infra

npm i https://pkg.pr.new/effect-app/libs/@effect-app/infra@763

@effect-app/vue

npm i https://pkg.pr.new/effect-app/libs/@effect-app/vue@763

@effect-app/vue-components

npm i https://pkg.pr.new/effect-app/libs/@effect-app/vue-components@763

commit: bcaf8e2

@patroza

Copy link
Copy Markdown
Member

@copilot document the plan for next step; relational fields

Agent-Logs-Url: https://github.com/effect-app/libs/sessions/ffdbe97c-c62f-4ae1-8a79-57e8f539221a
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>

CopilotAI commented May 22, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot document the plan for next step; relational fields

Added the Phase 2 relational follow-up plan to the config docs so it’s documented next to rootLevelFieldsWhenAvailable and the repository config surface. Addressed in 24782ef.

CopilotAI requested a review from patrozaMay 22, 2026 19:36
@patroza

Copy link
Copy Markdown
Member

@copilot don't write the separate fields also to data. and support any field type, including complex types, which should simply be json fields, like data is.

CopilotAIand others added 3 commits May 22, 2026 19:45
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/2c26dc3a-b352-4999-b5d5-98349e52640c
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/2c26dc3a-b352-4999-b5d5-98349e52640c
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>

CopilotAI commented May 22, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot don't write the separate fields also to data. and support any field type, including complex types, which should simply be json fields, like data is.

Addressed in 93db22d. Projected root fields are no longer duplicated into data, and root projection now covers any root field type by using JSON/JSONB columns for complex fields while keeping nested filters and root-array relation queries working.

@patroza

Copy link
Copy Markdown
Member

@copilot you misunderstood rootLevelFieldsWhenAvailable setting; the when available is about when database adapters usually use data column, when the setting is enabled you should switch to using root level columns and do migrations when there are schema changes.

you should not support both at the same time, with fallbacks. A migration of data should also happen offline, not on the fly. Queries and writes should either be to data column when setting is omitted/false, and to columns when true

CopilotAIand others added 2 commits May 23, 2026 05:17
Agent-Logs-Url: https://github.com/effect-app/libs/sessions/18e97927-7b93-4bc4-aefc-a0461aa0331e
Co-authored-by: patroza <42661+patroza@users.noreply.github.com>

CopilotAI commented May 23, 2026

Copy link
Copy Markdown
ContributorAuthor

@copilot you misunderstood rootLevelFieldsWhenAvailable setting; the when available is about when database adapters usually use data column, when the setting is enabled you should switch to using root...

Addressed in 34fb23e, with cleanup in 0b3b0b9. rootLevelFieldsWhenAvailable now switches SQL repos into an exclusive root-column mode: projected fields no longer fall back to data, runtime backfill/ALTER behavior was removed, and the docs/tests now reflect that existing schema/data migration is expected offline.

@patroza

Copy link
Copy Markdown
Member

@copilot update to latest main

…plan-relational-database-adoption
# Conflicts:
#	packages/effect-app/src/Model/Repository/internal/internal.ts
#	packages/effect-app/src/Store.ts
#	packages/infra/src/Store/SQL.ts
#	packages/infra/src/Store/SQL/Pg.ts
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@patroza