Commit bdfdf5fc by PLN (Algolia)

feat(presence): typed online-presence SSOT (profiles + per-release links)

The site hardcodes platform URLs across 7+ components; this consolidates them into
one typed source. models.py: Platform/LinkKind/ReleaseKind enums + PresenceLink,
ReleaseTrack, Release, Presence. presence.authored.yaml = verified inventory (6
profiles, 4 releases, 18 links) with provenance; build_presence.py validates →
presence.json and stamps default file-provenance. Wired into tide.py build +
generated TS (Presence interface) so the site can later consume it — one-directional,
opt-in (site keeps owning editorial gig content). Per-track links modelled as a
capability, populated only where a real direct URL exists. 61 tests green.
parent 9f15bee8
#!/usr/bin/env python3
"""build_presence — authored presence overlay → validated presence.json.
Reads presence.authored.yaml (the hand-maintained distribution SSOT: artist
profiles + per-release platform links), stamps a DEFAULT provenance on any link
that omits its own (source=file — these were consolidated from the site's hardcoded
components), validates the whole thing against models.Presence, and writes
presence.json. The site can consume that JSON to retire its duplicated link tables;
catalog/eda surfaces can join releases to tracks (.tidal id) and gigs (site slug).
python3 build_presence.py # → presence.json
"""
import json
from datetime import date
from pathlib import Path
import yaml
import models as M
HERE = Path(__file__).resolve().parent
SRC = HERE / "presence.authored.yaml"
OUT = HERE / "presence.json"
# where the links were consolidated FROM — the default provenance locator
SITE_COMPONENTS = "Web/www/next/components/parvagues/{MusicSection,AlbumCarousel,Layout,ParVaguesFooter}.js"
def build():
raw = yaml.safe_load(SRC.read_text())
as_of = raw.get("as_of") or date.today().isoformat()
default_prov = M.Provenance(source=M.Source.file, locator=SITE_COMPONENTS,
as_of=date.fromisoformat(as_of),
note="consolidated from the site's hardcoded link tables")
def stamp(link: dict) -> dict:
link.setdefault("prov", default_prov.model_dump(mode="json"))
return link
raw["profiles"] = [stamp(p) for p in raw.get("profiles", [])]
for rel in raw.get("releases", []):
rel["links"] = [stamp(x) for x in rel.get("links", [])]
for t in rel.get("tracks", []):
t["links"] = [stamp(x) for x in t.get("links", [])]
return M.Presence.model_validate(raw) # raises on any bad shape
def main():
p = build()
OUT.write_text(p.model_dump_json(indent=1, by_alias=True))
nlinks = len(p.profiles) + sum(len(r.links) + sum(len(t.links) for t in r.tracks)
for r in p.releases)
plats = sorted({l.platform.value for l in p.profiles})
print(f"✓ {OUT.name}: {len(p.profiles)} profiles ({', '.join(plats)}), "
f"{len(p.releases)} releases, {nlinks} links total")
if __name__ == "__main__":
main()
...@@ -618,3 +618,81 @@ class DesignTokens(BaseModel): ...@@ -618,3 +618,81 @@ class DesignTokens(BaseModel):
lifecycle: list[OntologyTerm] = Field(default_factory=list) lifecycle: list[OntologyTerm] = Field(default_factory=list)
agree: list[OntologyTerm] = Field(default_factory=list) agree: list[OntologyTerm] = Field(default_factory=list)
sample: list[TokenFamily] = Field(default_factory=list) sample: list[TokenFamily] = Field(default_factory=list)
# ── online presence / distribution (the "where to hear it" SSOT) ──────────────
# Today the site hardcodes these across 7+ components (footer, MusicSection,
# AlbumCarousel, AsSeenAt, Layout, SocialCTA, StreamingFeeds). This is the single
# typed source: artist-level profiles + per-release links, joinable to the catalog
# (track id = .tidal path) and gigs (site slug). The site can later consume the
# generated presence.json to retire the duplication — but it CHOOSES when (we keep
# the data flow one-directional and optional). Per-track links are modelled as a
# capability and populated only where a real direct URL exists (Bandcamp track
# pages, YouTube videos) — never fabricated. Every link carries provenance
# (feedback_metadata_provenance); build_presence stamps a default where omitted.
class Platform(str, Enum):
bandcamp = "bandcamp"
spotify = "spotify"
soundcloud = "soundcloud"
youtube = "youtube"
deezer = "deezer"
apple_music = "apple_music"
instagram = "instagram"
class LinkKind(str, Enum):
profile = "profile" # artist-level identity page
release = "release" # album / EP / single landing
track = "track" # a single track's direct page
playlist = "playlist" # a curated/auto playlist
video = "video" # a specific video
embed = "embed" # a player-embed URL (iframe src)
class ReleaseKind(str, Enum):
album = "album"
ep = "ep"
single = "single"
live = "live" # a live-set release (joins a gig slug)
class PresenceLink(BaseModel):
"""One URL on one platform, with provenance. The atom of the presence graph."""
platform: Platform
url: str
kind: LinkKind = LinkKind.profile
label: str = "" # display label ("Spotify", "Live @ CosmicFest")
ext_id: str = "" # platform-native id (spotify album id, sc user id)
embed_url: str = "" # optional iframe/player-embed variant
prov: Optional[Provenance] = None
class ReleaseTrack(BaseModel):
"""A track as it appears on a release, with any per-platform DIRECT links.
`track` is the canonical catalog id (.tidal path) when known — the join key."""
title: str
track: Optional[str] = None # canonical catalog id (.tidal path)
position: Optional[int] = None
links: list[PresenceLink] = Field(default_factory=list)
class Release(BaseModel):
"""An album/EP/single/live release and its per-platform links."""
slug: str # stable id (matches the bandcamp slug where one exists)
title: str
kind: ReleaseKind = ReleaseKind.album
gig: Optional[str] = None # site gig slug if this is a live-set release
year: Optional[int] = None
links: list[PresenceLink] = Field(default_factory=list) # release-level
tracks: list[ReleaseTrack] = Field(default_factory=list)
class Presence(BaseModel):
"""The whole distribution truth: artist profiles + releases. Generated artifact
presence.json (built from presence.authored.yaml, validated on emit)."""
model_config = ConfigDict(populate_by_name=True)
schema_: str = Field("parvagues online presence", alias="schema")
artist: str = "ParVagues"
as_of: str
profiles: list[PresenceLink] = Field(default_factory=list) # artist-level identities
releases: list[Release] = Field(default_factory=list)
# tide-table · AUTHORED online-presence overlay — ParVagues' distribution SSOT.
#
# The single typed source for "where to hear ParVagues": artist-level profiles +
# per-release platform links. Today these live HARDCODED across 7+ site components
# (next/components/parvagues/{Layout,ParVaguesFooter,MusicSection,AlbumCarousel,
# AsSeenAt,SocialCTA,StreamingFeeds}.js) — this file consolidates them so the site
# can later consume the generated presence.json instead of duplicating URLs.
#
# `build_presence.py` validates this against models.Presence → presence.json and
# stamps a default provenance (source=file, the site components, as_of) on any link
# that omits its own `prov`. Add per-track `links` only where a REAL direct URL
# exists (bandcamp track page, youtube video) — never fabricate.
#
# Join keys: release.gig = site gig slug (content/lives/.../<slug>.md);
# track.track = canonical catalog id (the .tidal path).
as_of: "2026-06-07"
artist: ParVagues
# ── artist-level identities (the footer/contact set) ─────────────────────────
profiles:
- { platform: bandcamp, url: "https://parvagues.bandcamp.com/", label: Bandcamp }
- { platform: spotify, url: "https://open.spotify.com/artist/0kznTQnx5QRhMwktmZboX4", label: Spotify, ext_id: "0kznTQnx5QRhMwktmZboX4" }
- { platform: soundcloud, url: "https://soundcloud.com/parvagues", label: SoundCloud, ext_id: "788076298" }
- { platform: youtube, url: "https://www.youtube.com/@parvagues", label: YouTube }
- { platform: deezer, url: "https://www.deezer.com/fr/artist/103670512", label: Deezer, ext_id: "103670512" }
- { platform: instagram, url: "https://www.instagram.com/parvagues.mp3/", label: Instagram }
# ── releases (per-platform links; ext_id = platform-native album id) ─────────
releases:
- slug: livecoding-opal-festival-2024
title: "Livecoding (Opal Festival 2024)"
kind: live
gig: opal-festival-2024
year: 2024
links:
- { platform: bandcamp, kind: release, url: "https://parvagues.bandcamp.com/album/livecoding-opal-festival-2024" }
- { platform: spotify, kind: release, url: "https://open.spotify.com/album/1VKLZWeolFNfES2bWzYCWZ", ext_id: "1VKLZWeolFNfES2bWzYCWZ" }
- { platform: deezer, kind: release, url: "https://www.deezer.com/fr/album/632734951", ext_id: "632734951" }
- { platform: apple_music, kind: release, url: "https://music.apple.com/fr/album/livecoding-opal-festival-2024/1773790990", ext_id: "1773790990" }
- { platform: youtube, kind: playlist, url: "https://www.youtube.com/playlist?list=OLAK5uy_l4MF3OCIXcdPMpsHGVX2Q9MiX6oU1zT6g", ext_id: "OLAK5uy_l4MF3OCIXcdPMpsHGVX2Q9MiX6oU1zT6g" }
- slug: connexion-tablie
title: "Connexion Établie EP"
kind: ep
year: 2023
links:
- { platform: bandcamp, kind: release, url: "https://parvagues.bandcamp.com/album/connexion-tablie" }
- { platform: spotify, kind: release, url: "https://open.spotify.com/album/4uzSN6Uv9IwcYeHdRtkUmM", ext_id: "4uzSN6Uv9IwcYeHdRtkUmM" }
- { platform: deezer, kind: release, url: "https://www.deezer.com/fr/album/505854371", ext_id: "505854371" }
- { platform: apple_music, kind: release, url: "https://music.apple.com/fr/album/_/1711226283", ext_id: "1711226283" }
- { platform: youtube, kind: video, url: "https://www.youtube.com/watch?v=VODSdQKrzyw&list=OLAK5uy_nzlx3b7YJYzrbagXF5swhENsCg5vJkT_Q", ext_id: "VODSdQKrzyw" }
- slug: live-cosmicfest
title: "Live @ CosmicFest v0"
kind: live
gig: cosmicfest
year: 2025
links:
- { platform: bandcamp, kind: release, url: "https://parvagues.bandcamp.com/album/live-cosmicfest" }
- slug: ton-num-ro
title: "Ton Numéro"
kind: single
links:
- { platform: bandcamp, kind: track, url: "https://parvagues.bandcamp.com/track/ton-num-ro" }
{
"schema": "parvagues online presence",
"artist": "ParVagues",
"as_of": "2026-06-07",
"profiles": [
{
"platform": "bandcamp",
"url": "https://parvagues.bandcamp.com/",
"kind": "profile",
"label": "Bandcamp",
"ext_id": "",
"embed_url": "",
"prov": {
"source": "file",
"locator": "Web/www/next/components/parvagues/{MusicSection,AlbumCarousel,Layout,ParVaguesFooter}.js",
"as_of": "2026-06-07",
"note": "consolidated from the site's hardcoded link tables"
}
},
{
"platform": "spotify",
"url": "https://open.spotify.com/artist/0kznTQnx5QRhMwktmZboX4",
"kind": "profile",
"label": "Spotify",
"ext_id": "0kznTQnx5QRhMwktmZboX4",
"embed_url": "",
"prov": {
"source": "file",
"locator": "Web/www/next/components/parvagues/{MusicSection,AlbumCarousel,Layout,ParVaguesFooter}.js",
"as_of": "2026-06-07",
"note": "consolidated from the site's hardcoded link tables"
}
},
{
"platform": "soundcloud",
"url": "https://soundcloud.com/parvagues",
"kind": "profile",
"label": "SoundCloud",
"ext_id": "788076298",
"embed_url": "",
"prov": {
"source": "file",
"locator": "Web/www/next/components/parvagues/{MusicSection,AlbumCarousel,Layout,ParVaguesFooter}.js",
"as_of": "2026-06-07",
"note": "consolidated from the site's hardcoded link tables"
}
},
{
"platform": "youtube",
"url": "https://www.youtube.com/@parvagues",
"kind": "profile",
"label": "YouTube",
"ext_id": "",
"embed_url": "",
"prov": {
"source": "file",
"locator": "Web/www/next/components/parvagues/{MusicSection,AlbumCarousel,Layout,ParVaguesFooter}.js",
"as_of": "2026-06-07",
"note": "consolidated from the site's hardcoded link tables"
}
},
{
"platform": "deezer",
"url": "https://www.deezer.com/fr/artist/103670512",
"kind": "profile",
"label": "Deezer",
"ext_id": "103670512",
"embed_url": "",
"prov": {
"source": "file",
"locator": "Web/www/next/components/parvagues/{MusicSection,AlbumCarousel,Layout,ParVaguesFooter}.js",
"as_of": "2026-06-07",
"note": "consolidated from the site's hardcoded link tables"
}
},
{
"platform": "instagram",
"url": "https://www.instagram.com/parvagues.mp3/",
"kind": "profile",
"label": "Instagram",
"ext_id": "",
"embed_url": "",
"prov": {
"source": "file",
"locator": "Web/www/next/components/parvagues/{MusicSection,AlbumCarousel,Layout,ParVaguesFooter}.js",
"as_of": "2026-06-07",
"note": "consolidated from the site's hardcoded link tables"
}
}
],
"releases": [
{
"slug": "livecoding-opal-festival-2024",
"title": "Livecoding (Opal Festival 2024)",
"kind": "live",
"gig": "opal-festival-2024",
"year": 2024,
"links": [
{
"platform": "bandcamp",
"url": "https://parvagues.bandcamp.com/album/livecoding-opal-festival-2024",
"kind": "release",
"label": "",
"ext_id": "",
"embed_url": "",
"prov": {
"source": "file",
"locator": "Web/www/next/components/parvagues/{MusicSection,AlbumCarousel,Layout,ParVaguesFooter}.js",
"as_of": "2026-06-07",
"note": "consolidated from the site's hardcoded link tables"
}
},
{
"platform": "spotify",
"url": "https://open.spotify.com/album/1VKLZWeolFNfES2bWzYCWZ",
"kind": "release",
"label": "",
"ext_id": "1VKLZWeolFNfES2bWzYCWZ",
"embed_url": "",
"prov": {
"source": "file",
"locator": "Web/www/next/components/parvagues/{MusicSection,AlbumCarousel,Layout,ParVaguesFooter}.js",
"as_of": "2026-06-07",
"note": "consolidated from the site's hardcoded link tables"
}
},
{
"platform": "deezer",
"url": "https://www.deezer.com/fr/album/632734951",
"kind": "release",
"label": "",
"ext_id": "632734951",
"embed_url": "",
"prov": {
"source": "file",
"locator": "Web/www/next/components/parvagues/{MusicSection,AlbumCarousel,Layout,ParVaguesFooter}.js",
"as_of": "2026-06-07",
"note": "consolidated from the site's hardcoded link tables"
}
},
{
"platform": "apple_music",
"url": "https://music.apple.com/fr/album/livecoding-opal-festival-2024/1773790990",
"kind": "release",
"label": "",
"ext_id": "1773790990",
"embed_url": "",
"prov": {
"source": "file",
"locator": "Web/www/next/components/parvagues/{MusicSection,AlbumCarousel,Layout,ParVaguesFooter}.js",
"as_of": "2026-06-07",
"note": "consolidated from the site's hardcoded link tables"
}
},
{
"platform": "youtube",
"url": "https://www.youtube.com/playlist?list=OLAK5uy_l4MF3OCIXcdPMpsHGVX2Q9MiX6oU1zT6g",
"kind": "playlist",
"label": "",
"ext_id": "OLAK5uy_l4MF3OCIXcdPMpsHGVX2Q9MiX6oU1zT6g",
"embed_url": "",
"prov": {
"source": "file",
"locator": "Web/www/next/components/parvagues/{MusicSection,AlbumCarousel,Layout,ParVaguesFooter}.js",
"as_of": "2026-06-07",
"note": "consolidated from the site's hardcoded link tables"
}
}
],
"tracks": []
},
{
"slug": "connexion-tablie",
"title": "Connexion Établie EP",
"kind": "ep",
"gig": null,
"year": 2023,
"links": [
{
"platform": "bandcamp",
"url": "https://parvagues.bandcamp.com/album/connexion-tablie",
"kind": "release",
"label": "",
"ext_id": "",
"embed_url": "",
"prov": {
"source": "file",
"locator": "Web/www/next/components/parvagues/{MusicSection,AlbumCarousel,Layout,ParVaguesFooter}.js",
"as_of": "2026-06-07",
"note": "consolidated from the site's hardcoded link tables"
}
},
{
"platform": "spotify",
"url": "https://open.spotify.com/album/4uzSN6Uv9IwcYeHdRtkUmM",
"kind": "release",
"label": "",
"ext_id": "4uzSN6Uv9IwcYeHdRtkUmM",
"embed_url": "",
"prov": {
"source": "file",
"locator": "Web/www/next/components/parvagues/{MusicSection,AlbumCarousel,Layout,ParVaguesFooter}.js",
"as_of": "2026-06-07",
"note": "consolidated from the site's hardcoded link tables"
}
},
{
"platform": "deezer",
"url": "https://www.deezer.com/fr/album/505854371",
"kind": "release",
"label": "",
"ext_id": "505854371",
"embed_url": "",
"prov": {
"source": "file",
"locator": "Web/www/next/components/parvagues/{MusicSection,AlbumCarousel,Layout,ParVaguesFooter}.js",
"as_of": "2026-06-07",
"note": "consolidated from the site's hardcoded link tables"
}
},
{
"platform": "apple_music",
"url": "https://music.apple.com/fr/album/_/1711226283",
"kind": "release",
"label": "",
"ext_id": "1711226283",
"embed_url": "",
"prov": {
"source": "file",
"locator": "Web/www/next/components/parvagues/{MusicSection,AlbumCarousel,Layout,ParVaguesFooter}.js",
"as_of": "2026-06-07",
"note": "consolidated from the site's hardcoded link tables"
}
},
{
"platform": "youtube",
"url": "https://www.youtube.com/watch?v=VODSdQKrzyw&list=OLAK5uy_nzlx3b7YJYzrbagXF5swhENsCg5vJkT_Q",
"kind": "video",
"label": "",
"ext_id": "VODSdQKrzyw",
"embed_url": "",
"prov": {
"source": "file",
"locator": "Web/www/next/components/parvagues/{MusicSection,AlbumCarousel,Layout,ParVaguesFooter}.js",
"as_of": "2026-06-07",
"note": "consolidated from the site's hardcoded link tables"
}
}
],
"tracks": []
},
{
"slug": "live-cosmicfest",
"title": "Live @ CosmicFest v0",
"kind": "live",
"gig": "cosmicfest",
"year": 2025,
"links": [
{
"platform": "bandcamp",
"url": "https://parvagues.bandcamp.com/album/live-cosmicfest",
"kind": "release",
"label": "",
"ext_id": "",
"embed_url": "",
"prov": {
"source": "file",
"locator": "Web/www/next/components/parvagues/{MusicSection,AlbumCarousel,Layout,ParVaguesFooter}.js",
"as_of": "2026-06-07",
"note": "consolidated from the site's hardcoded link tables"
}
}
],
"tracks": []
},
{
"slug": "ton-num-ro",
"title": "Ton Numéro",
"kind": "single",
"gig": null,
"year": null,
"links": [
{
"platform": "bandcamp",
"url": "https://parvagues.bandcamp.com/track/ton-num-ro",
"kind": "track",
"label": "",
"ext_id": "",
"embed_url": "",
"prov": {
"source": "file",
"locator": "Web/www/next/components/parvagues/{MusicSection,AlbumCarousel,Layout,ParVaguesFooter}.js",
"as_of": "2026-06-07",
"note": "consolidated from the site's hardcoded link tables"
}
}
],
"tracks": []
}
]
}
\ No newline at end of file
...@@ -49,6 +49,12 @@ def _patterns(): ...@@ -49,6 +49,12 @@ def _patterns():
return m.OUT return m.OUT
def _presence():
import build_presence as m
m.main() # validates against Presence on emit
return m.OUT
def _tokens(): def _tokens():
sys.path.insert(0, str(ROOT / "tools")) sys.path.insert(0, str(ROOT / "tools"))
import gen_tokens as t import gen_tokens as t
...@@ -69,6 +75,7 @@ STEPS = [ ...@@ -69,6 +75,7 @@ STEPS = [
("catalog_view", "triangle · A=score ⋈ C=metadata ⋈ B=recording (validated)", _catalog_view), ("catalog_view", "triangle · A=score ⋈ C=metadata ⋈ B=recording (validated)", _catalog_view),
("catalog", "GENERATED catalog · catalog_view ⊕ authored overlay", _catalog), ("catalog", "GENERATED catalog · catalog_view ⊕ authored overlay", _catalog),
("patterns", "pattern registry · phrases-as-things + n-gram clustering", _patterns), ("patterns", "pattern registry · phrases-as-things + n-gram clustering", _patterns),
("presence", "distribution SSOT · authored overlay → presence.json (validated)", _presence),
("tokens", "fleet color language · ontology → tokens.css + tokens.json", _tokens), ("tokens", "fleet color language · ontology → tokens.css + tokens.json", _tokens),
("ts_types", "pydantic models → generated TypeScript (DRY)", _ts_types), ("ts_types", "pydantic models → generated TypeScript (DRY)", _ts_types),
] ]
......
...@@ -3,8 +3,16 @@ ...@@ -3,8 +3,16 @@
export type AgreeLevel = 'empty' | 'unparsed' | 'no-claim' | 'agree' | 'partial' | 'conflict' | 'divergent' export type AgreeLevel = 'empty' | 'unparsed' | 'no-claim' | 'agree' | 'partial' | 'conflict' | 'divergent'
export type LinkKind = 'profile' | 'release' | 'track' | 'playlist' | 'video' | 'embed'
export type PatternScope = 'unique' | 'repeated' | 'shared' export type PatternScope = 'unique' | 'repeated' | 'shared'
export type Platform = 'bandcamp' | 'spotify' | 'soundcloud' | 'youtube' | 'deezer' | 'apple_music' | 'instagram'
export type ReleaseKind = 'album' | 'ep' | 'single' | 'live'
export type Source = 'user' | 'ear' | 'file' | 'web' | 'derived'
export type Variant = 'stream' | 'club' export type Variant = 'stream' | 'club'
/** A↔C: how well the site's claimed ingredients match the actual score. */ /** A↔C: how well the site's claimed ingredients match the actual score. */
...@@ -87,6 +95,44 @@ export interface PatternOccurrence { ...@@ -87,6 +95,44 @@ export interface PatternOccurrence {
raw?: string raw?: string
} }
/** One URL on one platform, with provenance. The atom of the presence graph. */
export interface PresenceLink {
platform: Platform
url: string
kind?: LinkKind
label?: string
ext_id?: string
embed_url?: string
prov?: Provenance | null
}
/** Where a value came from, so it can be trusted and corrected. */
export interface Provenance {
source: Source
locator?: string
as_of: string
note?: string
}
/** An album/EP/single/live release and its per-platform links. */
export interface Release {
slug: string
title: string
kind?: ReleaseKind
gig?: string | null
year?: number | null
links?: PresenceLink[]
tracks?: ReleaseTrack[]
}
/** A track as it appears on a release, with any per-platform DIRECT links. `track` is the canonical catalog id (.tidal path) when known — the join key. */
export interface ReleaseTrack {
title: string
track?: string | null
position?: number | null
links?: PresenceLink[]
}
export interface RoleGroup { export interface RoleGroup {
key: string key: string
label: string label: string
...@@ -198,3 +244,12 @@ export interface PatternRegistry { ...@@ -198,3 +244,12 @@ export interface PatternRegistry {
patterns?: PatternEntry[] patterns?: PatternEntry[]
tracks?: TrackPatternSig[] tracks?: TrackPatternSig[]
} }
/** The whole distribution truth: artist profiles + releases. Generated artifact presence.json (built from presence.authored.yaml, validated on emit). */
export interface Presence {
schema?: string
artist?: string
as_of: string
profiles?: PresenceLink[]
releases?: Release[]
}
...@@ -14,9 +14,9 @@ from pathlib import Path ...@@ -14,9 +14,9 @@ from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT / "armada" / "tide-table")) sys.path.insert(0, str(ROOT / "armada" / "tide-table"))
from models import CatalogView, Note, PatternRegistry, PlayerData # noqa: E402 from models import CatalogView, Note, PatternRegistry, PlayerData, Presence # noqa: E402
ROOTS = [PlayerData, Note, CatalogView, PatternRegistry] # top-level UI-facing models ROOTS = [PlayerData, Note, CatalogView, PatternRegistry, Presence] # top-level UI-facing models
OUT = ROOT / "armada" / "ui" / "src" / "types.gen.ts" OUT = ROOT / "armada" / "ui" / "src" / "types.gen.ts"
SCALARS = {"string": "string", "number": "number", "integer": "number", SCALARS = {"string": "string", "number": "number", "integer": "number",
"boolean": "boolean", "null": "null"} "boolean": "boolean", "null": "null"}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment