Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
725577c
feat: type-safe .riv schema system (POC)
mfazekas Jun 12, 2026
a9d3dd7
chore: fix lint (prettier) and exclude test-d.ts from jest
mfazekas Jun 12, 2026
6c1ecb3
chore: prettier format scripts
mfazekas Jun 15, 2026
6b01840
feat: extract enum values into schema, type enumProperty() and useRiv…
mfazekas Jun 15, 2026
c96e66f
feat: enforce typed property paths via phantom brand on TypedViewMode…
mfazekas Jun 15, 2026
c59be6d
feat: SchemaOf + TypedViewModelOf so typed params accept typeof impor…
mfazekas Jun 15, 2026
f0757b4
chore: use structural __schema inference in useViewModelInstance type…
mfazekas Jun 15, 2026
24658ef
chore: name the untyped overload brand as UntypedViewModelInstance
mfazekas Jun 15, 2026
59bd3b8
chore: add type tests for useRiveNumber hook
mfazekas Jun 15, 2026
c5b1842
chore: validate .riv schema files are up-to-date in CI
mfazekas Jun 15, 2026
6cc69ac
fix: restore number overload on fromSource to preserve backward compat
mfazekas Jun 15, 2026
a6263eb
fix: use spawnSync argv array instead of execSync shell string
mfazekas Jun 15, 2026
58d8952
fix: error on URL input without --out instead of producing an invalid…
mfazekas Jun 15, 2026
ae9c82c
chore: regenerate .riv.d.ts files with quoted property keys
mfazekas Jun 15, 2026
a41ed53
fix: exclude .riv.d.ts from lint, fix generator quoting to match pret…
mfazekas Jun 15, 2026
4ce9d18
chore: improve extractor error diagnostics
mfazekas Jun 15, 2026
7de7cc2
fix: wrap long throw to satisfy prettier
mfazekas Jun 15, 2026
cafa53e
fix: handle null makeRenderImage on headless Linux, catch microtask e…
mfazekas Jun 15, 2026
877cb53
fix: proxy stub for makeRenderImage when WebGL unavailable on headles…
mfazekas Jun 15, 2026
907aeed
fix: use CustomFileAssetLoader to skip embedded assets, avoids WebGL …
mfazekas Jun 15, 2026
9a7b938
fix(scripts): handle embedded images on headless Linux in rive-extrac…
mfazekas Jun 15, 2026
f26259b
fix(scripts): run WASM inline in rive-gen-types, drop spawnSync subpr…
mfazekas Jun 15, 2026
f3f1db6
chore: fix prettier formatting in rive-gen-types.ts
mfazekas Jun 15, 2026
3898d88
chore: remove unused __dirname from rive-gen-types.ts
mfazekas Jun 15, 2026
7372d17
fix: align typed useViewModelInstance overload with isLoading result …
mfazekas Jul 14, 2026
ac62564
chore: generate schema for arbtboards-models-instances.riv
mfazekas Jul 14, 2026
3f630dd
fix(tests): expect unquoted identifier keys in generated schema
mfazekas Jul 14, 2026
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
3 changes: 3 additions & 0 deletions .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ runs:
with:
node-version-file: .nvmrc

- name: Setup Bun
uses: oven-sh/setup-bun@v2

- name: Restore dependencies
id: yarn-cache
uses: actions/cache/restore@v4
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ jobs:
exit 1
fi

- name: Validate .riv schema files
run: |
yarn rive-gen-types --all example/assets/rive
if ! git diff --exit-code 'example/assets/rive/*.riv.d.ts'; then
echo "Error: .riv.d.ts files are out of date. Please run 'yarn rive-gen-types --all example/assets/rive' and commit the changes."
exit 1
fi

- name: Typecheck files
run: yarn typecheck

Expand Down
1 change: 1 addition & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export default defineConfig([
// tsd owns *.test-d.ts (yarn typetest) — deprecated calls there are
// intentional expectDeprecated() pins, not violations.
'**/*.test-d.ts',
'**/*.riv.d.ts',
// Agent worktrees (.claude/worktrees/*) are gitignored full-repo copies;
// linting them duplicates every finding and slows the run.
'**/.claude/',
Expand Down
Binary file added example/assets/rive/GradientBorder.riv
Binary file not shown.
17 changes: 17 additions & 0 deletions example/assets/rive/GradientBorder.riv.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Generated by rive-gen-types — do not edit manually. @generated
// eslint-disable
// Source: GradientBorder.riv
import type { RiveAsset } from '@rive-app/react-native';
declare const asset: RiveAsset<{
artboards: 'Layout';
defaultArtboard: 'Layout';
stateMachines: {
Layout: 'State';
};
viewModels: {
ViewModel: {
isFocused: 'boolean';
};
};
}>;
export default asset;
26 changes: 26 additions & 0 deletions example/assets/rive/arbtboards-models-instances.riv.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Generated by rive-gen-types — do not edit manually. @generated
// eslint-disable
// Source: arbtboards-models-instances.riv
import type { RiveAsset } from '@rive-app/react-native';
declare const asset: RiveAsset<{
artboards: 'artboard1' | 'artboard3' | 'artboard2' | 'artboardc1';
defaultArtboard: 'artboard1';
stateMachines: {
artboard1: 'sm13' | 'sm12' | 'sm11';
artboard3: 'sm33' | 'sm32' | 'sm31';
artboard2: 'sm23' | 'sm22' | 'sm21';
artboardc1: 'State Machine 1';
};
viewModels: {
viewmodel1: {
_id: 'string';
};
viewmodel2: {
_id: 'string';
};
viewmodel3: {
_id: 'string';
};
};
}>;
export default asset;
21 changes: 21 additions & 0 deletions example/assets/rive/artboard_db_test.riv.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Generated by rive-gen-types — do not edit manually. @generated
// eslint-disable
// Source: artboard_db_test.riv
import type { RiveAsset } from '@rive-app/react-native';
declare const asset: RiveAsset<{
artboards: 'Main' | 'ArtboardGreen' | 'ArtboardBlue' | 'ArtboardRed';
defaultArtboard: 'Main';
stateMachines: {
Main: 'State Machine 1';
ArtboardGreen: 'State Machine 1';
ArtboardBlue: 'State Machine 1';
ArtboardRed: 'State Machine 1';
};
viewModels: {
MainViewModel: {
artboard_1: 'artboard';
artboard_2: 'artboard';
};
};
}>;
export default asset;
97 changes: 97 additions & 0 deletions example/assets/rive/blinko.riv.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// Generated by rive-gen-types — do not edit manually. @generated
// eslint-disable
// Source: blinko.riv
import type { RiveAsset } from '@rive-app/react-native';
declare const asset: RiveAsset<{
artboards: 'Main' | 'StoreItem' | 'Token' | 'Indicator' | 'Puck' | 'StoreIcon' | 'Peg' | 'scoreBox';
defaultArtboard: 'Main';
stateMachines: {
Main: 'State Machine 1';
StoreItem: 'State Machine 1';
Token: 'State Machine 1';
Indicator: 'State Machine 1';
Puck: 'State Machine 1';
StoreIcon: 'State Machine 1';
Peg: 'State Machine 1';
scoreBox: 'State Machine 1';
};
viewModels: {
IndicatorVM: {
purchased: 'boolean';
};
StoreItemVM: {
tokenCount: 'number';
height: 'number';
itemHover: 'boolean';
cost: 'number';
description: 'string';
id: 'string';
itemType: 'string';
maxPurchases: 'number';
name: 'string';
purchase: 'trigger';
purchaseCount: 'number';
};
storeIconVM: {
storeiconClick: 'trigger';
iconHovered: 'boolean';
};
storeVM: {
'xbuttonClick': 'trigger';
'xbuttonHover': 'boolean';
'items': 'list';
'storeOpen': 'boolean';
'property of pegVM': 'viewModel:pegVM';
'multiplierValue': 'number';
'extraTokenSlotActive': 'boolean';
'extraTokenSlotCost': 'number';
'extraTokenSlotCount': 'number';
'purchaseExtraTokenSlot': 'trigger';
'purchaseSuperMultiplier': 'trigger';
'superMultiplierActive': 'boolean';
'superMultiplierCost': 'number';
'superMultiplierCount': 'number';
};
TokenVM: {
spinToken: 'boolean';
};
pegVM: {
blink: 'trigger';
multiplierValue: 'number';
pegType: 'enum:normal|multiplier';
pegBounced: 'trigger';
};
gameLogicVM: {
turnTokens: 'number';
turnScore: 'number';
buttonLabel: 'string';
message: 'string';
startTurn: 'trigger';
turnEnded: 'trigger';
gameEnded: 'boolean';
tokenCount: 'number';
scoreTotal: 'number';
};
scoreBox: {
Token: 'viewModel:TokenVM';
slotType: 'enum:addToken|normal';
landed: 'trigger';
scoreValue: 'number';
};
PuckVM: {
puckBounce: 'trigger';
puckRotation: 'number';
};
main: {
'PuckVM': 'viewModel:PuckVM';
'storeItemVM': 'viewModel:StoreItemVM';
'storeIconVM': 'viewModel:storeIconVM';
'pegVM': 'viewModel:pegVM';
'storeVM': 'viewModel:storeVM';
'buttonHover': 'boolean';
'tokenVM': 'viewModel:TokenVM';
'property of gameLogicVM': 'viewModel:gameLogicVM';
};
};
}>;
export default asset;
17 changes: 17 additions & 0 deletions example/assets/rive/bouncing_ball.riv.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Generated by rive-gen-types — do not edit manually. @generated
// eslint-disable
// Source: bouncing_ball.riv
import type { RiveAsset } from '@rive-app/react-native';
declare const asset: RiveAsset<{
artboards: 'Artboard';
defaultArtboard: 'Artboard';
stateMachines: {
Artboard: 'State Machine 1';
};
viewModels: {
vm: {
ypos: 'number';
};
};
}>;
export default asset;
17 changes: 17 additions & 0 deletions example/assets/rive/counter.riv.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Generated by rive-gen-types — do not edit manually. @generated
// eslint-disable
// Source: counter.riv
import type { RiveAsset } from '@rive-app/react-native';
declare const asset: RiveAsset<{
artboards: 'Artboard';
defaultArtboard: 'Artboard';
stateMachines: {
Artboard: 'State Machine 1';
};
viewModels: {
ViewModel1: {
cnt: 'number';
};
};
}>;
export default asset;
28 changes: 28 additions & 0 deletions example/assets/rive/databinding.riv.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Generated by rive-gen-types — do not edit manually. @generated
// eslint-disable
// Source: databinding.riv
import type { RiveAsset } from '@rive-app/react-native';
declare const asset: RiveAsset<{
artboards: 'Artboard';
defaultArtboard: 'Artboard';
stateMachines: {
Artboard: 'State Machine 1';
};
viewModels: {
Person: {
pet: 'viewModel:Pet';
jump: 'trigger';
likes_popcorn: 'boolean';
favourite_pet: 'enum:chipmunk|rat|frog|owl|cat|dog';
favourite_color: 'color';
age: 'number';
website: 'string';
name: 'string';
};
Pet: {
type: 'enum:chipmunk|rat|frog|owl|cat|dog';
name: 'string';
};
};
}>;
export default asset;
17 changes: 17 additions & 0 deletions example/assets/rive/databinding_images.riv.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Generated by rive-gen-types — do not edit manually. @generated
// eslint-disable
// Source: databinding_images.riv
import type { RiveAsset } from '@rive-app/react-native';
declare const asset: RiveAsset<{
artboards: 'Artboard';
defaultArtboard: 'Artboard';
stateMachines: {
Artboard: 'State Machine 1';
};
viewModels: {
MyViewModel: {
bound_image: 'image';
};
};
}>;
export default asset;
20 changes: 20 additions & 0 deletions example/assets/rive/databinding_lists.riv.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Generated by rive-gen-types — do not edit manually. @generated
// eslint-disable
// Source: databinding_lists.riv
import type { RiveAsset } from '@rive-app/react-native';
declare const asset: RiveAsset<{
artboards: 'Artboard';
defaultArtboard: 'Artboard';
stateMachines: {
Artboard: 'State Machine 1';
};
viewModels: {
Person: {
name: 'string';
};
DevRel: {
team: 'list';
};
};
}>;
export default asset;
12 changes: 12 additions & 0 deletions example/assets/rive/fallback_fonts.riv.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Generated by rive-gen-types — do not edit manually. @generated
// eslint-disable
// Source: fallback_fonts.riv
import type { RiveAsset } from '@rive-app/react-native';
declare const asset: RiveAsset<{
artboards: 'Artboard';
defaultArtboard: 'Artboard';
stateMachines: {
Artboard: 'State Machine 1';
};
}>;
export default asset;
17 changes: 17 additions & 0 deletions example/assets/rive/font_fallback.riv.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Generated by rive-gen-types — do not edit manually. @generated
// eslint-disable
// Source: font_fallback.riv
import type { RiveAsset } from '@rive-app/react-native';
declare const asset: RiveAsset<{
artboards: 'Artboard';
defaultArtboard: 'Artboard';
stateMachines: {
Artboard: 'State Machine 1';
};
viewModels: {
ViewModel: {
text: 'string';
};
};
}>;
export default asset;
12 changes: 12 additions & 0 deletions example/assets/rive/hello_world_text.riv.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Generated by rive-gen-types — do not edit manually. @generated
// eslint-disable
// Source: hello_world_text.riv
import type { RiveAsset } from '@rive-app/react-native';
declare const asset: RiveAsset<{
artboards: 'New Artboard';
defaultArtboard: 'New Artboard';
stateMachines: {
'New Artboard': 'State Machine 1';
};
}>;
export default asset;
Binary file added example/assets/rive/inputglow.riv
Binary file not shown.
17 changes: 17 additions & 0 deletions example/assets/rive/inputglow.riv.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Generated by rive-gen-types — do not edit manually. @generated
// eslint-disable
// Source: inputglow.riv
import type { RiveAsset } from '@rive-app/react-native';
declare const asset: RiveAsset<{
artboards: 'Layout';
defaultArtboard: 'Layout';
stateMachines: {
Layout: 'State';
};
viewModels: {
ViewModel: {
isFocused: 'boolean';
};
};
}>;
export default asset;
12 changes: 12 additions & 0 deletions example/assets/rive/ios_android_layouts_demo_v01.riv.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Generated by rive-gen-types — do not edit manually. @generated
// eslint-disable
// Source: ios_android_layouts_demo_v01.riv
import type { RiveAsset } from '@rive-app/react-native';
declare const asset: RiveAsset<{
artboards: 'iOS_Android_Layouts_demo_v01';
defaultArtboard: 'iOS_Android_Layouts_demo_v01';
stateMachines: {
iOS_Android_Layouts_demo_v01: 'State Machine 1';
};
}>;
export default asset;
Binary file added example/assets/rive/layout_test.riv
Binary file not shown.
17 changes: 17 additions & 0 deletions example/assets/rive/layout_test.riv.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Generated by rive-gen-types — do not edit manually. @generated
// eslint-disable
// Source: layout_test.riv
import type { RiveAsset } from '@rive-app/react-native';
declare const asset: RiveAsset<{
artboards: 'Artboard';
defaultArtboard: 'Artboard';
stateMachines: {
Artboard: 'State Machine 1';
};
viewModels: {
ViewModel1: {

};
};
}>;
export default asset;
Loading
Loading