Skip to content

Commit

Permalink
feat(data): Celest Data types (#209)
Browse files Browse the repository at this point in the history
- Adds `Database` and `Schema` types for configuring data providers
- Adds corresponding AST models for resolution
  • Loading branch information
dnys1 authored Oct 12, 2024
1 parent fa8579b commit c67a213
Show file tree
Hide file tree
Showing 16 changed files with 2,753 additions and 9 deletions.
64 changes: 64 additions & 0 deletions packages/celest/lib/src/data/database.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/// {@template celest.data.database}
/// A database which is deployed to the cloud.
/// {@endtemplate}
final class Database {
/// {@macro celest.data.database}
const Database({
required this.schema,
});

/// The schema of the database.
final Schema schema;
}

/// {@template celest.data.schema}
/// The schema of a database.
///
/// Currently, only Drift databases are supported via [Schema.drift].
/// {@endtemplate}
sealed class Schema {
/// {@macro celest.data.schema}
const Schema();

/// Creates a new schema for the given Drift [databaseType].
///
/// The [databaseType] must be a subclass of `DriftDatabase`.
///
/// ## Example
///
/// Follow the [Drift documentation](https://pub.dev/packages/drift) to create
/// a Drift database, for example `MyDatabase`.
///
/// This class does not need to be defined in your Celest backend, but must
/// be imported in the file where you define your Celest database.
///
/// ```dart
/// import 'package:drift/drift.dart';
///
/// part 'my_database.g.dart';
///
/// @DriftDatabase(tables: [Users])
/// class MyDatabase extends _$MyDatabase {
/// // ...
/// }
/// ```
///
/// In your Celest backend, create a new [Schema] using the [Schema.drift]
/// constructor to define your Celest [Database].
///
/// ```dart
/// import 'package:celest/celest.dart';
/// import 'my_database.dart';
///
/// const db = Database(
/// schema: Schema.drift(MyDatabase),
/// );
/// ```
const factory Schema.drift(Type databaseType) = _DriftSchema;
}

final class _DriftSchema extends Schema {
const _DriftSchema(this.databaseType);

final Type databaseType;
}
1 change: 1 addition & 0 deletions packages/celest/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ dependencies:
collection: ^1.18.0
convert: ^3.1.1
crypto_keys: ^0.3.0
drift: ^2.20.0
file: ^7.0.1
fixnum: ^1.1.0
google_cloud: ^0.2.0
Expand Down
4 changes: 4 additions & 0 deletions packages/celest_ast/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.1.4

- feat: Adds `Database` and `DatabaseSchema` models

## 0.1.3

- fix: Add missing switch case
Expand Down
175 changes: 175 additions & 0 deletions packages/celest_ast/lib/src/ast.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ abstract class Project implements Built<Project, ProjectBuilder>, AstNode {
List<Variable> variables = const [],
List<Secret> secrets = const [],
Auth? auth,
Map<String, Database> databases = const {},
required SdkConfiguration sdkConfig,
}) {
return _$Project._(
Expand All @@ -53,6 +54,7 @@ abstract class Project implements Built<Project, ProjectBuilder>, AstNode {
variables: variables.build(),
secrets: secrets.build(),
auth: auth,
databases: databases.build(),
sdkConfig: sdkConfig,
);
}
Expand All @@ -70,6 +72,7 @@ abstract class Project implements Built<Project, ProjectBuilder>, AstNode {
BuiltList<Variable> get variables;
BuiltList<Secret> get secrets;
Auth? get auth;
BuiltMap<String, Database> get databases;

SdkConfiguration get sdkConfig;

Expand Down Expand Up @@ -1057,3 +1060,175 @@ abstract class NodeReference

static Serializer<NodeReference> get serializer => _$nodeReferenceSerializer;
}

sealed class DatabaseSchema implements AstNode {
/// The type of database schema.
DatabaseSchemaType get type;

/// The Dart type declaring the database schema.
TypeReference get declaration;
}

class DatabaseSchemaType extends EnumClass {
const DatabaseSchemaType._(super.name);

static const DatabaseSchemaType drift = _$drift;

static BuiltSet<DatabaseSchemaType> get values => _$DatabaseSchemaTypeValues;
static DatabaseSchemaType valueOf(String name) =>
_$DatabaseSchemaTypeValueOf(name);

static Serializer<DatabaseSchemaType> get serializer =>
_$databaseSchemaTypeSerializer;
}

abstract class DriftDatabaseSchema
implements
Built<DriftDatabaseSchema, DriftDatabaseSchemaBuilder>,
DatabaseSchema {
factory DriftDatabaseSchema({
required TypeReference declaration,
required FileSpan location,
}) {
return _$DriftDatabaseSchema._(
declaration: declaration,
location: location,
);
}

factory DriftDatabaseSchema.build(
[void Function(DriftDatabaseSchemaBuilder) updates]) =
_$DriftDatabaseSchema;

DriftDatabaseSchema._();

@override
DatabaseSchemaType get type => DatabaseSchemaType.drift;

/// The Drift type of the database schema.
///
/// Must be a subtype of `GeneratedDatabase`.
@override
TypeReference get declaration;

@override
R accept<R>(AstVisitor<R> visitor) => visitor.visitDatabaseSchema(this);

@override
R acceptWithArg<R, A>(AstVisitorWithArg<R, A> visitor, A arg) =>
visitor.visitDatabaseSchema(this, arg);

Map<String, dynamic> toJson() =>
serializers.serializeWith(DriftDatabaseSchema.serializer, this)
as Map<String, dynamic>;

static Serializer<DriftDatabaseSchema> get serializer =>
_$driftDatabaseSchemaSerializer;
}

class DatabaseProviderType extends EnumClass {
const DatabaseProviderType._(super.name);

@BuiltValueEnumConst(wireName: 'CELEST')
static const DatabaseProviderType celest = _$celest;

static BuiltSet<DatabaseProviderType> get values => _$databaseProviderType;
static DatabaseProviderType valueOf(String name) =>
_$databaseProviderTypeValueOf(name);
}

abstract class Database implements Built<Database, DatabaseBuilder>, AstNode {
factory Database({
required String name,
required String dartName,
Iterable<String> docs = const [],
required DatabaseSchema schema,
required DatabaseConfig config,
required FileSpan location,
}) {
return _$Database._(
name: name,
dartName: dartName,
docs: docs.toBuiltList(),
schema: schema,
config: config,
location: location,
);
}

factory Database.build([void Function(DatabaseBuilder) updates]) = _$Database;

Database._();

/// The name of the database.
///
/// Defaults to the name of the schema type.
String get name;

/// The name of the Dart variable declaring the database.
String get dartName;

/// Documentation comments attached to the database declaration, if any.
BuiltList<String> get docs;

/// The schema definition of the database.
DatabaseSchema get schema;

/// The configuration for the database host.
DatabaseConfig get config;

@override
FileSpan get location;

@override
R accept<R>(AstVisitor<R> visitor) => visitor.visitDatabase(this);

@override
R acceptWithArg<R, A>(AstVisitorWithArg<R, A> visitor, A arg) =>
visitor.visitDatabase(this, arg);

Map<String, dynamic> toJson() =>
serializers.serializeWith(Database.serializer, this)
as Map<String, dynamic>;

static Serializer<Database> get serializer => _$databaseSerializer;
}

sealed class DatabaseConfig {
DatabaseProviderType get provider;
}

// Holds the hostname and token for a Celest database.
abstract class CelestDatabaseConfig
implements
DatabaseConfig,
Built<CelestDatabaseConfig, CelestDatabaseConfigBuilder> {
factory CelestDatabaseConfig({
required Variable hostname,
required Secret token,
}) {
return _$CelestDatabaseConfig._(
hostname: hostname,
token: token,
);
}

factory CelestDatabaseConfig.build(
[void Function(CelestDatabaseConfigBuilder) updates]) =
_$CelestDatabaseConfig;

CelestDatabaseConfig._();

@override
DatabaseProviderType get provider => DatabaseProviderType.celest;

Variable get hostname;
Secret get token;

Map<String, dynamic> toJson() =>
serializers.serializeWith(CelestDatabaseConfig.serializer, this)
as Map<String, dynamic>;

static Serializer<CelestDatabaseConfig> get serializer =>
_$celestDatabaseConfigSerializer;
}
Loading

0 comments on commit c67a213

Please sign in to comment.