@beaulewis/saas-cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +373 -0
- package/bin/saas.js +2 -0
- package/dist/chunk-26VE6QJ4.js +120 -0
- package/dist/chunk-26VE6QJ4.js.map +1 -0
- package/dist/chunk-3KD5CFV3.js +196 -0
- package/dist/chunk-3KD5CFV3.js.map +1 -0
- package/dist/chunk-5BCEXHNM.js +108 -0
- package/dist/chunk-5BCEXHNM.js.map +1 -0
- package/dist/chunk-N4OIAZSA.js +110 -0
- package/dist/chunk-N4OIAZSA.js.map +1 -0
- package/dist/chunk-ZD2ZSBK3.js +224 -0
- package/dist/chunk-ZD2ZSBK3.js.map +1 -0
- package/dist/dart-DXLFNGHR.js +41 -0
- package/dist/dart-DXLFNGHR.js.map +1 -0
- package/dist/drift-XYY4D366.js +59 -0
- package/dist/drift-XYY4D366.js.map +1 -0
- package/dist/flutter-J5BYPVIW.js +41 -0
- package/dist/flutter-J5BYPVIW.js.map +1 -0
- package/dist/freezed-QXFQ4GJC.js +58 -0
- package/dist/freezed-QXFQ4GJC.js.map +1 -0
- package/dist/gorouter-QBMTTFVR.js +56 -0
- package/dist/gorouter-QBMTTFVR.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1437 -0
- package/dist/index.js.map +1 -0
- package/dist/package-QO75XHBD.js +43 -0
- package/dist/package-QO75XHBD.js.map +1 -0
- package/dist/powersync-I3LR7TDN.js +37 -0
- package/dist/powersync-I3LR7TDN.js.map +1 -0
- package/dist/repository-BAOVD3NG.js +34 -0
- package/dist/repository-BAOVD3NG.js.map +1 -0
- package/dist/riverpod-XUU656PM.js +42 -0
- package/dist/riverpod-XUU656PM.js.map +1 -0
- package/dist/widget-YDKHPRXM.js +42 -0
- package/dist/widget-YDKHPRXM.js.map +1 -0
- package/package.json +89 -0
- package/templates/drift/dao.hbs +51 -0
- package/templates/drift/migration.hbs +15 -0
- package/templates/freezed/model.hbs +20 -0
- package/templates/gorouter/route.hbs +18 -0
- package/templates/powersync/rules.hbs +10 -0
- package/templates/powersync/schema.hbs +19 -0
- package/templates/repository/repository.hbs +62 -0
- package/templates/riverpod/async-notifier.hbs +44 -0
- package/templates/riverpod/family.hbs +9 -0
- package/templates/riverpod/future.hbs +9 -0
- package/templates/riverpod/notifier.hbs +34 -0
- package/templates/riverpod/stream.hbs +9 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Migration: {{name}}
|
|
2
|
+
// Generated: {{now}}
|
|
3
|
+
|
|
4
|
+
import 'package:drift/drift.dart';
|
|
5
|
+
|
|
6
|
+
/// Migration for {{name}}
|
|
7
|
+
Future<void> migrate{{pascalCase name}}(Migrator m) async {
|
|
8
|
+
// TODO: Add your migration steps here
|
|
9
|
+
//
|
|
10
|
+
// Example operations:
|
|
11
|
+
// await m.createTable(yourTable);
|
|
12
|
+
// await m.addColumn(yourTable, yourTable.newColumn);
|
|
13
|
+
// await m.alterTable(TableMigration(yourTable));
|
|
14
|
+
// await m.deleteTable('old_table_name');
|
|
15
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import 'package:freezed_annotation/freezed_annotation.dart';
|
|
2
|
+
|
|
3
|
+
part '{{fileName}}.freezed.dart';
|
|
4
|
+
part '{{fileName}}.g.dart';
|
|
5
|
+
|
|
6
|
+
@freezed
|
|
7
|
+
class {{className}} with _${{className}} {
|
|
8
|
+
const factory {{className}}({
|
|
9
|
+
{{#each fields}}
|
|
10
|
+
{{#if isNullable}}
|
|
11
|
+
{{type}}? {{name}},
|
|
12
|
+
{{else}}
|
|
13
|
+
required {{type}} {{name}},
|
|
14
|
+
{{/if}}
|
|
15
|
+
{{/each}}
|
|
16
|
+
}) = _{{className}};
|
|
17
|
+
|
|
18
|
+
factory {{className}}.fromJson(Map<String, dynamic> json) =>
|
|
19
|
+
_${{className}}FromJson(json);
|
|
20
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
GoRoute(
|
|
2
|
+
path: '{{path}}',
|
|
3
|
+
name: '{{routeName}}',
|
|
4
|
+
builder: (context, state) {
|
|
5
|
+
{{#if hasParams}}
|
|
6
|
+
{{#each params}}
|
|
7
|
+
final {{name}} = state.pathParameters['{{name}}']{{#if (eq type "String")}}!{{else}} != null ? {{type}}.parse(state.pathParameters['{{name}}']!) : null{{/if}};
|
|
8
|
+
{{/each}}
|
|
9
|
+
return {{screenName}}(
|
|
10
|
+
{{#each params}}
|
|
11
|
+
{{name}}: {{name}},
|
|
12
|
+
{{/each}}
|
|
13
|
+
);
|
|
14
|
+
{{else}}
|
|
15
|
+
return const {{screenName}}();
|
|
16
|
+
{{/if}}
|
|
17
|
+
},
|
|
18
|
+
),
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// PowerSync Sync Rules for {{tableName}}
|
|
2
|
+
// User-scoped data synchronization
|
|
3
|
+
|
|
4
|
+
bucket_definitions:
|
|
5
|
+
user_{{snakeCase tableName}}:
|
|
6
|
+
# Only sync records owned by the authenticated user
|
|
7
|
+
parameters:
|
|
8
|
+
- SELECT token->>'user_id' as user_id
|
|
9
|
+
data:
|
|
10
|
+
- SELECT * FROM {{snakeCase tableName}} WHERE {{userColumn}} = bucket.user_id
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// PowerSync Schema for {{tableName}}
|
|
2
|
+
|
|
3
|
+
import 'package:powersync/powersync.dart';
|
|
4
|
+
|
|
5
|
+
const {{camelCase tableName}}Table = Table('{{snakeCase tableName}}', [
|
|
6
|
+
Column.text('id'),
|
|
7
|
+
// TODO: Add your columns here
|
|
8
|
+
// Column.text('name'),
|
|
9
|
+
// Column.integer('count'),
|
|
10
|
+
// Column.real('price'),
|
|
11
|
+
Column.text('{{userColumn}}'),
|
|
12
|
+
Column.text('created_at'),
|
|
13
|
+
Column.text('updated_at'),
|
|
14
|
+
]);
|
|
15
|
+
|
|
16
|
+
// Add to your schema:
|
|
17
|
+
// final schema = Schema([
|
|
18
|
+
// {{camelCase tableName}}Table,
|
|
19
|
+
// ]);
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
|
2
|
+
|
|
3
|
+
part '{{snakeCase repositoryName}}.g.dart';
|
|
4
|
+
|
|
5
|
+
/// Repository for {{entityName}} data operations
|
|
6
|
+
abstract class {{repositoryName}} {
|
|
7
|
+
/// Get all {{pluralize entityNameLower}}
|
|
8
|
+
Future<List<{{entityName}}>> getAll();
|
|
9
|
+
|
|
10
|
+
/// Get a {{entityNameLower}} by ID
|
|
11
|
+
Future<{{entityName}}?> getById(String id);
|
|
12
|
+
|
|
13
|
+
/// Create a new {{entityNameLower}}
|
|
14
|
+
Future<{{entityName}}> create({{entityName}} {{entityNameLower}});
|
|
15
|
+
|
|
16
|
+
/// Update an existing {{entityNameLower}}
|
|
17
|
+
Future<{{entityName}}> update({{entityName}} {{entityNameLower}});
|
|
18
|
+
|
|
19
|
+
/// Delete a {{entityNameLower}} by ID
|
|
20
|
+
Future<void> delete(String id);
|
|
21
|
+
|
|
22
|
+
/// Watch all {{pluralize entityNameLower}}
|
|
23
|
+
Stream<List<{{entityName}}>> watchAll();
|
|
24
|
+
|
|
25
|
+
/// Watch a single {{entityNameLower}} by ID
|
|
26
|
+
Stream<{{entityName}}?> watchById(String id);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/// Implementation of {{repositoryName}}
|
|
30
|
+
class {{repositoryName}}Impl implements {{repositoryName}} {
|
|
31
|
+
{{repositoryName}}Impl(this._dataSource);
|
|
32
|
+
|
|
33
|
+
final {{entityName}}DataSource _dataSource;
|
|
34
|
+
|
|
35
|
+
@override
|
|
36
|
+
Future<List<{{entityName}}>> getAll() => _dataSource.getAll();
|
|
37
|
+
|
|
38
|
+
@override
|
|
39
|
+
Future<{{entityName}}?> getById(String id) => _dataSource.getById(id);
|
|
40
|
+
|
|
41
|
+
@override
|
|
42
|
+
Future<{{entityName}}> create({{entityName}} {{entityNameLower}}) => _dataSource.create({{entityNameLower}});
|
|
43
|
+
|
|
44
|
+
@override
|
|
45
|
+
Future<{{entityName}}> update({{entityName}} {{entityNameLower}}) => _dataSource.update({{entityNameLower}});
|
|
46
|
+
|
|
47
|
+
@override
|
|
48
|
+
Future<void> delete(String id) => _dataSource.delete(id);
|
|
49
|
+
|
|
50
|
+
@override
|
|
51
|
+
Stream<List<{{entityName}}>> watchAll() => _dataSource.watchAll();
|
|
52
|
+
|
|
53
|
+
@override
|
|
54
|
+
Stream<{{entityName}}?> watchById(String id) => _dataSource.watchById(id);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@riverpod
|
|
58
|
+
{{repositoryName}} {{camelCase repositoryName}}({{pascalCase repositoryName}}Ref ref) {
|
|
59
|
+
return {{repositoryName}}Impl(
|
|
60
|
+
ref.read({{entityNameLower}}DataSourceProvider),
|
|
61
|
+
);
|
|
62
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import 'dart:async';
|
|
2
|
+
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
|
3
|
+
|
|
4
|
+
part '{{snakeCase name}}_notifier.g.dart';
|
|
5
|
+
|
|
6
|
+
@riverpod
|
|
7
|
+
class {{pascalCase name}}Notifier extends _${{pascalCase name}}Notifier {
|
|
8
|
+
@override
|
|
9
|
+
FutureOr<{{{state}}}> build() async {
|
|
10
|
+
// TODO: Fetch initial data
|
|
11
|
+
return ref.read({{camelCase name}}RepositoryProvider).getAll();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
Future<void> refresh() async {
|
|
15
|
+
state = const AsyncLoading();
|
|
16
|
+
state = await AsyncValue.guard(() async {
|
|
17
|
+
return ref.read({{camelCase name}}RepositoryProvider).getAll();
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
Future<void> add({{singularize state}} item) async {
|
|
22
|
+
state = const AsyncLoading();
|
|
23
|
+
state = await AsyncValue.guard(() async {
|
|
24
|
+
await ref.read({{camelCase name}}RepositoryProvider).create(item);
|
|
25
|
+
return ref.read({{camelCase name}}RepositoryProvider).getAll();
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
Future<void> update({{singularize state}} item) async {
|
|
30
|
+
state = const AsyncLoading();
|
|
31
|
+
state = await AsyncValue.guard(() async {
|
|
32
|
+
await ref.read({{camelCase name}}RepositoryProvider).update(item);
|
|
33
|
+
return ref.read({{camelCase name}}RepositoryProvider).getAll();
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
Future<void> delete(String id) async {
|
|
38
|
+
state = const AsyncLoading();
|
|
39
|
+
state = await AsyncValue.guard(() async {
|
|
40
|
+
await ref.read({{camelCase name}}RepositoryProvider).delete(id);
|
|
41
|
+
return ref.read({{camelCase name}}RepositoryProvider).getAll();
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
|
2
|
+
|
|
3
|
+
part '{{snakeCase name}}_provider.g.dart';
|
|
4
|
+
|
|
5
|
+
@riverpod
|
|
6
|
+
Future<{{{state}}}> {{camelCase name}}({{pascalCase name}}Ref ref, String id) async {
|
|
7
|
+
// TODO: Fetch data by ID
|
|
8
|
+
return ref.read({{camelCase name}}RepositoryProvider).getById(id);
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
|
2
|
+
|
|
3
|
+
part '{{snakeCase name}}_provider.g.dart';
|
|
4
|
+
|
|
5
|
+
@riverpod
|
|
6
|
+
Future<{{{state}}}> {{camelCase name}}({{pascalCase name}}Ref ref) async {
|
|
7
|
+
// TODO: Implement data fetching logic
|
|
8
|
+
return ref.read({{camelCase name}}RepositoryProvider).get();
|
|
9
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
|
2
|
+
|
|
3
|
+
part '{{snakeCase name}}_notifier.g.dart';
|
|
4
|
+
|
|
5
|
+
@riverpod
|
|
6
|
+
class {{pascalCase name}}Notifier extends _${{pascalCase name}}Notifier {
|
|
7
|
+
@override
|
|
8
|
+
{{{state}}} build() {
|
|
9
|
+
{{#if (eq state "List")}}
|
|
10
|
+
return [];
|
|
11
|
+
{{else}}
|
|
12
|
+
// TODO: Return initial state
|
|
13
|
+
throw UnimplementedError();
|
|
14
|
+
{{/if}}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
void update({{{state}}} newState) {
|
|
18
|
+
state = newState;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
{{#if (eq state "List")}}
|
|
22
|
+
void add(dynamic item) {
|
|
23
|
+
state = [...state, item];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
void remove(dynamic item) {
|
|
27
|
+
state = state.where((e) => e != item).toList();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
void clear() {
|
|
31
|
+
state = [];
|
|
32
|
+
}
|
|
33
|
+
{{/if}}
|
|
34
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
|
2
|
+
|
|
3
|
+
part '{{snakeCase name}}_provider.g.dart';
|
|
4
|
+
|
|
5
|
+
@riverpod
|
|
6
|
+
Stream<{{{state}}}> {{camelCase name}}({{pascalCase name}}Ref ref) {
|
|
7
|
+
// TODO: Return stream of data
|
|
8
|
+
return ref.read({{camelCase name}}RepositoryProvider).watch();
|
|
9
|
+
}
|