Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .changeset/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [["@izod/core", "@izod/react"]],
"linked": [],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
}
78 changes: 78 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

permissions:
contents: read
pull-requests: write

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- uses: pnpm/action-setup@5d445ecbfcb90fdf1556a629d018c79e97ff973b # v6.0.6

- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24.15.0
cache: pnpm

- run: pnpm install --frozen-lockfile

- run: pnpm run lint
- run: pnpm run format:check
- run: pnpm run typecheck
- run: pnpm run test
- run: pnpm run test:coverage
- run: pnpm run build

- name: Post coverage comment
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
COMMENT_MARKER="<!-- izod-coverage -->"
BODY="$COMMENT_MARKER
## Coverage Report

| Package | Statements | Branches | Functions | Lines |
|---------|-----------|----------|-----------|-------|"

for pkg in packages/core packages/react; do
SUMMARY="$pkg/coverage/coverage-summary.json"
if [ ! -f "$SUMMARY" ]; then
continue
fi

NAME=$(jq -r '.total | "\(.statements.pct)% | \(.branches.pct)% | \(.functions.pct)% | \(.lines.pct)%"' "$SUMMARY")
PKG_NAME=$(jq -r '.name' "$pkg/package.json")
BODY="$BODY
| \`$PKG_NAME\` | $NAME |"
done

BODY="$BODY

*Updated by CI — $(date -u '+%Y-%m-%d %H:%M UTC')*"

EXISTING=$(gh api "repos/${{ github.repository }}/issues/${PR_NUMBER}/comments" \
--jq ".[] | select(.body | startswith(\"$COMMENT_MARKER\")) | .id" \
| head -1)

if [ -n "$EXISTING" ]; then
gh api "repos/${{ github.repository }}/issues/comments/${EXISTING}" \
-X PATCH -f body="$BODY"
else
gh api "repos/${{ github.repository }}/issues/${PR_NUMBER}/comments" \
-X POST -f body="$BODY"
fi
50 changes: 50 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Deploy Demo to GitHub Pages

on:
push:
branches: [main]
workflow_dispatch:

permissions:
contents: read
pages: write
id-token: write

concurrency:
group: pages
cancel-in-progress: false

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- uses: pnpm/action-setup@5d445ecbfcb90fdf1556a629d018c79e97ff973b # v6.0.6

- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24.15.0
cache: pnpm

- run: pnpm install --frozen-lockfile
- run: pnpm run build

- name: Build Astro demo
working-directory: examples/astro-demo
run: pnpm run build

- uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0
with:
path: examples/astro-demo/dist

deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0
36 changes: 36 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Release

on:
push:
branches: [main]

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}

permissions:
contents: write
pull-requests: write
id-token: write

jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- uses: pnpm/action-setup@5d445ecbfcb90fdf1556a629d018c79e97ff973b # v6.0.6

- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24.15.0
registry-url: 'https://registry.npmjs.org'

- run: pnpm install --frozen-lockfile

- uses: changesets/action@d94a5c301145045a0960133674e003b265942a22 # v1.8.0
with:
publish: pnpm run release
version: pnpm run version
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_CONFIG_PROVENANCE: true
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ dist
dist-ssr
*.local

# Coverage
coverage

# Turbo
.turbo

# Editor directories and files
.vscode/*
!.vscode/extensions.json
Expand Down
1 change: 1 addition & 0 deletions .husky/commit-msg
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pnpm exec commitlint --edit "$1"
3 changes: 3 additions & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pnpm run lint
pnpm run format:check
pnpm run test
1 change: 1 addition & 0 deletions .node-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
24.15.0
2 changes: 2 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
save-exact=true
ignore-scripts=true
4 changes: 4 additions & 0 deletions .oxfmtrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"$schema": "./node_modules/oxfmt/configuration_schema.json",
"singleQuote": true
}
11 changes: 11 additions & 0 deletions .oxlintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"plugins": ["typescript", "react", "unicorn", "oxc"],
"categories": {
"correctness": "error"
},
"rules": {},
"env": {
"builtin": true
}
}
3 changes: 0 additions & 3 deletions .prettierrc

This file was deleted.

68 changes: 68 additions & 0 deletions .zed/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
{
"file_scan_exclusions": ["**/*.gen.ts"],
"lsp": {
"oxlint": {
"initialization_options": {
"settings": {
"configPath": ".oxlintrc.json",
"run": "onType"
}
}
},
"oxfmt": {
"initialization_options": {
"settings": {
"run": "onSave",
"configPath": ".oxfmtrc.json"
}
}
}
},
"languages": {
"TypeScript": {
"format_on_save": "on",
"prettier": { "allowed": false },
"formatter": [{ "language_server": { "name": "oxfmt" } }]
},
"TSX": {
"format_on_save": "on",
"prettier": { "allowed": false },
"formatter": [{ "language_server": { "name": "oxfmt" } }]
},
"JavaScript": {
"format_on_save": "on",
"prettier": { "allowed": false },
"formatter": [{ "language_server": { "name": "oxfmt" } }]
},
"JSON": {
"format_on_save": "on",
"prettier": { "allowed": false },
"formatter": [{ "language_server": { "name": "oxfmt" } }]
},
"JSONC": {
"format_on_save": "on",
"prettier": { "allowed": false },
"formatter": [{ "language_server": { "name": "oxfmt" } }]
},
"HTML": {
"format_on_save": "on",
"prettier": { "allowed": false },
"formatter": [{ "language_server": { "name": "oxfmt" } }]
},
"CSS": {
"format_on_save": "on",
"prettier": { "allowed": false },
"formatter": [{ "language_server": { "name": "oxfmt" } }]
},
"YAML": {
"format_on_save": "on",
"prettier": { "allowed": false },
"formatter": [{ "language_server": { "name": "oxfmt" } }]
},
"Markdown": {
"format_on_save": "on",
"prettier": { "allowed": false },
"formatter": [{ "language_server": { "name": "oxfmt" } }]
}
}
}
52 changes: 52 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# izod

Type-safe iframe communication using the Standard Schema interface for runtime validation.

## Commands

- `pnpm run build` — build all packages with tsdown (via turbo)
- `pnpm run test` — run tests with vitest (via turbo)
- `pnpm run test:coverage` — run tests with coverage
- `pnpm run typecheck` — type-check with tsc (via turbo)
- `pnpm run lint` — oxlint across the repo
- `pnpm run format` — oxfmt across the repo
- `pnpm run format:check` — check formatting

## Conventions

- TypeScript strict mode, target ES2022
- No single-character variable names — use descriptive names
- No nested ternaries
- Conventional Commits enforced via commitlint
- Exact pinned dependency versions (no `~`/`^`), managed via pnpm catalog
- oxlint for linting, oxfmt for formatting (no eslint/prettier)
- Vitest for testing with happy-dom environment
- Turborepo for monorepo orchestration

## Architecture

- `packages/core/` — `@izod/core`: iframe communication engine (no React dependency)
- `createChild()` — parent-side iframe creation and handshake
- `connectToParent()` — child-side connection to parent window
- Uses Standard Schema interface for event data validation
- `packages/react/` — `@izod/react`: React hooks wrapper around core
- `child.useCreate()` — hook for parent component to create child iframe
- `parent.useConnect()` — hook for child component to connect to parent
- `examples/` — TanStack Start demo app (workspace package, not published)
- All event schemas accept any Standard Schema compliant validator (zod 3.24+, valibot, arktype, etc.)
- React is a peer dependency of `@izod/react` only

## Supply Chain Config — Do Not Modify Without Approval

This repo enforces strict install-time supply chain defenses:

- Exact pinned versions (no `~`/`^`).
- `minimumReleaseAge` of 7 days (pnpm: minutes).
- Install/lifecycle scripts disabled by default; only packages in
`onlyBuiltDependencies` (in `pnpm-workspace.yaml`) may run them.
- `blockExoticSubdeps: true`, `trustPolicy: no-downgrade` (in `pnpm-workspace.yaml`).

**Never disable, loosen, or bypass these settings** — including adding packages
to the script allow-list, shortening `minimumReleaseAge`, or setting
`dangerouslyAllowAllBuilds` — without explicit confirmation from the user in
the current conversation. A prior approval does not carry over.
1 change: 1 addition & 0 deletions CLAUDE.md
Loading