Skip to content

fix(core): add byline to generated collection interfaces (Fixes #2888) - #2889

Merged
ascorbic merged 5 commits into
emdash-cms:mainfrom
amasen02:fix/type-generator-byline-2888
Sep 24, 2026
Merged

ascorbic merged 5 commits into
emdash-cms:mainfrom
amasen02:fix/type-generator-byline-2888

Conversation

@amasen02

@amasen02 amasen02 commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Adds byline?: BylineSummary | null; to collection interfaces generated by zod-generator.ts and imports BylineSummary from emdash in generated emdash-env.d.ts declaration files.

At runtime, hydrateEntryBylines in query.ts attaches both entry.data.bylines (ContentBylineCredit[]) and entry.data.byline (BylineSummary | null), but the type generator previously only emitted bylines?. This enables type-safe access to entry.data.byline without requiring manual casts.

Closes #2888

Type of change

  • Bug fix
  • Feature (requires maintainer-approved Discussion)
  • Refactor (no behavior change)
  • Translation
  • Documentation
  • Performance improvement
  • Tests
  • Chore (dependencies, CI, tooling)

Checklist

  • I have read CONTRIBUTING.md
  • pnpm typecheck passes
  • pnpm lint passes
  • pnpm test passes (or targeted tests for my change)
  • pnpm format has been run
  • I have added/updated tests for my changes (if applicable)
  • User-visible strings in the admin UI are wrapped for translation (if applicable). Do not include messages.po changes except in translation PRs — a workflow extracts catalogs on merge to main.
  • I have added and reviewed the user-facing changeset (if this PR changes a published package)
  • New features link to an approved Discussion: https://github.com/emdash-cms/emdash/discussions/...
  • I have included screenshots below if this PR changes the UI

AI-generated code disclosure

  • This PR includes AI-generated code — model/tool: Cortex OSS Patcher Agent

Screenshots / test output

Not applicable (non-UI change). Targeted unit tests in zod-generator.test.ts pass cleanly:

 ✓ tests/unit/schema/zod-generator-datetime.test.ts (10 tests)
 ✓ tests/unit/schema/zod-generator.test.ts (58 tests)

@changeset-bot

changeset-bot Bot commented Sep 3, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: b56f8ee

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 17 packages
Name Type
emdash Patch
@emdash-cms/cloudflare Patch
@emdash-cms/sandbox-workerd Patch
@emdash-cms/fixture-perf-site Patch
@emdash-cms/perf-demo-site Patch
@emdash-cms/cache-demo-site Patch
@emdash-cms/do-demo-site Patch
@emdash-cms/do-solo-demo-site Patch
@emdash-cms/admin Patch
@emdash-cms/auth Patch
@emdash-cms/blocks Patch
create-emdash Patch
@emdash-cms/gutenberg-to-portable-text Patch
@emdash-cms/x402 Patch
@emdash-cms/auth-atproto Patch
@emdash-cms/release-service Patch
@emdash-cms/plugin-embeds Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

github-actions Bot commented Sep 3, 2026 •

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@amasen02

amasen02 commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

I have read the CLA Document and I hereby sign the CLA

github-actions Bot added a commit that referenced this pull request Sep 3, 2026
@amasen02
amasen02 marked this pull request as ready for review September 4, 2026 02:29
@github-actions github-actions Bot added the review/needs-review No maintainer or bot review yet label Sep 4, 2026

@emdashbot emdashbot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The approach is correct: getEmDashCollection / getEmDashEntry already attach entry.data.byline at runtime, so the generated collection interfaces should expose it. The fix is minimal and consistent with the existing bylines? and terms? hydrated fields.

I checked:

  • packages/core/src/query.ts — hydrateEntryBylines sets data.byline = credits[0]?.byline ?? null on both the folded fast-path and the query path.
  • packages/core/src/database/repositories/types.ts and packages/core/src/index.ts — BylineSummary is a real exported type from the emdash package.
  • packages/core/src/schema/zod-generator.ts — the new byline?: BylineSummary | null; line and the added import are correctly emitted for every generated interface.
  • Tests cover the new property and import.
  • The slug byline is already in RESERVED_FIELD_SLUGS, so it cannot collide with user fields.

Headline: code is fine, but the changeset could be more reader-facing, and the committed emdash-env.d.ts files in templates/demos/fixtures are now stale and won't expose the new type until the dev server regenerates them.


Findings

  • [suggestion] .changeset/type-generator-byline-2888.md:5

    The changeset is technically accurate, but it leads with an internal implementation detail ("the type generator") and explains the fix in terms of matching runtime functions. A CHANGELOG entry should lead with the observable surface so readers can tell whether the release affects them.

    Generated `emdash-env.d.ts` files now include `entry.data.byline?: BylineSummary | null` alongside `bylines`, matching the byline data hydrated by `getEmDashEntry` and `getEmDashCollection` at runtime.
    
  • [suggestion] templates/blog/emdash-env.d.ts:6-17

    This committed, generated file (and the matching files in templates/*, demos/*, fixtures/perf-site, e2e/fixture*, etc.) is now stale: it imports ContentBylineCredit but not BylineSummary, and the generated interfaces omit byline?: BylineSummary | null;. Until the dev server regenerates them, users starting from these templates won't see the type-safe byline field that this PR adds. Consider running pnpm dev (or the typegen flow) in each tracked project and committing the regenerated emdash-env.d.ts files.

    Example expected diff for this file:

    import type { BylineSummary, ContentBylineCredit, TaxonomyTerm, PortableTextBlock } from "emdash";
    

    and add byline?: BylineSummary | null; next to each existing bylines?: ContentBylineCredit[]; line.

@github-actions github-actions Bot added review/awaiting-author Reviewed; waiting on the author to respond and removed review/needs-review No maintainer or bot review yet labels Sep 4, 2026
@github-actions github-actions Bot added review/needs-rereview Author pushed changes since the last review area/templates size/M overlap and removed review/awaiting-author Reviewed; waiting on the author to respond size/S labels Sep 5, 2026
@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Overlapping PRs

This PR modifies files that are also changed by other open PRs:

This may cause merge conflicts or duplicated work. A maintainer will coordinate.

@gornostay25

Copy link
Copy Markdown
Contributor

@amasen02 Thanks for picking up #2888 so quickly after I opened it — fix looks solid, and the regenerated template types address exactly what emdashbot flagged in review.

That said, I think the Overlapping PRs bot flag here is a false positive and shouldn't have been a reason to close this PR.

#1099 and #2889 solve completely different problems:

The only overlap is 4 shared emdash-env.d.ts files in starter/portfolio templates:

  • templates/starter/emdash-env.d.ts
  • templates/starter-cloudflare/emdash-env.d.ts
  • templates/portfolio/emdash-env.d.ts
  • templates/portfolio-cloudflare/emdash-env.d.ts

Both PRs touch these because they're auto-generated committed type files — not because the changes are related. #1099 updates them as a side effect of template work; #2889 regenerates them to include the new byline field. The actual diffs in those files are orthogonal (urlPattern/routing vs byline typing).

A merge conflict in generated files is trivial to resolve (regenerate after merge). There's no duplicated work or conflicting intent.

emdashbot already reviewed the code as correct. Would it be possible to reopen this PR? The byline type fix is still needed upstream and the overlap warning doesn't reflect a real dependency on #1099.

@amasen02 amasen02 reopened this Sep 5, 2026
@amasen02

amasen02 commented Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

Reopened! Thanks for the context on #1099 and clarifying that the overlap warning was just on the generated emdash-env.d.ts files. All checks are green and ready whenever you're set to merge.

@emdashbot emdashbot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The approach remains correct: the generated interfaces should expose the byline field because getEmDashCollection/getEmDashEntry already attach it at runtime, and BylineSummary is a real export from the emdash package. The core change in zod-generator.ts is minimal and consistent with the existing bylines?/terms? hydrated fields, and the new test covers the import and property.

The prior review asked for a reader-facing changeset and regenerated emdash-env.d.ts files. The author has addressed both: the changeset now leads with the generated-file surface, and all 23 tracked emdash-env.d.ts files were updated with the BylineSummary import and byline property. Core code and tests look fine.

One regenerated file is malformed, though: templates/blog/emdash-env.d.ts has duplicated byline?: BylineSummary | null; declarations in both the Page and Post interfaces. It needs to be regenerated cleanly or the duplicates removed so the committed file matches the generator output.

Comment thread templates/blog/emdash-env.d.ts Outdated
Comment on lines +17 to +18
byline?: BylineSummary | null;
byline?: BylineSummary | null;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[needs fixing] The Page interface here has two consecutive byline?: BylineSummary | null; declarations, and the Post interface has the same duplicate at lines 33–34. TypeScript will merge identical interface members, but the file header says it is generated by EmDash and should not be edited manually. The zod-generator.ts change emits only one byline line per interface, so this file no longer matches generator output and was clearly patched by hand.

Regenerate the file (e.g. pnpm dev in templates/blog) or remove the duplicate lines so it matches the output of generateTypesFile.

Suggested change
byline?: BylineSummary | null;
byline?: BylineSummary | null;
publishedAt: Date | null;
byline?: BylineSummary | null;
bylines?: ContentBylineCredit[];
terms?: Record<string, TaxonomyTerm[]>;
}

(Apply the same deletion in the Post interface at lines 33–34.)

@amasen02

amasen02 commented Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

Pushed commit \97966fd5\ removing the duplicate \�yline\ property declarations in \ emplates/blog/emdash-env.d.ts\ for both \Page\ and \Post\ interfaces. Verified unit test suite (\packages/core/tests/unit/schema/zod-generator.test.ts) passes 58/58 cleanly.

@amasen02

amasen02 commented Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

@gornostay25 Appreciate the clear breakdown and context! You're completely right — the only overlap is in the regenerated template typing declarations. If #1099 merges first or if anything changes on main, I'm glad to rebase and re-run the generator on top of current main immediately so everything lands cleanly.

@ascorbic ascorbic added the bot:review Trigger an emdashbot code review on this PR label Sep 7, 2026

@emdashbot emdashbot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a sensible, minimal fix: getEmDashCollection/getEmDashEntry already attach entry.data.byline, so the generated emdash-env.d.ts interfaces should expose it. The core change in packages/core/src/schema/zod-generator.ts is limited to adding the byline property and the BylineSummary import, consistent with the existing bylines/terms hydrated fields.

I verified:

  • hydrateEntryBylines in query.ts sets data.byline = credits[0]?.byline ?? null, so the type matches runtime.
  • BylineSummary is exported as a type from packages/core/src/index.ts, so the generated import resolves.
  • The previously malformed templates/blog/emdash-env.d.ts is now clean — no duplicated byline lines.
  • All 23 tracked emdash-env.d.ts files include the BylineSummary import and a single byline?: BylineSummary | null; line per interface.
  • The zod-generator.test.ts additions cover both the generated interface string and the generated file imports.

Remaining notes (non-blocking):

  • The changeset body would be stronger with a present-tense verb lead (the changeset README recommends leading with "Fixes", "Adds", etc.).
  • Several template emdash-env.d.ts files (e.g. templates/marketing, demos/plugins-demo, packages/core/tests/integration/fixture) pre-date the generator's current terms?/TaxonomyTerm output. They are now consistent with their prior state plus byline, but they are not a fully clean regeneration. Worth a follow-up generator pass, though not required for this bug fix.

"emdash": patch
---

Generated `emdash-env.d.ts` files now include `entry.data.byline?: BylineSummary | null` alongside `bylines`, matching the byline data hydrated by `getEmDashEntry` and `getEmDashCollection` at runtime.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[suggestion] The body is technically accurate, but the changeset README asks changesets to lead with a present-tense verb ("Fixes", "Adds", "Updates", etc.) and name the user-facing surface. Starting with "Generated ..." buries the action.

Suggested change
Generated `emdash-env.d.ts` files now include `entry.data.byline?: BylineSummary | null` alongside `bylines`, matching the byline data hydrated by `getEmDashEntry` and `getEmDashCollection` at runtime.
Fixes generated `emdash-env.d.ts` files to include `entry.data.byline?: BylineSummary | null` alongside `bylines`, matching the byline data hydrated by `getEmDashEntry` and `getEmDashCollection` at runtime.

@emdashbot emdashbot Bot removed the bot:review Trigger an emdashbot code review on this PR label Sep 7, 2026

@ascorbic ascorbic left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks

@ascorbic
ascorbic enabled auto-merge (squash) September 7, 2026 14:53
@pkg-pr-new

pkg-pr-new Bot commented Sep 7, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

@emdash-cms/admin

npm i https://pkg.pr.new/@emdash-cms/admin@2889

@emdash-cms/auth

npm i https://pkg.pr.new/@emdash-cms/auth@2889

@emdash-cms/auth-atproto

npm i https://pkg.pr.new/@emdash-cms/auth-atproto@2889

@emdash-cms/blocks

npm i https://pkg.pr.new/@emdash-cms/blocks@2889

@emdash-cms/cloudflare

npm i https://pkg.pr.new/@emdash-cms/cloudflare@2889

@emdash-cms/contentful-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/contentful-to-portable-text@2889

emdash

npm i https://pkg.pr.new/emdash@2889

create-emdash

npm i https://pkg.pr.new/create-emdash@2889

@emdash-cms/gutenberg-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/gutenberg-to-portable-text@2889

@emdash-cms/plugin-cli

npm i https://pkg.pr.new/@emdash-cms/plugin-cli@2889

@emdash-cms/plugin-types

npm i https://pkg.pr.new/@emdash-cms/plugin-types@2889

@emdash-cms/registry-client

npm i https://pkg.pr.new/@emdash-cms/registry-client@2889

@emdash-cms/registry-lexicons

npm i https://pkg.pr.new/@emdash-cms/registry-lexicons@2889

@emdash-cms/registry-moderation

npm i https://pkg.pr.new/@emdash-cms/registry-moderation@2889

@emdash-cms/registry-verification

npm i https://pkg.pr.new/@emdash-cms/registry-verification@2889

@emdash-cms/sandbox-workerd

npm i https://pkg.pr.new/@emdash-cms/sandbox-workerd@2889

@emdash-cms/x402

npm i https://pkg.pr.new/@emdash-cms/x402@2889

@emdash-cms/plugin-ai-moderation

npm i https://pkg.pr.new/@emdash-cms/plugin-ai-moderation@2889

@emdash-cms/plugin-atproto

npm i https://pkg.pr.new/@emdash-cms/plugin-atproto@2889

@emdash-cms/plugin-audit-log

npm i https://pkg.pr.new/@emdash-cms/plugin-audit-log@2889

@emdash-cms/plugin-color

npm i https://pkg.pr.new/@emdash-cms/plugin-color@2889

@emdash-cms/plugin-embeds

npm i https://pkg.pr.new/@emdash-cms/plugin-embeds@2889

@emdash-cms/plugin-field-kit

npm i https://pkg.pr.new/@emdash-cms/plugin-field-kit@2889

@emdash-cms/plugin-forms

npm i https://pkg.pr.new/@emdash-cms/plugin-forms@2889

@emdash-cms/plugin-webhook-notifier

npm i https://pkg.pr.new/@emdash-cms/plugin-webhook-notifier@2889

commit: b56f8ee

@gornostay25

Copy link
Copy Markdown
Contributor

@ascorbic @amasen02 We shoud probably rerun tests

Copilot:

I'll help you find a solution for this failing job. Let me start by retrieving the job logs.Now let me get the test file to understand what the test is doing:## Solution

The test cold-starts from the packed install is failing because the injected route at http://localhost:${platform.port}/_emdash/api/setup/dev-bypass?redirect=/ is not becoming ready within the timeout period.

Root Causes Identified:

  1. Missing binary symlinks during pnpm install - The logs show numerous warnings about failed bin creations:

    [WARN] Failed to create bin at .../node_modules/.bin/emdash
    [WARN] Failed to create bin at .../node_modules/.bin/em
    [WARN] Failed to create bin at .../node_modules/.bin/emdash-plugin
    

    These are trying to create symlinks to files that don't exist yet (e.g., /dist/cli/index.mjs).

  2. Virtual module resolution failure - The actual error in the test output shows:

    [object-cache] backend unavailable: Error: Cannot find package 'virtual:emdash/object-cache'
    

    This indicates that Vite's virtual module resolution is failing during dev server startup.

  3. Build artifacts missing - The warnings suggest that the build outputs (like dist/cli/index.mjs and dist/ directories) haven't been generated in the packed tarball or aren't being built in the isolated environment.

Recommended Fix

The issue is in the packLocalPackages() function and the package preparation. When packing local packages, ensure that build artifacts are included:

In isolated-install.test.ts, modify the prepareStandaloneTemplate function to ensure builds are triggered before copying:

// Add this before packing packages in beforeAll hook:
async function ensurePackagesAreBuilt(packages: WorkspacePackage[]): Promise<void> {
  await Promise.all(
    packages.map(({ dir }) => 
      runPnpm(["run", "build"], dir, 120_000)
    ),
  );
}

// Then in beforeAll, before packLocalPackages:
beforeAll(async () => {
  await ensureBuilt();
  temporaryDirectory = mkdtempSync(join(tmpdir(), "emdash-isolated-install-"));
  const tarballDir = join(temporaryDirectory, "tarballs");
  const storeDir = join(temporaryDirectory, "pnpm-store");
  mkdirSync(tarballDir);
  
  const workspacePackages = localPackageClosure(discoverWorkspacePackages());
  await ensurePackagesAreBuilt(workspacePackages);  // Add this line
  
  const tarballs = await packLocalPackages(workspacePackages, tarballDir);
  // ... rest of the code

Alternative: Verify package.json includes build outputs in files field

Ensure the root package.json and emdash packages have proper files field entries that include all dist directories:

{
  "files": [
    "dist",
    "src",
    "package.json"
  ]
}

The core issue is that the packed tarballs need to include the compiled output (dist files) so that when installed in the isolated environment, the binary references and Vite virtual modules can be properly resolved.

@ascorbic
ascorbic merged commit 86a33ee into emdash-cms:main Sep 24, 2026
80 of 81 checks passed
@emdashbot emdashbot Bot mentioned this pull request Sep 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Type generator omits entry.data.byline while getEmDashEntry/getEmDashCollection hydrate it at runtime

3 participants