Skip to content

feat(sdk): tighten Tailor field output types#1640

Merged
toiroakr merged 18 commits into
v2from
perf/tailortots-template-types
Jul 3, 2026
Merged

feat(sdk): tighten Tailor field output types#1640
toiroakr merged 18 commits into
v2from
perf/tailortots-template-types

Conversation

@dqn

@dqn dqn commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Tailor field outputs now infer stricter string shapes for UUID, date, datetime, time, and decimal fields.

Type Output

type DateString = `${number}-${number}-${number}`;
type TimeString = `${number}:${number}`;
type TimeZoneOffsetString = "Z" | "z" | `${"+" | "-"}${TimeString}`;
type DateTimeString =
  `${DateString}${"T" | "t"}${TimeString}:${number}${"" | `.${number}`}${TimeZoneOffsetString}`;
Field Before After
UUID string `${string}-${string}-${string}-${string}-${string}`
date string DateString
datetime string | Date DateTimeString | Date
time string TimeString
decimal string `${number}`

Helper Usage

Scalar helpers are available when a value starts as string or unknown and needs to be narrowed before passing it to a strict scalar API. UUID example:

import {
  assertUUIDString,
  isUUIDString,
  parseUUIDString,
  type UUIDString,
} from "@tailor-platform/sdk";

function useGuard(value: unknown) {
  if (!isUUIDString(value)) return;

  // value is UUIDString here.
  return value;
}

function useAssert(value: unknown) {
  assertUUIDString(value, "customerId");

  // value is UUIDString after the assertion.
  return value;
}

function useParse(value: unknown): UUIDString {
  // Returns the typed value or throws TypeError.
  return parseUUIDString(value, "customerId");
}

The same is*String, assert*String, and parse*String helper families are available for date, datetime, time, and decimal strings.

Type Cost

Metric Before After Delta
Instantiations 141,631 134,536 -7,095 (-5.01%)
Types 49,946 40,333 -9,613 (-19.25%)

Notes

  • Breaking: code that assigns arbitrary string values to inferred UUID, date, datetime, time, or decimal field outputs may need matching string shapes or an explicit widen.
  • Datetime parsing supports these date-time shapes:
    • yyyy-MM-ddTHH:mm:ssZ
    • yyyy-MM-ddTHH:mm:ss+09:00
  • Public scalar helpers now support narrowing input values before passing them to strict scalar APIs: is*String, parse*String, and assert*String variants are available for UUID, date, datetime, time, and decimal strings.
  • Generated Kysely types, migration DB helper types, auth tailor.d.ts attributes/attribute lists, and runtime user IDs now use the same strict scalar aliases.

@changeset-bot

changeset-bot Bot commented Jul 2, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: c9f0b8f

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

This PR includes changesets to release 2 packages
Name Type
@tailor-platform/sdk Major
@tailor-platform/create-sdk Major

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

@pkg-pr-new

pkg-pr-new Bot commented Jul 2, 2026

Copy link
Copy Markdown

Open in StackBlitz

pnpm add https://pkg.pr.new/@tailor-platform/create-sdk@c9f0b8f
pnpm add https://pkg.pr.new/@tailor-platform/sdk@c9f0b8f

commit: c9f0b8f

@github-actions

This comment has been minimized.

@dqn dqn marked this pull request as ready for review July 2, 2026 23:23
@dqn dqn requested a review from a team as a code owner July 2, 2026 23:23
@dqn dqn requested a review from toiroakr July 2, 2026 23:23
@dqn dqn marked this pull request as draft July 2, 2026 23:29
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@dqn dqn marked this pull request as ready for review July 3, 2026 04:29
date: /^\d{4}-\d{2}-\d{2}$/,
datetime:
/^\d{4}-\d{2}-\d{2}[Tt](?<hour>[01]\d|2[0-3]):(?<minute>[0-5]\d):(?<second>[0-5]\d|60)(\.(?<fraction>\d+))?(?<offset>[Zz]|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/,
time: /^(?<hour>\d{2}):(?<minute>\d{2})$/,

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 time regex only checks digit count, so isTimeString("99:99") returns true.

By contrast, the datetime regex above (lines 4-5) validates the actual range with [01]\d|2[0-3] / [0-5]\d, so isDateTimeString("2024-01-01T99:99:00Z") returns false.

Should time be range-restricted the same way?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in f0d5d39.

import type { OptionalKeysOf } from "type-fest";
import type { z } from "zod";

type UUIDString = `${string}-${string}-${string}-${string}-${string}`;

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.

Instead of redefining UUIDString in this file, import it from packages/sdk/src/configure/types/scalar.types.ts.

If the real type is tightened later, this test will keep passing against the stale local definition.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in f0d5d39.

* @param value - Value to check
* @returns True when the value is a UUID string
*/
export function isUUIDString(value: unknown): value is UUIDString {

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.

[nit] The is*/parse*/assert* helpers for UUID/date/datetime/time/decimal (15 functions total) are identical copy-paste apart from the validator and label string.

A generic factory like makeScalarHelpers(isValid, expected) would let a 6th scalar type be added in one place.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in f0d5d39.

// Generate union type from enum values
typeStr = metadata.allowedValues.map((v) => `"${v.value}"`).join(" | ");
}
const typeStr =

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 7-level nested ternary chain maps field type to a TS type string, which is hard to read.

A flat Record<string, string> lookup table would make this easier to scan and extend.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in f0d5d39.

@toiroakr toiroakr assigned dqn and unassigned toiroakr Jul 3, 2026
@dqn dqn requested a review from toiroakr July 3, 2026 08:34
@dqn dqn assigned toiroakr and unassigned dqn Jul 3, 2026
@github-actions

This comment has been minimized.

Resolve conflicts from parallel test refactors on v2: reconcile
test.each table-driven rewrites with this branch's UUIDString/
DateString/Timestamp scalar tightening, restoring date/datetime
edge-case coverage that the v2 shrink pass had dropped.
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown

Code Metrics Report (packages/sdk)

main (00327c6) #1640 (c638904) +/-
Coverage 72.5% 73.7% +1.2%
Code to Test Ratio 1:0.4 1:0.4 +0.0
Details
  |                    | main (00327c6) | #1640 (c638904) |  +/-  |
  |--------------------|----------------|-----------------|-------|
+ | Coverage           |          72.5% |           73.7% | +1.2% |
  |   Files            |            433 |             430 |    -3 |
  |   Lines            |          16411 |           16474 |   +63 |
+ |   Covered          |          11898 |           12151 |  +253 |
+ | Code to Test Ratio |          1:0.4 |           1:0.4 |  +0.0 |
  |   Code             |         108441 |          111763 | +3322 |
+ |   Test             |          47500 |           49237 | +1737 |

Code coverage of files in pull request scope (79.0% → 82.7%)

Details
Files Coverage +/- Status
packages/sdk/example/tailordb/user.ts 0.0% -100.0% affected
packages/sdk/llm-challenge/src/types.ts 0.0% -100.0% affected
packages/sdk/packages/sdk-codemod/src/registry.ts 0.0% -60.0% affected
packages/sdk/src/cli/commands/deploy/test_fixtures/tailor.config.generators-compat.ts 0.0% -100.0% affected
packages/sdk/src/cli/commands/deploy/test_fixtures/tailor.config.plugins-compat.ts 0.0% -100.0% affected
packages/sdk/src/cli/commands/deploy/auth-invoker.ts 0.0% -100.0% affected
packages/sdk/src/cli/commands/deploy/invoker.ts 100.0% +100.0% affected
packages/sdk/src/cli/commands/function/logs.ts 39.7% -4.6% affected
packages/sdk/src/cli/commands/function/test-run.ts 56.8% -3.4% affected
packages/sdk/src/cli/commands/generate/service.ts 58.3% -9.9% affected
packages/sdk/src/cli/commands/login.ts 37.3% -0.6% affected
packages/sdk/src/cli/commands/profile/create.ts 77.2% +72.7% affected
packages/sdk/src/cli/commands/profile/update.ts 92.3% +0.2% affected
packages/sdk/src/cli/commands/secret/delete.ts 5.2% -94.8% affected
packages/sdk/src/cli/commands/setup/generate.ts 92.5% -0.4% affected
packages/sdk/src/cli/commands/tailordb/migrate/db-types-generator.ts 92.3% -4.9% modified
packages/sdk/src/cli/commands/tailordb/migrate/snapshot.ts 80.4% +0.0% affected
packages/sdk/src/cli/commands/user/switch.ts 88.2% +0.7% affected
packages/sdk/src/cli/commands/workflow/start.ts 83.6% +12.5% affected
packages/sdk/src/cli/commands/workspace/create.ts 86.7% +0.2% affected
packages/sdk/src/cli/crashreport/report.ts 88.0% +2.2% affected
packages/sdk/src/cli/index.ts 27.2% -6.1% affected
packages/sdk/src/cli/query/type-field-order.ts 85.7% +85.7% affected
packages/sdk/src/cli/services/application.ts 84.1% +3.3% affected
packages/sdk/src/cli/services/executor/loader.ts 84.6% +1.2% affected
packages/sdk/src/cli/services/workflow/service.ts 83.7% +3.7% affected
packages/sdk/src/cli/shared/auth-namespace.ts 100.0% +100.0% affected
packages/sdk/src/cli/shared/config-loader.ts 74.1% -8.2% affected
packages/sdk/src/cli/shared/context.ts 94.4% +15.5% affected
packages/sdk/src/cli/shared/register-ts-hook.ts 100.0% +100.0% affected
packages/sdk/src/cli/shared/type-generator.ts 91.4% +8.7% modified
packages/sdk/src/cli/ts-hook.mjs 84.4% +84.4% affected
packages/sdk/src/configure/index.ts 100.0% 0.0% modified
packages/sdk/src/configure/services/auth/index.ts 100.0% +25.0% affected
packages/sdk/src/configure/services/executor/trigger/event.ts 80.7% 0.0% modified
packages/sdk/src/configure/services/staticwebsite/index.ts 100.0% +100.0% affected
packages/sdk/src/configure/services/tailordb/schema.ts 86.0% +4.4% modified
packages/sdk/src/configure/services/workflow/job.ts 90.0% +4.2% affected
packages/sdk/src/configure/services/workflow/registry.ts 95.0% +11.1% affected
packages/sdk/src/configure/services/workflow/test-env-key.ts 100.0% +6.6% modified
packages/sdk/src/configure/services/workflow/workflow.ts 66.6% +6.6% affected
packages/sdk/src/configure/types/field-format.ts 100.0% +100.0% added
packages/sdk/src/configure/types/index.ts 0.0% 0.0% modified
packages/sdk/src/configure/types/scalar.ts 100.0% +100.0% added
packages/sdk/src/configure/types/type.ts 100.0% 0.0% modified
packages/sdk/src/kysely/index.ts 33.3% 0.0% modified
packages/sdk/src/parser/service/auth/schema.ts 92.3% +5.1% affected
packages/sdk/src/parser/service/tailordb/builder-helpers.ts 100.0% +100.0% affected
packages/sdk/src/plugin/builtin/kysely-type/index.ts 100.0% 0.0% modified
packages/sdk/src/plugin/builtin/kysely-type/type-processor.ts 86.0% -5.7% modified
packages/sdk/src/plugin/builtin/kysely-type/types.ts 0.0% 0.0% modified
packages/sdk/src/plugin/builtin/seed/index.ts 0.0% -1.6% affected
packages/sdk/src/runtime/context.ts 100.0% 0.0% modified
packages/sdk/src/runtime/idp.ts 100.0% 0.0% modified
packages/sdk/src/vitest/mock.ts 94.9% +1.9% modified
packages/sdk/src/vitest/workflow-local.ts 76.5% +76.5% affected
packages/sdk/src/vitest/workflow-runtime.ts 57.1% +23.8% affected

SDK Configure Bundle Size

main (00327c6) #1640 (c638904) +/-
configure-index-size 20.32KB 21.9KB 1.58KB
dependency-chunks-size 47.12KB 41.06KB -6.06KB
total-bundle-size 67.44KB 62.96KB -4.48KB

Runtime Performance

main (00327c6) #1640 (c638904) +/-
Generate Median 2,987ms 3,010ms 23ms
Generate Max 3,023ms 3,024ms 1ms
Apply Build Median 3,033ms 3,062ms 29ms
Apply Build Max 3,071ms 3,088ms 17ms

Type Performance (instantiations)

main (00327c6) #1640 (c638904) +/-
tailordb-basic 39,489 42,656 3,167
tailordb-optional 4,385 4,537 152
tailordb-relation 5,103 5,220 117
tailordb-validate 742 762 20
tailordb-hooks 5,222 6,349 1,127
tailordb-object 12,510 12,602 92
tailordb-enum 1,450 1,510 60
resolver-basic 9,272 9,247 -25
resolver-nested 26,139 26,114 -25
resolver-array 18,078 18,053 -25
executor-schedule 4,310 4,297 -13
executor-webhook 949 936 -13
executor-record 5,664 5,697 33
executor-resolver 4,108 4,092 -16
executor-operation-function 937 924 -13
executor-operation-gql 945 932 -13
executor-operation-webhook 956 943 -13
executor-operation-workflow 1,789 1,768 -21

Reported by octocov

@toiroakr toiroakr merged commit 67ee736 into v2 Jul 3, 2026
41 checks passed
@toiroakr toiroakr deleted the perf/tailortots-template-types branch July 3, 2026 20:59
@toiroakr

toiroakr commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

LGTM

Sign up for free to 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