Skip to content

Commit

Permalink
feat: Support custom cache location
Browse files Browse the repository at this point in the history
  • Loading branch information
devtronic committed Feb 8, 2025
1 parent febe972 commit b1416d2
Show file tree
Hide file tree
Showing 10 changed files with 136 additions and 34 deletions.
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
## 4.1.0

### Features

#### Cache location

You're now able to set a custom cache location by setting `catalyst_builder: { cacheDir: 'a/cache/path' }` property in the pubspec.yaml

Take a look in [pubspec.yaml](example/pubspec.yaml) for an example.

### Internal

- The `CacheHelper` is no longer static.

## 4.0.0

This major update has breaking changes.
Expand Down Expand Up @@ -28,6 +42,7 @@ Bump the minimum Dart SDK version to 3.5.0
- `analyzer`: `'>=5.2.0 <7.0.0'` => `'>=5.2.0 <8.0.0'`

#### Annotations

Removed the deprecated `@Parameter` annotation. Use `@Inject` instead.

#### Build customization
Expand Down
52 changes: 38 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,24 @@ dev_dependencies:
Don't forget to exclude the `.catalyst_builder_cache` directory from VCS.

## Config reference

Some parts of the builder can be configured by adding a `catalyst_builder` section to the `pubspec.yaml`

```yaml
# pubspec.yaml
name: your_package
# dependencies:
# catalyst_builder:
# ...
catalyst_builder:
cacheDir: '.cache/catalyst_builder'
```

| Property | Type | Description | Default |
|------------|---------|------------------------------------------------------|-------------------------|
| `cacheDir` | String? | The path to the cache directory for preflight files. | .catalyst_builder_cache |

## Usage

Decorate your services with `@Service`:
Expand All @@ -45,6 +63,7 @@ class MyService {}
```

Decorate in your entry point file any top level symbol with `@GenerateServiceProvider`:

```dart
// my_entrypoint.dart
Expand Down Expand Up @@ -72,7 +91,7 @@ import 'my_entrypoint.catalyst_builder.g.dart';
void main() {
// Create a new instance of the service provider
var provider = DefaultServiceProvider();
// Boot it to wire services
provider.boot();
Expand Down Expand Up @@ -102,10 +121,10 @@ class SingletonService {}
class TransientService {}
```

| Lifetime | Description |
| --------- | ----------- |
| Lifetime | Description |
|-----------|----------------------------------------------------------------------------------|
| Singleton | The instance is stored in the provider. You'll always receive the same instance. |
| Transient | Everytime you call `resolve` or `tryResolve` you'll receive a fresh instance. |
| Transient | Everytime you call `resolve` or `tryResolve` you'll receive a fresh instance. |

### Exposing

Expand Down Expand Up @@ -241,6 +260,7 @@ void main() {}
## Registering services at runtime (v2.1.0+)

Sometimes you need to register services at runtime. For this, you can use the `register` method:

```dart
void main() {
var provider = ExampleProvider();
Expand All @@ -255,10 +275,11 @@ void main() {
```

## Create a sub-provider with additional services / parameters (v2.2.0+)

In some cases, you want to register services or parameters only for a specific service.
The services or parameters should not be placed inside the global service provider.
To solve this problem, you can use the `enhance` method, which accepts an array of additional services and
a map of additional parameters. These are only available in the returned ServiceProvider.
The services or parameters should not be placed inside the global service provider.
To solve this problem, you can use the `enhance` method, which accepts an array of additional services and
a map of additional parameters. These are only available in the returned ServiceProvider.

```dart
void main() {
Expand All @@ -271,7 +292,7 @@ void main() {
services: [
// Important: Specify the type explicitly or cast the outer array to dynamic. Otherwise dart can not infer the
// correct return type!
LazyServiceDescriptor<MySelfRegisteredService>(
LazyServiceDescriptor<MySelfRegisteredService>(
(p) => MySelfRegisteredService(p.resolve(), p.parameters['foo']),
const Service(exposeAs: SelfRegisteredService),
),
Expand All @@ -284,8 +305,10 @@ void main() {
```

## Tagged services (v2.3.0+)

You can tag services using the `tags` property on the `Service` annotation. This is useful if you need to group services
and load all services with a certain tag at once.

```dart
@Service(tags: [#groupTag, #anotherTag])
class MyService1 {}
Expand Down Expand Up @@ -315,6 +338,7 @@ void main() {
## Inject tagged services (v3.2.0+)

The `@Inject` annotation allows you to inject a list of services tagged with a certain tag.

```dart
abstract class MyServiceBase {}
Expand All @@ -326,10 +350,8 @@ class MyService2 extends MyServiceBase {}
@Service()
class ServiceWithDeps {
ServiceWithDeps(
@Inject(tag: #groupTag) List<MyServiceBase> services,
) {
ServiceWithDeps(@Inject(tag: #groupTag) List<MyServiceBase> services,) {
// services includes MyService1 and MyService2
}
}
Expand All @@ -339,10 +361,12 @@ class ServiceWithDeps {
## Include services from dependencies

By default, the builder includes only services from the root package.
If you've dependencies that provides decorated services (`@Service`) you need to set `includePackageDependencies` to true.
If you've dependencies that provides decorated services (`@Service`) you need to set `includePackageDependencies` to
true.

```dart
@GenerateServiceProvider(
providerClassName: 'ExampleProvider',
includePackageDependencies: true, // Set this to true
includePackageDependencies: true, // Set this to true
)
```
2 changes: 1 addition & 1 deletion example/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
build/
*.g.dart

.catalyst_builder_cache/
.cache/
3 changes: 3 additions & 0 deletions example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ dependencies:
dev_dependencies:
lints: ^5.1.1
build_runner: ^2.0.1

catalyst_builder:
cacheDir: '.cache/catalyst_builder'
42 changes: 42 additions & 0 deletions lib/src/builder/dto/config.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import 'dart:convert';
import 'dart:io';

import 'package:path/path.dart' as p;
import 'package:yaml/yaml.dart';

import '../constants.dart' as c;

/// Represents the config file for advanced configuration
class Config {
/// The directory for the builder cache.
/// This could be an relative or absolute path.
String cacheDir;

/// Creates the config object
Config({
this.cacheDir = c.cacheDir,
});

/// Load the configuration from [configFileName] or fallback to the default.
factory Config.load() {
var configFile = File(p.join(p.current, 'pubspec.yaml'));

if (configFile.existsSync()) {
var content = loadYaml(configFile.readAsStringSync()) as YamlMap;
if (content.containsKey('catalyst_builder')) {
var yamlJson = jsonEncode(content['catalyst_builder']);
var configFromYaml = jsonDecode(yamlJson) as Map;
return Config.fromJson(configFromYaml.cast());
}
}

return Config();
}

/// Creates a new instance from the result of [toJson].
factory Config.fromJson(Map<String, dynamic> json) {
return Config(
cacheDir: json['cacheDir']?.toString() ?? c.cacheDir,
);
}
}
1 change: 1 addition & 0 deletions lib/src/builder/dto/dto.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export 'config.dart';
export 'constructor_arg.dart';
export 'extracted_service.dart';
export 'inject_annotation.dart';
Expand Down
6 changes: 4 additions & 2 deletions lib/src/builder/preflight_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import 'helpers.dart';
/// The PreflightBuilder scans the files for @Service annotations.
/// The result is stored in preflight.json files.
class PreflightBuilder implements Builder {
final CacheHelper _cacheHelper = CacheHelper();

@override
final Map<String, List<String>> buildExtensions = {
r'$lib$': [],
Expand All @@ -34,11 +36,11 @@ class PreflightBuilder implements Builder {

final cachedPath = _getFilename(buildStep);
if (extractedAnnotations.services.isEmpty) {
await CacheHelper.deleteFileFromCache(cachedPath);
await _cacheHelper.deleteFileFromCache(cachedPath);
return;
}

await CacheHelper.writeFileToCache(
await _cacheHelper.writeFileToCache(
cachedPath,
jsonEncode(extractedAnnotations),
);
Expand Down
6 changes: 4 additions & 2 deletions lib/src/builder/service_provider_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import 'generator/service_provider/service_provider.dart';
/// The ServiceProviderBuilder creates a service provider from the resulting
/// preflight .json files.
class ServiceProviderBuilder implements Builder {
final CacheHelper _cacheHelper = CacheHelper();

@override
FutureOr<void> build(BuildStep buildStep) async {
if (!buildStep.inputId.path.endsWith(entrypointExtension)) {
Expand All @@ -40,8 +42,8 @@ class ServiceProviderBuilder implements Builder {
final services = <ExtractedService>[];

final source = entrypoint.includePackageDependencies
? CacheHelper.preflightFiles
: CacheHelper.getPreflightFilesForPackage(
? _cacheHelper.preflightFiles
: _cacheHelper.getPreflightFilesForPackage(
entrypoint.assetId.pathSegments.first,
);

Expand Down
33 changes: 19 additions & 14 deletions lib/src/cache_helper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,47 +5,52 @@ import 'package:glob/list_local_fs.dart';
import 'package:path/path.dart' as p;

import './builder/constants.dart';
import './builder/dto/dto.dart';

abstract final class CacheHelper {
static final _filePattern = '**/*$preflightExtension';
final class CacheHelper {
static const _filePattern = '**/*$preflightExtension';
static final _preflightFiles = Glob(_filePattern, recursive: true);

/// Returns the path to the cache directory
static final String _cachePath = p.join(
p.current,
cacheDir,
);
late final String _cachePath;

static final Directory _cacheDir = Directory(_cachePath);
late final Directory _cacheDir = Directory(_cachePath);

static Stream<FileSystemEntity> get preflightFiles =>
CacheHelper() {
var config = Config.load();
_cachePath = p.isAbsolute(config.cacheDir)
? config.cacheDir
: p.join(p.current, config.cacheDir);
}

Stream<FileSystemEntity> get preflightFiles =>
_preflightFiles.list(root: _cachePath);

static Stream<FileSystemEntity> getPreflightFilesForPackage(String package) {
Stream<FileSystemEntity> getPreflightFilesForPackage(String package) {
return Glob('$package/$_filePattern', recursive: true)
.list(root: _cachePath);
}

static Future<void> cleanCacheDir() async {
Future<void> cleanCacheDir() async {
if (await _cacheDir.exists()) {
await _cacheDir.delete(recursive: true);
}
}

static Future<void> createCacheDirectory() async {
Future<void> createCacheDirectory() async {
if (!(await _cacheDir.exists())) {
await _cacheDir.create(recursive: true);
}
}

static Future<void> deleteFileFromCache(String filename) async {
Future<void> deleteFileFromCache(String filename) async {
var f = _getCacheFile(filename);
if (await f.exists()) {
await f.delete(recursive: true);
}
}

static Future<void> writeFileToCache(
Future<void> writeFileToCache(
String filename,
String contents,
) async {
Expand All @@ -56,7 +61,7 @@ abstract final class CacheHelper {
await f.writeAsString(contents, mode: FileMode.writeOnly);
}

static File _getCacheFile(String filename) {
File _getCacheFile(String filename) {
var cachedName = p.join(_cachePath, filename);
var f = File(cachedName);
return f;
Expand Down
10 changes: 9 additions & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
name: catalyst_builder
description: A lightweight and easy to use dependency injection provider builder for dart.
version: 4.0.0
version: 4.1.0
homepage: 'https://github.com/mintware-de/catalyst_builder'
repository: 'https://github.com/mintware-de/catalyst_builder'

topics:
- code-generation
- builder
- dependency-injection
- annotations
- service-provider

environment:
sdk: ">=3.5.0 <4.0.0"

Expand All @@ -14,6 +21,7 @@ dependencies:
glob: ^2.1.0
path: ^1.8.0
analyzer: '>=6.2.0 <8.0.0'
yaml: ^3.0.0

dev_dependencies:
test: any
Expand Down

0 comments on commit b1416d2

Please sign in to comment.