├── .changeset ├── README.md └── config.json ├── .gitignore ├── .gitmodules ├── .gitpod.yml ├── .ignore ├── .prettierignore ├── .prettierrc ├── .vscode └── settings.json ├── LICENSE ├── NOTES.md ├── README.md ├── ROADMAP.md ├── TODO.md ├── build-all ├── .gitignore ├── CHANGELOG.md ├── package.json ├── src │ └── index.ts └── tsconfig.json ├── connectors ├── absurd-sql-connector │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── main │ │ │ ├── Mutex.ts │ │ │ ├── __tests__ │ │ │ │ └── connection.test.ts │ │ │ └── connection.ts │ │ ├── pkg.ts │ │ ├── tracer.ts │ │ └── worker │ │ │ └── worker.ts │ └── tsconfig.json ├── capacitor-sqlite-connector │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── babel.config.cjs │ ├── package.json │ ├── src │ │ ├── Connection.ts │ │ └── index.ts │ └── tsconfig.json ├── sqlite3-connector │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── babel.config.cjs │ ├── package.json │ ├── src │ │ ├── Connection.ts │ │ ├── Mutex.ts │ │ └── index.ts │ └── tsconfig.json ├── sqljs-connector │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── babel.config.cjs │ ├── package.json │ ├── src │ │ ├── Connection.ts │ │ ├── __tests__ │ │ │ ├── connection.test.ts │ │ │ └── test.sqlite │ │ └── index.ts │ └── tsconfig.json └── wa-sqlite-connector │ ├── .gitignore │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ ├── Connection.ts │ ├── ConnectionPool.ts │ ├── index.ts │ ├── sqliteInit.ts │ └── trace.ts │ └── tsconfig.json ├── examples ├── chinook │ ├── .gitignore │ ├── CHANGELOG.md │ ├── README.md │ ├── babel.config.cjs │ ├── db │ │ ├── Chinook_Sqlite.sql │ │ └── chinook.sqlite │ ├── exploratory.md │ ├── package.json │ ├── scripts │ │ ├── bootstrap.js │ │ ├── convertDates.js │ │ └── notebook-bkup.md │ ├── src │ │ ├── __tests__ │ │ │ ├── mutator.test.ts │ │ │ ├── query.test.ts │ │ │ └── setup.ts │ │ ├── deviceId.ts │ │ ├── domain.aphro │ │ ├── domain │ │ │ ├── Album.ts │ │ │ ├── Artist.ts │ │ │ ├── Customer.ts │ │ │ ├── Employee.ts │ │ │ ├── Genre.ts │ │ │ ├── GenreMutationsImpl.ts │ │ │ ├── Invoice.ts │ │ │ ├── InvoiceLine.ts │ │ │ ├── MediaType.ts │ │ │ ├── Playlist.ts │ │ │ ├── PlaylistTrack.ts │ │ │ ├── Track.ts │ │ │ └── generated │ │ │ │ ├── Album.sqlite.sql │ │ │ │ ├── AlbumBase.ts │ │ │ │ ├── AlbumQuery.ts │ │ │ │ ├── AlbumSpec.ts │ │ │ │ ├── Artist.sqlite.sql │ │ │ │ ├── ArtistBase.ts │ │ │ │ ├── ArtistQuery.ts │ │ │ │ ├── ArtistSpec.ts │ │ │ │ ├── Customer.sqlite.sql │ │ │ │ ├── CustomerBase.ts │ │ │ │ ├── CustomerQuery.ts │ │ │ │ ├── CustomerSpec.ts │ │ │ │ ├── Employee.sqlite.sql │ │ │ │ ├── EmployeeBase.ts │ │ │ │ ├── EmployeeQuery.ts │ │ │ │ ├── EmployeeSpec.ts │ │ │ │ ├── Genre.sqlite.sql │ │ │ │ ├── GenreBase.ts │ │ │ │ ├── GenreMutations.ts │ │ │ │ ├── GenreQuery.ts │ │ │ │ ├── GenreSpec.ts │ │ │ │ ├── Invoice.sqlite.sql │ │ │ │ ├── InvoiceBase.ts │ │ │ │ ├── InvoiceLine.sqlite.sql │ │ │ │ ├── InvoiceLineBase.ts │ │ │ │ ├── InvoiceLineQuery.ts │ │ │ │ ├── InvoiceLineSpec.ts │ │ │ │ ├── InvoiceQuery.ts │ │ │ │ ├── InvoiceSpec.ts │ │ │ │ ├── MediaType.sqlite.sql │ │ │ │ ├── MediaTypeBase.ts │ │ │ │ ├── MediaTypeQuery.ts │ │ │ │ ├── MediaTypeSpec.ts │ │ │ │ ├── Playlist.sqlite.sql │ │ │ │ ├── PlaylistBase.ts │ │ │ │ ├── PlaylistQuery.ts │ │ │ │ ├── PlaylistSpec.ts │ │ │ │ ├── PlaylistTrack.sqlite.sql │ │ │ │ ├── PlaylistTrackBase.ts │ │ │ │ ├── PlaylistTrackQuery.ts │ │ │ │ ├── PlaylistTrackSpec.ts │ │ │ │ ├── Track.sqlite.sql │ │ │ │ ├── TrackBase.ts │ │ │ │ ├── TrackQuery.ts │ │ │ │ ├── TrackSpec.ts │ │ │ │ ├── exports-node-sql.ts │ │ │ │ ├── exports-sql.ts │ │ │ │ ├── exports.ts │ │ │ │ └── types.d.ts │ │ └── index.ts │ └── tsconfig.json ├── demo │ ├── index.html │ ├── package.json │ ├── public │ │ └── wa-sqlite-async.wasm │ ├── src │ │ ├── domain.aphro │ │ ├── domain │ │ │ ├── User.ts │ │ │ └── generated │ │ │ │ ├── User.sqlite.sql │ │ │ │ ├── UserBase.ts │ │ │ │ ├── UserQuery.ts │ │ │ │ ├── UserSpec.ts │ │ │ │ ├── exports-node-sql.ts │ │ │ │ ├── exports-sql.ts │ │ │ │ ├── exports.ts │ │ │ │ └── types.d.ts │ │ ├── global.d.ts │ │ └── main.tsx │ ├── tsconfig.json │ └── vite.config.js ├── monopoly-p2p │ └── README.md ├── monopoly │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── domain.aphro │ │ ├── generated │ │ │ ├── Game.sqlite.sql │ │ │ ├── Game.ts │ │ │ ├── GameQuery.ts │ │ │ ├── GameSpec.ts │ │ │ ├── Person.sqlite.sql │ │ │ ├── Person.ts │ │ │ ├── PersonQuery.ts │ │ │ ├── PersonSpec.ts │ │ │ ├── Player.sqlite.sql │ │ │ ├── Player.ts │ │ │ ├── PlayerQuery.ts │ │ │ ├── PlayerSpec.ts │ │ │ ├── Property.sqlite.sql │ │ │ ├── Property.ts │ │ │ ├── PropertyQuery.ts │ │ │ ├── PropertySpec.ts │ │ │ ├── domain.graphql │ │ │ └── domain.graphql-resolvers.ts │ │ └── main.ts │ └── tsconfig.json ├── todo-mvc-mem │ ├── .gitignore │ ├── CHANGELOG.md │ ├── README copy.md │ ├── README.md │ ├── base.css │ ├── package.json │ ├── pnpm-lock.yaml │ ├── src │ │ ├── App.tsx │ │ ├── domain.aphro │ │ ├── generated │ │ │ ├── Todo.ts │ │ │ ├── TodoList.ts │ │ │ └── generated │ │ │ │ ├── TodoBase.ts │ │ │ │ ├── TodoListBase.ts │ │ │ │ ├── TodoListQuery.ts │ │ │ │ ├── TodoListSpec.ts │ │ │ │ ├── TodoQuery.ts │ │ │ │ ├── TodoSpec.ts │ │ │ │ ├── exports.ts │ │ │ │ └── types.d.ts │ │ ├── index.html │ │ ├── index.tsx │ │ └── store.ts │ ├── style.css │ ├── tsconfig.json │ └── webpack.config.js ├── todo-mvc-p2p │ └── README.md └── todo-mvc │ └── README.md ├── extensions ├── authorization-grammar │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ └── index.ts │ └── tsconfig.json ├── decorator-grammar │ └── .npmignore ├── graphql-codegen │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── babel.config.cjs │ ├── package.json │ ├── src │ │ ├── graphql │ │ │ ├── GenGraphQLTypedefs.ts │ │ │ ├── GraphqlFile.ts │ │ │ ├── __tests__ │ │ │ │ └── GenGraphQLTypedefs.test.ts │ │ │ ├── connectionName.ts │ │ │ ├── fieldTypeToGraphQLType.ts │ │ │ ├── gatherReadFields.ts │ │ │ ├── inlineEnumName.ts │ │ │ └── shouldExpose.ts │ │ ├── index.ts │ │ └── typescript │ │ │ ├── GenGraphQLTypescriptResolvers.ts │ │ │ └── __tests__ │ │ │ └── GenGraphQLTypescriptResolvers.test.ts │ └── tsconfig.json ├── graphql-grammar │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── babel.config.cjs │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ ├── compile.test.ts │ │ │ └── testSchemaFile.ts │ │ └── index.ts │ └── tsconfig.json ├── mutation-codegen │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── babel.config.cjs │ ├── package.json │ ├── src │ │ ├── index.ts │ │ └── typescript │ │ │ ├── GenTypescriptMutationImpls.ts │ │ │ ├── GenTypescriptMutations.ts │ │ │ ├── __tests__ │ │ │ ├── GenTypescriptMutationImpls.test.ts │ │ │ └── GenTypescriptMutationsCodegen.test.ts │ │ │ └── shared.ts │ └── tsconfig.json └── mutation-grammar │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── babel.config.cjs │ ├── package.json │ ├── src │ ├── __tests__ │ │ ├── compile.test.ts │ │ └── testSchemaFile.ts │ ├── index.ts │ └── mutation.ts │ └── tsconfig.json ├── integration-tests ├── browser │ ├── CHANGELOG.md │ ├── README.md │ ├── index.html │ ├── package.json │ ├── public │ │ └── wa-sqlite-async.wasm │ ├── src │ │ └── main.ts │ ├── tsconfig.json │ └── vite.config.js ├── node │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── babel.config.cjs │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ ├── bootstrap.test.ts │ │ │ ├── count-multihop.test.ts │ │ │ ├── count.test.ts │ │ │ ├── createGraph.ts │ │ │ ├── declared-mutations.test.ts │ │ │ ├── direct-load.test.ts │ │ │ ├── empty.test.ts │ │ │ ├── ephemeral.test.ts │ │ │ ├── filter.test.ts │ │ │ ├── junction.test.ts │ │ │ ├── lambdas.test.ts │ │ │ ├── mutation-on-mutation.ts │ │ │ ├── mutators.test.ts │ │ │ ├── orderBy.test.ts │ │ │ ├── point-hop-queryall.test.ts │ │ │ ├── reactivity.test.ts │ │ │ ├── take.test.ts │ │ │ └── testBase.ts │ │ ├── createTestTables.ts │ │ └── testdb.ts │ └── tsconfig.json └── shared │ ├── .gitignore │ ├── CHANGELOG.md │ ├── package.json │ ├── src │ ├── domain-memory │ │ ├── Component.ts │ │ ├── ComponentMutationsImpl.ts │ │ ├── Deck.ts │ │ ├── DeckMutationsImpl.ts │ │ ├── DeckToEditorsEdge.ts │ │ ├── DeckToEditorsEdgeMutationsImpl.ts │ │ ├── Slide.ts │ │ ├── SlideMutationsImpl.ts │ │ ├── User.ts │ │ ├── UserMutationsImpl.ts │ │ └── generated │ │ │ ├── ComponentBase.ts │ │ │ ├── ComponentMutations.ts │ │ │ ├── ComponentQuery.ts │ │ │ ├── ComponentSpec.ts │ │ │ ├── DeckBase.ts │ │ │ ├── DeckMutations.ts │ │ │ ├── DeckQuery.ts │ │ │ ├── DeckSpec.ts │ │ │ ├── DeckToEditorsEdgeBase.ts │ │ │ ├── DeckToEditorsEdgeMutations.ts │ │ │ ├── DeckToEditorsEdgeQuery.ts │ │ │ ├── DeckToEditorsEdgeSpec.ts │ │ │ ├── SlideBase.ts │ │ │ ├── SlideMutations.ts │ │ │ ├── SlideQuery.ts │ │ │ ├── SlideSpec.ts │ │ │ ├── UserBase.ts │ │ │ ├── UserMutations.ts │ │ │ ├── UserQuery.ts │ │ │ ├── UserSpec.ts │ │ │ ├── exports.ts │ │ │ └── types.d.ts │ ├── domain │ │ ├── AppState.ts │ │ ├── AppStateMutationsImpl.ts │ │ ├── Component.ts │ │ ├── ComponentMutationsImpl.ts │ │ ├── Deck.ts │ │ ├── DeckMutationsImpl.ts │ │ ├── DeckToEditorsEdge.ts │ │ ├── DeckToEditorsEdgeMutationsImpl.ts │ │ ├── Foo.ts │ │ ├── Identity.ts │ │ ├── Slide.ts │ │ ├── SlideMutationsImpl.ts │ │ ├── User.ts │ │ ├── UserMutationsImpl.ts │ │ └── generated │ │ │ ├── AppStateBase.ts │ │ │ ├── AppStateMutations.ts │ │ │ ├── AppStateSpec.ts │ │ │ ├── Component.sqlite.sql │ │ │ ├── ComponentBase.ts │ │ │ ├── ComponentMutations.ts │ │ │ ├── ComponentQuery.ts │ │ │ ├── ComponentSpec.ts │ │ │ ├── Deck.sqlite.sql │ │ │ ├── DeckBase.ts │ │ │ ├── DeckMutations.ts │ │ │ ├── DeckQuery.ts │ │ │ ├── DeckSpec.ts │ │ │ ├── DeckToEditorsEdge.sqlite.sql │ │ │ ├── DeckToEditorsEdgeBase.ts │ │ │ ├── DeckToEditorsEdgeMutations.ts │ │ │ ├── DeckToEditorsEdgeQuery.ts │ │ │ ├── DeckToEditorsEdgeSpec.ts │ │ │ ├── Foo.sqlite.sql │ │ │ ├── FooBase.ts │ │ │ ├── FooQuery.ts │ │ │ ├── FooSpec.ts │ │ │ ├── IdentityBase.ts │ │ │ ├── IdentitySpec.ts │ │ │ ├── Slide.sqlite.sql │ │ │ ├── SlideBase.ts │ │ │ ├── SlideMutations.ts │ │ │ ├── SlideQuery.ts │ │ │ ├── SlideSpec.ts │ │ │ ├── User.sqlite.sql │ │ │ ├── UserBase.ts │ │ │ ├── UserMutations.ts │ │ │ ├── UserQuery.ts │ │ │ ├── UserSpec.ts │ │ │ ├── exports-node-sql.ts │ │ │ ├── exports-sql.ts │ │ │ ├── exports.ts │ │ │ └── types.d.ts │ ├── index.ts │ └── schema │ │ ├── domain.aphro │ │ └── in-memory.aphro │ └── tsconfig.json ├── jaeger.sh ├── package.json ├── packages ├── cache-runtime-ts │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── babel.config.cjs │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ └── Cache.test.ts │ │ ├── cache.ts │ │ ├── index.ts │ │ └── queryCache.ts │ └── tsconfig.json ├── codegen-api │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── package.json │ ├── src │ │ ├── CodegenFile.ts │ │ ├── CodegenStep.ts │ │ └── index.ts │ └── tsconfig.json ├── codegen-cli │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ └── cli.test.ts │ │ └── cli.ts │ └── tsconfig.json ├── codegen-sql │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── babel.config.cjs │ ├── package.json │ ├── src │ │ ├── GenSqlTableSchema.ts │ │ ├── SqlFile.ts │ │ ├── __tests__ │ │ │ └── GenSqlTableSchema.test.ts │ │ └── index.ts │ └── tsconfig.json ├── codegen-ts │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── babel.config.cjs │ ├── package.json │ ├── src │ │ ├── GenSQLExports.ts │ │ ├── GenSQLExports_node.ts │ │ ├── GenSchemaExports.ts │ │ ├── GenTypes_d_ts.ts │ │ ├── GenTypescriptModel.ts │ │ ├── GenTypescriptModelManualMethodsClass.ts │ │ ├── GenTypescriptQuery.ts │ │ ├── GenTypescriptSpec.ts │ │ ├── TypescriptFile.ts │ │ ├── __tests__ │ │ │ ├── GenTypescriptModel.test.ts │ │ │ ├── GenTypescriptQuery.test.ts │ │ │ ├── GenTypesriptSpec.test.ts │ │ │ └── tsUtils.test.ts │ │ ├── index.ts │ │ └── tsUtils.ts │ └── tsconfig.json ├── codegen │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── babel.config.cjs │ ├── package.json │ ├── src │ │ ├── CodegenFile.ts │ │ ├── CodegenPipeline.ts │ │ ├── __tests__ │ │ │ ├── CodegenFile.test.ts │ │ │ └── uniqueImports.test.ts │ │ ├── index.ts │ │ └── uniqueImports.ts │ └── tsconfig.json ├── context-runtime-ts │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── babel.config.cjs │ ├── package.json │ ├── src │ │ ├── DBResolver.ts │ │ ├── HeteroModelMap.ts │ │ ├── INode.ts │ │ ├── OptimisticPromise.ts │ │ ├── __tests__ │ │ │ ├── context.test.ts │ │ │ └── transactionLog.test.ts │ │ ├── changeset.ts │ │ ├── context.ts │ │ ├── index.ts │ │ ├── resolvers.ts │ │ ├── runtimeConfig.ts │ │ ├── transaction.ts │ │ ├── transactionLog.ts │ │ └── viewer.ts │ └── tsconfig.json ├── feature-gates │ ├── .gitignore │ ├── .npmignore │ ├── package.json │ ├── src │ │ └── index.ts │ └── tsconfig.json ├── grammar-extension-api │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── package.json │ ├── src │ │ └── index.ts │ └── tsconfig.json ├── instrument │ ├── .gitignore │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.ts │ │ └── tracer.ts │ └── tsconfig.json ├── migration-runtime-ts │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ └── automigrate.test.ts │ │ ├── autoMigrate.ts │ │ ├── bootstrap.ts │ │ └── index.ts │ └── tsconfig.json ├── model-runtime-ts │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── babel.config.cjs │ ├── package.json │ ├── src │ │ ├── Edge.ts │ │ ├── MemoryDB.ts │ │ ├── Model.ts │ │ ├── ModelMap.ts │ │ ├── ModelReference.ts │ │ ├── Node.ts │ │ ├── NotifyQueue.ts │ │ ├── __tests__ │ │ │ ├── MemoryDB.test.ts │ │ │ └── Model.test.ts │ │ ├── datasetKey.ts │ │ ├── index.ts │ │ ├── modelDataEncoding.ts │ │ ├── modelGenMemo.ts │ │ ├── observe.ts │ │ └── that.ts │ └── tsconfig.json ├── mutator-runtime-ts │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── babel.config.cjs │ ├── package.json │ ├── src │ │ ├── ChangesetExecutor.ts │ │ ├── MutationsBase.ts │ │ ├── Mutator.ts │ │ ├── NotifyQueue.ts │ │ ├── Persistor.ts │ │ ├── commit.ts │ │ ├── index.ts │ │ ├── makeSavable.ts │ │ ├── memoryWriter.ts │ │ ├── sql │ │ │ ├── __tests__ │ │ │ │ └── sqlWriter.test.ts │ │ │ └── sqlWriter.ts │ │ ├── trace.ts │ │ └── writer.ts │ └── tsconfig.json ├── parse-ts │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── babel.config.cjs │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ └── extractors.test.ts │ │ ├── extractors.ts │ │ ├── index.ts │ │ ├── nodeChildren.ts │ │ └── toAst.ts │ └── tsconfig.json ├── query-runtime-ts │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── babel.config.cjs │ ├── package.json │ ├── src │ │ ├── ChunkIterable.ts │ │ ├── CountLoadExpression.ts │ │ ├── Expression.ts │ │ ├── ExpressionVisitor.ts │ │ ├── Field.ts │ │ ├── HopPlan.ts │ │ ├── ModelLoadExpression.ts │ │ ├── Plan.ts │ │ ├── Predicate.ts │ │ ├── Query.ts │ │ ├── QueryFactory.ts │ │ ├── StorageAdapter.ts │ │ ├── __tests__ │ │ │ └── ChunkIterable.test.ts │ │ ├── explain │ │ │ ├── __tests__ │ │ │ │ └── orderPlans.test.ts │ │ │ ├── orderPlans.ts │ │ │ └── printPlan.ts │ │ ├── index.ts │ │ ├── live │ │ │ ├── LiveResult.ts │ │ │ └── __tests__ │ │ │ │ └── LiveResult.test.ts │ │ ├── memory │ │ │ ├── MemoryHopChunkIterable.ts │ │ │ ├── MemoryHopExpression.ts │ │ │ ├── MemoryHopQuery.ts │ │ │ ├── MemorySourceChunkIterable.ts │ │ │ ├── MemorySourceExpression.ts │ │ │ └── MemorySourceQuery.ts │ │ ├── sql │ │ │ ├── SQLExpression.ts │ │ │ ├── SQLHopChunkIterable.ts │ │ │ ├── SQLHopExpression.ts │ │ │ ├── SQLHopQuery.ts │ │ │ ├── SQLSourceChunkIterable.ts │ │ │ ├── SQLSourceExpression.ts │ │ │ ├── SQLSourceQuery.ts │ │ │ ├── __tests__ │ │ │ │ ├── SQLSourceChunkIterable.test.ts │ │ │ │ └── specAndOpsToQuery.test.ts │ │ │ └── specAndOpsToQuery.ts │ │ └── trace.ts │ └── tsconfig.json ├── react │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── babel.config.cjs │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ └── cache.test.ts │ │ ├── createHooks.ts │ │ ├── hooks.ts │ │ ├── index.ts │ │ └── useSync.ts │ └── tsconfig.json ├── runtime-ts │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ └── index.ts │ └── tsconfig.json ├── schema-api │ ├── .gitignore │ ├── .npmignore │ ├── .pnpm-debug.log │ ├── CHANGELOG.md │ ├── package.json │ ├── src │ │ └── index.ts │ └── tsconfig.json ├── schema │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── README.md │ ├── babel.config.cjs │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ └── schemaFilePipeline.test.ts │ │ ├── compile.ts │ │ ├── edge.ts │ │ ├── field.ts │ │ ├── index.ts │ │ ├── module.ts │ │ ├── node.ts │ │ ├── parser │ │ │ ├── __tests__ │ │ │ │ ├── condense.test.ts │ │ │ │ ├── documentSchemaFile.ts │ │ │ │ ├── documentType.test.ts │ │ │ │ ├── grammar.test.ts │ │ │ │ ├── parse.test.ts │ │ │ │ └── testSchemaFile.ts │ │ │ ├── condense.ts │ │ │ ├── condenseEntities.ts │ │ │ ├── ohm │ │ │ │ ├── grammar.ohm │ │ │ │ └── grammar.ts │ │ │ └── parse.ts │ │ ├── runtimeConfig.ts │ │ ├── type.ts │ │ └── validate.ts │ └── tsconfig.json ├── sql-ts │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── babel.config.cjs │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ └── sqlite.test.ts │ │ ├── index.ts │ │ └── sql.ts │ └── tsconfig.json └── vscode │ ├── .npmignore │ ├── .vscode │ └── launch.json │ ├── .vscodeignore │ ├── CHANGELOG.md │ ├── README.md │ ├── language-configuration.json │ ├── package.json │ ├── syntaxes │ └── aphrodite.tmLanguage.json │ └── vsc-extension-quickstart.md ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── syntaxkind.md ├── tsconfig-templates └── lib.json └── turbo.json /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@2.0.0/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "restricted", 8 | "baseBranch": "main", 9 | "updateInternalDependencies": "patch", 10 | "ignore": [] 11 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | .DS_STORE 4 | .turbo/ 5 | tsconfig.tsbuildinfo 6 | .pnpm-debug.log 7 | mealtrained/ -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vlcn-io/vlcn-orm/ff90a4d588a5bed0fdcea0335d328f7c4dd51cd8/.gitmodules -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | tasks: 2 | - init: pnpm install && cd build-all && pnpm build && cd .. 3 | -------------------------------------------------------------------------------- /.ignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # node modules 2 | node_modules 3 | 4 | # builded sources 5 | build 6 | dist 7 | 8 | # coverage reports 9 | coverage 10 | 11 | # IntelliJ stuffs 12 | .idea/ 13 | 14 | # parcel cache 15 | .cache 16 | 17 | generated/ -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "all", 3 | "tabWidth": 2, 4 | "printWidth": 100, 5 | "bracketSpacing": true, 6 | "semi": true, 7 | "singleQuote": true, 8 | "arrowParens": "avoid", 9 | "useTabs": false 10 | } 11 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": true, 3 | "rpc.enabled": true, 4 | "typescript.tsdk": "node_modules/typescript/lib" 5 | } 6 | -------------------------------------------------------------------------------- /NOTES.md: -------------------------------------------------------------------------------- 1 | # Releases 2 | 3 | ## Step 1 4 | 5 | Run 6 | ``` 7 | pnpm changeset 8 | ``` 9 | 10 | Select only the packages that were actually modified. `changeset` will discover depedents and bump them correctly. 11 | 12 | ## Step 2 13 | 14 | Run 15 | ``` 16 | pnpm changeset version 17 | ``` 18 | 19 | Literally "version" rather than some version name/number. 20 | 21 | Answer the questions. 22 | 23 | ## Step 3 24 | 25 | Run 26 | ``` 27 | pnpm install 28 | ``` 29 | 30 | ## Step 4 31 | 32 | 33 | Run 34 | ``` 35 | pnpm publish -r --access=public --otp=___ 36 | ``` 37 | 38 | # Inspiration 39 | 40 | Lamport: https://www.youtube.com/watch?v=rkZzg7Vowao 41 | 42 | Solidjs architecture: https://www.youtube.com/watch?v=_ne2BsvFBH0, https://www.youtube.com/watch?v=j8ANWdE7wfY 43 | 44 | 45 | # Dep Tracking 46 | 47 | How might we have Model properties integrated into SolidJS's reactivity system? 48 | Live queries too. 49 | 50 | 51 | # Signoz: 52 | 53 | http://localhost:3301/application -------------------------------------------------------------------------------- /build-all/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /build-all/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/build-all", 3 | "version": "0.2.6", 4 | "main": "lib/index.js", 5 | "type": "module", 6 | "devDependencies": { 7 | "typescript": "^4.8.2" 8 | }, 9 | "scripts": { 10 | "clean": "tsc --build --clean", 11 | "build": "tsc --build", 12 | "watch": "tsc --build -w", 13 | "deep-clean": "rm -rf ./lib || true && rm tsconfig.tsbuildinfo || true" 14 | }, 15 | "jest": { 16 | "testMatch": [ 17 | "**/__tests__/**/*.test.js" 18 | ] 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /build-all/src/index.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vlcn-io/vlcn-orm/ff90a4d588a5bed0fdcea0335d328f7c4dd51cd8/build-all/src/index.ts -------------------------------------------------------------------------------- /build-all/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"], 8 | "references": [ 9 | { "path": "../connectors/absurd-sql-connector" }, 10 | { "path": "../connectors/sqljs-connector" }, 11 | { "path": "../connectors/sqlite3-connector" }, 12 | { "path": "../integration-tests/node" }, 13 | { "path": "../packages/codegen" }, 14 | { "path": "../packages/codegen-api" }, 15 | { "path": "../packages/codegen-cli" }, 16 | { "path": "../packages/codegen-sql" }, 17 | { "path": "../packages/codegen-ts" }, 18 | { "path": "../packages/grammar-extension-api" }, 19 | { "path": "../packages/runtime-ts" }, 20 | { "path": "../packages/react" }, 21 | { "path": "../packages/schema" }, 22 | { "path": "../packages/schema-api" }, 23 | { "path": "../packages/sql-ts" }, 24 | { "path": "../extensions/mutation-codegen" }, 25 | { "path": "../extensions/mutation-grammar" }, 26 | { "path": "../extensions/graphql-grammar" }, 27 | { "path": "../extensions/graphql-codegen" }, 28 | { "path": "../connectors/wa-sqlite-connector" }, 29 | { "path": "../packages/instrument" } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /connectors/absurd-sql-connector/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /connectors/absurd-sql-connector/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /connectors/absurd-sql-connector/README.md: -------------------------------------------------------------------------------- 1 | # AbsurdSQL 2 | 3 | Adapter to let `Aphrodite` query `AbsurdSQL` 4 | 5 | We need custom support given `AbsurdSQL` is run in a web-worker and the application issuing queries is in the main browser thread. I.e., the connection from application to db is via `postMessage` in the browser. 6 | 7 | Prior art: 8 | - https://raw.githubusercontent.com/gammaql/greldal/20f65226256ec217ea056bf7e0c1eca48b5bb721/src/docs/utils/SQLJSClient.js 9 | - https://github.com/ngokevin/expo-sqlite-plus-web/blob/main/src/db.web.ts#L22 -------------------------------------------------------------------------------- /connectors/absurd-sql-connector/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/absurd-sql-connector", 3 | "version": "0.3.2", 4 | "main": "lib/index.js", 5 | "type": "module", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/tantaman/aphrodite.git", 9 | "directory": "packages/absurd-sql-connector" 10 | }, 11 | "dependencies": { 12 | "@aphro/absurd-sql": "^0.0.53", 13 | "@aphro/instrument": "workspace:*", 14 | "@aphro/runtime-ts": "workspace:*", 15 | "@aphro/sql.js": "^1.7.0", 16 | "@opentelemetry/api": "^1.1.0", 17 | "@strut/counter": "^0.0.11" 18 | }, 19 | "devDependencies": { 20 | "@babel/core": "^7.18.13", 21 | "@babel/preset-env": "^7.18.10", 22 | "@types/jest": "^28.1.8", 23 | "jest": "^29.0.1", 24 | "typescript": "^4.8.2" 25 | }, 26 | "scripts": { 27 | "clean": "tsc --build --clean", 28 | "build": "tsc --build", 29 | "watch": "tsc --build -w", 30 | "test": "node ./node_modules/jest/bin/jest.js", 31 | "deep-clean": "rm -rf ./lib || true && rm tsconfig.tsbuildinfo || true" 32 | }, 33 | "jest": { 34 | "testMatch": [ 35 | "**/__tests__/**/*.test.js" 36 | ] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /connectors/absurd-sql-connector/src/index.ts: -------------------------------------------------------------------------------- 1 | import Connection from './main/connection.js'; 2 | export { default as Connection } from './main/connection.js'; 3 | import { DBResolver, basicResolver } from '@aphro/runtime-ts'; 4 | 5 | /** 6 | * Convenience function to create a connection to absurd-sql and return 7 | * a db resolver that resolves to that connection. 8 | * 9 | * You should _only_ ever call `createResolver` one time from your application. 10 | * After calling `createResolver`, attach the provided resolver to `Context` and/or pass 11 | * your resolver instance around to where it is needed. 12 | * 13 | * Only call this once since each call will try to start up a new sqlite instance. 14 | * 15 | * @returns DBResolver 16 | */ 17 | export async function createResolver(dbName: string): Promise { 18 | const connection = new Connection(dbName); 19 | await connection.ready; 20 | return basicResolver(dbName, connection); 21 | } 22 | -------------------------------------------------------------------------------- /connectors/absurd-sql-connector/src/main/__tests__/connection.test.ts: -------------------------------------------------------------------------------- 1 | // we can inject a mock worker to enable testing of the connection 2 | test('TEST TODO', () => {}); 3 | -------------------------------------------------------------------------------- /connectors/absurd-sql-connector/src/pkg.ts: -------------------------------------------------------------------------------- 1 | export default '@aphro/absurd-sql'; 2 | -------------------------------------------------------------------------------- /connectors/absurd-sql-connector/src/tracer.ts: -------------------------------------------------------------------------------- 1 | import { tracer, Tracer } from '@aphro/instrument'; 2 | 3 | const t: Tracer = tracer('@aphro/absurd-sql-connector', '0.2.1'); 4 | export default t; 5 | -------------------------------------------------------------------------------- /connectors/absurd-sql-connector/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"], 8 | "references": [{ "path": "../../packages/runtime-ts" }, { "path": "../../packages/instrument" }] 9 | } 10 | -------------------------------------------------------------------------------- /connectors/capacitor-sqlite-connector/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /connectors/capacitor-sqlite-connector/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /connectors/capacitor-sqlite-connector/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @aphro/capacitro-sqlite-connector 2 | 3 | ## 0.0.3 4 | 5 | ### Patch Changes 6 | 7 | - Export queries and specs, move connectors to own packages, fix #43 and other bugs 8 | - Updated dependencies 9 | - @aphro/runtime-ts@0.3.8 10 | 11 | ## 0.0.2 12 | 13 | ### Patch Changes 14 | 15 | - transaction support 16 | - Updated dependencies 17 | - @aphro/runtime-ts@0.3.7 18 | -------------------------------------------------------------------------------- /connectors/capacitor-sqlite-connector/README.md: -------------------------------------------------------------------------------- 1 | Uses https://github.com/storesafe/cordova-sqlite-storage (which works with Capacitor/Ionic) rather than https://github.com/capacitor-community/sqlite. 2 | 3 | Why not use https://github.com/capacitor-community/sqlite? 4 | 5 | The API really is not very clean (no connection objects, weird `changes` return values, no `bind` for params), looking through issues, the project may have a few unresolved memory leaks and the documentation is hard to follow. -------------------------------------------------------------------------------- /connectors/capacitor-sqlite-connector/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | '@babel/preset-env', 5 | { 6 | targets: { 7 | node: 'current', 8 | }, 9 | }, 10 | ], 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /connectors/capacitor-sqlite-connector/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/capacitor-sqlite-connector", 3 | "version": "0.0.3", 4 | "main": "lib/index.js", 5 | "type": "module", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/tantaman/aphrodite.git", 9 | "directory": "packages/capacitor-sqlite-connector" 10 | }, 11 | "dependencies": { 12 | "@aphro/runtime-ts": "workspace:*", 13 | "@awesome-cordova-plugins/sqlite": "^5.44.0" 14 | }, 15 | "devDependencies": { 16 | "@awesome-cordova-plugins/core": "^5.44.0", 17 | "@babel/core": "^7.18.13", 18 | "@babel/preset-env": "^7.18.10", 19 | "@types/jest": "^28.1.8", 20 | "jest": "^29.0.1", 21 | "rxjs": "^7.5.6", 22 | "typescript": "^4.8.2" 23 | }, 24 | "scripts": { 25 | "clean": "tsc --build --clean", 26 | "build": "tsc --build", 27 | "watch": "tsc --build -w", 28 | "test": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js", 29 | "deep-clean": "rm -rf ./lib || true && rm tsconfig.tsbuildinfo || true" 30 | }, 31 | "jest": { 32 | "testMatch": [ 33 | "**/__tests__/**/*.test.js" 34 | ] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /connectors/capacitor-sqlite-connector/src/index.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vlcn-io/vlcn-orm/ff90a4d588a5bed0fdcea0335d328f7c4dd51cd8/connectors/capacitor-sqlite-connector/src/index.ts -------------------------------------------------------------------------------- /connectors/capacitor-sqlite-connector/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"], 8 | "references": [{ "path": "../../packages/runtime-ts" }] 9 | } 10 | -------------------------------------------------------------------------------- /connectors/sqlite3-connector/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /connectors/sqlite3-connector/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /connectors/sqlite3-connector/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @aphro/sqlite3-connector 2 | 3 | ## 0.3.2 4 | 5 | ### Patch Changes 6 | 7 | - Export queries and specs, move connectors to own packages, fix #43 and other bugs 8 | - Updated dependencies 9 | - @aphro/runtime-ts@0.3.8 10 | 11 | ## 0.3.1 12 | 13 | ### Patch Changes 14 | 15 | - transaction support 16 | - Updated dependencies 17 | - @aphro/runtime-ts@0.3.7 18 | -------------------------------------------------------------------------------- /connectors/sqlite3-connector/README.md: -------------------------------------------------------------------------------- 1 | # sqlite3-connector 2 | 3 | Enable connectivity between Aphrodite and `sqlite3` -------------------------------------------------------------------------------- /connectors/sqlite3-connector/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | '@babel/preset-env', 5 | { 6 | targets: { 7 | node: 'current', 8 | }, 9 | }, 10 | ], 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /connectors/sqlite3-connector/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/sqlite3-connector", 3 | "version": "0.3.2", 4 | "main": "lib/index.js", 5 | "type": "module", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/tantaman/aphrodite.git", 9 | "directory": "packages/sqlite3-connector" 10 | }, 11 | "dependencies": { 12 | "@aphro/runtime-ts": "workspace:*", 13 | "@types/sqlite3": "^3.1.8", 14 | "sqlite3": "^5.0.11" 15 | }, 16 | "devDependencies": { 17 | "@babel/core": "^7.18.13", 18 | "@babel/preset-env": "^7.18.10", 19 | "@types/jest": "^28.1.8", 20 | "@types/node": "^18.7.13", 21 | "jest": "^29.0.1", 22 | "typescript": "^4.8.2" 23 | }, 24 | "scripts": { 25 | "clean": "tsc --build --clean", 26 | "build": "tsc --build", 27 | "watch": "tsc --build -w", 28 | "test": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js", 29 | "deep-clean": "rm -rf ./lib || true && rm tsconfig.tsbuildinfo || true" 30 | }, 31 | "jest": { 32 | "testMatch": [ 33 | "**/__tests__/**/*.test.js" 34 | ] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /connectors/sqlite3-connector/src/index.ts: -------------------------------------------------------------------------------- 1 | import { DBResolver } from '@aphro/runtime-ts'; 2 | import { basicResolver } from '@aphro/runtime-ts'; 3 | import { createConnection } from './Connection.js'; 4 | export { createConnection } from './Connection.js'; 5 | 6 | /** 7 | * Convenience function to create a connection to absurd-sql and return 8 | * a db resolver that resolves to that connection. 9 | * 10 | * You should _only_ ever call `openDbAndCreateResolver` one time from your application. 11 | * After calling `createResolver`, attach the provided resolver to `Context` and/or pass 12 | * your resolver instance around to where it is needed. 13 | * 14 | * Only call this once since each call will try to start up a new sqlite instance. 15 | * 16 | * @returns DBResolver 17 | */ 18 | export async function openDbAndCreateResolver( 19 | dbName: string, 20 | file: string | null, 21 | ): Promise { 22 | const conn = await createConnection(file); 23 | return basicResolver(dbName, conn); 24 | } 25 | -------------------------------------------------------------------------------- /connectors/sqlite3-connector/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"], 8 | "references": [{ "path": "../../packages/runtime-ts" }] 9 | } 10 | -------------------------------------------------------------------------------- /connectors/sqljs-connector/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /connectors/sqljs-connector/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /connectors/sqljs-connector/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | '@babel/preset-env', 5 | { 6 | targets: { 7 | node: 'current', 8 | }, 9 | }, 10 | ], 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /connectors/sqljs-connector/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/sqljs-connector", 3 | "version": "0.3.2", 4 | "main": "lib/index.js", 5 | "type": "module", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/tantaman/aphrodite.git", 9 | "directory": "packages/sqljs-connector" 10 | }, 11 | "dependencies": { 12 | "@aphro/runtime-ts": "workspace:*", 13 | "@aphro/sql.js": "^1.7.0", 14 | "@strut/counter": "^0.0.11" 15 | }, 16 | "devDependencies": { 17 | "@babel/core": "^7.18.13", 18 | "@babel/preset-env": "^7.18.10", 19 | "@types/jest": "^28.1.8", 20 | "@types/node": "^18.7.13", 21 | "jest": "^29.0.1", 22 | "typescript": "^4.8.2" 23 | }, 24 | "scripts": { 25 | "clean": "tsc --build --clean", 26 | "build": "tsc --build", 27 | "watch": "tsc --build -w", 28 | "test": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js", 29 | "deep-clean": "rm -rf ./lib || true && rm tsconfig.tsbuildinfo || true" 30 | }, 31 | "jest": { 32 | "testMatch": [ 33 | "**/__tests__/**/*.test.js" 34 | ] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /connectors/sqljs-connector/src/__tests__/connection.test.ts: -------------------------------------------------------------------------------- 1 | // import { sql } from '@aphro/sql-ts'; 2 | // import initSqlJs from '@aphro/sql.js/dist/sql-wasm.js'; 3 | // import { Connection } from '../index.js'; 4 | // // import * as fs from 'fs'; 5 | // // const filebuffer = fs.readFileSync('./test.sqlite'); 6 | 7 | // initSqlJs().then(function (SQL) { 8 | // // const conn = new Connection(new SQL.Database()); 9 | // // conn.query(sql`CREATE TABLE "foo" ( "id" bigint NOT NULL )`); 10 | // // conn.query(sql`INSERT INTO "foo" (${sql.value(1)})`); 11 | // // const result = conn.query(sql`SELECT * FROM "foo"`); 12 | // // console.log(result); 13 | // }); 14 | 15 | test('see https://github.com/sql-js/sql.js/issues/517', () => {}); 16 | -------------------------------------------------------------------------------- /connectors/sqljs-connector/src/__tests__/test.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vlcn-io/vlcn-orm/ff90a4d588a5bed0fdcea0335d328f7c4dd51cd8/connectors/sqljs-connector/src/__tests__/test.sqlite -------------------------------------------------------------------------------- /connectors/sqljs-connector/src/index.ts: -------------------------------------------------------------------------------- 1 | import { DBResolver, basicResolver, SQLResolvedDB, sql } from '@aphro/runtime-ts'; 2 | // @ts-ignore 3 | import initSqlJs from '@aphro/sql.js'; 4 | import { Connection, createConnection } from './Connection.js'; 5 | 6 | /** 7 | * Convenience function to create a connection to absurd-sql and return 8 | * a db resolver that resolves to that connection. 9 | * 10 | * You should _only_ ever call `createResolver` one time from your application. 11 | * After calling `createResolver`, attach the provided resolver to `Context` and/or pass 12 | * your resolver instance around to where it is needed. 13 | * 14 | * Only call this once since each call will try to start up a new sqlite instance. 15 | * 16 | * @returns DBResolver 17 | */ 18 | export async function openDbAndCreateResolver( 19 | dbName: string, 20 | file: string | null, 21 | ): Promise { 22 | const sqlPromise = initSqlJs({ 23 | locateFile: (file: string) => { 24 | return 'https://esm.sh/@aphro/sql.js/dist/sql-wasm.wasm'; 25 | }, 26 | }); 27 | let dataPromise: Promise | null = null; 28 | if (file != null) { 29 | dataPromise = fetch(file).then(res => res.arrayBuffer()); 30 | } 31 | const [SQL, buf] = await Promise.all([sqlPromise, dataPromise]); 32 | return basicResolver(dbName, createConnection(SQL, buf)); 33 | } 34 | -------------------------------------------------------------------------------- /connectors/sqljs-connector/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"], 8 | "references": [{ "path": "../../packages/runtime-ts" }] 9 | } 10 | -------------------------------------------------------------------------------- /connectors/wa-sqlite-connector/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /connectors/wa-sqlite-connector/README.md: -------------------------------------------------------------------------------- 1 | # wa-sqlite 2 | 3 | Adapter to let `Aphrodite` query `wa-sqlite` 4 | -------------------------------------------------------------------------------- /connectors/wa-sqlite-connector/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/wa-sqlite-connector", 3 | "version": "0.3.3", 4 | "main": "lib/index.js", 5 | "type": "module", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/tantaman/aphrodite.git", 9 | "directory": "packages/wa-sqlite-connector" 10 | }, 11 | "dependencies": { 12 | "@aphro/instrument": "workspace:*", 13 | "@aphro/runtime-ts": "workspace:*", 14 | "@opentelemetry/api": "^1.1.0", 15 | "@strut/counter": "^0.0.11", 16 | "wa-sqlite": "github:rhashimoto/wa-sqlite#buildless" 17 | }, 18 | "devDependencies": { 19 | "@babel/core": "^7.18.13", 20 | "@babel/preset-env": "^7.18.10", 21 | "@types/jest": "^28.1.8", 22 | "jest": "^29.0.1", 23 | "typescript": "^4.8.2" 24 | }, 25 | "scripts": { 26 | "clean": "tsc --build --clean", 27 | "build": "tsc --build", 28 | "watch": "tsc --build -w", 29 | "deep-clean": "rm -rf ./lib || true && rm tsconfig.tsbuildinfo || true" 30 | }, 31 | "jest": { 32 | "testMatch": [ 33 | "**/__tests__/**/*.test.js" 34 | ] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /connectors/wa-sqlite-connector/src/index.ts: -------------------------------------------------------------------------------- 1 | import { DBResolver, basicResolver } from '@aphro/runtime-ts'; 2 | import createPool from './ConnectionPool.js'; 3 | 4 | /** 5 | * Convenience function to create a connection to absurd-sql and return 6 | * a db resolver that resolves to that connection. 7 | * 8 | * You should _only_ ever call `createResolver` one time from your application. 9 | * After calling `createResolver`, attach the provided resolver to `Context` and/or pass 10 | * your resolver instance around to where it is needed. 11 | * 12 | * Only call this once since each call will try to start up a new sqlite instance. 13 | * 14 | * @returns DBResolver 15 | */ 16 | export async function openDbAndCreateResolver(dbName: string): Promise { 17 | const pool = await createPool(dbName); 18 | return basicResolver(dbName, pool); 19 | } 20 | -------------------------------------------------------------------------------- /connectors/wa-sqlite-connector/src/sqliteInit.ts: -------------------------------------------------------------------------------- 1 | import SQLiteAsyncESMFactory from 'wa-sqlite/dist/wa-sqlite-async.mjs'; 2 | import * as SQLite from 'wa-sqlite'; 3 | // @ts-ignore 4 | import { IDBBatchAtomicVFS } from 'wa-sqlite/src/examples/IDBBatchAtomicVFS.js'; 5 | 6 | let api: SQLiteAPI | null = null; 7 | export default async function getSqliteApi(): Promise { 8 | if (api != null) { 9 | return api; 10 | } 11 | 12 | const module = await SQLiteAsyncESMFactory({ 13 | locateFile(file: string) { 14 | return file; 15 | }, 16 | }); 17 | const sqlite3 = SQLite.Factory(module); 18 | sqlite3.vfs_register(new IDBBatchAtomicVFS('idb-batch-atomic', { durability: 'relaxed' })); 19 | 20 | return sqlite3; 21 | } 22 | -------------------------------------------------------------------------------- /connectors/wa-sqlite-connector/src/trace.ts: -------------------------------------------------------------------------------- 1 | import { tracer, Tracer } from '@aphro/instrument'; 2 | 3 | const t: Tracer = tracer('@aphro/wa-sqlite-connector', '0.2.3'); 4 | 5 | export default t; 6 | -------------------------------------------------------------------------------- /connectors/wa-sqlite-connector/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["./src/"], 9 | "references": [{ "path": "../../packages/runtime-ts" }, { "path": "../../packages/instrument" }] 10 | } 11 | -------------------------------------------------------------------------------- /examples/chinook/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /examples/chinook/README.md: -------------------------------------------------------------------------------- 1 | # Aphrodite Chinook 2 | 3 | `Aphrodite` Schemas to match the [Chinook / North Wind datasets](https://github.com/lerocha/chinook-database). 4 | 5 | Deployed to `TypeCell` for interactive use and querying. -------------------------------------------------------------------------------- /examples/chinook/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | '@babel/preset-env', 5 | { 6 | targets: { 7 | node: 'current', 8 | }, 9 | }, 10 | ], 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /examples/chinook/db/chinook.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vlcn-io/vlcn-orm/ff90a4d588a5bed0fdcea0335d328f7c4dd51cd8/examples/chinook/db/chinook.sqlite -------------------------------------------------------------------------------- /examples/chinook/exploratory.md: -------------------------------------------------------------------------------- 1 | To support: 2 | 3 | ```sql 4 | select artistId, count(*) from album group by artistId order by count(*) desc 5 | ``` 6 | 7 | ```ts 8 | aritst.queryAll().orderBy(a => a.queryAlbums().count()); 9 | ``` 10 | 11 | Ordering by a query from the source would just be a join? 12 | 13 | It is: 14 | 1. An aggregation via grouping against the source id 15 | 2. an ordering by the count 16 | 17 | ```sql 18 | select artist.*, count(*) from artist join album on album.artistId = artist.id group by artist.id order by count(*) 19 | ``` 20 | 21 | ```ts 22 | artist.queryAll().wantData().queryAlbums().count() 23 | ``` 24 | 25 | to get the artists + their album count. 26 | 27 | simpler example: 28 | 29 | ```ts 30 | artist.queryAll().wantData().queryAlbums().gen() 31 | ``` 32 | 33 | result: 34 | ```sql 35 | select artist.*, album.* from artist join album on album.artistId = artist.id 36 | ``` -------------------------------------------------------------------------------- /examples/chinook/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/chinook", 3 | "version": "0.3.6", 4 | "main": "lib/index.js", 5 | "type": "module", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/tantaman/aphrodite.git", 9 | "directory": "examples/chinook" 10 | }, 11 | "dependencies": { 12 | "@aphro/runtime-ts": "workspace:*" 13 | }, 14 | "devDependencies": { 15 | "@aphro/codegen-cli": "workspace:*", 16 | "@babel/core": "^7.18.13", 17 | "@babel/preset-env": "^7.18.10", 18 | "@databases/sqlite": "^4.0.1", 19 | "@types/jest": "^28.1.8", 20 | "@types/node": "^18.7.13", 21 | "jest": "^29.0.1", 22 | "typescript": "^4.8.2" 23 | }, 24 | "scripts": { 25 | "aphro": "aphro gen ./src/domain.aphro --dest ./src/domain", 26 | "clean": "tsc --build --clean", 27 | "build": "tsc --build", 28 | "watch": "tsc --build -w", 29 | "deep-clean": "rm -rf ./lib || true && rm tsconfig.tsbuildinfo || true", 30 | "bootstrap": "rm ./db/chinook.sqlite || true && node scripts/bootstrap.js && cd ./db && cat Chinook_Sqlite.sql | sqlite3 chinook.sqlite", 31 | "test": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js" 32 | }, 33 | "jest": { 34 | "testMatch": [ 35 | "**/__tests__/**/*.test.js" 36 | ] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /examples/chinook/scripts/bootstrap.js: -------------------------------------------------------------------------------- 1 | import connect, { sql } from '@databases/sqlite'; 2 | import fs from 'fs'; 3 | import path from 'path'; 4 | 5 | const db = connect('./db/chinook.sqlite'); 6 | 7 | async function createTables() { 8 | const generatedDir = path.join('.', 'src', 'generated'); 9 | const schemaPaths = fs.readdirSync(generatedDir).filter(name => name.endsWith('.sqlite.sql')); 10 | 11 | const schemas = schemaPaths.map(s => sql.file(path.join(generatedDir, s))); 12 | await Promise.all(schemas.map(s => db.query(s))); 13 | } 14 | 15 | await createTables(); 16 | 17 | // use `npm run bootstrap` -- seeding is done via cat rather than in this script at the moment. 18 | -------------------------------------------------------------------------------- /examples/chinook/scripts/convertDates.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | 3 | const contents = fs.readFileSync('./db/Chinook_Sqlite.sql', { encoding: 'utf8' }); 4 | //const contents = fs.readFileSync('./db/temp.sql', { encoding: 'utf8' }); 5 | 6 | const newContents = contents.replace( 7 | /'([0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2})'/g, 8 | (_match, p1) => { 9 | return new Date(p1).getTime(); 10 | }, 11 | ); 12 | 13 | console.log(newContents); 14 | -------------------------------------------------------------------------------- /examples/chinook/src/__tests__/mutator.test.ts: -------------------------------------------------------------------------------- 1 | // import CustomerMutations from '../generated/CustomerMutations'; 2 | // import Employee from '../generated/Employee'; 3 | // import EmployeeMutations from '../generated/EmployeeMutations'; 4 | import setup from './setup'; 5 | 6 | // Oof... we should make an in-memory copy the the db 7 | const ctx = setup(); 8 | 9 | // test('creating some nodes', async () => { 10 | // const employee = await Employee.queryAll(ctx).take(1).genxOnlyValue(); 11 | // const [handle] = CustomerMutations.create(ctx, { 12 | // email: 'foo@bar.com', 13 | // firstName: 'Foo', 14 | // lastName: 'Bar', 15 | // supportRep: employee, 16 | // }).save(); 17 | // await handle; 18 | // }); 19 | 20 | test('prevent clobbering db and uncomment above test', () => {}); 21 | -------------------------------------------------------------------------------- /examples/chinook/src/__tests__/query.test.ts: -------------------------------------------------------------------------------- 1 | import Employee from '../domain/Employee'; 2 | import Artist from '../domain/Artist'; 3 | import Album from '../domain/Album'; 4 | import setup from './setup'; 5 | 6 | const ctx = setup(); 7 | 8 | test('Query random things', async () => { 9 | const [managers, artists, albums, supported] = await Promise.all([ 10 | Employee.queryAll(ctx).queryReportsTo().gen(), 11 | Artist.queryAll(ctx).gen(), 12 | Album.queryAll(ctx).gen(), 13 | Employee.queryAll(ctx).querySupports().gen(), 14 | ]); 15 | 16 | expect(managers.length).toBeGreaterThan(0); 17 | expect(artists.length).toBeGreaterThan(0); 18 | expect(albums.length).toBeGreaterThan(0); 19 | expect(supported.length).toBeGreaterThan(0); 20 | }); 21 | -------------------------------------------------------------------------------- /examples/chinook/src/__tests__/setup.ts: -------------------------------------------------------------------------------- 1 | import connect, { sql } from '@databases/sqlite'; 2 | import { anonymous, basicResolver, context } from '@aphro/runtime-ts'; 3 | import { fileURLToPath } from 'url'; 4 | import * as path from 'path'; 5 | 6 | const __filename = fileURLToPath(import.meta.url); 7 | const __dirname = path.dirname(__filename); 8 | 9 | export default function setup() { 10 | const db = connect(__dirname + '/../../db/chinook.sqlite'); 11 | return context(anonymous(), basicResolver('chinook', db)); 12 | } 13 | -------------------------------------------------------------------------------- /examples/chinook/src/deviceId.ts: -------------------------------------------------------------------------------- 1 | // TODO: calculate a reasonable deviceid for the browser we're in 2 | export default 'aaaa'; 3 | -------------------------------------------------------------------------------- /examples/chinook/src/domain/Album.ts: -------------------------------------------------------------------------------- 1 | import AlbumBase from "./generated/AlbumBase.js"; 2 | export { Data } from "./generated/AlbumBase.js"; 3 | 4 | export default class Album extends AlbumBase { 5 | // insert any manual method you may have here 6 | } 7 | -------------------------------------------------------------------------------- /examples/chinook/src/domain/Artist.ts: -------------------------------------------------------------------------------- 1 | import ArtistBase from "./generated/ArtistBase.js"; 2 | export { Data } from "./generated/ArtistBase.js"; 3 | 4 | export default class Artist extends ArtistBase { 5 | // insert any manual method you may have here 6 | } 7 | -------------------------------------------------------------------------------- /examples/chinook/src/domain/Customer.ts: -------------------------------------------------------------------------------- 1 | import CustomerBase from "./generated/CustomerBase.js"; 2 | export { Data } from "./generated/CustomerBase.js"; 3 | 4 | export default class Customer extends CustomerBase { 5 | // insert any manual method you may have here 6 | } 7 | -------------------------------------------------------------------------------- /examples/chinook/src/domain/Employee.ts: -------------------------------------------------------------------------------- 1 | import EmployeeBase from "./generated/EmployeeBase.js"; 2 | export { Data } from "./generated/EmployeeBase.js"; 3 | 4 | export default class Employee extends EmployeeBase { 5 | // insert any manual method you may have here 6 | } 7 | -------------------------------------------------------------------------------- /examples/chinook/src/domain/Genre.ts: -------------------------------------------------------------------------------- 1 | import GenreBase from "./generated/GenreBase.js"; 2 | export { Data } from "./generated/GenreBase.js"; 3 | 4 | export default class Genre extends GenreBase { 5 | // insert any manual method you may have here 6 | } 7 | -------------------------------------------------------------------------------- /examples/chinook/src/domain/Invoice.ts: -------------------------------------------------------------------------------- 1 | import InvoiceBase from "./generated/InvoiceBase.js"; 2 | export { Data } from "./generated/InvoiceBase.js"; 3 | 4 | export default class Invoice extends InvoiceBase { 5 | // insert any manual method you may have here 6 | } 7 | -------------------------------------------------------------------------------- /examples/chinook/src/domain/InvoiceLine.ts: -------------------------------------------------------------------------------- 1 | import InvoiceLineBase from "./generated/InvoiceLineBase.js"; 2 | export { Data } from "./generated/InvoiceLineBase.js"; 3 | 4 | export default class InvoiceLine extends InvoiceLineBase { 5 | // insert any manual method you may have here 6 | } 7 | -------------------------------------------------------------------------------- /examples/chinook/src/domain/MediaType.ts: -------------------------------------------------------------------------------- 1 | import MediaTypeBase from "./generated/MediaTypeBase.js"; 2 | export { Data } from "./generated/MediaTypeBase.js"; 3 | 4 | export default class MediaType extends MediaTypeBase { 5 | // insert any manual method you may have here 6 | } 7 | -------------------------------------------------------------------------------- /examples/chinook/src/domain/Playlist.ts: -------------------------------------------------------------------------------- 1 | import PlaylistBase from "./generated/PlaylistBase.js"; 2 | export { Data } from "./generated/PlaylistBase.js"; 3 | 4 | export default class Playlist extends PlaylistBase { 5 | // insert any manual method you may have here 6 | } 7 | -------------------------------------------------------------------------------- /examples/chinook/src/domain/PlaylistTrack.ts: -------------------------------------------------------------------------------- 1 | import PlaylistTrackBase from "./generated/PlaylistTrackBase.js"; 2 | export { Data } from "./generated/PlaylistTrackBase.js"; 3 | 4 | export default class PlaylistTrack extends PlaylistTrackBase { 5 | // insert any manual method you may have here 6 | } 7 | -------------------------------------------------------------------------------- /examples/chinook/src/domain/Track.ts: -------------------------------------------------------------------------------- 1 | import TrackBase from "./generated/TrackBase.js"; 2 | export { Data } from "./generated/TrackBase.js"; 3 | 4 | export default class Track extends TrackBase { 5 | // insert any manual method you may have here 6 | } 7 | -------------------------------------------------------------------------------- /examples/chinook/src/domain/generated/Album.sqlite.sql: -------------------------------------------------------------------------------- 1 | -- SIGNED-SOURCE: 2 | -- STATEMENT 3 | CREATE TABLE 4 | "album" ("id", "title", "artistId", PRIMARY KEY ("id")); -------------------------------------------------------------------------------- /examples/chinook/src/domain/generated/Artist.sqlite.sql: -------------------------------------------------------------------------------- 1 | -- SIGNED-SOURCE: 2 | -- STATEMENT 3 | CREATE TABLE 4 | "artist" ("id", "name", PRIMARY KEY ("id")); -------------------------------------------------------------------------------- /examples/chinook/src/domain/generated/Customer.sqlite.sql: -------------------------------------------------------------------------------- 1 | -- SIGNED-SOURCE: 2 | -- STATEMENT 3 | CREATE TABLE 4 | "customer" ( 5 | "id", 6 | "firstName", 7 | "lastName", 8 | "company", 9 | "address", 10 | "city", 11 | "state", 12 | "country", 13 | "postalCode", 14 | "phone", 15 | "fax", 16 | "email", 17 | "supportRepId", 18 | PRIMARY KEY ("id") 19 | ); -------------------------------------------------------------------------------- /examples/chinook/src/domain/generated/Employee.sqlite.sql: -------------------------------------------------------------------------------- 1 | -- SIGNED-SOURCE: <535495a449a77496759a5e3cb925a61a> 2 | -- STATEMENT 3 | CREATE TABLE 4 | "employee" ( 5 | "id", 6 | "lastName", 7 | "firstName", 8 | "title", 9 | "reportsToId", 10 | "birthdate", 11 | "hiredate", 12 | "address", 13 | "city", 14 | "state", 15 | "country", 16 | "postalCode", 17 | "phone", 18 | "fax", 19 | "email", 20 | PRIMARY KEY ("id") 21 | ); -------------------------------------------------------------------------------- /examples/chinook/src/domain/generated/Genre.sqlite.sql: -------------------------------------------------------------------------------- 1 | -- SIGNED-SOURCE: <6659dc39c2f0fd6b8ced999a310befbf> 2 | -- STATEMENT 3 | CREATE TABLE 4 | "genre" ("id", "name", PRIMARY KEY ("id")); -------------------------------------------------------------------------------- /examples/chinook/src/domain/generated/Invoice.sqlite.sql: -------------------------------------------------------------------------------- 1 | -- SIGNED-SOURCE: 2 | -- STATEMENT 3 | CREATE TABLE 4 | "invoice" ( 5 | "id", 6 | "customerId", 7 | "invoiceDate", 8 | "billingAddress", 9 | "billingCity", 10 | "billingState", 11 | "billingCountry", 12 | "billingPostalCode", 13 | "total", 14 | PRIMARY KEY ("id") 15 | ); -------------------------------------------------------------------------------- /examples/chinook/src/domain/generated/InvoiceLine.sqlite.sql: -------------------------------------------------------------------------------- 1 | -- SIGNED-SOURCE: <02482512fc99368115f9f924b4eba544> 2 | -- STATEMENT 3 | CREATE TABLE 4 | "invoiceline" ( 5 | "id", 6 | "invoiceId", 7 | "trackId", 8 | "unitPrice", 9 | "quantity", 10 | PRIMARY KEY ("id") 11 | ); -------------------------------------------------------------------------------- /examples/chinook/src/domain/generated/MediaType.sqlite.sql: -------------------------------------------------------------------------------- 1 | -- SIGNED-SOURCE: <64370081725ed7c957d4f20cd1be4dfa> 2 | -- STATEMENT 3 | CREATE TABLE 4 | "mediatype" ("id", "name", PRIMARY KEY ("id")); -------------------------------------------------------------------------------- /examples/chinook/src/domain/generated/Playlist.sqlite.sql: -------------------------------------------------------------------------------- 1 | -- SIGNED-SOURCE: <7613eb8a38668e66459092953ed5448e> 2 | -- STATEMENT 3 | CREATE TABLE 4 | "playlist" ("id", "name", PRIMARY KEY ("id")); -------------------------------------------------------------------------------- /examples/chinook/src/domain/generated/PlaylistTrack.sqlite.sql: -------------------------------------------------------------------------------- 1 | -- SIGNED-SOURCE: 2 | -- STATEMENT 3 | CREATE TABLE 4 | "playlisttrack" ("id1", "id2"); -------------------------------------------------------------------------------- /examples/chinook/src/domain/generated/Track.sqlite.sql: -------------------------------------------------------------------------------- 1 | -- SIGNED-SOURCE: <56a5fdb7cb3182a7603af79842cf5563> 2 | -- STATEMENT 3 | CREATE TABLE 4 | "track" ( 5 | "id", 6 | "name", 7 | "albumId", 8 | "mediaTypeId", 9 | "genreId", 10 | "composer", 11 | "milliseconds", 12 | "bytes", 13 | "unitPrice", 14 | PRIMARY KEY ("id") 15 | ); -------------------------------------------------------------------------------- /examples/chinook/src/domain/generated/exports-sql.ts: -------------------------------------------------------------------------------- 1 | // SIGNED-SOURCE: 2 | /** 3 | * AUTO-GENERATED FILE 4 | * Do not modify. Update your schema and re-generate for changes. 5 | */ 6 | import Album from "./Album.sqlite.sql?raw"; 7 | import Artist from "./Artist.sqlite.sql?raw"; 8 | import Customer from "./Customer.sqlite.sql?raw"; 9 | import Employee from "./Employee.sqlite.sql?raw"; 10 | import Genre from "./Genre.sqlite.sql?raw"; 11 | import Invoice from "./Invoice.sqlite.sql?raw"; 12 | import InvoiceLine from "./InvoiceLine.sqlite.sql?raw"; 13 | import MediaType from "./MediaType.sqlite.sql?raw"; 14 | import Playlist from "./Playlist.sqlite.sql?raw"; 15 | import Track from "./Track.sqlite.sql?raw"; 16 | import PlaylistTrack from "./PlaylistTrack.sqlite.sql?raw"; 17 | export default { 18 | sqlite: { 19 | chinook: { 20 | Album, 21 | Artist, 22 | Customer, 23 | Employee, 24 | Genre, 25 | Invoice, 26 | InvoiceLine, 27 | MediaType, 28 | Playlist, 29 | Track, 30 | PlaylistTrack, 31 | }, 32 | }, 33 | }; 34 | -------------------------------------------------------------------------------- /examples/chinook/src/domain/generated/exports.ts: -------------------------------------------------------------------------------- 1 | // SIGNED-SOURCE: 2 | /** 3 | * AUTO-GENERATED FILE 4 | * Do not modify. Update your schema and re-generate for changes. 5 | */ 6 | export { default as Album } from "../Album.js"; 7 | export { default as Artist } from "../Artist.js"; 8 | export { default as Customer } from "../Customer.js"; 9 | export { default as Employee } from "../Employee.js"; 10 | export { default as Genre } from "../Genre.js"; 11 | export { default as GenreMutations } from "./GenreMutations.js"; 12 | export { default as Invoice } from "../Invoice.js"; 13 | export { default as InvoiceLine } from "../InvoiceLine.js"; 14 | export { default as MediaType } from "../MediaType.js"; 15 | export { default as Playlist } from "../Playlist.js"; 16 | export { default as Track } from "../Track.js"; 17 | export { default as PlaylistTrack } from "../PlaylistTrack.js"; 18 | -------------------------------------------------------------------------------- /examples/chinook/src/domain/generated/types.d.ts: -------------------------------------------------------------------------------- 1 | // SIGNED-SOURCE: <7946820adce4295e4ffad7d91d8edf9a> 2 | /** 3 | * AUTO-GENERATED FILE 4 | * Do not modify. Update your schema and re-generate for changes. 5 | */ 6 | declare module "*.sql?raw"; 7 | -------------------------------------------------------------------------------- /examples/chinook/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './domain/generated/exports.js'; 2 | -------------------------------------------------------------------------------- /examples/chinook/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"], 8 | "references": [{ "path": "../../packages/runtime-ts" }, { "path": "../../packages/codegen-cli" }] 9 | } 10 | -------------------------------------------------------------------------------- /examples/demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | demo 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/demo", 3 | "private": true, 4 | "license": "MIT", 5 | "type": "module", 6 | "scripts": { 7 | "start": "vite", 8 | "build": "vite build", 9 | "aphro": "aphro gen ./src/domain.aphro --dest ./src/domain && pnpm copy", 10 | "copy": "cp src/domain/generated/*.sql dist/domain/generated", 11 | "clean": "rm -rf dist", 12 | "tsc": "tsc --noEmit" 13 | }, 14 | "dependencies": { 15 | "@aphro/react": "workspace:*", 16 | "@aphro/runtime-ts": "workspace:*", 17 | "@aphro/wa-sqlite-connector": "workspace:*", 18 | "react": "^18.2.0", 19 | "react-dom": "^18.2.0" 20 | }, 21 | "devDependencies": { 22 | "@aphro/codegen-cli": "workspace:*", 23 | "@types/react": "^18.0.17", 24 | "@types/react-dom": "^18.0.6", 25 | "typescript": "^4.8.2", 26 | "vite": "^3.0.4" 27 | }, 28 | "version": "0.1.10" 29 | } 30 | -------------------------------------------------------------------------------- /examples/demo/public/wa-sqlite-async.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vlcn-io/vlcn-orm/ff90a4d588a5bed0fdcea0335d328f7c4dd51cd8/examples/demo/public/wa-sqlite-async.wasm -------------------------------------------------------------------------------- /examples/demo/src/domain.aphro: -------------------------------------------------------------------------------- 1 | engine: sqlite 2 | db: demo 3 | 4 | User as Node { 5 | 1 id: ID 6 | 2 email: string 7 | } 8 | -------------------------------------------------------------------------------- /examples/demo/src/domain/User.ts: -------------------------------------------------------------------------------- 1 | import UserBase from './generated/UserBase.js'; 2 | export type { Data } from './generated/UserBase.js'; 3 | 4 | export default class User extends UserBase { 5 | // insert any manual method you may have here 6 | } 7 | -------------------------------------------------------------------------------- /examples/demo/src/domain/generated/User.sqlite.sql: -------------------------------------------------------------------------------- 1 | -- SIGNED-SOURCE: <9a3800acf2a1c2b8d75c64180549682e> 2 | -- STATEMENT 3 | CREATE TABLE 4 | "user" ( 5 | "id" 6 | /* n=1 */ 7 | , 8 | "email" 9 | /* n=2 */ 10 | , 11 | PRIMARY KEY ("id") 12 | ); -------------------------------------------------------------------------------- /examples/demo/src/domain/generated/exports-node-sql.ts: -------------------------------------------------------------------------------- 1 | // SIGNED-SOURCE: 2 | /** 3 | * AUTO-GENERATED FILE 4 | * Do not modify. Update your schema and re-generate for changes. 5 | */ 6 | 7 | // @ts-ignore 8 | import * as path from "path"; 9 | // @ts-ignore 10 | import * as fs from "fs"; 11 | 12 | // @ts-ignore 13 | import { fileURLToPath } from "url"; 14 | 15 | const __filename = fileURLToPath(import.meta.url); 16 | const __dirname = path.dirname(__filename); 17 | 18 | const [User] = await Promise.all([ 19 | fs.promises.readFile(path.join(__dirname, "User.sqlite.sql"), { 20 | encoding: "utf8", 21 | }), 22 | ]); 23 | 24 | export default { 25 | sqlite: { 26 | demo: { 27 | User, 28 | }, 29 | }, 30 | }; 31 | -------------------------------------------------------------------------------- /examples/demo/src/domain/generated/exports-sql.ts: -------------------------------------------------------------------------------- 1 | // SIGNED-SOURCE: 2 | /** 3 | * AUTO-GENERATED FILE 4 | * Do not modify. Update your schema and re-generate for changes. 5 | */ 6 | import User from "./User.sqlite.sql?raw"; 7 | export default { 8 | sqlite: { 9 | demo: { 10 | User, 11 | }, 12 | }, 13 | }; 14 | -------------------------------------------------------------------------------- /examples/demo/src/domain/generated/exports.ts: -------------------------------------------------------------------------------- 1 | // SIGNED-SOURCE: <1c6e2363775cb1812578ec35d4cdfd47> 2 | /** 3 | * AUTO-GENERATED FILE 4 | * Do not modify. Update your schema and re-generate for changes. 5 | */ 6 | export { default as User } from "../User.js"; 7 | export { default as UserSpec } from "./UserSpec.js"; 8 | export { default as UserQuery } from "./UserQuery.js"; 9 | -------------------------------------------------------------------------------- /examples/demo/src/domain/generated/types.d.ts: -------------------------------------------------------------------------------- 1 | // SIGNED-SOURCE: <7946820adce4295e4ffad7d91d8edf9a> 2 | /** 3 | * AUTO-GENERATED FILE 4 | * Do not modify. Update your schema and re-generate for changes. 5 | */ 6 | declare module "*.sql?raw"; 7 | -------------------------------------------------------------------------------- /examples/demo/src/global.d.ts: -------------------------------------------------------------------------------- 1 | type FetchFrag any }, K extends string> = Awaited< 2 | ReturnType 3 | >[K]; 4 | 5 | type Frags any }> = Awaited>; 6 | -------------------------------------------------------------------------------- /examples/demo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "node", 4 | "outDir": "./dist/", 5 | "sourceMap": true, 6 | "strictNullChecks": true, 7 | "module": "esnext", 8 | "jsx": "react", 9 | "target": "esnext", 10 | "allowJs": true, 11 | "checkJs": false, 12 | "importHelpers": true, 13 | "baseUrl": ".", 14 | "rootDir": ".", 15 | "resolveJsonModule": true, 16 | "allowSyntheticDefaultImports": true, 17 | "typeRoots": ["./src/@types"], 18 | "plugins": [{ "name": "typescript-plugin-css-modules" }], 19 | "incremental": true, 20 | "composite": true 21 | }, 22 | "include": ["./src/"] 23 | } 24 | -------------------------------------------------------------------------------- /examples/demo/vite.config.js: -------------------------------------------------------------------------------- 1 | // vite.config.js 2 | export default { 3 | server: { 4 | fs: { 5 | strict: false, 6 | }, 7 | }, 8 | build: {}, 9 | }; 10 | -------------------------------------------------------------------------------- /examples/monopoly-p2p/README.md: -------------------------------------------------------------------------------- 1 | # Monopoly P2P 2 | 3 | WIP 4 | 5 | todo-mvc is currently the only example in a complete state. Monopoly & monopoly p2p are under development. -------------------------------------------------------------------------------- /examples/monopoly/README.md: -------------------------------------------------------------------------------- 1 | # Monopoly (WIP) 2 | 3 | todo-mvc is currently the only example in a complete state. Monopoly & monopoly p2p are under development. 4 | 5 | Implements a game of monopoly via a central server that exposes the game API over GraphQL. 6 | 7 | See monopoly-p2p for a p2p monopoly game. -------------------------------------------------------------------------------- /examples/monopoly/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/monopoly", 3 | "version": "1.2.8", 4 | "main": "index.js", 5 | "private": true, 6 | "license": "MIT", 7 | "type": "module", 8 | "scripts": { 9 | "aphro": "aphro gen ./src/domain.aphro --dest ./src/generated && cp src/generated/*.sql dist/generated && cp src/generated/*.graphql dist/generated", 10 | "clean": "tsc --build --clean", 11 | "build": "tsc --build", 12 | "watch": "tsc --build -w", 13 | "dev": "cross-env NODE_ENV=development ts-node-dev --exit-child --respawn src/main.ts", 14 | "start": "cross-env NODE_ENV=development node dist/main.js" 15 | }, 16 | "dependencies": { 17 | "@aphro/runtime-ts": "workspace:*", 18 | "@databases/sqlite": "^4.0.1", 19 | "@graphql-tools/schema": "^9.0.2", 20 | "@graphql-yoga/node": "^2.13.11", 21 | "graphql": "^16.6.0" 22 | }, 23 | "devDependencies": { 24 | "@aphro/codegen-cli": "workspace:*", 25 | "@types/node": "^18.7.13", 26 | "cross-env": "^7.0.3", 27 | "ts-node": "^10.9.1", 28 | "ts-node-dev": "^2.0.0", 29 | "typescript": "^4.8.2" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /examples/monopoly/src/generated/Game.sqlite.sql: -------------------------------------------------------------------------------- 1 | -- SIGNED-SOURCE: 2 | CREATE TABLE 3 | IF NOT EXISTS "game" ( 4 | "id" bigint NOT NULL, 5 | "name" text NOT NULL, 6 | primary key ("id") 7 | ) -------------------------------------------------------------------------------- /examples/monopoly/src/generated/Person.sqlite.sql: -------------------------------------------------------------------------------- 1 | -- SIGNED-SOURCE: <0ba0200ab00198aadbeb9e21776f3a9a> 2 | CREATE TABLE 3 | IF NOT EXISTS "person" ( 4 | "id" bigint NOT NULL, 5 | "token" text NOT NULL, 6 | primary key ("id") 7 | ) -------------------------------------------------------------------------------- /examples/monopoly/src/generated/Player.sqlite.sql: -------------------------------------------------------------------------------- 1 | -- SIGNED-SOURCE: 2 | CREATE TABLE 3 | IF NOT EXISTS "player" ( 4 | "id" bigint NOT NULL, 5 | "piece" text NOT NULL, 6 | "ownerId" bigint NOT NULL, 7 | "gameId" bigint NOT NULL, 8 | primary key ("id") 9 | ) -------------------------------------------------------------------------------- /examples/monopoly/src/generated/Property.sqlite.sql: -------------------------------------------------------------------------------- 1 | -- SIGNED-SOURCE: <08d2c4888e57b6cdcaa6a8f0ef8ad9c7> 2 | CREATE TABLE 3 | IF NOT EXISTS "property" ( 4 | "id" bigint NOT NULL, 5 | "name" text NOT NULL, 6 | "ownerId" bigint, 7 | "gameId" bigint NOT NULL, 8 | "cost" float NOT NULL, 9 | "mortgaged" boolean NOT NULL, 10 | "numHouses" int NOT NULL, 11 | "numHotels" int NOT NULL, 12 | primary key ("id") 13 | ) -------------------------------------------------------------------------------- /examples/monopoly/src/generated/domain.graphql-resolvers.ts: -------------------------------------------------------------------------------- 1 | // SIGNED-SOURCE: <27692841a2c8c823fd282d35dc964acf> 2 | /** 3 | * AUTO-GENERATED FILE 4 | * Do not modify. Update your schema and re-generate for changes. 5 | * For partially generated files, place modifications between the generated `BEGIN-MANUAL-SECTION` and 6 | * `END-MANUAL-SECTION` markers. 7 | */ 8 | import Person from "./Person.js"; 9 | import { Context } from "@aphro/runtime-ts"; 10 | import { P } from "@aphro/runtime-ts"; 11 | 12 | export const resolvers = { 13 | Query: { 14 | async person( 15 | parent, 16 | args, 17 | ctx: { aphrodite: Context }, 18 | info 19 | ): Promise { 20 | return await Person.gen(ctx.aphrodite, args.id); 21 | }, 22 | 23 | async persons( 24 | parent, 25 | args, 26 | ctx: { aphrodite: Context }, 27 | info 28 | ): Promise { 29 | return await Person.queryAll(ctx.aphrodite) 30 | .whereId(P.in(new Set(args.ids))) 31 | .gen(); 32 | }, 33 | }, 34 | }; 35 | -------------------------------------------------------------------------------- /examples/monopoly/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowSyntheticDefaultImports": true, 4 | "module": "esnext", 5 | "target": "esnext", 6 | "moduleResolution": "Node", 7 | "skipLibCheck": true, 8 | "sourceMap": true, 9 | "outDir": "./dist", 10 | "baseUrl": "./" 11 | }, 12 | "include": ["./src/"], 13 | "references": [{ "path": "../../packages/codegen-cli" }, { "path": "../../packages/runtime-ts" }] 14 | } 15 | -------------------------------------------------------------------------------- /examples/todo-mvc-mem/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /examples/todo-mvc-mem/README.md: -------------------------------------------------------------------------------- 1 | # TodoMVC - Mem 2 | 3 | `Aphro` can use `SQL` as a backing store or it can work with the models in memory only. 4 | 5 | The use case for the latter is a small set of application state that you'd like to work with completely in memory. You can persist the entire contents of the in-memory DB as a blob in LocalStorage or IndexDB to enable persistence across sessions. -------------------------------------------------------------------------------- /examples/todo-mvc-mem/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/todo-mvc-mem", 3 | "private": true, 4 | "license": "MIT", 5 | "type": "module", 6 | "scripts": { 7 | "start": "webpack serve", 8 | "build": "webpack", 9 | "aphro": "aphro gen ./src/domain.aphro --dest ./src/generated", 10 | "clean": "rm -rf dist", 11 | "ts-build": "tsc" 12 | }, 13 | "dependencies": { 14 | "@aphro/react": "workspace:*", 15 | "@aphro/runtime-ts": "workspace:*", 16 | "react": "^18.2.0", 17 | "react-dom": "^18.2.0" 18 | }, 19 | "devDependencies": { 20 | "@aphro/codegen-cli": "workspace:*", 21 | "@types/react": "^18.0.17", 22 | "@types/react-dom": "^18.0.6", 23 | "html-webpack-plugin": "^5.5.0", 24 | "raw-loader": "^4.0.2", 25 | "resolve-typescript-plugin": "^1.2.0", 26 | "ts-loader": "^9.3.1", 27 | "typescript": "^4.8.2", 28 | "webpack": "^5.74.0", 29 | "webpack-cli": "^4.10.0", 30 | "webpack-dev-server": "^4.10.0" 31 | }, 32 | "version": "0.1.10" 33 | } 34 | -------------------------------------------------------------------------------- /examples/todo-mvc-mem/src/domain.aphro: -------------------------------------------------------------------------------- 1 | engine: memory 2 | db: todomvc 3 | 4 | Todo as Node { 5 | id: ID 6 | listId: ID 7 | text: string 8 | completed: bool 9 | } 10 | 11 | TodoList as Node { 12 | id: ID 13 | filter: Enumeration 14 | editing: ID | null 15 | } & OutboundEdges { 16 | todos: Edge 17 | } -------------------------------------------------------------------------------- /examples/todo-mvc-mem/src/generated/Todo.ts: -------------------------------------------------------------------------------- 1 | import TodoBase from "./generated/TodoBase.js"; 2 | export { Data } from "./generated/TodoBase.js"; 3 | 4 | export default class Todo extends TodoBase { 5 | // insert any manual method you may have here 6 | } 7 | -------------------------------------------------------------------------------- /examples/todo-mvc-mem/src/generated/TodoList.ts: -------------------------------------------------------------------------------- 1 | import TodoListBase from "./generated/TodoListBase.js"; 2 | export { Data } from "./generated/TodoListBase.js"; 3 | 4 | export default class TodoList extends TodoListBase { 5 | // insert any manual method you may have here 6 | } 7 | -------------------------------------------------------------------------------- /examples/todo-mvc-mem/src/generated/generated/exports.ts: -------------------------------------------------------------------------------- 1 | // SIGNED-SOURCE: <43cba4e780321beb1a115a65c06ed92e> 2 | /** 3 | * AUTO-GENERATED FILE 4 | * Do not modify. Update your schema and re-generate for changes. 5 | */ 6 | export { default as Todo } from "../Todo.js"; 7 | export { default as TodoList } from "../TodoList.js"; 8 | -------------------------------------------------------------------------------- /examples/todo-mvc-mem/src/generated/generated/types.d.ts: -------------------------------------------------------------------------------- 1 | // SIGNED-SOURCE: <7946820adce4295e4ffad7d91d8edf9a> 2 | /** 3 | * AUTO-GENERATED FILE 4 | * Do not modify. Update your schema and re-generate for changes. 5 | */ 6 | declare module "*.sql?raw"; 7 | -------------------------------------------------------------------------------- /examples/todo-mvc-mem/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Aphrodite • TodoMVC 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /examples/todo-mvc-mem/src/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { createRoot } from 'react-dom/client'; 3 | import App from './App.js'; 4 | 5 | const container = document.getElementById('container'); 6 | if (container == null) { 7 | throw new Error(); 8 | } 9 | const root = createRoot(container); 10 | root.render( 11 | Loading...}> 12 | 13 | , 14 | ); 15 | -------------------------------------------------------------------------------- /examples/todo-mvc-mem/src/store.ts: -------------------------------------------------------------------------------- 1 | import { createHooks } from '@aphro/react'; 2 | import { anonymous, basicResolver, MemoryDB, sid } from '@aphro/runtime-ts'; 3 | import { context, Context } from '@aphro/runtime-ts'; 4 | import TodoList from './generated/TodoList.js'; 5 | 6 | export const ctx = context(anonymous(), basicResolver('todomvc', new MemoryDB())); 7 | (window as any).TodoList = TodoList; 8 | (window as any).ctx = ctx; 9 | 10 | async function bootstrap(ctx: Context): Promise { 11 | let list = await TodoList.queryAll(ctx).genOnlyValue(); 12 | if (list == null) { 13 | list = TodoList.create(ctx, { 14 | id: sid('aaaa'), 15 | filter: 'all', 16 | editing: null, 17 | }).save().optimistic; 18 | } 19 | 20 | return list; 21 | } 22 | 23 | const initialized = bootstrap(ctx).then(() => { 24 | return ctx; 25 | }); 26 | 27 | export const { useQuery, useQueryOne, useBind } = createHooks(initialized); 28 | -------------------------------------------------------------------------------- /examples/todo-mvc-mem/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist/", // path to output directory 4 | "sourceMap": true, // allow sourcemap support 5 | "strictNullChecks": true, // enable strict null checks as a best practice 6 | "module": "esnext", // specify module code generation 7 | "target": "esnext", // specify ECMAScript target version 8 | "moduleResolution": "node", 9 | "rootDir": "./", 10 | "allowJs": true, 11 | "strict": true, 12 | "jsx": "react" 13 | }, 14 | "include": ["./src/"] 15 | } 16 | -------------------------------------------------------------------------------- /examples/todo-mvc-mem/webpack.config.js: -------------------------------------------------------------------------------- 1 | import HtmlWebpackPlugin from 'html-webpack-plugin'; 2 | import ResolveTypeScriptPlugin from 'resolve-typescript-plugin'; 3 | import path from 'path'; 4 | import { fileURLToPath } from 'url'; 5 | 6 | const __filename = fileURLToPath(import.meta.url); 7 | const __dirname = path.dirname(__filename); 8 | 9 | export default { 10 | devServer: { 11 | static: { 12 | directory: path.resolve(__dirname), 13 | publicPath: '/', 14 | }, 15 | allowedHosts: 'all', 16 | hot: true, 17 | }, 18 | entry: './src/index.tsx', 19 | mode: 'development', 20 | resolve: { 21 | plugins: [new ResolveTypeScriptPlugin()], 22 | extensions: ['.dev.js', '.js', '.json', '.wasm', 'ts', 'tsx'], 23 | fallback: { 24 | crypto: false, 25 | path: false, 26 | fs: false, 27 | }, 28 | }, 29 | plugins: [new HtmlWebpackPlugin({ template: './src/index.html' })], 30 | module: { 31 | rules: [ 32 | { 33 | test: /\.sql$/i, 34 | use: 'raw-loader', 35 | }, 36 | { 37 | test: /\.tsx?$/, 38 | use: 'ts-loader', 39 | exclude: /node_modules/, 40 | }, 41 | ], 42 | }, 43 | }; 44 | -------------------------------------------------------------------------------- /examples/todo-mvc-p2p/README.md: -------------------------------------------------------------------------------- 1 | # Todo MVC P2P 2 | 3 | Extension of Todo MVC that allow p2p collaboration on todo lists. -------------------------------------------------------------------------------- /examples/todo-mvc/README.md: -------------------------------------------------------------------------------- 1 | moved to https://github.com/tantaman/aphrodite-browser-starter 2 | -------------------------------------------------------------------------------- /extensions/authorization-grammar/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /extensions/authorization-grammar/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /extensions/authorization-grammar/README.md: -------------------------------------------------------------------------------- 1 | # Auth Grammar 2 | 3 | Extends `Aphrodite SDL` with a grammar for defining row, column and edge level visibility. 4 | 5 | Before: 6 | ``` 7 | User as Node { 8 | id: ID 9 | name: NaturalLanguage 10 | password: PBKDF2 11 | } 12 | ``` 13 | 14 | After: 15 | ``` 16 | User as Node { 17 | id: ID 18 | name: NaturalLanguage 19 | password: PBKDF2 & Auth { red: [AllowIf((viewer, node) => node.id === viewer.id)] } # field level privacy 20 | } & Authorization { # object level privacy 21 | read: [ 22 | AlwaysAllow # everyone can see everyone 23 | ] 24 | write: [ 25 | AllowIf((viewer, node) => node.id === viewer.id) # only user themselves can update themselves 26 | ] 27 | } 28 | ``` 29 | 30 | > TODO: this should also extend the `mutation` grammar to allow auth on specific mutations. -------------------------------------------------------------------------------- /extensions/authorization-grammar/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/authorization-grammar", 3 | "version": "0.2.6", 4 | "main": "lib/index.js", 5 | "type": "module", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/tantaman/aphrodite.git", 9 | "directory": "extensions/authorization-grammar" 10 | }, 11 | "devDependencies": { 12 | "typescript": "^4.8.2" 13 | }, 14 | "scripts": { 15 | "clean": "tsc --build --clean", 16 | "build": "tsc --build", 17 | "watch": "tsc --build -w", 18 | "deep-clean": "rm -rf ./lib || true && rm tsconfig.tsbuildinfo || true" 19 | }, 20 | "jest": { 21 | "testMatch": [ 22 | "**/__tests__/**/*.test.js" 23 | ] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /extensions/authorization-grammar/src/index.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vlcn-io/vlcn-orm/ff90a4d588a5bed0fdcea0335d328f7c4dd51cd8/extensions/authorization-grammar/src/index.ts -------------------------------------------------------------------------------- /extensions/authorization-grammar/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./lib/", // path to output directory 4 | "sourceMap": true, // allow sourcemap support 5 | "strictNullChecks": true, // enable strict null checks as a best practice 6 | "module": "esnext", // specify module code generation 7 | "target": "esnext", // specify ECMAScript target version 8 | "skipLibCheck": true, 9 | "moduleResolution": "Node", 10 | "emitDecoratorMetadata": true, 11 | "experimentalDecorators": true, 12 | "baseUrl": "./src/", 13 | "declaration": true, 14 | "allowJs": true, 15 | "composite": true, 16 | "declarationMap": true, 17 | "incremental": true, 18 | "rootDir": "./src" 19 | }, 20 | "include": ["./src/"], 21 | "references": [] 22 | } 23 | -------------------------------------------------------------------------------- /extensions/decorator-grammar/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /extensions/graphql-codegen/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /extensions/graphql-codegen/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /extensions/graphql-codegen/README.md: -------------------------------------------------------------------------------- 1 | # GraphQL Codegen 2 | 3 | ## src/graphql 4 | 5 | Generates the `.graphql` schema file 6 | 7 | ## src/typescript 8 | 9 | Generates resolvers for the schema for `typescript`. 10 | 11 | Assumes a [`yoga`](https://www.graphql-yoga.com/) compliant API for resolver definition. 12 | 13 | e.g., https://www.digitalocean.com/community/tutorials/graphql-schemas-resolvers-graphql -------------------------------------------------------------------------------- /extensions/graphql-codegen/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | '@babel/preset-env', 5 | { 6 | targets: { 7 | node: 'current', 8 | }, 9 | }, 10 | ], 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /extensions/graphql-codegen/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/graphql-codegen", 3 | "version": "0.2.9", 4 | "main": "lib/index.js", 5 | "type": "module", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/tantaman/aphrodite.git", 9 | "directory": "extensions/graphql-codegen" 10 | }, 11 | "dependencies": { 12 | "@aphro/codegen": "workspace:*", 13 | "@aphro/codegen-api": "workspace:*", 14 | "@aphro/codegen-ts": "workspace:*", 15 | "@aphro/graphql-grammar": "workspace:*", 16 | "@aphro/schema": "workspace:*", 17 | "@aphro/schema-api": "workspace:*", 18 | "@strut/utils": "^0.1.1" 19 | }, 20 | "devDependencies": { 21 | "@babel/core": "^7.18.13", 22 | "@babel/preset-env": "^7.18.10", 23 | "@types/jest": "^28.1.8", 24 | "jest": "^29.0.1", 25 | "typescript": "^4.8.2" 26 | }, 27 | "scripts": { 28 | "clean": "tsc --build --clean", 29 | "build": "tsc --build", 30 | "watch": "tsc --build -w", 31 | "test": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js", 32 | "deep-clean": "rm -rf ./lib || true && rm tsconfig.tsbuildinfo || true" 33 | }, 34 | "jest": { 35 | "testMatch": [ 36 | "**/__tests__/**/*.test.js" 37 | ] 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /extensions/graphql-codegen/src/graphql/GraphqlFile.ts: -------------------------------------------------------------------------------- 1 | import { sign } from '@aphro/codegen'; 2 | import { CodegenFile, hashTemplates } from '@aphro/codegen-api'; 3 | 4 | export default class GraphQLFile implements CodegenFile { 5 | #contents: string; 6 | readonly templates = hashTemplates; 7 | 8 | constructor( 9 | public readonly name: string, 10 | contents: string, 11 | public readonly isUnsigned: boolean = false, 12 | ) { 13 | this.#contents = contents; 14 | } 15 | 16 | get contents(): string { 17 | let contents = this.#contents; 18 | return sign(contents, this.templates); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /extensions/graphql-codegen/src/graphql/connectionName.ts: -------------------------------------------------------------------------------- 1 | import { 2 | SchemaEdge, 3 | EdgeDeclaration, 4 | EdgeReferenceDeclaration, 5 | SchemaNode, 6 | } from '@aphro/schema-api'; 7 | import { upcaseAt } from '@strut/utils'; 8 | 9 | export function connectionName(n: SchemaNode, e: EdgeDeclaration | EdgeReferenceDeclaration) { 10 | return n.name + 'To' + upcaseAt(e.name, 0) + 'Connection'; 11 | } 12 | 13 | export function edgeName(n: SchemaNode, e: EdgeDeclaration | EdgeReferenceDeclaration) { 14 | return n.name + 'To' + upcaseAt(e.name, 0) + 'Edge'; 15 | } 16 | -------------------------------------------------------------------------------- /extensions/graphql-codegen/src/graphql/gatherReadFields.ts: -------------------------------------------------------------------------------- 1 | import { GraphQL } from '@aphro/graphql-grammar'; 2 | import { 3 | SchemaEdge, 4 | EdgeDeclaration, 5 | EdgeReferenceDeclaration, 6 | Field, 7 | SchemaNode, 8 | FieldDeclaration, 9 | } from '@aphro/schema-api'; 10 | 11 | export function gatherReadFields(n: SchemaNode): FieldDeclaration[] { 12 | return (n.extensions.graphql?.read || []) 13 | .map(fieldName => n.fields[fieldName]) 14 | .filter(f => f != null); 15 | } 16 | 17 | export function gatherReadEdges(n: SchemaNode): (EdgeDeclaration | EdgeReferenceDeclaration)[] { 18 | const edges = n.extensions.outboundEdges?.edges; 19 | if (edges == null) { 20 | return []; 21 | } 22 | 23 | return (n.extensions.graphql?.read || []) 24 | .map(fieldName => edges[fieldName]) 25 | .filter(f => f != null); 26 | } 27 | -------------------------------------------------------------------------------- /extensions/graphql-codegen/src/graphql/inlineEnumName.ts: -------------------------------------------------------------------------------- 1 | import { SchemaNode, Enum } from '@aphro/schema-api'; 2 | import { upcaseAt } from '@strut/utils'; 3 | 4 | export function inlineEnumName(n: SchemaNode, f: Enum): string { 5 | return 'Enum' + n.name + upcaseAt(f.name, 0); 6 | } 7 | -------------------------------------------------------------------------------- /extensions/graphql-codegen/src/graphql/shouldExpose.ts: -------------------------------------------------------------------------------- 1 | import { SchemaNode } from '@aphro/schema-api'; 2 | 3 | export default function shouldExpose(n: SchemaNode): boolean { 4 | return ( 5 | n.extensions.graphql != null && 6 | (n.extensions.graphql.read?.length > 0 || n.extensions.graphql.write?.length > 0) 7 | ); 8 | } 9 | 10 | export function exposesRoot(n: SchemaNode): boolean { 11 | return shouldExpose(n) && n.extensions?.graphql?.root != null; 12 | } 13 | -------------------------------------------------------------------------------- /extensions/graphql-codegen/src/index.ts: -------------------------------------------------------------------------------- 1 | export { GenGraphQLTypescriptResolvers } from './typescript/GenGraphQLTypescriptResolvers.js'; 2 | export { GenGraphQLTypedefs } from './graphql/GenGraphQLTypedefs.js'; 3 | -------------------------------------------------------------------------------- /extensions/graphql-codegen/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"], 8 | "references": [ 9 | { "path": "../../packages/schema-api" }, 10 | { "path": "../../packages/schema" }, 11 | { "path": "../../packages/codegen-api" }, 12 | { "path": "../../packages/codegen" }, 13 | { "path": "../../packages/codegen-ts" }, 14 | { "path": "../graphql-grammar" } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /extensions/graphql-grammar/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /extensions/graphql-grammar/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /extensions/graphql-grammar/README.md: -------------------------------------------------------------------------------- 1 | # GraphQL Grammar 2 | 3 | Extends the `Aphrodite` grammar with support for exposing fields and edges of a node to `GraphQL`. -------------------------------------------------------------------------------- /extensions/graphql-grammar/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | '@babel/preset-env', 5 | { 6 | targets: { 7 | node: 'current', 8 | }, 9 | }, 10 | ], 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /extensions/graphql-grammar/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/graphql-grammar", 3 | "version": "0.2.8", 4 | "main": "lib/index.js", 5 | "type": "module", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/tantaman/aphrodite.git", 9 | "directory": "extensions/graphql-grammar" 10 | }, 11 | "dependencies": { 12 | "@aphro/grammar-extension-api": "workspace:*", 13 | "@aphro/schema": "workspace:*", 14 | "@aphro/schema-api": "workspace:*" 15 | }, 16 | "devDependencies": { 17 | "@babel/core": "^7.18.13", 18 | "@babel/preset-env": "^7.18.10", 19 | "@types/jest": "^28.1.8", 20 | "jest": "^29.0.1", 21 | "typescript": "^4.8.2" 22 | }, 23 | "scripts": { 24 | "clean": "tsc --build --clean", 25 | "build": "tsc --build", 26 | "watch": "tsc --build -w", 27 | "test": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js", 28 | "deep-clean": "rm -rf ./lib || true && rm tsconfig.tsbuildinfo || true" 29 | }, 30 | "jest": { 31 | "testMatch": [ 32 | "**/__tests__/**/*.test.js" 33 | ] 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /extensions/graphql-grammar/src/__tests__/compile.test.ts: -------------------------------------------------------------------------------- 1 | import { createCompiler } from '@aphro/schema'; 2 | import { contents, compiled } from './testSchemaFile.js'; 3 | import extension from '../index.js'; 4 | 5 | const compiler = createCompiler({ grammarExtensions: [extension] }); 6 | test('Parsing with the compiled grammar', () => { 7 | const [errors, result] = compiler.compileFromString(contents); 8 | expect(result).toEqual(compiled); 9 | }); 10 | -------------------------------------------------------------------------------- /extensions/graphql-grammar/src/__tests__/testSchemaFile.ts: -------------------------------------------------------------------------------- 1 | import { name } from '../index.js'; 2 | 3 | export const contents = ` 4 | db: test 5 | engine: sqlite 6 | 7 | User as Node { 8 | id: ID 9 | name: NaturalLanguage 10 | } & GraphQL { 11 | read { 12 | id 13 | name 14 | } 15 | } 16 | `; 17 | 18 | export const compiled = { 19 | edges: {}, 20 | nodes: { 21 | User: { 22 | type: 'node', 23 | extensions: { 24 | [name]: { 25 | name, 26 | read: ['id', 'name'], 27 | write: [], 28 | root: undefined, 29 | }, 30 | }, 31 | fields: { 32 | id: { name: 'id', type: [{ of: 'User', type: 'id' }] }, 33 | name: { name: 'name', type: [{ type: 'naturalLanguage' }] }, 34 | }, 35 | name: 'User', 36 | primaryKey: 'id', 37 | storage: { db: 'test', engine: 'sqlite', tablish: 'user', type: 'sql', name: 'storage' }, 38 | }, 39 | }, 40 | }; 41 | -------------------------------------------------------------------------------- /extensions/graphql-grammar/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"], 8 | "references": [ 9 | { "path": "../../packages/schema-api" }, 10 | { "path": "../../packages/grammar-extension-api" }, 11 | { "path": "../../packages/schema" } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /extensions/mutation-codegen/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /extensions/mutation-codegen/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /extensions/mutation-codegen/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | '@babel/preset-env', 5 | { 6 | targets: { 7 | node: 'current', 8 | }, 9 | }, 10 | ], 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /extensions/mutation-codegen/src/index.ts: -------------------------------------------------------------------------------- 1 | export { GenTypescriptMutations } from './typescript/GenTypescriptMutations.js'; 2 | export { GenTypescriptMutationImpls } from './typescript/GenTypescriptMutationImpls.js'; 3 | -------------------------------------------------------------------------------- /extensions/mutation-codegen/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"], 8 | "references": [ 9 | { "path": "../../packages/schema-api" }, 10 | { "path": "../../packages/codegen" }, 11 | { "path": "../../packages/codegen-api" }, 12 | { "path": "../../packages/codegen-ts" }, 13 | { "path": "../../packages/schema" }, 14 | { "path": "../../packages/parse-ts" }, 15 | { "path": "../mutation-grammar" }, 16 | { "path": "../../packages/feature-gates" } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /extensions/mutation-grammar/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /extensions/mutation-grammar/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /extensions/mutation-grammar/README.md: -------------------------------------------------------------------------------- 1 | # Mutation Grammar 2 | 3 | Extends `Aphrodite SDL` with a grammar for defining mutations. 4 | 5 | Before: 6 | ``` 7 | User as Node { 8 | id: ID 9 | name: NaturalLanguage 10 | password: PBKDF2 11 | } 12 | ``` 13 | 14 | After: 15 | ``` 16 | User as Node { 17 | id: ID 18 | name: NaturalLanguage 19 | password: PBKDF2 20 | } & Mutations { 21 | create { 22 | name 23 | password 24 | } 25 | 26 | delete {} 27 | 28 | rename { 29 | name 30 | } 31 | } 32 | ``` 33 | 34 | This can be used in conjunction with the Auth extension to enable declaring auth policies on mutations. -------------------------------------------------------------------------------- /extensions/mutation-grammar/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | '@babel/preset-env', 5 | { 6 | targets: { 7 | node: 'current', 8 | }, 9 | }, 10 | ], 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /extensions/mutation-grammar/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/mutation-grammar", 3 | "version": "0.3.2", 4 | "main": "lib/index.js", 5 | "type": "module", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/tantaman/aphrodite.git", 9 | "directory": "extensions/mutation-grammar" 10 | }, 11 | "dependencies": { 12 | "@aphro/grammar-extension-api": "workspace:*", 13 | "@aphro/schema": "workspace:*", 14 | "@aphro/schema-api": "workspace:*" 15 | }, 16 | "devDependencies": { 17 | "@babel/core": "^7.18.13", 18 | "@babel/preset-env": "^7.18.10", 19 | "@types/jest": "^28.1.8", 20 | "jest": "^29.0.1", 21 | "typescript": "^4.8.2" 22 | }, 23 | "scripts": { 24 | "clean": "tsc --build --clean", 25 | "build": "tsc --build", 26 | "watch": "tsc --build -w", 27 | "test": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js", 28 | "deep-clean": "rm -rf ./lib || true && rm tsconfig.tsbuildinfo || true" 29 | }, 30 | "jest": { 31 | "testMatch": [ 32 | "**/__tests__/**/*.test.js" 33 | ] 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /extensions/mutation-grammar/src/__tests__/compile.test.ts: -------------------------------------------------------------------------------- 1 | import { createCompiler } from '@aphro/schema'; 2 | import { contents, compiled } from './testSchemaFile.js'; 3 | import extension from '../index.js'; 4 | 5 | const compiler = createCompiler({ grammarExtensions: [extension] }); 6 | test('Parsing with the compiled grammar', () => { 7 | const [errors, result] = compiler.compileFromString(contents); 8 | expect(result).toEqual(compiled); 9 | }); 10 | -------------------------------------------------------------------------------- /extensions/mutation-grammar/src/mutation.ts: -------------------------------------------------------------------------------- 1 | import { SchemaEdge, SchemaNode } from '@aphro/schema-api'; 2 | import { FullArgDef, MutationArgDef } from './index.js'; 3 | 4 | function transformQuickToFull(node: SchemaNode | SchemaEdge, arg: MutationArgDef): FullArgDef { 5 | const field = node.fields[arg.name]; 6 | if (field == null) { 7 | throw new Error( 8 | `When generating mutation for ${node.name} could not find a field named ${arg.name}. Did you mean to declare the type with the argument?`, 9 | ); 10 | } 11 | return { 12 | type: 'full', 13 | optional: arg.optional, 14 | name: arg.name, 15 | typeDef: field.type, 16 | }; 17 | } 18 | 19 | export const mutationFn = { 20 | transformMaybeQuickToFull(node: SchemaNode | SchemaEdge, arg: MutationArgDef): FullArgDef { 21 | switch (arg.type) { 22 | case 'full': 23 | return arg; 24 | case 'quick': 25 | return transformQuickToFull(node, arg); 26 | } 27 | }, 28 | 29 | transformQuickToFull, 30 | }; 31 | -------------------------------------------------------------------------------- /extensions/mutation-grammar/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"], 8 | "references": [ 9 | { "path": "../../packages/schema-api" }, 10 | { "path": "../../packages/grammar-extension-api" }, 11 | { "path": "../../packages/schema" } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /integration-tests/browser/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @aphro/integration-tests-browser 2 | 3 | ## 0.0.2 4 | 5 | ### Patch Changes 6 | 7 | - Export queries and specs, move connectors to own packages, fix #43 and other bugs 8 | - Updated dependencies 9 | - @aphro/runtime-ts@0.3.8 10 | -------------------------------------------------------------------------------- /integration-tests/browser/README.md: -------------------------------------------------------------------------------- 1 | # integration-tests : browser 2 | 3 | Runs integration tests in a true browser environment via Mocha. 4 | -------------------------------------------------------------------------------- /integration-tests/browser/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | Aphrodite Browser Integration Test 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 24 | 25 | 26 | 27 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /integration-tests/browser/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/integration-tests-browser", 3 | "private": true, 4 | "license": "MIT", 5 | "type": "module", 6 | "scripts": { 7 | "start": "vite", 8 | "deep-clean": "rm -rf dist", 9 | "tsc": "tsc --noEmit" 10 | }, 11 | "dependencies": { 12 | "@aphro/runtime-ts": "workspace:*", 13 | "mocha": "^10.0.0", 14 | "typescript": "^4.8.2", 15 | "vite": "^3.0.9" 16 | }, 17 | "version": "0.0.2" 18 | } 19 | -------------------------------------------------------------------------------- /integration-tests/browser/public/wa-sqlite-async.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vlcn-io/vlcn-orm/ff90a4d588a5bed0fdcea0335d328f7c4dd51cd8/integration-tests/browser/public/wa-sqlite-async.wasm -------------------------------------------------------------------------------- /integration-tests/browser/src/main.ts: -------------------------------------------------------------------------------- 1 | console.log('hello'); 2 | -------------------------------------------------------------------------------- /integration-tests/browser/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strict": true, 4 | "moduleResolution": "node", 5 | "outDir": "./dist/", 6 | "sourceMap": true, 7 | "strictNullChecks": true, 8 | "module": "esnext", 9 | "jsx": "react", 10 | "target": "esnext", 11 | "allowJs": true, 12 | "checkJs": false, 13 | "importHelpers": true, 14 | "baseUrl": ".", 15 | "rootDir": ".", 16 | "resolveJsonModule": true, 17 | "allowSyntheticDefaultImports": true, 18 | "typeRoots": ["./src/@types"], 19 | "incremental": true, 20 | "composite": true 21 | }, 22 | "include": ["./src/"], 23 | "references": [] 24 | } 25 | -------------------------------------------------------------------------------- /integration-tests/browser/vite.config.js: -------------------------------------------------------------------------------- 1 | // vite.config.js 2 | export default {}; 3 | -------------------------------------------------------------------------------- /integration-tests/node/.gitignore: -------------------------------------------------------------------------------- 1 | /lib -------------------------------------------------------------------------------- /integration-tests/node/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /integration-tests/node/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | '@babel/preset-env', 5 | { 6 | targets: { 7 | node: 'current', 8 | }, 9 | }, 10 | ], 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /integration-tests/node/src/__tests__/bootstrap.test.ts: -------------------------------------------------------------------------------- 1 | import { resolver } from '../testdb.js'; 2 | import { sqlFiles } from '@aphro/integration-tests-shared'; 3 | import { bootstrap, sql } from '@aphro/runtime-ts'; 4 | 5 | // test('creating tables that do not exist', async () => { 6 | // await bootstrap.createIfNotExists(resolver, sqlFiles); 7 | // }); 8 | 9 | test('creating tables that do exist', async () => { 10 | await bootstrap.createIfNotExists(resolver, sqlFiles); 11 | await bootstrap.createIfNotExists(resolver, sqlFiles); 12 | 13 | let threw = false; 14 | try { 15 | await bootstrap.createThrowIfExists(resolver, sqlFiles); 16 | } catch (e) { 17 | threw = true; 18 | } 19 | expect(threw).toBe(true); 20 | // \/ the below is flaky. The above /\ always works 🤷‍♂️ 21 | // expect(async () => {...}).rejects.toThrow(); 22 | }); 23 | 24 | // test('auto-migrate', async () => { 25 | // // no deltas, be silent 26 | // // deltas, make a change 27 | // // require numbering of fields so we can detect renames? 28 | // await bootstrap.createAutomigrateIfExists(resolver, sqlFiles); 29 | // }); 30 | -------------------------------------------------------------------------------- /integration-tests/node/src/__tests__/count.test.ts: -------------------------------------------------------------------------------- 1 | import { context, Context, viewer, Cache, asId, commit, P } from '@aphro/runtime-ts'; 2 | import { destroyDb, initDb } from './testBase.js'; 3 | import domain from '@aphro/integration-tests-shared'; 4 | const { User } = domain.sql; 5 | 6 | let ctx: Context; 7 | const cache = new Cache(); 8 | beforeAll(async () => { 9 | const resolver = await initDb(); 10 | ctx = context(viewer(asId('me')), resolver, cache); 11 | }); 12 | 13 | test('count', async () => { 14 | await User.create(ctx, { name: 'Bill' }).save(); 15 | 16 | let count = await User.queryAll(ctx).count().genxOnlyValue(); 17 | expect(count).toBe(1); 18 | 19 | await commit( 20 | ctx, 21 | [1, 2, 3, 4].flatMap(i => User.create(ctx, { name: 'U' + i })), 22 | ); 23 | 24 | count = await User.queryAll(ctx).count().genxOnlyValue(); 25 | expect(count).toBe(5); 26 | }); 27 | 28 | test('count optimization', () => { 29 | const optimizedPlan = User.queryAll(ctx).count().plan().optimize(); 30 | 31 | expect(optimizedPlan.derivations.length).toEqual(1); 32 | expect(optimizedPlan.derivations[0].type).toEqual('countLoad'); 33 | }); 34 | 35 | afterAll(async () => { 36 | await destroyDb(); 37 | }); 38 | -------------------------------------------------------------------------------- /integration-tests/node/src/__tests__/declared-mutations.test.ts: -------------------------------------------------------------------------------- 1 | import { context, Context, viewer, Cache, asId, commit } from '@aphro/runtime-ts'; 2 | import domain from '@aphro/integration-tests-shared'; 3 | 4 | const { DeckMutations, UserMutations } = domain.sql; 5 | 6 | import { initDb, destroyDb } from './testBase'; 7 | 8 | let ctx: Context; 9 | beforeAll(async () => { 10 | const resolver = await initDb(); 11 | ctx = context(viewer(asId('me')), resolver, new Cache()); 12 | }); 13 | 14 | test('Creating models via declared mutations', async () => { 15 | // TODO: collapse create? 16 | // TODO: can we remove some of the redundancy of `ctx`? 17 | const userChangeset = UserMutations.create(ctx, { name: 'Bill' }).toChangesets(); 18 | const deckChangeset = DeckMutations.create(ctx, { 19 | name: 'First Presentation', 20 | owner: userChangeset[0], 21 | selectedSlide: null, 22 | }).toChangesets(); 23 | 24 | // TODO: drop, rest, etc... so we can get first two typed but still commit the rest... 25 | const [user, deck] = await commit(ctx, [userChangeset[0], deckChangeset[0]]); 26 | 27 | expect(deck.name).toEqual('First Presentation'); 28 | expect(user.name).toEqual('Bill'); 29 | }); 30 | 31 | afterAll(async () => { 32 | await destroyDb(); 33 | }); 34 | -------------------------------------------------------------------------------- /integration-tests/node/src/__tests__/empty.test.ts: -------------------------------------------------------------------------------- 1 | import { context, Context, viewer, Cache, asId, commit, P } from '@aphro/runtime-ts'; 2 | import { destroyDb, initDb } from './testBase.js'; 3 | import domain from '@aphro/integration-tests-shared'; 4 | const { UserQuery, UserMutations } = domain.sql; 5 | 6 | let ctx: Context; 7 | const cache = new Cache(); 8 | beforeAll(async () => { 9 | const resolver = await initDb(); 10 | ctx = context(viewer(asId('me')), resolver, cache); 11 | }); 12 | 13 | test('Empty query with operations applied is still empty!', async () => { 14 | await commit( 15 | ctx, 16 | [1, 2, 3, 4].flatMap(i => UserMutations.create(ctx, { name: 'U' + i }).toChangesets()), 17 | ); 18 | 19 | const noUsers = await UserQuery.empty(ctx).gen(); 20 | expect(noUsers.length).toEqual(0); 21 | 22 | const noSlides = await UserQuery.empty(ctx).queryDecks().querySlides().gen(); 23 | expect(noSlides.length).toEqual(0); 24 | 25 | // TODO: empty queries need to still function for count operations 26 | // const zero = await UserQuery.empty(ctx).count().genxOnlyValue(); 27 | // expect(zero).toBe(0); 28 | }); 29 | 30 | test('Empty is optimized', async () => { 31 | const plan = UserQuery.empty(ctx).plan().optimize(); 32 | expect(plan.derivations.length).toBe(0); 33 | }); 34 | 35 | afterAll(async () => { 36 | await destroyDb(); 37 | }); 38 | -------------------------------------------------------------------------------- /integration-tests/node/src/__tests__/mutation-on-mutation.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vlcn-io/vlcn-orm/ff90a4d588a5bed0fdcea0335d328f7c4dd51cd8/integration-tests/node/src/__tests__/mutation-on-mutation.ts -------------------------------------------------------------------------------- /integration-tests/node/src/__tests__/testBase.ts: -------------------------------------------------------------------------------- 1 | import createTestTables from '../createTestTables.js'; 2 | import { resolver } from '../testdb.js'; 3 | 4 | export async function initDb() { 5 | await createTestTables(); 6 | return resolver; 7 | } 8 | 9 | export async function destroyDb() { 10 | const db = resolver.engine('sqlite').db('test'); 11 | await db.dispose(); 12 | } 13 | -------------------------------------------------------------------------------- /integration-tests/node/src/createTestTables.ts: -------------------------------------------------------------------------------- 1 | import { resolver } from './testdb.js'; 2 | import { bootstrap } from '@aphro/runtime-ts'; 3 | import { sqlFiles } from '@aphro/integration-tests-shared'; 4 | 5 | export default async function createTestTables() { 6 | await bootstrap.createThrowIfExists(resolver, sqlFiles); 7 | } 8 | -------------------------------------------------------------------------------- /integration-tests/node/src/testdb.ts: -------------------------------------------------------------------------------- 1 | import { DBResolver, MemoryDB, SQLResolvedDB } from '@aphro/runtime-ts'; 2 | import { createConnection } from '@aphro/sqlite3-connector'; 3 | 4 | function sqlDb() { 5 | return createConnection(null); 6 | } 7 | 8 | function memDb() { 9 | return new MemoryDB(); 10 | } 11 | 12 | let sqlConnection: SQLResolvedDB | null = null; 13 | let memoryConnection: ReturnType | null = null; 14 | async function createResolver(): Promise { 15 | if (sqlConnection == null) { 16 | sqlConnection = await sqlDb(); 17 | } 18 | if (memoryConnection == null) { 19 | memoryConnection = memDb(); 20 | } 21 | 22 | return { 23 | // TODO 24 | // @ts-ignore 25 | engine(e: 'sqlite' | 'memory') { 26 | switch (e) { 27 | case 'sqlite': 28 | return { 29 | db(db: string) { 30 | return sqlConnection; 31 | }, 32 | }; 33 | case 'memory': 34 | return { 35 | db(db: string) { 36 | return memoryConnection; 37 | }, 38 | }; 39 | } 40 | }, 41 | }; 42 | } 43 | 44 | export const resolver = await createResolver(); 45 | -------------------------------------------------------------------------------- /integration-tests/node/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"], 8 | "references": [ 9 | { "path": "../../packages/runtime-ts" }, 10 | { "path": "../../packages/codegen-cli" }, 11 | { "path": "../../connectors/sqlite3-connector" }, 12 | { "path": "../shared" } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /integration-tests/shared/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /integration-tests/shared/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @aphro/integration-tests-shared 2 | 3 | ## 0.0.2 4 | 5 | ### Patch Changes 6 | 7 | - Export queries and specs, move connectors to own packages, fix #43 and other bugs 8 | - Updated dependencies 9 | - @aphro/runtime-ts@0.3.8 10 | -------------------------------------------------------------------------------- /integration-tests/shared/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/integration-tests-shared", 3 | "private": true, 4 | "version": "0.0.2", 5 | "main": "lib/index.js", 6 | "type": "module", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/tantaman/aphrodite.git", 10 | "directory": "integration-tests/shared" 11 | }, 12 | "dependencies": { 13 | "@aphro/runtime-ts": "workspace:*" 14 | }, 15 | "devDependencies": { 16 | "@aphro/codegen-cli": "workspace:*", 17 | "typescript": "^4.8.2" 18 | }, 19 | "scripts": { 20 | "clean": "tsc --build --clean", 21 | "build": "tsc --build", 22 | "watch": "tsc --build -w", 23 | "test": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js", 24 | "aphro": "aphro gen src/schema/domain.aphro -d src/domain && aphro gen src/schema/in-memory.aphro -d src/domain-memory && pnpm copy", 25 | "copy": "cp src/domain/generated/*.sql lib/domain/generated", 26 | "deep-clean": "rm -rf ./lib || true && rm tsconfig.tsbuildinfo || true" 27 | }, 28 | "jest": { 29 | "testMatch": [ 30 | "**/__tests__/**/*.test.js" 31 | ] 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /integration-tests/shared/src/domain-memory/Component.ts: -------------------------------------------------------------------------------- 1 | import ComponentBase from "./generated/ComponentBase.js"; 2 | export { Data } from "./generated/ComponentBase.js"; 3 | 4 | export default class Component extends ComponentBase { 5 | // insert any manual method you may have here 6 | } 7 | -------------------------------------------------------------------------------- /integration-tests/shared/src/domain-memory/ComponentMutationsImpl.ts: -------------------------------------------------------------------------------- 1 | import { CreateArgs } from "./generated/ComponentMutations.js"; 2 | import { DeleteArgs } from "./generated/ComponentMutations.js"; 3 | import { Changeset, sid } from "@aphro/runtime-ts"; 4 | import { Data } from "./generated/ComponentBase.js"; 5 | import Component from "./Component.js"; 6 | import { IMutationBuilder } from "@aphro/runtime-ts"; 7 | 8 | export function createImpl( 9 | mutator: Omit, "toChangeset">, 10 | { subtype, slide, content }: CreateArgs 11 | ): void | Changeset[] { 12 | mutator.set({ 13 | subtype, 14 | slideId: slide.id, 15 | content, 16 | }); 17 | } 18 | 19 | export function deleteImpl( 20 | model: Component, 21 | mutator: Omit, "toChangeset">, 22 | {}: DeleteArgs 23 | ): void | Changeset[] { 24 | // Use the provided mutator to make your desired changes. 25 | // e.g., mutator.set({name: "Foo" }); 26 | // You do not need to return anything from this method. The mutator will track your changes. 27 | // If you do return changesets, those changesets will be applied in addition to the changes made to the mutator. 28 | } 29 | -------------------------------------------------------------------------------- /integration-tests/shared/src/domain-memory/Deck.ts: -------------------------------------------------------------------------------- 1 | import DeckBase from "./generated/DeckBase.js"; 2 | export { Data } from "./generated/DeckBase.js"; 3 | 4 | export default class Deck extends DeckBase { 5 | // insert any manual method you may have here 6 | } 7 | -------------------------------------------------------------------------------- /integration-tests/shared/src/domain-memory/DeckToEditorsEdge.ts: -------------------------------------------------------------------------------- 1 | import DeckToEditorsEdgeBase from "./generated/DeckToEditorsEdgeBase.js"; 2 | export { Data } from "./generated/DeckToEditorsEdgeBase.js"; 3 | 4 | export default class DeckToEditorsEdge extends DeckToEditorsEdgeBase { 5 | // insert any manual method you may have here 6 | } 7 | -------------------------------------------------------------------------------- /integration-tests/shared/src/domain-memory/DeckToEditorsEdgeMutationsImpl.ts: -------------------------------------------------------------------------------- 1 | import { CreateArgs } from './generated/DeckToEditorsEdgeMutations.js'; 2 | import { Changeset } from '@aphro/runtime-ts'; 3 | import { Data } from './generated/DeckToEditorsEdgeBase.js'; 4 | import DeckToEditorsEdge from './DeckToEditorsEdge.js'; 5 | import { IMutationBuilder } from '@aphro/runtime-ts'; 6 | 7 | export function createImpl( 8 | mutator: Omit, 'toChangeset'>, 9 | { src, dest }: CreateArgs, 10 | ): void | Changeset[] { 11 | mutator.set({ 12 | id1: src.id, 13 | id2: dest.id, 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /integration-tests/shared/src/domain-memory/Slide.ts: -------------------------------------------------------------------------------- 1 | import SlideBase from "./generated/SlideBase.js"; 2 | export { Data } from "./generated/SlideBase.js"; 3 | 4 | export default class Slide extends SlideBase { 5 | // insert any manual method you may have here 6 | } 7 | -------------------------------------------------------------------------------- /integration-tests/shared/src/domain-memory/User.ts: -------------------------------------------------------------------------------- 1 | import UserBase from "./generated/UserBase.js"; 2 | export { Data } from "./generated/UserBase.js"; 3 | 4 | export default class User extends UserBase { 5 | // insert any manual method you may have here 6 | } 7 | -------------------------------------------------------------------------------- /integration-tests/shared/src/domain-memory/generated/types.d.ts: -------------------------------------------------------------------------------- 1 | // SIGNED-SOURCE: <7946820adce4295e4ffad7d91d8edf9a> 2 | /** 3 | * AUTO-GENERATED FILE 4 | * Do not modify. Update your schema and re-generate for changes. 5 | */ 6 | declare module "*.sql?raw"; 7 | -------------------------------------------------------------------------------- /integration-tests/shared/src/domain/AppState.ts: -------------------------------------------------------------------------------- 1 | import AppStateBase from "./generated/AppStateBase.js"; 2 | export { Data } from "./generated/AppStateBase.js"; 3 | 4 | export default class AppState extends AppStateBase { 5 | // insert any manual method you may have here 6 | } 7 | -------------------------------------------------------------------------------- /integration-tests/shared/src/domain/AppStateMutationsImpl.ts: -------------------------------------------------------------------------------- 1 | import { CreateArgs } from './generated/AppStateMutations.js'; 2 | import { OpenDeckArgs } from './generated/AppStateMutations.js'; 3 | import { Changeset, sid } from '@aphro/runtime-ts'; 4 | import { Data } from './AppState.js'; 5 | import AppState from './AppState.js'; 6 | import { IMutationBuilder } from '@aphro/runtime-ts'; 7 | import Identity from './Identity.js'; 8 | 9 | export function createImpl( 10 | mutator: Omit, 'toChangeset'>, 11 | { identity, openDeckId }: CreateArgs, 12 | ): void | Changeset[] { 13 | mutator.set({ 14 | id: sid('aaaa'), 15 | identity: identity as Identity, // TODO: nested field shouldn't be able to take changesets 16 | openDeckId: openDeckId || undefined, 17 | }); 18 | } 19 | 20 | export function openDeckImpl( 21 | model: AppState, 22 | mutator: Omit, 'toChangeset'>, 23 | { openDeck }: OpenDeckArgs, 24 | ): void | Changeset[] { 25 | mutator.set({ 26 | openDeckId: openDeck, 27 | }); 28 | } 29 | -------------------------------------------------------------------------------- /integration-tests/shared/src/domain/Component.ts: -------------------------------------------------------------------------------- 1 | import ComponentBase from "./generated/ComponentBase.js"; 2 | export { Data } from "./generated/ComponentBase.js"; 3 | 4 | export default class Component extends ComponentBase { 5 | // insert any manual method you may have here 6 | } 7 | -------------------------------------------------------------------------------- /integration-tests/shared/src/domain/ComponentMutationsImpl.ts: -------------------------------------------------------------------------------- 1 | import { CreateArgs } from "./generated/ComponentMutations.js"; 2 | import { DeleteArgs } from "./generated/ComponentMutations.js"; 3 | import { Changeset, sid } from "@aphro/runtime-ts"; 4 | import { Data } from "./generated/ComponentBase.js"; 5 | import Component from "./Component.js"; 6 | import { IMutationBuilder } from "@aphro/runtime-ts"; 7 | 8 | export function createImpl( 9 | mutator: Omit, "toChangeset">, 10 | { subtype, slide, content }: CreateArgs 11 | ): void | Changeset[] { 12 | mutator.set({ 13 | id: sid("aaaa"), 14 | subtype, 15 | slideId: slide.id, 16 | content, 17 | }); 18 | } 19 | 20 | export function deleteImpl( 21 | model: Component, 22 | mutator: Omit, "toChangeset">, 23 | {}: DeleteArgs 24 | ): void | Changeset[] { 25 | // Use the provided mutator to make your desired changes. 26 | // e.g., mutator.set({name: "Foo" }); 27 | // You do not need to return anything from this method. The mutator will track your changes. 28 | // If you do return changesets, those changesets will be applied in addition to the changes made to the mutator. 29 | } 30 | -------------------------------------------------------------------------------- /integration-tests/shared/src/domain/Deck.ts: -------------------------------------------------------------------------------- 1 | import DeckBase from "./generated/DeckBase.js"; 2 | export { Data } from "./generated/DeckBase.js"; 3 | 4 | export default class Deck extends DeckBase { 5 | // insert any manual method you may have here 6 | } 7 | -------------------------------------------------------------------------------- /integration-tests/shared/src/domain/DeckToEditorsEdge.ts: -------------------------------------------------------------------------------- 1 | import DeckToEditorsEdgeBase from "./generated/DeckToEditorsEdgeBase.js"; 2 | export { Data } from "./generated/DeckToEditorsEdgeBase.js"; 3 | 4 | export default class DeckToEditorsEdge extends DeckToEditorsEdgeBase { 5 | // insert any manual method you may have here 6 | } 7 | -------------------------------------------------------------------------------- /integration-tests/shared/src/domain/DeckToEditorsEdgeMutationsImpl.ts: -------------------------------------------------------------------------------- 1 | import { CreateArgs } from "./generated/DeckToEditorsEdgeMutations.js"; 2 | import { Changeset } from "@aphro/runtime-ts"; 3 | import { Data } from "./DeckToEditorsEdge.js"; 4 | import DeckToEditorsEdge from "./DeckToEditorsEdge.js"; 5 | import { IMutationBuilder } from "@aphro/runtime-ts"; 6 | 7 | export function createImpl( 8 | mutator: Omit, "toChangeset">, 9 | { src, dest }: CreateArgs 10 | ): void | Changeset[] { 11 | mutator.set({ 12 | id1: src.id, 13 | id2: dest.id, 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /integration-tests/shared/src/domain/Foo.ts: -------------------------------------------------------------------------------- 1 | import FooBase from "./generated/FooBase.js"; 2 | export { Data } from "./generated/FooBase.js"; 3 | 4 | export default class Foo extends FooBase { 5 | // insert any manual method you may have here 6 | } 7 | -------------------------------------------------------------------------------- /integration-tests/shared/src/domain/Identity.ts: -------------------------------------------------------------------------------- 1 | import IdentityBase from "./generated/IdentityBase.js"; 2 | export { Data } from "./generated/IdentityBase.js"; 3 | 4 | export default class Identity extends IdentityBase { 5 | // insert any manual method you may have here 6 | } 7 | -------------------------------------------------------------------------------- /integration-tests/shared/src/domain/Slide.ts: -------------------------------------------------------------------------------- 1 | import SlideBase from "./generated/SlideBase.js"; 2 | export { Data } from "./generated/SlideBase.js"; 3 | 4 | export default class Slide extends SlideBase { 5 | // insert any manual method you may have here 6 | } 7 | -------------------------------------------------------------------------------- /integration-tests/shared/src/domain/User.ts: -------------------------------------------------------------------------------- 1 | import UserBase from "./generated/UserBase.js"; 2 | export { Data } from "./generated/UserBase.js"; 3 | 4 | export default class User extends UserBase { 5 | // insert any manual method you may have here 6 | } 7 | -------------------------------------------------------------------------------- /integration-tests/shared/src/domain/generated/AppStateSpec.ts: -------------------------------------------------------------------------------- 1 | // SIGNED-SOURCE: 2 | /** 3 | * AUTO-GENERATED FILE 4 | * Do not modify. Update your schema and re-generate for changes. 5 | */ 6 | import { Context } from "@aphro/runtime-ts"; 7 | import { decodeModelData } from "@aphro/runtime-ts"; 8 | import { encodeModelData } from "@aphro/runtime-ts"; 9 | import { SID_of } from "@aphro/runtime-ts"; 10 | import { NodeSpecWithCreate } from "@aphro/runtime-ts"; 11 | import AppState from "../AppState.js"; 12 | import { Data } from "./AppStateBase.js"; 13 | 14 | const fields = { 15 | id: { 16 | encoding: "none", 17 | }, 18 | identity: { 19 | encoding: "json", 20 | }, 21 | openDeckId: { 22 | encoding: "none", 23 | }, 24 | copiedComponents: { 25 | encoding: "json", 26 | }, 27 | } as const; 28 | const AppStateSpec: NodeSpecWithCreate = { 29 | type: "node", 30 | createFrom(ctx: Context, data: Data, raw: boolean = true) { 31 | return new AppState(ctx, data); 32 | }, 33 | 34 | primaryKey: "id", 35 | 36 | storage: { 37 | engine: "ephemeral", 38 | db: "--", 39 | type: "ephemeral", 40 | tablish: "ephemeral", 41 | }, 42 | 43 | fields, 44 | 45 | outboundEdges: {}, 46 | }; 47 | 48 | export default AppStateSpec; 49 | -------------------------------------------------------------------------------- /integration-tests/shared/src/domain/generated/Component.sqlite.sql: -------------------------------------------------------------------------------- 1 | -- SIGNED-SOURCE: <633fde7f64a228d518fc5739ddba8a1b> 2 | -- STATEMENT 3 | CREATE TABLE 4 | "component" ( 5 | "id" 6 | /* n=1 */ 7 | , 8 | "subtype" 9 | /* n=2 */ 10 | , 11 | "slideId" 12 | /* n=3 */ 13 | , 14 | "content" 15 | /* n=4 */ 16 | , 17 | PRIMARY KEY ("id") 18 | ); -------------------------------------------------------------------------------- /integration-tests/shared/src/domain/generated/Deck.sqlite.sql: -------------------------------------------------------------------------------- 1 | -- SIGNED-SOURCE: 2 | -- STATEMENT 3 | CREATE TABLE 4 | "deck" ( 5 | "id" 6 | /* n=1 */ 7 | , 8 | "name" 9 | /* n=2 */ 10 | , 11 | "created" 12 | /* n=3 */ 13 | , 14 | "modified" 15 | /* n=4 */ 16 | , 17 | "ownerId" 18 | /* n=5 */ 19 | , 20 | "selectedSlideId" 21 | /* n=6 */ 22 | , 23 | PRIMARY KEY ("id") 24 | ); -------------------------------------------------------------------------------- /integration-tests/shared/src/domain/generated/DeckToEditorsEdge.sqlite.sql: -------------------------------------------------------------------------------- 1 | -- SIGNED-SOURCE: <1401d5f3602f56def175869be473cb43> 2 | -- STATEMENT 3 | CREATE TABLE 4 | "decktoeditorsedge" ( 5 | "id1" 6 | /* n=1 */ 7 | , 8 | "id2" 9 | /* n=2 */ 10 | ); -------------------------------------------------------------------------------- /integration-tests/shared/src/domain/generated/Foo.sqlite.sql: -------------------------------------------------------------------------------- 1 | -- SIGNED-SOURCE: 2 | -- STATEMENT 3 | CREATE TABLE 4 | "foo" ("id", "name", PRIMARY KEY ("id")); -------------------------------------------------------------------------------- /integration-tests/shared/src/domain/generated/IdentitySpec.ts: -------------------------------------------------------------------------------- 1 | // SIGNED-SOURCE: <344297bc81fcb796dffdaa5dcb36406d> 2 | /** 3 | * AUTO-GENERATED FILE 4 | * Do not modify. Update your schema and re-generate for changes. 5 | */ 6 | import { Context } from "@aphro/runtime-ts"; 7 | import { decodeModelData } from "@aphro/runtime-ts"; 8 | import { encodeModelData } from "@aphro/runtime-ts"; 9 | import { SID_of } from "@aphro/runtime-ts"; 10 | import { NodeSpecWithCreate } from "@aphro/runtime-ts"; 11 | import Identity from "../Identity.js"; 12 | import { Data } from "./IdentityBase.js"; 13 | 14 | const fields = { 15 | id: { 16 | encoding: "none", 17 | }, 18 | identifier: { 19 | encoding: "none", 20 | }, 21 | token: { 22 | encoding: "none", 23 | }, 24 | } as const; 25 | const IdentitySpec: NodeSpecWithCreate = { 26 | type: "node", 27 | createFrom(ctx: Context, data: Data, raw: boolean = true) { 28 | return new Identity(ctx, data); 29 | }, 30 | 31 | primaryKey: "id", 32 | 33 | storage: { 34 | engine: "ephemeral", 35 | db: "--", 36 | type: "ephemeral", 37 | tablish: "ephemeral", 38 | }, 39 | 40 | fields, 41 | 42 | outboundEdges: {}, 43 | }; 44 | 45 | export default IdentitySpec; 46 | -------------------------------------------------------------------------------- /integration-tests/shared/src/domain/generated/Slide.sqlite.sql: -------------------------------------------------------------------------------- 1 | -- SIGNED-SOURCE: <8b28cf0658b1b9b42eca74f34c7a46a0> 2 | -- STATEMENT 3 | CREATE TABLE 4 | "slide" ( 5 | "id" 6 | /* n=1 */ 7 | , 8 | "deckId" 9 | /* n=2 */ 10 | , 11 | "order" 12 | /* n=3 */ 13 | , 14 | PRIMARY KEY ("id") 15 | ); -------------------------------------------------------------------------------- /integration-tests/shared/src/domain/generated/User.sqlite.sql: -------------------------------------------------------------------------------- 1 | -- SIGNED-SOURCE: <49bb24eb9c8827bd5a8eafe30329090c> 2 | -- STATEMENT 3 | CREATE TABLE 4 | "user" ( 5 | "id" 6 | /* n=1 */ 7 | , 8 | "name" 9 | /* n=2 */ 10 | , 11 | "created" 12 | /* n=3 */ 13 | , 14 | "modified" 15 | /* n=4 */ 16 | , 17 | PRIMARY KEY ("id") 18 | ); -------------------------------------------------------------------------------- /integration-tests/shared/src/domain/generated/exports-sql.ts: -------------------------------------------------------------------------------- 1 | // SIGNED-SOURCE: <80307cd362b7812ce62825fd6239861f> 2 | /** 3 | * AUTO-GENERATED FILE 4 | * Do not modify. Update your schema and re-generate for changes. 5 | */ 6 | import User from "./User.sqlite.sql?raw"; 7 | import Deck from "./Deck.sqlite.sql?raw"; 8 | import Slide from "./Slide.sqlite.sql?raw"; 9 | import Component from "./Component.sqlite.sql?raw"; 10 | import Foo from "./Foo.sqlite.sql?raw"; 11 | import DeckToEditorsEdge from "./DeckToEditorsEdge.sqlite.sql?raw"; 12 | export default { 13 | sqlite: { 14 | example: { 15 | User, 16 | Deck, 17 | Slide, 18 | Component, 19 | Foo, 20 | DeckToEditorsEdge, 21 | }, 22 | }, 23 | }; 24 | -------------------------------------------------------------------------------- /integration-tests/shared/src/domain/generated/types.d.ts: -------------------------------------------------------------------------------- 1 | // SIGNED-SOURCE: <7946820adce4295e4ffad7d91d8edf9a> 2 | /** 3 | * AUTO-GENERATED FILE 4 | * Do not modify. Update your schema and re-generate for changes. 5 | */ 6 | declare module "*.sql?raw"; 7 | -------------------------------------------------------------------------------- /integration-tests/shared/src/index.ts: -------------------------------------------------------------------------------- 1 | import * as sql from './domain/generated/exports'; 2 | import * as mem from './domain-memory/generated/exports'; 3 | export default { 4 | sql, 5 | mem, 6 | }; 7 | 8 | export { default as sqlFiles } from './domain/generated/exports-node-sql.js'; 9 | -------------------------------------------------------------------------------- /integration-tests/shared/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"], 8 | "references": [{ "path": "../../packages/runtime-ts" }, { "path": "../../packages/codegen-cli" }] 9 | } 10 | -------------------------------------------------------------------------------- /jaeger.sh: -------------------------------------------------------------------------------- 1 | docker run -d --name jaeger \ 2 | -e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \ 3 | -e COLLECTOR_OTLP_ENABLED=true \ 4 | -p 6831:6831/udp \ 5 | -p 6832:6832/udp \ 6 | -p 5778:5778 \ 7 | -p 16686:16686 \ 8 | -p 4317:4317 \ 9 | -p 4318:4318 \ 10 | -p 14250:14250 \ 11 | -p 14268:14268 \ 12 | -p 14269:14269 \ 13 | -p 9411:9411 \ 14 | jaegertracing/all-in-one:1.37 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "version": "0.0.0", 4 | "packageManager": "pnpm@6.30.0", 5 | "engines": { 6 | "node": ">=14", 7 | "pnpm": ">=3" 8 | }, 9 | "devDependencies": { 10 | "@changesets/cli": "^2.24.3", 11 | "@tsconfig/node16": "^1.0.3", 12 | "turbo": "^1.4.3", 13 | "typescript": "^4.8.2" 14 | }, 15 | "scripts": { 16 | "build": "cd build-all && pnpm build", 17 | "deep-clean": "turbo run deep-clean", 18 | "test": "turbo run test", 19 | "todos": "leasot '**/*.ts' --ignore '**/node_modules'", 20 | "preinstall": "npx only-allow pnpm" 21 | }, 22 | "dependencies": { 23 | "react": "^18.2.0", 24 | "suspend-react": "^0.0.8" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/cache-runtime-ts/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /packages/cache-runtime-ts/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /packages/cache-runtime-ts/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | '@babel/preset-env', 5 | { 6 | targets: { 7 | node: 'current', 8 | }, 9 | }, 10 | ], 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /packages/cache-runtime-ts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/cache-runtime-ts", 3 | "version": "0.2.6", 4 | "main": "lib/index.js", 5 | "type": "module", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/tantaman/aphrodite.git", 9 | "directory": "packages/cache-runtime-ts" 10 | }, 11 | "dependencies": { 12 | "@strut/sid": "^0.1.2", 13 | "@strut/utils": "^0.1.1" 14 | }, 15 | "devDependencies": { 16 | "@babel/core": "^7.18.13", 17 | "@babel/preset-env": "^7.18.10", 18 | "@types/jest": "^28.1.8", 19 | "fast-check": "^3.1.2", 20 | "jest": "^29.0.1", 21 | "typescript": "^4.8.2" 22 | }, 23 | "scripts": { 24 | "clean": "tsc --build --clean", 25 | "build": "tsc --build", 26 | "watch": "tsc --build -w", 27 | "test": "node --experimental-vm-modules --expose-gc --allow-natives-syntax ./node_modules/jest/bin/jest.js", 28 | "deep-clean": "rm -rf ./lib || true && rm tsconfig.tsbuildinfo || true" 29 | }, 30 | "jest": { 31 | "testMatch": [ 32 | "**/__tests__/**/*.test.js" 33 | ] 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/cache-runtime-ts/src/index.ts: -------------------------------------------------------------------------------- 1 | import Cache from './cache.js'; 2 | 3 | export default Cache; 4 | -------------------------------------------------------------------------------- /packages/cache-runtime-ts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"], 8 | "references": [] 9 | } 10 | -------------------------------------------------------------------------------- /packages/codegen-api/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /packages/codegen-api/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /packages/codegen-api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/codegen-api", 3 | "version": "0.2.6", 4 | "main": "lib/index.js", 5 | "type": "module", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/tantaman/aphrodite.git", 9 | "directory": "packages/codegen-api" 10 | }, 11 | "dependencies": { 12 | "@aphro/schema-api": "workspace:*" 13 | }, 14 | "devDependencies": { 15 | "typescript": "^4.8.2" 16 | }, 17 | "scripts": { 18 | "clean": "tsc --build --clean", 19 | "build": "tsc --build", 20 | "watch": "tsc --build -w", 21 | "deep-clean": "rm -rf ./lib || true && rm tsconfig.tsbuildinfo || true" 22 | }, 23 | "jest": { 24 | "testMatch": [ 25 | "**/__tests__/**/*.test.js" 26 | ] 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/codegen-api/src/CodegenFile.ts: -------------------------------------------------------------------------------- 1 | export interface CodegenFile { 2 | readonly name: string; 3 | readonly contents: string; 4 | readonly templates: Templates; 5 | readonly isUnsigned: boolean; 6 | readonly nochange?: boolean; 7 | } 8 | 9 | export type Templates = { 10 | signature: string; 11 | startManual: string; 12 | endManual: string; 13 | }; 14 | 15 | export const algolTemplates = { 16 | signature: '// SIGNED-SOURCE: <>', 17 | startManual: '// BEGIN-MANUAL-SECTION: []', 18 | endManual: '// END-MANUAL-SECTION', 19 | }; 20 | 21 | export const sqlTemplates = { 22 | signature: '-- SIGNED-SOURCE: <>', 23 | startManual: '-- BEGIN-MANUAL-SECTION: []', 24 | endManual: '-- END-MANUAL-SECTION', 25 | }; 26 | 27 | export const hashTemplates = { 28 | signature: '# SIGNED-SOURCE: <>', 29 | startManual: '# BEGIN-MANUAL-SECTION: []', 30 | endManual: '# END-MANUAL-SECTION', 31 | }; 32 | -------------------------------------------------------------------------------- /packages/codegen-api/src/CodegenStep.ts: -------------------------------------------------------------------------------- 1 | import { CodegenFile } from './CodegenFile.js'; 2 | 3 | export default abstract class CodegenStep { 4 | constructor() {} 5 | 6 | abstract gen(): Promise; 7 | } 8 | -------------------------------------------------------------------------------- /packages/codegen-api/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './CodegenFile.js'; 2 | export { default as CodegenStep } from './CodegenStep.js'; 3 | import CodegenStep from './CodegenStep.js'; 4 | import { SchemaNode, SchemaEdge, SchemaFile } from '@aphro/schema-api'; 5 | 6 | export type Step = { 7 | new (opts: { 8 | nodeOrEdge: SchemaNode | SchemaEdge; 9 | edges: { [key: string]: SchemaEdge }; 10 | dest: string; 11 | }): CodegenStep; 12 | accepts: (x: SchemaNode | SchemaEdge) => boolean; 13 | }; 14 | 15 | export type GlobalStep = { 16 | new (nodes: SchemaNode[], edges: SchemaEdge[], dest: string): CodegenStep; 17 | accepts: (nodes: SchemaNode[], edges: SchemaEdge[]) => boolean; 18 | }; 19 | 20 | export const generatedDir = 'generated'; 21 | -------------------------------------------------------------------------------- /packages/codegen-api/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"], 8 | "references": [{ "path": "../schema-api" }] 9 | } 10 | -------------------------------------------------------------------------------- /packages/codegen-cli/.gitignore: -------------------------------------------------------------------------------- 1 | bin/ -------------------------------------------------------------------------------- /packages/codegen-cli/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /packages/codegen-cli/README.md: -------------------------------------------------------------------------------- 1 | # Codegen CLI 2 | 3 | The command line interface for running the codegen commands. 4 | 5 | Currently includes and executes core extensions. -------------------------------------------------------------------------------- /packages/codegen-cli/src/__tests__/cli.test.ts: -------------------------------------------------------------------------------- 1 | test('TEST TODO', () => {}); 2 | -------------------------------------------------------------------------------- /packages/codegen-cli/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./bin/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"], 8 | "references": [ 9 | { "path": "../codegen-api" }, 10 | { "path": "../schema" }, 11 | { "path": "../schema-api" }, 12 | { "path": "../codegen" }, 13 | { "path": "../codegen-ts" }, 14 | { "path": "../codegen-sql" }, 15 | { "path": "../../extensions/mutation-grammar" }, 16 | { "path": "../../extensions/mutation-codegen" }, 17 | { "path": "../../extensions/graphql-grammar" }, 18 | { "path": "../../extensions/graphql-codegen" } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /packages/codegen-sql/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /packages/codegen-sql/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /packages/codegen-sql/README.md: -------------------------------------------------------------------------------- 1 | # Codegen SQL 2 | 3 | Code generators for all SQL dialects. These generators generate table definitions, not queries, given query definitions are crafted at runtime. -------------------------------------------------------------------------------- /packages/codegen-sql/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | '@babel/preset-env', 5 | { 6 | targets: { 7 | node: 'current', 8 | }, 9 | }, 10 | ], 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /packages/codegen-sql/src/SqlFile.ts: -------------------------------------------------------------------------------- 1 | import { sign } from '@aphro/codegen'; 2 | import { CodegenFile, sqlTemplates } from '@aphro/codegen-api'; 3 | import { format } from 'sql-formatter'; 4 | 5 | export default class SqlFile implements CodegenFile { 6 | #contents: string; 7 | readonly templates = sqlTemplates; 8 | 9 | constructor( 10 | public readonly name: string, 11 | contents: string, 12 | private dialect: string, 13 | public readonly isUnsigned: boolean = false, 14 | ) { 15 | this.#contents = contents; 16 | } 17 | 18 | get contents(): string { 19 | return sign( 20 | format(this.#contents, { language: this.#dialectToLanguage() as any }), 21 | this.templates, 22 | ); 23 | } 24 | 25 | #dialectToLanguage() { 26 | if (this.dialect === 'postgres') { 27 | return 'postgresql'; 28 | } 29 | 30 | return this.dialect; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/codegen-sql/src/index.ts: -------------------------------------------------------------------------------- 1 | export { default as GenSqlTableSchema } from './GenSqlTableSchema.js'; 2 | -------------------------------------------------------------------------------- /packages/codegen-sql/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"], 8 | "references": [ 9 | { "path": "../codegen-api" }, 10 | { "path": "../schema" }, 11 | { "path": "../schema-api" }, 12 | { "path": "../codegen" }, 13 | { "path": "../sql-ts" } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /packages/codegen-ts/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /packages/codegen-ts/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /packages/codegen-ts/README.md: -------------------------------------------------------------------------------- 1 | # Codegen TS 2 | 3 | The core generators for TypeScript. 4 | - Model 5 | - Spec 6 | - Query 7 | 8 | Mutators, Authz, GraphQL, etc. codegen are supplied via extensions. -------------------------------------------------------------------------------- /packages/codegen-ts/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | '@babel/preset-env', 5 | { 6 | targets: { 7 | node: 'current', 8 | }, 9 | }, 10 | ], 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /packages/codegen-ts/src/GenSQLExports_node.ts: -------------------------------------------------------------------------------- 1 | import { SchemaEdge, SchemaNode } from '@aphro/schema-api'; 2 | import { GenSQLExports } from './GenSQLExports.js'; 3 | 4 | export class GenSQLExports_node extends GenSQLExports { 5 | protected getImports() { 6 | // The user might not want to pull node types into their project. Makes sense if it is a browser project. 7 | // So ts-ignore these. 8 | return ` 9 | // @ts-ignore 10 | import * as path from 'path'; 11 | // @ts-ignore 12 | import * as fs from 'fs'; 13 | 14 | // @ts-ignore 15 | import { fileURLToPath } from 'url'; 16 | 17 | const __filename = fileURLToPath(import.meta.url); 18 | const __dirname = path.dirname(__filename); 19 | 20 | const [${this.all.map(nore => nore.name).join(',\n')}] = await Promise.all([ 21 | ${this.all.map(this.getReadFileCode).join(',\n')} 22 | ]); 23 | `; 24 | } 25 | 26 | protected getFilename() { 27 | return 'exports-node-sql.ts'; 28 | } 29 | 30 | private getReadFileCode(nore: SchemaNode | SchemaEdge): string { 31 | return `fs.promises.readFile(path.join(__dirname, '${nore.name}.${nore.storage.engine}.sql'), {encoding: "utf8"})`; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/codegen-ts/src/GenTypes_d_ts.ts: -------------------------------------------------------------------------------- 1 | // declare module "*.sql?raw"; 2 | import { CodegenStep, CodegenFile, generatedDir } from '@aphro/codegen-api'; 3 | import { SchemaEdge, SchemaNode } from '@aphro/schema-api'; 4 | import * as path from 'path'; 5 | import TypescriptFile from './TypescriptFile.js'; 6 | 7 | export class GenTypes_d_ts extends CodegenStep { 8 | constructor( 9 | private nodes: SchemaNode[], 10 | private edges: SchemaEdge[], 11 | private schemaFileName: string, 12 | ) { 13 | super(); 14 | } 15 | 16 | static accepts(nodes: SchemaNode[], edges: SchemaEdge[]): boolean { 17 | return true; 18 | } 19 | 20 | async gen(): Promise { 21 | const filename = 'types.d.ts'; 22 | return new TypescriptFile(path.join(generatedDir, filename), `declare module "*.sql?raw";`); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/codegen-ts/src/TypescriptFile.ts: -------------------------------------------------------------------------------- 1 | import { sign } from '@aphro/codegen'; 2 | import { CodegenFile, algolTemplates } from '@aphro/codegen-api'; 3 | // @ts-ignore 4 | import prettier from 'prettier'; 5 | 6 | export default class TypescriptFile implements CodegenFile { 7 | #contents: string; 8 | readonly templates = algolTemplates; 9 | 10 | constructor( 11 | public readonly name: string, 12 | contents: string, 13 | public readonly isUnsigned: boolean = false, 14 | public readonly nochange: boolean = false, 15 | ) { 16 | this.#contents = contents; 17 | } 18 | 19 | get contents(): string { 20 | let contents = this.#contents; 21 | if (this.isUnsigned) { 22 | return prettier.format(contents, { parser: 'typescript' }); 23 | } 24 | 25 | contents = 26 | `/** 27 | * AUTO-GENERATED FILE 28 | * Do not modify. Update your schema and re-generate for changes. 29 | */ 30 | ` + this.#contents; 31 | 32 | return sign(prettier.format(contents, { parser: 'typescript' }), this.templates); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/codegen-ts/src/__tests__/GenTypesriptSpec.test.ts: -------------------------------------------------------------------------------- 1 | test('write some tests dude', () => {}); 2 | -------------------------------------------------------------------------------- /packages/codegen-ts/src/__tests__/tsUtils.test.ts: -------------------------------------------------------------------------------- 1 | import { fieldToTsType } from '../tsUtils'; 2 | 3 | test('field to ts type', () => { 4 | expect( 5 | fieldToTsType({ 6 | type: ['null'], 7 | }), 8 | ).toEqual('null'); 9 | 10 | expect( 11 | fieldToTsType({ 12 | type: [ 13 | { 14 | type: 'primitive', 15 | subtype: 'null', 16 | }, 17 | ], 18 | }), 19 | ).toEqual('null'); 20 | 21 | expect( 22 | fieldToTsType({ 23 | type: ['Foo'], 24 | }), 25 | ).toEqual('Foo'); 26 | }); 27 | -------------------------------------------------------------------------------- /packages/codegen-ts/src/index.ts: -------------------------------------------------------------------------------- 1 | export { default as GenTypescriptModel } from './GenTypescriptModel.js'; 2 | export { default as GenTypescriptQuery } from './GenTypescriptQuery.js'; 3 | export { default as GenTypescriptSpec } from './GenTypescriptSpec.js'; 4 | export { default as GenTypescriptModelManualMethodsClass } from './GenTypescriptModelManualMethodsClass.js'; 5 | export * from './tsUtils.js'; 6 | export { default as TypescriptFile } from './TypescriptFile.js'; 7 | export * from './GenSchemaExports.js'; 8 | export * from './GenSQLExports.js'; 9 | export * from './GenTypes_d_ts.js'; 10 | export * from './GenSQLExports_node.js'; 11 | -------------------------------------------------------------------------------- /packages/codegen-ts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src", 6 | "declarationMap": false 7 | }, 8 | "include": ["./src/"], 9 | "references": [ 10 | { "path": "../codegen-api" }, 11 | { "path": "../schema" }, 12 | { "path": "../schema-api" }, 13 | { "path": "../codegen" }, 14 | { "path": "../feature-gates" } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /packages/codegen/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /packages/codegen/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /packages/codegen/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | targets: { 7 | node: "current", 8 | }, 9 | }, 10 | ], 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /packages/codegen/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/codegen", 3 | "version": "0.2.8", 4 | "main": "lib/index.js", 5 | "type": "module", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/tantaman/aphrodite.git", 9 | "directory": "packages/codegen" 10 | }, 11 | "dependencies": { 12 | "@aphro/codegen-api": "workspace:*", 13 | "@aphro/schema": "workspace:*", 14 | "@aphro/schema-api": "workspace:*", 15 | "@strut/counter": "^0.0.11", 16 | "@strut/sid": "^0.1.2", 17 | "@strut/utils": "^0.1.1", 18 | "md5": "^2.3.0" 19 | }, 20 | "devDependencies": { 21 | "@babel/core": "^7.18.13", 22 | "@babel/preset-env": "^7.18.10", 23 | "@types/jest": "^28.1.8", 24 | "@types/node": "^18.7.13", 25 | "@types/prettier": "^2.7.0", 26 | "@typescript-eslint/typescript-estree": "^5.35.1", 27 | "fast-check": "^3.1.2", 28 | "jest": "^29.0.1", 29 | "typescript": "^4.8.2" 30 | }, 31 | "scripts": { 32 | "clean": "tsc --build --clean", 33 | "build": "tsc --build", 34 | "watch": "tsc --build -w", 35 | "test": "node ./node_modules/jest/bin/jest.js", 36 | "deep-clean": "rm -rf ./lib || true && rm tsconfig.tsbuildinfo || true" 37 | }, 38 | "jest": { 39 | "testMatch": [ 40 | "**/__tests__/**/*.test.js" 41 | ] 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/codegen/src/index.ts: -------------------------------------------------------------------------------- 1 | export { default as CodegenPipeline } from './CodegenPipeline.js'; 2 | export { default as uniqueImports } from './uniqueImports.js'; 3 | export * from './CodegenFile.js'; 4 | -------------------------------------------------------------------------------- /packages/codegen/src/uniqueImports.ts: -------------------------------------------------------------------------------- 1 | import { Import } from '@aphro/schema-api'; 2 | 3 | export default function uniqueImports(imports: readonly Import[]): Import[] { 4 | const seen = new Set(); 5 | const ret = imports.filter(i => { 6 | const key = toKey(i); 7 | if (seen.has(key)) { 8 | return false; 9 | } 10 | 11 | seen.add(key); 12 | return true; 13 | }); 14 | 15 | return ret; 16 | } 17 | 18 | function toKey(i: Import) { 19 | return i.name + '-' + i.as + '-' + i.from; 20 | } 21 | -------------------------------------------------------------------------------- /packages/codegen/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"], 8 | "references": [{ "path": "../codegen-api" }, { "path": "../schema" }, { "path": "../schema-api" }] 9 | } 10 | -------------------------------------------------------------------------------- /packages/context-runtime-ts/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /packages/context-runtime-ts/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /packages/context-runtime-ts/README.md: -------------------------------------------------------------------------------- 1 | # Config Runtime TS 2 | 3 | Package responsible for providing configuration to runtime layers. 4 | 5 | Query layer builds some query which can be run against a backend. That mapping from query to backend is taken care of 6 | here. 7 | 8 | Model has a mutator which persists to same backend. Query is created and then mapped by this package to the data store. -------------------------------------------------------------------------------- /packages/context-runtime-ts/babel.config.cjs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vlcn-io/vlcn-orm/ff90a4d588a5bed0fdcea0335d328f7c4dd51cd8/packages/context-runtime-ts/babel.config.cjs -------------------------------------------------------------------------------- /packages/context-runtime-ts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/context-runtime-ts", 3 | "version": "0.3.6", 4 | "main": "lib/index.js", 5 | "type": "module", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/tantaman/aphrodite.git", 9 | "directory": "packages/context-runtime-ts" 10 | }, 11 | "dependencies": { 12 | "@aphro/cache-runtime-ts": "workspace:*", 13 | "@aphro/schema-api": "workspace:*", 14 | "@aphro/sql-ts": "workspace:*", 15 | "@strut/events": "^0.0.10", 16 | "@strut/sid": "^0.1.2", 17 | "@strut/utils": "^0.1.1" 18 | }, 19 | "devDependencies": { 20 | "@jest/globals": "^29.0.1", 21 | "@types/jest": "^28.1.8", 22 | "jest": "^29.0.1", 23 | "typescript": "^4.8.2" 24 | }, 25 | "scripts": { 26 | "clean": "tsc --build --clean", 27 | "build": "tsc --build", 28 | "watch": "tsc --build -w", 29 | "test": "node --experimental-vm-modules --expose-gc ./node_modules/jest/bin/jest.js", 30 | "deep-clean": "rm -rf ./lib || true && rm tsconfig.tsbuildinfo || true" 31 | }, 32 | "jest": { 33 | "testMatch": [ 34 | "**/__tests__/**/*.test.js" 35 | ] 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /packages/context-runtime-ts/src/HeteroModelMap.ts: -------------------------------------------------------------------------------- 1 | import { SID_of } from '@strut/sid'; 2 | import { nullthrows } from '@strut/utils'; 3 | import { IModel } from './INode.js'; 4 | 5 | export default class ImmutableHeteroModelMap { 6 | protected map: Map, IModel | null> = new Map(); 7 | 8 | get, D extends {}>(id: SID_of): T | null { 9 | const ret = this.map.get(id); 10 | if (ret == null) { 11 | return null; 12 | } 13 | 14 | return ret as T; 15 | } 16 | 17 | getx, D extends {}>(id: SID_of): T { 18 | return nullthrows(this.map.get(id)) as T; 19 | } 20 | } 21 | 22 | export class MutableHeteroModelMap extends ImmutableHeteroModelMap { 23 | set, D extends {}>(id: SID_of, n: T | null): void { 24 | this.map.set(id, n); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/context-runtime-ts/src/OptimisticPromise.ts: -------------------------------------------------------------------------------- 1 | /* TODO: maybe just get rid of all this optimistic promise crap. 2 | * Complicates the code and is only a problem because React can't handle async correctly. 3 | */ 4 | export default class OptimisticPromise extends Promise { 5 | // @ts-ignore 6 | #optimistic: T; 7 | 8 | get optimistic(): T { 9 | return this.#optimistic; 10 | } 11 | 12 | __setOptimisticResult(r: T): void { 13 | this.#optimistic = r; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/context-runtime-ts/src/__tests__/context.test.ts: -------------------------------------------------------------------------------- 1 | import { asId } from '@strut/sid'; 2 | import { debugContext } from '../context.js'; 3 | import { viewer } from '../viewer.js'; 4 | import { jest } from '@jest/globals'; 5 | 6 | test('debug context intercepts and prints all calls to the db', () => { 7 | const ctx = debugContext(viewer(asId('sdf'))); 8 | 9 | const db = ctx.dbResolver.engine('memory').db('test'); 10 | expect(db).not.toBeUndefined(); 11 | 12 | console.log = jest.fn(); 13 | db.read({ 14 | type: 'read', 15 | tablish: 'foo', 16 | roots: [], 17 | }); 18 | expect(console.log).toBeCalledTimes(2); 19 | // expect(console.log).nthCalledWith(1, ['query']); 20 | // expect(console.log).nthCalledWith(2, [ 21 | // [ 22 | // { 23 | // type: 'read', 24 | // tablish: 'foo', 25 | // roots: [], 26 | // }, 27 | // ], 28 | // ]); 29 | }); 30 | -------------------------------------------------------------------------------- /packages/context-runtime-ts/src/__tests__/transactionLog.test.ts: -------------------------------------------------------------------------------- 1 | import TransactionLog, { GenericTransactionLog } from '../transactionLog'; 2 | declare const global: { 3 | gc: () => void; 4 | }; 5 | 6 | test('weakly observable', async () => { 7 | const log = new GenericTransactionLog(50); 8 | 9 | log.observe(makeObserver()); 10 | expect(log.numObservers).toBe(1); 11 | 12 | log.push(1); 13 | 14 | expect(log.numObservers).toBe(1); 15 | 16 | await new Promise(resolve => setTimeout(resolve, 0)); 17 | global.gc(); 18 | 19 | log.push(2); 20 | 21 | expect(log.numObservers).toBe(0); 22 | }); 23 | 24 | test('stays under capacity', () => { 25 | const log = new GenericTransactionLog(5); 26 | for (let i = 0; i < 100; ++i) { 27 | log.push(1); 28 | expect(log.length).toBe(Math.min(i + 1, 5)); 29 | } 30 | }); 31 | 32 | test('notifies observers', async () => { 33 | const log = new GenericTransactionLog(5); 34 | let notified = false; 35 | const observer = () => { 36 | notified = true; 37 | }; 38 | log.observe(observer); 39 | log.push(1); 40 | expect(notified).toBe(true); 41 | 42 | await new Promise(resolve => setTimeout(resolve, 0)); 43 | global.gc(); 44 | 45 | notified = false; 46 | log.push(2); 47 | expect(notified).toBe(true); 48 | }); 49 | 50 | function makeObserver() { 51 | return () => {}; 52 | } 53 | -------------------------------------------------------------------------------- /packages/context-runtime-ts/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './DBResolver.js'; 2 | export { default as context } from './context.js'; 3 | export * from './context.js'; 4 | export * from './viewer.js'; 5 | export { basicResolver, noStorageResolver } from './resolvers.js'; 6 | export * from './changeset.js'; 7 | export * from './INode.js'; 8 | export { default as HeteroModelMap, MutableHeteroModelMap } from './HeteroModelMap.js'; 9 | export * from './transaction.js'; 10 | export { default as OptimisticPromise } from './OptimisticPromise.js'; 11 | -------------------------------------------------------------------------------- /packages/context-runtime-ts/src/runtimeConfig.ts: -------------------------------------------------------------------------------- 1 | import { nullthrows } from '@strut/utils'; 2 | import { DBResolver } from './DBResolver.js'; 3 | 4 | let resolver: DBResolver; 5 | const config = { 6 | set resolver(r: DBResolver) { 7 | resolver = r; 8 | }, 9 | 10 | get resolver(): DBResolver { 11 | return nullthrows(resolver); 12 | }, 13 | }; 14 | 15 | export default config; 16 | -------------------------------------------------------------------------------- /packages/context-runtime-ts/src/transaction.ts: -------------------------------------------------------------------------------- 1 | import { SID_of } from '@strut/sid'; 2 | import HeteroModelMap from './HeteroModelMap.js'; 3 | import { Changeset } from './changeset.js'; 4 | import { IModel } from './INode.js'; 5 | 6 | export type Transaction = { 7 | readonly changes: Map, Changeset>; 8 | readonly nodes: HeteroModelMap; 9 | readonly persistHandle: Promise; 10 | // readonly options: CommitOptions; 11 | }; 12 | -------------------------------------------------------------------------------- /packages/context-runtime-ts/src/viewer.ts: -------------------------------------------------------------------------------- 1 | import { SID_of } from '@strut/sid'; 2 | 3 | export type ViewerAuth = 'authenticated' | 'anonymous'; 4 | 5 | export type Viewer = 6 | | { 7 | auth: 'authenticated'; 8 | // TODO: we should probably not give out the viewer id. Doing so allows 9 | // devs to create security holes. 10 | readonly id: SID_of; 11 | readonly key: string; 12 | } 13 | | { 14 | auth: 'anonymous'; 15 | readonly key: string; 16 | }; 17 | 18 | // TODO: we should force proof of authentication so these can't be created arbitrarily 19 | // by devs. for users that are not actually logged in. I.e., protecting devs from mistakes. 20 | export function viewer(id: SID_of): Viewer { 21 | return { 22 | auth: 'authenticated', 23 | id, 24 | get key() { 25 | return 'authenticated' + '-' + id; 26 | }, 27 | }; 28 | } 29 | 30 | export function anonymous(): Viewer { 31 | return { 32 | auth: 'anonymous', 33 | get key() { 34 | return 'anonymous'; 35 | }, 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /packages/context-runtime-ts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"], 8 | "references": [ 9 | { "path": "../schema-api" }, 10 | { "path": "../cache-runtime-ts" }, 11 | { "path": "../sql-ts" } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /packages/feature-gates/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /packages/feature-gates/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /packages/feature-gates/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/feature-gates", 3 | "version": "0.0.1", 4 | "main": "lib/index.js", 5 | "type": "module", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/tantaman/aphrodite.git", 9 | "directory": "packages/feature-gates" 10 | }, 11 | "devDependencies": { 12 | "typescript": "^4.8.2" 13 | }, 14 | "scripts": { 15 | "clean": "tsc --build --clean", 16 | "build": "tsc --build", 17 | "watch": "tsc --build -w", 18 | "deep-clean": "rm -rf ./lib || true && rm tsconfig.tsbuildinfo || true" 19 | }, 20 | "jest": { 21 | "testMatch": [ 22 | "**/__tests__/**/*.test.js" 23 | ] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/feature-gates/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Features we've decided to disable or enable in the current build of Aphrodite 3 | * 4 | * This was introduced as a way to strip down Aphrodite to a less complex beast 5 | * by disabling non essential features. 6 | */ 7 | export default { 8 | NAMED_MUTATIONS: true, 9 | }; 10 | -------------------------------------------------------------------------------- /packages/feature-gates/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/grammar-extension-api/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /packages/grammar-extension-api/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /packages/grammar-extension-api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/grammar-extension-api", 3 | "version": "0.2.6", 4 | "main": "lib/index.js", 5 | "type": "module", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/tantaman/aphrodite.git", 9 | "directory": "packages/grammar-extension-api" 10 | }, 11 | "dependencies": { 12 | "@aphro/schema-api": "workspace:*", 13 | "ohm-js": "^16.4.0" 14 | }, 15 | "devDependencies": { 16 | "typescript": "^4.8.2" 17 | }, 18 | "scripts": { 19 | "clean": "tsc --build --clean", 20 | "build": "tsc --build", 21 | "watch": "tsc --build -w", 22 | "deep-clean": "rm -rf ./lib || true && rm tsconfig.tsbuildinfo || true" 23 | }, 24 | "jest": { 25 | "testMatch": [ 26 | "**/__tests__/**/*.test.js" 27 | ] 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/grammar-extension-api/src/index.ts: -------------------------------------------------------------------------------- 1 | import { ValidationError } from '@aphro/schema-api'; 2 | import { ActionDict } from 'ohm-js'; 3 | 4 | type RuleName = string; 5 | interface ExtensionPoints { 6 | NodeFunction?: RuleName; 7 | EdgeFunction?: RuleName; 8 | // eventually fields too 9 | // and... extensions of extensions? e.g., auth on mutations... 10 | 11 | // should we just invert control instead? 12 | // make a pipeline where each stage of the pipeline augments 13 | // the parser... 14 | // 15 | // and provide utils to do so. 16 | // 17 | // this'll make extensions of extensions easier to implement. 18 | // or... we can just do it this way and one can register an 19 | // extension point when they add their extension... 20 | // 21 | // declare module, interface extension trick... 22 | } 23 | 24 | export interface GrammarExtension { 25 | readonly name: string; //Symbol; 26 | readonly extends: ExtensionPoints; 27 | 28 | grammar(): string; 29 | actions(): ActionDict; 30 | condensor(ast: TAst): [ValidationError[], TCondensed]; 31 | } 32 | -------------------------------------------------------------------------------- /packages/grammar-extension-api/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"], 8 | "references": [{ "path": "../schema-api" }] 9 | } 10 | -------------------------------------------------------------------------------- /packages/instrument/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /packages/instrument/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @aphro/instrument 2 | 3 | ## 0.0.6 4 | 5 | ### Patch Changes 6 | 7 | - Export queries and specs, move connectors to own packages, fix #43 and other bugs 8 | 9 | ## 0.0.5 10 | 11 | ### Patch Changes 12 | 13 | - transaction support 14 | 15 | ## 0.0.4 16 | 17 | ### Patch Changes 18 | 19 | - Strict mode for typescript, useEffect vs useSyncExternalStore, useLiveResult hook 20 | 21 | ## 0.0.3 22 | 23 | ### Patch Changes 24 | 25 | - rebuild -- last publish had a clobbered version of pnpm 26 | 27 | ## 0.0.2 28 | 29 | ### Patch Changes 30 | 31 | - workaround to adhere to strict mode in generated code #43 32 | -------------------------------------------------------------------------------- /packages/instrument/README.md: -------------------------------------------------------------------------------- 1 | # instrument 2 | 3 | Helper functions to trace and measure program execution. 4 | -------------------------------------------------------------------------------- /packages/instrument/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/instrument", 3 | "version": "0.0.6", 4 | "main": "lib/index.js", 5 | "type": "module", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/tantaman/aphrodite.git", 9 | "directory": "packages/instrument" 10 | }, 11 | "dependencies": { 12 | "@opentelemetry/api": "^1.1.0" 13 | }, 14 | "devDependencies": { 15 | "@babel/core": "^7.18.13", 16 | "@babel/preset-env": "^7.18.10", 17 | "@types/jest": "^28.1.8", 18 | "jest": "^29.0.1", 19 | "typescript": "^4.8.2" 20 | }, 21 | "scripts": { 22 | "clean": "tsc --build --clean", 23 | "build": "tsc --build", 24 | "watch": "tsc --build -w", 25 | "deep-clean": "rm -rf ./lib || true && rm tsconfig.tsbuildinfo || true" 26 | }, 27 | "jest": { 28 | "testMatch": [ 29 | "**/__tests__/**/*.test.js" 30 | ] 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/instrument/src/index.ts: -------------------------------------------------------------------------------- 1 | export { default as tracer, Tracer } from './tracer.js'; 2 | -------------------------------------------------------------------------------- /packages/instrument/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"], 8 | "references": [] 9 | } 10 | -------------------------------------------------------------------------------- /packages/migration-runtime-ts/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /packages/migration-runtime-ts/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /packages/migration-runtime-ts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/migration-runtime-ts", 3 | "version": "0.1.7", 4 | "main": "lib/index.js", 5 | "type": "module", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/tantaman/aphrodite.git", 9 | "directory": "packages/migration-runtime-ts" 10 | }, 11 | "dependencies": { 12 | "@aphro/context-runtime-ts": "workspace:*", 13 | "@aphro/sql-ts": "workspace:*", 14 | "@databases/sqlite": "^4.0.1", 15 | "@strut/utils": "^0.1.1" 16 | }, 17 | "devDependencies": { 18 | "@babel/core": "^7.18.13", 19 | "@babel/preset-env": "^7.18.10", 20 | "@types/jest": "^28.1.8", 21 | "@types/prettier": "^2.7.0", 22 | "@typescript-eslint/typescript-estree": "^5.35.1", 23 | "jest": "^29.0.1", 24 | "md5": "^2.3.0", 25 | "prettier": "^2.7.1", 26 | "sql-formatter": "^10.0.0", 27 | "typescript": "^4.8.2" 28 | }, 29 | "scripts": { 30 | "clean": "tsc --build --clean", 31 | "build": "tsc --build", 32 | "watch": "tsc --build -w", 33 | "test": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js", 34 | "deep-clean": "rm -rf ./lib || true && rm tsconfig.tsbuildinfo || true" 35 | }, 36 | "jest": { 37 | "testMatch": [ 38 | "**/__tests__/**/*.test.js" 39 | ] 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /packages/migration-runtime-ts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"], 8 | "references": [ 9 | { 10 | "path": "../../packages/sql-ts" 11 | }, 12 | { 13 | "path": "../../packages/context-runtime-ts" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /packages/model-runtime-ts/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ 2 | -------------------------------------------------------------------------------- /packages/model-runtime-ts/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /packages/model-runtime-ts/README.md: -------------------------------------------------------------------------------- 1 | # Model 2 | 3 | Runtime library for models generated from schemas. 4 | 5 | TODO: 6 | 1. Validation step... 7 | 1. To ensure foreign key edges have an appropriate inverse field edge 8 | 1. on the other schema. 9 | 2. Enable model superclasses / traits 10 | 3. IDL 11 | 4. Stop using keys from edges / fields 12 | 5. Docs 13 | 6. Edge queries and edge data 14 | 7. Semantic types 15 | 16 | Are the synthetic transactions not good enough / not doing it? 17 | 18 | What does a non synth tx look like? 19 | Slide, Deck, etc. mutation methods return changesets? 20 | Changesets are accumulated and then executed by the caller? 21 | 22 | Does the model never execute its own changesets? 23 | But it is on the client code to decide how many changesets to accumulate before executing them? 24 | 25 | What if a model needs some transient state (changesets to be committed) before it can do more? 26 | 27 | --- 28 | 29 | If it is up to clients to commit changesets then they are better able to integrate more disperate systems that they may want to mutate atomically. 30 | 31 | But if a client becomes a client? What happens to the changesets it was executing? Does it now have to pass them back instead? 32 | 33 | --- 34 | -------------------------------------------------------------------------------- /packages/model-runtime-ts/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | targets: { 7 | node: "current", 8 | }, 9 | }, 10 | ], 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /packages/model-runtime-ts/src/Edge.ts: -------------------------------------------------------------------------------- 1 | import { Context, IEdge, EdgeSpecWithCreate } from '@aphro/context-runtime-ts'; 2 | import Model from './Model.js'; 3 | 4 | export default abstract class Edge extends Model implements IEdge { 5 | abstract readonly spec: EdgeSpecWithCreate; 6 | 7 | constructor(ctx: Context, data: T) { 8 | super(ctx, data); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/model-runtime-ts/src/ModelReference.ts: -------------------------------------------------------------------------------- 1 | import { SID_of } from '@strut/sid'; 2 | 3 | /** 4 | * Represents a yet to be resolved reference to a model. 5 | * 6 | * This is "yet to be resolved" either because the model has not been created yet 7 | * or because it has not been loaded from storage yet. 8 | * 9 | * Likely should create sub-types for each case. 10 | */ 11 | // export default class ModelReference extends PersistedModel<{ 12 | // id: SID_of; 13 | // }> { 14 | // constructor(id: SID_of, private aSchemaName: string) { 15 | // super({ id }); 16 | // } 17 | 18 | // get schemaName() { 19 | // return this.aSchemaName; 20 | // } 21 | 22 | // toStorage(): Object { 23 | // throw new Error('Cannot persist a reference'); 24 | // } 25 | // } 26 | -------------------------------------------------------------------------------- /packages/model-runtime-ts/src/Node.ts: -------------------------------------------------------------------------------- 1 | import { SID_of } from '@strut/sid'; 2 | import { Disposer } from '@strut/events'; 3 | import { Context } from '@aphro/context-runtime-ts'; 4 | import { typedKeys } from '@strut/utils'; 5 | import { INode, NodeSpecWithCreate } from '@aphro/context-runtime-ts'; 6 | import Model from './Model.js'; 7 | 8 | export interface HasId { 9 | readonly id: SID_of; 10 | } 11 | 12 | export function isHasId(object: any): object is HasId { 13 | return 'id' in object && typeof object.id === 'string'; 14 | } 15 | 16 | export default abstract class Node extends Model implements INode { 17 | abstract readonly id: SID_of; 18 | abstract readonly spec: NodeSpecWithCreate; 19 | 20 | constructor(ctx: Context, data: T) { 21 | super(ctx, data); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/model-runtime-ts/src/__tests__/MemoryDB.test.ts: -------------------------------------------------------------------------------- 1 | import MemoryDB from '../MemoryDB.js'; 2 | 3 | test('create then read', () => {}); 4 | -------------------------------------------------------------------------------- /packages/model-runtime-ts/src/datasetKey.ts: -------------------------------------------------------------------------------- 1 | import { JunctionEdgeSpec, NodeSpec } from '@aphro/schema-api'; 2 | 3 | export type DatasetKey = string; 4 | 5 | export default function specToDatasetKey(spec: NodeSpec | JunctionEdgeSpec): DatasetKey { 6 | return spec.storage.engine + '-' + spec.storage.db + '-' + spec.storage.tablish; 7 | } 8 | -------------------------------------------------------------------------------- /packages/model-runtime-ts/src/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Node } from './Node.js'; 2 | export { default as Edge } from './Edge.js'; 3 | export { default as specToDatasetKey } from './datasetKey.js'; 4 | export { default as observe } from './observe.js'; 5 | export { default as MemoryDB } from './MemoryDB.js'; 6 | export { default as modelGenMemo } from './modelGenMemo.js'; 7 | export * from './modelDataEncoding.js'; 8 | -------------------------------------------------------------------------------- /packages/model-runtime-ts/src/modelGenMemo.ts: -------------------------------------------------------------------------------- 1 | import { Context, OptimisticPromise } from '@aphro/context-runtime-ts'; 2 | import { SID_of } from '@strut/sid'; 3 | 4 | /** 5 | * Memoizes `gen`, `genFoo` type methods where we're loading a model by id. 6 | * 7 | * If multiple concurrent access to the method happens, return the promise awaiting to be resolved. 8 | * If the thing is already cached, returns that. 9 | * 10 | * TODO: can we move this deeper into the query layer itself? 11 | * TODO: apply this to 1-1 edges too. E.g., `deck->genOwner` 12 | */ 13 | export default function modelGenMemo( 14 | dbname: string, 15 | tablish: string, 16 | gen: (ctx: Context, id: SID_of) => Promise, 17 | ) { 18 | const priorHandles: Map> = new Map(); 19 | return async (ctx: Context, id: SID_of) => { 20 | const key = ctx.cache.cacheId + '~' + id; 21 | const priorHandle = priorHandles.get(key); 22 | if (priorHandle) { 23 | return priorHandle; 24 | } 25 | const existing = ctx.cache.get(id as SID_of, dbname, tablish); 26 | if (existing != null) { 27 | return existing; 28 | } 29 | const currentHandle = gen(ctx, id); 30 | priorHandles.set(key, currentHandle); 31 | currentHandle.finally(() => priorHandles.delete(key)); 32 | return currentHandle; 33 | }; 34 | } 35 | -------------------------------------------------------------------------------- /packages/model-runtime-ts/src/observe.ts: -------------------------------------------------------------------------------- 1 | type It = { 2 | [Symbol.iterator]: () => It; 3 | throw(): { done: true; value: T }; 4 | return(): { done: true; value: T }; 5 | next(): { done: false; value: Promise }; 6 | }; 7 | 8 | export default function observe(initialize: (change: (x: T) => T) => null | (() => void)) { 9 | let stale = false; 10 | let value: T; 11 | let resolve: ((value: T | PromiseLike) => void) | null; 12 | const dispose = initialize(change); 13 | 14 | function change(x: T) { 15 | if (resolve) resolve(x), (resolve = null); 16 | else stale = true; 17 | return (value = x); 18 | } 19 | 20 | function next(): { done: false; value: Promise } { 21 | return { 22 | done: false, 23 | value: stale ? ((stale = false), Promise.resolve(value)) : new Promise(_ => (resolve = _)), 24 | }; 25 | } 26 | 27 | const ret: It = { 28 | [Symbol.iterator]: () => ret, 29 | throw: () => (dispose != null && dispose(), { done: true, value }), 30 | return: () => (dispose != null && dispose(), { done: true, value }), 31 | next, 32 | }; 33 | return ret; 34 | } 35 | -------------------------------------------------------------------------------- /packages/model-runtime-ts/src/that.ts: -------------------------------------------------------------------------------- 1 | export default function that(this: any) { 2 | return this; 3 | } 4 | -------------------------------------------------------------------------------- /packages/model-runtime-ts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"], 8 | "references": [{ "path": "../schema-api" }, { "path": "../context-runtime-ts" }] 9 | } 10 | -------------------------------------------------------------------------------- /packages/mutator-runtime-ts/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /packages/mutator-runtime-ts/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /packages/mutator-runtime-ts/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | '@babel/preset-env', 5 | { 6 | targets: { 7 | node: 'current', 8 | }, 9 | }, 10 | ], 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /packages/mutator-runtime-ts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/mutator-runtime-ts", 3 | "version": "0.4.2", 4 | "main": "lib/index.js", 5 | "type": "module", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/tantaman/aphrodite.git", 9 | "directory": "packages/mutator-runtime-ts" 10 | }, 11 | "dependencies": { 12 | "@aphro/context-runtime-ts": "workspace:*", 13 | "@aphro/instrument": "workspace:*", 14 | "@aphro/model-runtime-ts": "workspace:*", 15 | "@aphro/schema-api": "workspace:*", 16 | "@aphro/sql-ts": "workspace:*", 17 | "@strut/sid": "^0.1.2", 18 | "@strut/utils": "^0.1.1", 19 | "nanoid": "^4.0.0" 20 | }, 21 | "devDependencies": { 22 | "@babel/core": "^7.18.13", 23 | "@babel/preset-env": "^7.18.10", 24 | "@types/jest": "^28.1.8", 25 | "fast-check": "^3.1.2", 26 | "jest": "^29.0.1", 27 | "typescript": "^4.8.2" 28 | }, 29 | "scripts": { 30 | "test": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js", 31 | "clean": "tsc --build --clean", 32 | "build": "tsc --build", 33 | "watch": "tsc --build -w", 34 | "deep-clean": "rm -rf ./lib || true && rm tsconfig.tsbuildinfo || true" 35 | }, 36 | "jest": { 37 | "testMatch": [ 38 | "**/__tests__/**/*.test.js" 39 | ] 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /packages/mutator-runtime-ts/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Mutator.js'; 2 | export * from './commit.js'; 3 | export { default as MutationsBase } from './MutationsBase.js'; 4 | export { default as makeSavable } from './makeSavable.js'; 5 | -------------------------------------------------------------------------------- /packages/mutator-runtime-ts/src/makeSavable.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Changeset, 3 | Context, 4 | IModel, 5 | OptimisticPromise, 6 | SavableChangeset, 7 | } from '@aphro/context-runtime-ts'; 8 | import { commit } from './commit.js'; 9 | 10 | export default function makeSavable, D extends {}>( 11 | ctx: Context, 12 | cs: Changeset, 13 | ): Changeset & SavableChangeset { 14 | return { 15 | ...cs, 16 | save(): OptimisticPromise { 17 | return commit(ctx, cs); 18 | }, 19 | save0(): M { 20 | return commit(ctx, cs).optimistic; 21 | }, 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /packages/mutator-runtime-ts/src/memoryWriter.ts: -------------------------------------------------------------------------------- 1 | import { Context, IModel, MemoryResolvedDB, ResolvedDB } from '@aphro/context-runtime-ts'; 2 | 3 | export default { 4 | async upsertGroup(db: ResolvedDB, nodes: IModel[]): Promise { 5 | const first = nodes[0]; 6 | const spec = first.spec; 7 | 8 | await (db as MemoryResolvedDB).write({ 9 | type: 'write', 10 | op: 'upsert', 11 | models: nodes, 12 | tablish: spec.storage.tablish, 13 | }); 14 | }, 15 | 16 | async deleteGroup(db: ResolvedDB, nodes: IModel[]): Promise { 17 | const first = nodes[0]; 18 | const spec = first.spec; 19 | 20 | await (db as MemoryResolvedDB).write({ 21 | type: 'write', 22 | op: 'delete', 23 | models: nodes, 24 | tablish: spec.storage.tablish, 25 | }); 26 | }, 27 | }; 28 | -------------------------------------------------------------------------------- /packages/mutator-runtime-ts/src/trace.ts: -------------------------------------------------------------------------------- 1 | import { tracer, Tracer } from '@aphro/instrument'; 2 | 3 | const t: Tracer = tracer('@aphro/mutator-runtime-ts', '0.3.4'); 4 | 5 | export default t; 6 | -------------------------------------------------------------------------------- /packages/mutator-runtime-ts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"], 8 | "references": [ 9 | { "path": "../schema-api" }, 10 | { "path": "../model-runtime-ts" }, 11 | { "path": "../context-runtime-ts" }, 12 | { "path": "../sql-ts" }, 13 | { "path": "../instrument" } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /packages/parse-ts/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /packages/parse-ts/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /packages/parse-ts/README.md: -------------------------------------------------------------------------------- 1 | Utilities to parse typescript files. -------------------------------------------------------------------------------- /packages/parse-ts/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | '@babel/preset-env', 5 | { 6 | targets: { 7 | node: 'current', 8 | }, 9 | }, 10 | ], 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /packages/parse-ts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/parse-ts", 3 | "version": "0.2.6", 4 | "main": "lib/index.js", 5 | "type": "module", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/tantaman/aphrodite.git", 9 | "directory": "packages/parse-ts" 10 | }, 11 | "dependencies": { 12 | "typescript": "^4.8.2" 13 | }, 14 | "devDependencies": { 15 | "@babel/core": "^7.18.13", 16 | "@babel/preset-env": "^7.18.10", 17 | "@types/jest": "^28.1.8", 18 | "@typescript-eslint/typescript-estree": "^5.35.1", 19 | "fast-check": "^3.1.2", 20 | "jest": "^29.0.1" 21 | }, 22 | "scripts": { 23 | "clean": "tsc --build --clean", 24 | "build": "tsc --build", 25 | "watch": "tsc --build -w", 26 | "test": "node ./node_modules/jest/bin/jest.js", 27 | "deep-clean": "rm -rf ./lib || true && rm tsconfig.tsbuildinfo || true" 28 | }, 29 | "jest": { 30 | "testMatch": [ 31 | "**/__tests__/**/*.test.js" 32 | ] 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/parse-ts/src/__tests__/extractors.test.ts: -------------------------------------------------------------------------------- 1 | import { exports, imports } from '../extractors.js'; 2 | import { stringToAst } from '../toAst.js'; 3 | 4 | const file = ` 5 | import foo from './boo'; 6 | import bar from './baz'; 7 | 8 | const x = 1; 9 | const y = 2; 10 | 11 | export function one() {} 12 | export function two() {} 13 | `; 14 | 15 | test('extracting import statements', () => { 16 | const ast = stringToAst('test', file); 17 | expect(imports(ast).map(e => e.importClause?.name?.escapedText)).toEqual(['foo', 'bar']); 18 | }); 19 | 20 | test('extracting export statements', () => { 21 | const ast = stringToAst('test', file); 22 | const exported = exports(ast); 23 | 24 | expect(exported.map(e => e.name?.escapedText)).toEqual(['one', 'two']); 25 | }); 26 | -------------------------------------------------------------------------------- /packages/parse-ts/src/extractors.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | import ts from 'typescript'; 3 | import { filter } from './nodeChildren.js'; 4 | 5 | // non complete implementation of export extraction. 6 | // meets the current minimum bar for GenTypescriptMutationImpls 7 | export function exports(file: ts.SourceFile) { 8 | return filter(file, (n): n is ts.FunctionDeclaration => { 9 | switch (n.kind) { 10 | case ts.SyntaxKind.FunctionDeclaration: 11 | const modifiers = n.modifiers; 12 | if (modifiers == null || modifiers[0] == null) { 13 | return false; 14 | } 15 | 16 | return modifiers[0].kind === ts.SyntaxKind.ExportKeyword; 17 | } 18 | 19 | return false; 20 | }); 21 | } 22 | 23 | export function imports(file: ts.SourceFile): ts.ImportDeclaration[] { 24 | const x = []; 25 | // x.filter(); 26 | return filter(file, (n): n is ts.ImportDeclaration => { 27 | return n.kind === ts.SyntaxKind.ImportDeclaration; 28 | }); 29 | } 30 | -------------------------------------------------------------------------------- /packages/parse-ts/src/index.ts: -------------------------------------------------------------------------------- 1 | export * as extractors from './extractors.js'; 2 | export * as nodeChildren from './nodeChildren.js'; 3 | export * as toAst from './toAst.js'; 4 | -------------------------------------------------------------------------------- /packages/parse-ts/src/nodeChildren.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | import ts from 'typescript'; 3 | 4 | export function filter(n: ts.Node, pred: (n: ts.Node) => n is S): S[] { 5 | const ret: S[] = []; 6 | n.forEachChild((c: ts.Node) => { 7 | if (pred(c)) { 8 | ret.push(c); 9 | } 10 | }); 11 | return ret; 12 | } 13 | 14 | export function map(n: ts.Node, m: (n: ts.Node) => R): R[] { 15 | const ret: R[] = []; 16 | n.forEachChild((c: ts.Node) => { 17 | ret.push(m(c)); 18 | }); 19 | return ret; 20 | } 21 | -------------------------------------------------------------------------------- /packages/parse-ts/src/toAst.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | import ts from 'typescript'; 3 | 4 | export function stringToAst( 5 | filename: string, 6 | fileContents: string, 7 | target: ts.ScriptTarget = 99, //ts.ScriptTarget.Latest, 8 | ): ts.SourceFile { 9 | return ts.createSourceFile(filename, fileContents, target, true); 10 | } 11 | -------------------------------------------------------------------------------- /packages/parse-ts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"], 8 | "references": [] 9 | } 10 | -------------------------------------------------------------------------------- /packages/query-runtime-ts/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ 2 | -------------------------------------------------------------------------------- /packages/query-runtime-ts/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /packages/query-runtime-ts/README.md: -------------------------------------------------------------------------------- 1 | # Query 2 | 3 | The query layer built atop schemas -------------------------------------------------------------------------------- /packages/query-runtime-ts/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | targets: { 7 | node: "current", 8 | }, 9 | }, 10 | ], 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /packages/query-runtime-ts/src/CountLoadExpression.ts: -------------------------------------------------------------------------------- 1 | import { Context, INode } from '@aphro/context-runtime-ts'; 2 | import { ChunkIterable, SyncMappedChunkIterable } from './ChunkIterable'; 3 | import { DerivedExpression } from './Expression'; 4 | 5 | /** 6 | * More context on Expressions exists in `./Expression.ts` 7 | * 8 | * A ModelLoadExpression is a DerivedExpression that converts raw data 9 | * returned by the data source into `Aphrodite` model instances. 10 | * 11 | * E.g., If you defined a `Todo` node in your schema then queried all todos, 12 | * a `ModelLoadExpression` is added to this query to convert the rows to `Todo` instances. 13 | */ 14 | export default class CountLoadExpression implements DerivedExpression { 15 | readonly type = 'countLoad'; 16 | constructor(private ctx: Context) {} 17 | 18 | chainAfter(iterable: ChunkIterable) { 19 | return iterable.map(d => (d as any)['count(*)']); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/query-runtime-ts/src/ExpressionVisitor.ts: -------------------------------------------------------------------------------- 1 | import { filter, hop, orderBy, take } from "./Expression.js"; 2 | 3 | export interface ExpressionVisitor { 4 | filter(f: ReturnType): TRet; 5 | orderBy(o: ReturnType): TRet; 6 | limit(l: ReturnType): TRet; 7 | hop(h: ReturnType): TRet; 8 | } 9 | -------------------------------------------------------------------------------- /packages/query-runtime-ts/src/Field.ts: -------------------------------------------------------------------------------- 1 | import { IModel, INode } from '@aphro/context-runtime-ts'; 2 | 3 | export interface FieldGetter { 4 | readonly get: (m: Tm) => Tv; 5 | } 6 | 7 | /** 8 | * Don't be confused by `ModelFieldGetter` 9 | * You may see `model._get(fieldName)` and assume that we're not doing filters 10 | * in the database but instead loading the model into the application before filtering it. 11 | * 12 | * This is not the case. ModelFieldGetters are optimized away into SQL statements whenever possible. 13 | * They have logic to fetch data from the model in the rare case they can not be optimized (e.g., the user 14 | * filters based on arbitrary logic and not based on an expression supported in SQL). 15 | * 16 | * Read more about query optimization here: https://tantaman.com/2022-05-26-query-plan-optimization.html 17 | */ 18 | export class ModelFieldGetter> 19 | implements FieldGetter 20 | { 21 | constructor(public readonly fieldName: Tk) {} 22 | 23 | get(model: Tm): Td[Tk] { 24 | return model._get(this.fieldName); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/query-runtime-ts/src/ModelLoadExpression.ts: -------------------------------------------------------------------------------- 1 | import { Context, IModel, INode } from '@aphro/context-runtime-ts'; 2 | import { ChunkIterable, SyncMappedChunkIterable } from './ChunkIterable'; 3 | import { DerivedExpression } from './Expression'; 4 | 5 | /** 6 | * More context on Expressions exists in `./Expression.ts` 7 | * 8 | * A ModelLoadExpression is a DerivedExpression that converts raw data 9 | * returned by the data source into `Aphrodite` model instances. 10 | * 11 | * E.g., If you defined a `Todo` node in your schema then queried all todos, 12 | * a `ModelLoadExpression` is added to this query to convert the rows to `Todo` instances. 13 | */ 14 | export default class ModelLoadExpression> 15 | implements DerivedExpression 16 | { 17 | readonly type = 'modelLoad'; 18 | constructor(private ctx: Context, private factory: (ctx: Context, data: TData) => TModel) {} 19 | 20 | chainAfter(iterable: ChunkIterable) { 21 | return iterable.map(d => this.factory(this.ctx, d)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/query-runtime-ts/src/StorageAdapter.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Storage adapter should exist elsewhere? 3 | At a higher level where we have dependencies for things such as dexie or sql or cypher. 4 | */ 5 | -------------------------------------------------------------------------------- /packages/query-runtime-ts/src/explain/orderPlans.ts: -------------------------------------------------------------------------------- 1 | import HopPlan from '../HopPlan.js'; 2 | import { IPlan } from '../Plan.js'; 3 | 4 | export default function orderPlans(plan: IPlan): IPlan[] { 5 | const plans: IPlan[] = []; 6 | let sourcePlan: IPlan | null = plan; 7 | while (sourcePlan != null) { 8 | plans.push(sourcePlan); 9 | if (sourcePlan instanceof HopPlan) { 10 | sourcePlan = sourcePlan.sourcePlan; 11 | } else { 12 | sourcePlan = null; 13 | } 14 | } 15 | 16 | plans.reverse(); 17 | return plans; 18 | } 19 | -------------------------------------------------------------------------------- /packages/query-runtime-ts/src/explain/printPlan.ts: -------------------------------------------------------------------------------- 1 | import { IPlan } from '../Plan.js'; 2 | import orderPlans from './orderPlans.js'; 3 | 4 | export default function printPlan(plan: IPlan) { 5 | // Query plans can be chained after other query plans. 6 | // To get the in-order list of plans, we need to go backwards through the linked list of plans, 7 | // push each onto an array and then reverse the array. 8 | const plans = orderPlans(plan); 9 | 10 | // TODO: make this more sophisticated and visit expressions and so on. 11 | for (const p of plans) { 12 | console.log(p); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/query-runtime-ts/src/index.ts: -------------------------------------------------------------------------------- 1 | export { default as P, Predicate } from './Predicate.js'; 2 | export { Query, DerivedQuery, UpdateType, EmptyQuery } from './Query.js'; 3 | export { default as QueryFactory } from './QueryFactory.js'; 4 | export * from './Expression.js'; 5 | export * from './Field.js'; 6 | export { default as printPlan } from './explain/printPlan.js'; 7 | export { default as LiveResult } from './live/LiveResult.js'; 8 | -------------------------------------------------------------------------------- /packages/query-runtime-ts/src/live/__tests__/LiveResult.test.ts: -------------------------------------------------------------------------------- 1 | test('Generators', () => { 2 | // This is tested in `integration-tests-ts` 3 | }); 4 | -------------------------------------------------------------------------------- /packages/query-runtime-ts/src/memory/MemoryHopQuery.ts: -------------------------------------------------------------------------------- 1 | import { HopExpression } from '../Expression.js'; 2 | import { HopQuery, Query } from '../Query.js'; 3 | import { EdgeSpec } from '@aphro/schema-api'; 4 | import { Context, IModel } from '@aphro/context-runtime-ts'; 5 | import MemoryHopExpression from './MemoryHopExpression.js'; 6 | 7 | export default class MemoryHopQuery extends HopQuery { 8 | static create(ctx: Context, sourceQuery: Query, edge: EdgeSpec) { 9 | // source could be anything. 10 | // dest is memory. 11 | // standalone edge could be memory or sql... 12 | return new MemoryHopQuery( 13 | ctx, 14 | sourceQuery, 15 | new MemoryHopExpression(ctx, edge, { what: 'model' }), 16 | ); 17 | } 18 | } 19 | 20 | function createChainedHopExpression(edge: EdgeSpec): HopExpression { 21 | throw new Error('In memory hop not yet supported'); 22 | } 23 | -------------------------------------------------------------------------------- /packages/query-runtime-ts/src/memory/MemorySourceQuery.ts: -------------------------------------------------------------------------------- 1 | import { Context, IModel, ModelSpecWithCreate } from '@aphro/context-runtime-ts'; 2 | import { SourceQuery } from '../Query.js'; 3 | import MemorySourceExpression from './MemorySourceExpression.js'; 4 | 5 | export default class MemorySourceQuery> extends SourceQuery { 6 | constructor(ctx: Context, spec: ModelSpecWithCreate) { 7 | super(ctx, new MemorySourceExpression(ctx, spec, { what: 'model' })); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/query-runtime-ts/src/sql/SQLSourceQuery.ts: -------------------------------------------------------------------------------- 1 | import { Context, IModel, ModelSpecWithCreate } from '@aphro/context-runtime-ts'; 2 | import { SourceQuery } from '../Query.js'; 3 | import SQLSourceExpression from './SQLSourceExpression.js'; 4 | 5 | export default class SQLSourceQuery> extends SourceQuery { 6 | constructor(ctx: Context, spec: ModelSpecWithCreate) { 7 | super(ctx, new SQLSourceExpression(ctx, spec, { what: 'model' })); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/query-runtime-ts/src/sql/__tests__/specAndOpsToQuery.test.ts: -------------------------------------------------------------------------------- 1 | test('TEST TODO', () => {}); 2 | -------------------------------------------------------------------------------- /packages/query-runtime-ts/src/trace.ts: -------------------------------------------------------------------------------- 1 | import { tracer, Tracer } from '@aphro/instrument'; 2 | 3 | const t: Tracer = tracer('@aphro/query-runtime-ts', '0.2.3'); 4 | 5 | export default t; 6 | -------------------------------------------------------------------------------- /packages/query-runtime-ts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"], 8 | "references": [ 9 | { "path": "../model-runtime-ts" }, 10 | { "path": "../schema-api" }, 11 | { "path": "../sql-ts" }, 12 | { "path": "../context-runtime-ts" }, 13 | { "path": "../instrument" } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /packages/react/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ 2 | -------------------------------------------------------------------------------- /packages/react/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /packages/react/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | targets: { 7 | node: "current", 8 | }, 9 | }, 10 | ], 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /packages/react/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/react", 3 | "version": "1.2.3", 4 | "main": "lib/index.js", 5 | "type": "module", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/tantaman/aphrodite.git", 9 | "directory": "packages/react" 10 | }, 11 | "dependencies": { 12 | "@strut/counter": "^0.0.11", 13 | "suspend-react": "^0.0.8" 14 | }, 15 | "peerDependencies": { 16 | "@aphro/runtime-ts": "^0.3.8", 17 | "react": "^18.2.0" 18 | }, 19 | "devDependencies": { 20 | "@aphro/runtime-ts": "workspace:*", 21 | "@babel/core": "^7.18.13", 22 | "@babel/preset-env": "^7.18.10", 23 | "@types/jest": "^28.1.8", 24 | "@types/react": "^18.0.17", 25 | "@typescript-eslint/typescript-estree": "^5.35.1", 26 | "jest": "^29.0.1", 27 | "react": "^18.2.0", 28 | "typescript": "^4.8.2" 29 | }, 30 | "scripts": { 31 | "clean": "tsc --build --clean", 32 | "build": "tsc --build", 33 | "watch": "tsc --build -w", 34 | "deep-clean": "rm -rf ./lib || true && rm tsconfig.tsbuildinfo || true", 35 | "test": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js" 36 | }, 37 | "jest": { 38 | "testMatch": [ 39 | "**/__tests__/**/*.test.js", 40 | "**/__tests__/**/*.test.jsx" 41 | ] 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/react/src/__tests__/cache.test.ts: -------------------------------------------------------------------------------- 1 | import { QueryCache } from '../hooks.js'; 2 | 3 | test('evicts at size limit', () => { 4 | const cache = new QueryCache(2); 5 | 6 | for (let i = 0; i < 10; ++i) { 7 | cache.set(i + '', []); 8 | expect(cache.size).toBeLessThanOrEqual(2); 9 | } 10 | }); 11 | -------------------------------------------------------------------------------- /packages/react/src/index.ts: -------------------------------------------------------------------------------- 1 | export { useBind, useQuery, UseQueryData, UseQueryOptions, useLiveResult } from './hooks.js'; 2 | export { createHooks } from './createHooks.js'; 3 | -------------------------------------------------------------------------------- /packages/react/src/useSync.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react'; 2 | 3 | type Resolution = { 4 | loading: boolean; 5 | error?: any; 6 | data?: T; 7 | }; 8 | 9 | // TODO: update to use eager promises. 10 | // Note -- could you technically unify `useSync` and `useQuery`? 11 | // Probably... if `query->gen` did caching.... 12 | export default function useSync(fn: () => Promise, deps: any[] = []): Resolution { 13 | const [resolution, setResolution] = useState>({ 14 | loading: true, 15 | }); 16 | useEffect(() => { 17 | fn() 18 | .then(r => { 19 | setResolution({ 20 | loading: false, 21 | data: r, 22 | }); 23 | }) 24 | .catch(e => { 25 | setResolution({ 26 | loading: false, 27 | error: e, 28 | }); 29 | }); 30 | }, []); 31 | return resolution; 32 | } 33 | -------------------------------------------------------------------------------- /packages/react/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src", 6 | "jsx": "react" 7 | }, 8 | "include": ["./src/"], 9 | "references": [{ "path": "../runtime-ts" }] 10 | } 11 | -------------------------------------------------------------------------------- /packages/runtime-ts/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /packages/runtime-ts/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /packages/runtime-ts/README.md: -------------------------------------------------------------------------------- 1 | Single package for all typescript runtime components. For simpler devex for the end user. -------------------------------------------------------------------------------- /packages/runtime-ts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/runtime-ts", 3 | "version": "0.3.8", 4 | "main": "lib/index.js", 5 | "type": "module", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/tantaman/aphrodite.git", 9 | "directory": "packages/runtime-ts" 10 | }, 11 | "dependencies": { 12 | "@aphro/cache-runtime-ts": "workspace:*", 13 | "@aphro/context-runtime-ts": "workspace:*", 14 | "@aphro/migration-runtime-ts": "workspace:*", 15 | "@aphro/model-runtime-ts": "workspace:*", 16 | "@aphro/mutator-runtime-ts": "workspace:*", 17 | "@aphro/query-runtime-ts": "workspace:*", 18 | "@aphro/sql-ts": "workspace:*", 19 | "@strut/sid": "^0.1.2", 20 | "@strut/utils": "^0.1.1" 21 | }, 22 | "devDependencies": { 23 | "typescript": "^4.8.2" 24 | }, 25 | "scripts": { 26 | "clean": "tsc --build --clean", 27 | "build": "tsc --build", 28 | "watch": "tsc --build -w", 29 | "deep-clean": "rm -rf ./lib || true && rm tsconfig.tsbuildinfo || true" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/runtime-ts/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from '@aphro/context-runtime-ts'; 2 | export * from '@aphro/model-runtime-ts'; 3 | export * from '@aphro/mutator-runtime-ts'; 4 | export * from '@aphro/query-runtime-ts'; 5 | export * from '@strut/sid'; 6 | export * from '@aphro/migration-runtime-ts'; 7 | export { applyMixins } from '@strut/utils'; 8 | export { default as sid } from '@strut/sid'; 9 | export { default as Cache } from '@aphro/cache-runtime-ts'; 10 | export * from '@aphro/sql-ts'; 11 | -------------------------------------------------------------------------------- /packages/runtime-ts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"], 8 | "references": [ 9 | { "path": "../cache-runtime-ts" }, 10 | { "path": "../context-runtime-ts" }, 11 | { "path": "../model-runtime-ts" }, 12 | { "path": "../mutator-runtime-ts" }, 13 | { "path": "../query-runtime-ts" }, 14 | { "path": "../migration-runtime-ts" }, 15 | { "path": "../sql-ts" } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /packages/schema-api/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /packages/schema-api/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /packages/schema-api/.pnpm-debug.log: -------------------------------------------------------------------------------- 1 | { 2 | "0 debug pnpm:scope": { 3 | "selected": 1, 4 | "workspacePrefix": "/Users/tantaman/workspace/aphrodite" 5 | }, 6 | "1 error pnpm": { 7 | "code": "ELIFECYCLE", 8 | "errno": "ENOENT", 9 | "syscall": "spawn", 10 | "file": "sh", 11 | "pkgid": "@aphro/schema-api@0.0.1", 12 | "stage": "build", 13 | "script": "rm -rf ./lib && tsc", 14 | "pkgname": "@aphro/schema-api", 15 | "err": { 16 | "name": "pnpm", 17 | "message": "@aphro/schema-api@0.0.1 build: `rm -rf ./lib && tsc`\nspawn ENOENT", 18 | "code": "ELIFECYCLE", 19 | "stack": "pnpm: @aphro/schema-api@0.0.1 build: `rm -rf ./lib && tsc`\nspawn ENOENT\n at ChildProcess. (/Users/tantaman/.nvm/versions/node/v17.5.0/pnpm-global/5/node_modules/.pnpm/pnpm@6.32.4/node_modules/pnpm/dist/pnpm.cjs:92290:22)\n at ChildProcess.emit (node:events:526:28)\n at maybeClose (node:internal/child_process:1090:16)\n at Process.ChildProcess._handle.onexit (node:internal/child_process:302:5)" 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /packages/schema-api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/schema-api", 3 | "version": "0.2.6", 4 | "main": "lib/index.js", 5 | "type": "module", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/tantaman/aphrodite.git", 9 | "directory": "packages/schema-api" 10 | }, 11 | "devDependencies": { 12 | "typescript": "^4.8.2" 13 | }, 14 | "scripts": { 15 | "clean": "tsc --build --clean", 16 | "build": "tsc --build", 17 | "watch": "tsc --build -w", 18 | "deep-clean": "rm -rf ./lib || true && rm tsconfig.tsbuildinfo || true" 19 | }, 20 | "jest": { 21 | "testMatch": [ 22 | "**/__tests__/**/*.test.js" 23 | ] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/schema-api/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/schema/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /packages/schema/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /packages/schema/README.md: -------------------------------------------------------------------------------- 1 | # Schema 2 | 3 | The schema definition language and compiler. -------------------------------------------------------------------------------- /packages/schema/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | targets: { 7 | node: "current", 8 | }, 9 | }, 10 | ], 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /packages/schema/src/__tests__/schemaFilePipeline.test.ts: -------------------------------------------------------------------------------- 1 | test('TDOO', () => {}); 2 | -------------------------------------------------------------------------------- /packages/schema/src/index.ts: -------------------------------------------------------------------------------- 1 | export { createCompiler } from './compile.js'; 2 | export { stopsCodegen } from './validate.js'; 3 | export { default as nodeFn } from './node.js'; 4 | export { default as edgeFn } from './edge.js'; 5 | export { default as fieldFn } from './field.js'; 6 | export * from './module.js'; 7 | -------------------------------------------------------------------------------- /packages/schema/src/module.ts: -------------------------------------------------------------------------------- 1 | import { Import } from '@aphro/schema-api'; 2 | 3 | export function tsImport(name: string | null, as: string | null, from: string): Import { 4 | return { 5 | name: name?.trim(), 6 | as, 7 | from, 8 | }; 9 | } 10 | 11 | export function javaImport(from: string): Import { 12 | return { 13 | from, 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /packages/schema/src/parser/__tests__/documentSchemaFile.ts: -------------------------------------------------------------------------------- 1 | export const contents = ` 2 | Application as UnmanagedNode { 3 | currentScreen: HomeScreen | ProfileScreen 4 | } 5 | 6 | HomeScreen as UnmanagedNode { 7 | 8 | } 9 | 10 | ProfileScreen as UnmanagedNode { 11 | 12 | } 13 | `; 14 | -------------------------------------------------------------------------------- /packages/schema/src/parser/__tests__/documentType.test.ts: -------------------------------------------------------------------------------- 1 | import { createParser } from '../parse.js'; 2 | import { contents } from './documentSchemaFile'; 3 | 4 | const { parseString } = createParser(); 5 | test('Parsing with the compiled grammar', () => { 6 | const parsed = parseString(contents); 7 | expect(parsed).toEqual(ast); 8 | }); 9 | 10 | const ast = { 11 | preamble: {}, 12 | entities: [ 13 | { 14 | type: 'node', 15 | as: 'UnmanagedNode', 16 | name: 'Application', 17 | fields: [{ name: 'currentScreen', type: ['HomeScreen', { type: 'union' }, 'ProfileScreen'] }], 18 | extensions: [], 19 | }, 20 | { type: 'node', as: 'UnmanagedNode', name: 'HomeScreen', fields: [], extensions: [] }, 21 | { type: 'node', as: 'UnmanagedNode', name: 'ProfileScreen', fields: [], extensions: [] }, 22 | ], 23 | }; 24 | -------------------------------------------------------------------------------- /packages/schema/src/parser/__tests__/grammar.test.ts: -------------------------------------------------------------------------------- 1 | import { contents, ast } from './testSchemaFile.js'; 2 | import { compileGrammar } from '../ohm/grammar.js'; 3 | 4 | const grammar = compileGrammar(); 5 | 6 | test('parsing a small schema', () => { 7 | const match = grammar.match(contents); 8 | expect(match.succeeded()).toBe(true); 9 | }); 10 | -------------------------------------------------------------------------------- /packages/schema/src/parser/__tests__/parse.test.ts: -------------------------------------------------------------------------------- 1 | import { createParser } from '../parse.js'; 2 | import { contents, ast } from './testSchemaFile.js'; 3 | 4 | const { parseString } = createParser(); 5 | test('Parsing with the compiled grammar', () => { 6 | const parsed = parseString(contents); 7 | // Getting a shit ton of output on this line when the test fails? 8 | // You probably forgot to call `.toAst` or `.sourceString` on some parameter in `parse.ts` 9 | expect(parsed).toEqual(ast); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/schema/src/parser/condenseEntities.ts: -------------------------------------------------------------------------------- 1 | import { NodeReference, SchemaFileAst, ValidationError } from '@aphro/schema-api'; 2 | 3 | export default function condenseEntities( 4 | entities: { 5 | [key: string]: Ta; 6 | }, 7 | preamble: SchemaFileAst['preamble'], 8 | condensor: (entity: Ta, preamble: SchemaFileAst['preamble']) => [ValidationError[], Tc], 9 | ): [ 10 | ValidationError[], 11 | { 12 | [key: string]: Tc; 13 | }, 14 | ] { 15 | let errors: ValidationError[] = []; 16 | const condensedEntities: { [key: NodeReference]: Tc } = Object.entries(entities).reduce( 17 | (l: { [key: string]: Tc }, [key, entity]) => { 18 | const [entityErrors, condensed] = condensor(entity, preamble); 19 | errors = errors.concat(entityErrors); 20 | l[key] = condensed; 21 | return l; 22 | }, 23 | {}, 24 | ); 25 | return [errors, condensedEntities]; 26 | } 27 | -------------------------------------------------------------------------------- /packages/schema/src/runtimeConfig.ts: -------------------------------------------------------------------------------- 1 | import { GrammarExtension } from '@aphro/grammar-extension-api'; 2 | import { Step } from '@aphro/codegen-api'; 3 | 4 | export type Config = { 5 | grammarExtensions?: GrammarExtension[]; 6 | codegenExtensions?: Step[]; 7 | }; 8 | -------------------------------------------------------------------------------- /packages/schema/src/type.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vlcn-io/vlcn-orm/ff90a4d588a5bed0fdcea0335d328f7c4dd51cd8/packages/schema/src/type.ts -------------------------------------------------------------------------------- /packages/schema/src/validate.ts: -------------------------------------------------------------------------------- 1 | import { SchemaFile, ValidationError } from '@aphro/schema-api'; 2 | 3 | export default function validate(schemaFile: SchemaFile): ValidationError[] { 4 | return []; 5 | } 6 | 7 | export function stopsCodegen(error: ValidationError): boolean { 8 | return error.severity === 'error'; 9 | } 10 | 11 | /* 12 | - Validate imports 13 | - Validate id_of 14 | - Validate inbound and outbound edges 15 | 16 | SQL: 17 | - Validate indexing of fields (foreign key, junction) 18 | */ 19 | -------------------------------------------------------------------------------- /packages/schema/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"], 8 | "references": [ 9 | { "path": "../schema-api" }, 10 | { "path": "../grammar-extension-api" }, 11 | { "path": "../codegen-api" } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /packages/sql-ts/.gitignore: -------------------------------------------------------------------------------- 1 | lib/ -------------------------------------------------------------------------------- /packages/sql-ts/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /packages/sql-ts/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | '@babel/preset-env', 5 | { 6 | targets: { 7 | node: 'current', 8 | }, 9 | }, 10 | ], 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /packages/sql-ts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@aphro/sql-ts", 3 | "version": "0.2.6", 4 | "main": "lib/index.js", 5 | "type": "module", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/tantaman/aphrodite.git", 9 | "directory": "packages/sql-ts" 10 | }, 11 | "devDependencies": { 12 | "@babel/core": "^7.18.13", 13 | "@babel/preset-env": "^7.18.10", 14 | "@types/jest": "^28.1.8", 15 | "fast-check": "^3.1.2", 16 | "jest": "^29.0.1", 17 | "typescript": "^4.8.2" 18 | }, 19 | "scripts": { 20 | "clean": "tsc --build --clean", 21 | "build": "tsc --build", 22 | "watch": "tsc --build -w", 23 | "test": "node ./node_modules/jest/bin/jest.js", 24 | "deep-clean": "rm -rf ./lib || true && rm tsconfig.tsbuildinfo || true" 25 | }, 26 | "jest": { 27 | "testMatch": [ 28 | "**/__tests__/**/*.test.js" 29 | ] 30 | }, 31 | "dependencies": { 32 | "@databases/escape-identifier": "^1.0.3", 33 | "@databases/sql": "^3.2.0" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/sql-ts/src/index.ts: -------------------------------------------------------------------------------- 1 | export { SQLQuery, sql, formatters } from './sql.js'; 2 | -------------------------------------------------------------------------------- /packages/sql-ts/src/sql.ts: -------------------------------------------------------------------------------- 1 | import { escapePostgresIdentifier, escapeSQLiteIdentifier } from '@databases/escape-identifier'; 2 | import { FormatConfig } from '@databases/sql'; 3 | export { default as sql, SQLQuery } from '@databases/sql'; 4 | 5 | const pgFormat: FormatConfig = { 6 | escapeIdentifier: str => escapePostgresIdentifier(str), 7 | formatValue: (value, index) => ({ placeholder: `$${index + 1}`, value }), 8 | }; 9 | 10 | const sqliteFormat: FormatConfig = { 11 | escapeIdentifier: str => escapeSQLiteIdentifier(str), 12 | formatValue: value => ({ placeholder: '?', value }), 13 | }; 14 | 15 | const error = { 16 | escapeIdentifier: (str: string) => { 17 | throw new Error('Memory storage should not go through sql formatting'); 18 | }, 19 | formatValue: (value: unknown) => { 20 | throw new Error('Memory storage should not go through sql formatting'); 21 | }, 22 | } as const; 23 | 24 | export const formatters: { [key in 'sqlite' | 'postgres' | 'memory' | 'ephemeral']: FormatConfig } = 25 | { 26 | sqlite: sqliteFormat, 27 | postgres: pgFormat, 28 | ephemeral: error, 29 | memory: error, 30 | } as const; 31 | -------------------------------------------------------------------------------- /packages/sql-ts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig-templates/lib.json", 3 | "compilerOptions": { 4 | "outDir": "./lib/", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/"], 8 | "references": [] 9 | } 10 | -------------------------------------------------------------------------------- /packages/vscode/.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /packages/vscode/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that launches the extension inside a new window 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | { 6 | "version": "0.2.0", 7 | "configurations": [ 8 | { 9 | "name": "Extension", 10 | "type": "extensionHost", 11 | "request": "launch", 12 | "args": [ 13 | "--extensionDevelopmentPath=${workspaceFolder}" 14 | ] 15 | } 16 | ] 17 | } -------------------------------------------------------------------------------- /packages/vscode/.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | .vscode-test/** 3 | .gitignore 4 | vsc-extension-quickstart.md 5 | -------------------------------------------------------------------------------- /packages/vscode/language-configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": { 3 | "lineComment": "#" 4 | }, 5 | "brackets": [ 6 | ["<", ">"], 7 | ["(", ")"], 8 | ["{", "}"] 9 | ], 10 | "autoClosingPairs": [ 11 | ["<", ">"], 12 | ["(", ")"], 13 | ["{", "}"] 14 | ], 15 | "surroundingPairs": [ 16 | ["<", ">"], 17 | ["(", ")"] 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /packages/vscode/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aphrodite", 3 | "displayName": "aphrodite", 4 | "description": "Support for Aphrodite schemas", 5 | "version": "0.2.6", 6 | "engines": { 7 | "vscode": "^1.65.0" 8 | }, 9 | "categories": [ 10 | "Programming Languages" 11 | ], 12 | "contributes": { 13 | "languages": [ 14 | { 15 | "id": "aphrodite", 16 | "aliases": [ 17 | "Aphrodite", 18 | "aphrodite" 19 | ], 20 | "extensions": [ 21 | ".aphro" 22 | ], 23 | "configuration": "./language-configuration.json" 24 | } 25 | ], 26 | "grammars": [ 27 | { 28 | "language": "aphrodite", 29 | "scopeName": "source.aphro", 30 | "path": "./syntaxes/aphrodite.tmLanguage.json" 31 | } 32 | ] 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tsconfig-templates/lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "sourceMap": true, 4 | "strictNullChecks": true, 5 | "module": "esnext", 6 | "target": "esnext", 7 | "skipLibCheck": true, 8 | "moduleResolution": "Node", 9 | "baseUrl": "./src/", 10 | "declaration": true, 11 | "allowJs": true, 12 | "composite": true, 13 | "declarationMap": true, 14 | "incremental": true, 15 | "strict": true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseBranch": "origin/main", 3 | "pipeline": { 4 | "build": { 5 | "dependsOn": [], 6 | "outputs": [] 7 | }, 8 | "test": { 9 | "dependsOn": [] 10 | }, 11 | "clean": { 12 | "dependsOn": [] 13 | }, 14 | "deep-clean": { 15 | "dependsOn": [] 16 | } 17 | } 18 | } 19 | --------------------------------------------------------------------------------