Imported from Trustybits/grids (
packages/contracts/AGENTS.md). Install upstream withnpx skills add Trustybits/grids --skill contracts. Copyright stays with the author.
@grids/contracts
Shared contracts — the interfaces and domain types that cross package boundaries in grids.so. This package is the agreed-upon shape between the front end (apps/web) and its backend implementations (@grids/pro, and the local stubs in apps/web/src/{dao,auth}/stubbed/). Both sides depend on @grids/contracts; neither depends on the other.
It is (almost entirely) a declaration package: no backend SDKs, no business logic, no I/O. The handful of runtime values it ships are plain enums/constants (see "Runtime values" below).
What lives here
src/auth/— theAuthProviderinterface and theAuthUserdomain object.AuthUserdeliberately reduces a provider's user (uid/email/displayName/photoURL) to a minimal shape so consumers never touch a vendorUsertype.src/dao/— the data-access interfaces. One interface per concern (GridDao,UserDao,SlugDao,ChatDao,RoadmapDao,UpvoteDao,BadgeDao,CustomerDao,AnalyticsEventDao,BusinessStatsDao,GridStatsDao,CloudFunctionsDao,StorageDao,UserGameDataDao), plusDbUtilsandfactory/DaoFactory.ts(theDaoFactoryinterface that hands out every DAO). DAO methods are typed entirely in terms of the domain types fromsrc/types/— never database/SDK types.src/types/— the domain model:Grid(the top-level document),Tile,TileContent(discriminated union of tile types),UserProfile,GameData,Badge,Roadmap,Analytics.
Public entry points
Consumers import from subpaths, each backed by a barrel (index.ts) and mapped in package.json exports to the built dist/:
@grids/contracts/auth→src/auth/index.ts@grids/contracts/dao→src/dao/index.ts@grids/contracts/types→src/types/index.ts@grids/contracts(root) →src/index.ts(re-exports all three barrels, types and runtime values alike)
Runtime values (important)
Most exports are type-only, but a few are real runtime values: the ContentType enum (types/TileContent.ts), the AnalyticsEventType enum (types/Analytics.ts), and the BADGE_IDS const (types/Badge.ts). Because of these:
src/types/index.tsand the rootsrc/index.tsuseexport *(value-preserving), so these values are reachable from both@grids/contracts/typesand the bare@grids/contractsspecifier.src/dao/index.tsandsrc/auth/index.tsare interface-only and useexport type.- If you add a new runtime value, re-export it with
export *(notexport type) so it survives through the barrels.
Build & tooling
npm run build—tscemitsdist/(declarations + JS + source maps); this is what consumers actually resolve via theexportsmap, so build before depending on changes (the rootbuild:web-deps/devscripts do this for you).npm run type-check—tsc --noEmit.npm run lint— ESLint, zero warnings allowed.- ESM +
NodeNextresolution: relative imports must carry the.jsextension (e.g.from "./Tile.js") even though the source is.ts.
When writing code
- Keep this package host-agnostic. No imports of
firebase/*or any other backend SDK, no environment reads, no runtime side effects — only types and the small set of enums/consts above. - Adding a contract: define the interface/type in the right
src/{auth,dao,types}/file, re-export it from that folder'sindex.ts, and (for a new DAO) add its getter toDaoFactory. Thennpm run buildso downstream packages see it. - A change here is a breaking change for every consumer. Update the implementations in
@grids/proand the stubs inapps/web/src/{dao,auth}/stubbed/in lockstep —implementsclauses on both sides will fail to type-check until they match.