Skip to content

Commit

Permalink
👽 Use env files for API keys
Browse files Browse the repository at this point in the history
  • Loading branch information
techouse committed Nov 5, 2022
1 parent b39b79b commit 8ee2a9e
Show file tree
Hide file tree
Showing 13 changed files with 275 additions and 162 deletions.
6 changes: 6 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
APP_VERSION=2.1.7
GITHUB_REPOSITORY_URL=https://github.com/techouse/alfred-tailwindcss-docs
SUPPORTED_VERSIONS=v0,v1,v2,v3
ALGOLIA_SEARCH_INDEX=
ALGOLIA_APPLICATION_ID=
ALGOLIA_SEARCH_ONLY_API_KEY=
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ build/
# macOS specific
.DS_Store

bin/query_cache/
bin/update_cache/
bin/*_cache/
sign.sh

.env
54 changes: 54 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Makefile

help:
@printf "%-20s %s\n" "Target" "Description"
@printf "%-20s %s\n" "------" "-----------"
@make -pqR : 2>/dev/null \
| awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' \
| sort \
| egrep -v -e '^[^[:alnum:]]' -e '^$@$$' \
| xargs -I _ sh -c 'printf "%-20s " _; make _ -nB | (grep -i "^# Help:" || echo "") | tail -1 | sed "s/^# Help: //g"'

analyze:
@# Help: Analyze the project's Dart code.
dart analyze --fatal-infos

compile:
@# Help: Compile the executable binary
bash ./build.sh

check_format:
@# Help: Check the formatting of one or more Dart files.
dart format --output=none --set-exit-if-changed .

check_outdated:
@# Help: Check which of the project's packages are outdated.
dart pub outdated

check_style:
@# Help: Analyze the project's Dart code and check the formatting one or more Dart files.
make analyze && make check_format

code_gen:
@# Help: Run the build system for Dart code generation and modular compilation.
dart run build_runner build --delete-conflicting-outputs

code_gen_watcher:
@# Help: Run the build system for Dart code generation and modular compilation as a watcher.
dart run build_runner watch --delete-conflicting-outputs

format:
@# Help: Format one or more Dart files.
dart format .

install:
@# Help: Install all the project's packages
dart pub get

sure:
@# Help: Analyze the project's Dart code, check the formatting one or more Dart files and run unit tests for the current project.
make check_style && make tests

upgrade:
@# Help: Upgrade all the project's packages.
dart pub upgrade
120 changes: 21 additions & 99 deletions bin/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,149 +13,71 @@ import 'package:args/args.dart' show ArgParser, ArgResults;
import 'package:collection/collection.dart' show IterableExtension;
import 'package:html_unescape/html_unescape.dart' show HtmlUnescape;

import 'src/constants/config.dart' show Config;
import 'src/env/env.dart' show Env;
import 'src/models/search_result.dart' show SearchResult;
import 'src/services/algolia_search.dart' show AlgoliaSearch;

final HtmlUnescape unescape = HtmlUnescape();
part 'main_helpers.dart';

final AlfredWorkflow workflow = AlfredWorkflow();
final AlfredUpdater updater = AlfredUpdater(
githubRepositoryUrl: Config.githubRepositoryUrl,
currentVersion: Config.version,
updateInterval: Duration(days: 7),
);
bool verbose = false;
bool update = false;
bool _verbose = false;
bool _update = false;

void main(List<String> arguments) async {
try {
exitCode = 0;

workflow.clearItems();
_workflow.clearItems();

final ArgParser parser = ArgParser()
..addOption('query', abbr: 'q', defaultsTo: '')
..addFlag('verbose', abbr: 'v', defaultsTo: false)
..addFlag('update', abbr: 'u', defaultsTo: false);
final ArgResults args = parser.parse(arguments);

update = args['update'];
if (update) {
_update = args['update'];
if (_update) {
stdout.writeln('Updating workflow...');

return await updater.update();
return await _updater.update();
}

verbose = args['verbose'];
_verbose = args['verbose'];

List<String> query =
args['query'].replaceAll(RegExp(r'\s+'), ' ').trim().split(' ');
String? version =
query.firstWhereOrNull((el) => Config.supportedVersions.contains(el));
query.firstWhereOrNull((el) => Env.supportedVersions.contains(el));
if (version != null) {
query.removeWhere((str) => str == version);
} else {
version = Config.supportedVersions.last;
version = Env.supportedVersions.last;
}
final String queryString = query.join(' ').trim().toLowerCase();

if (verbose) stdout.writeln('Query: "$queryString"');
if (_verbose) stdout.writeln('Query: "$queryString"');

if (queryString.isEmpty) {
_showPlaceholder();
} else {
workflow.cacheKey = '${queryString}_$version';
if (await workflow.getItems() == null) {
_workflow.cacheKey = '${queryString}_$version';
if (await _workflow.getItems() == null) {
await _performSearch(queryString, version: version);
}
}
} on FormatException catch (err) {
exitCode = 2;
workflow.addItem(AlfredItem(title: err.toString()));
_workflow.addItem(AlfredItem(title: err.toString()));
} catch (err) {
exitCode = 1;
workflow.addItem(AlfredItem(title: err.toString()));
if (verbose) rethrow;
_workflow.addItem(AlfredItem(title: err.toString()));
if (_verbose) rethrow;
} finally {
if (!update) {
if (await updater.updateAvailable()) {
workflow.run(addToBeginning: updateItem);
if (!_update) {
if (await _updater.updateAvailable()) {
_workflow.run(addToBeginning: updateItem);
} else {
workflow.run();
_workflow.run();
}
}
}
}

const updateItem = AlfredItem(
title: 'Auto-Update available!',
subtitle: 'Press <enter> to auto-update to a new version of this workflow.',
arg: 'update:workflow',
match:
'Auto-Update available! Press <enter> to auto-update to a new version of this workflow.',
icon: AlfredItemIcon(path: 'alfredhatcog.png'),
valid: true,
);

void _showPlaceholder() {
workflow.addItem(
const AlfredItem(
title: 'Search the Tailwind CSS docs...',
icon: AlfredItemIcon(path: 'icon.png'),
),
);
}

Future<void> _performSearch(String query, {String? version}) async {
final AlgoliaQuerySnapshot snapshot = await AlgoliaSearch.query(
query,
version: version,
);

if (snapshot.nbHits > 0) {
final AlfredItems items = AlfredItems(
snapshot.hits
.map((snapshot) => SearchResult.fromJson(snapshot.data))
.map((result) {
final int level = int.tryParse(result.type.substring(3)) ?? 0;
final String? title = result.hierarchy.getLevel(level);
final Map<String, String?> hierarchy = result.hierarchy.toJson()
..removeWhere((_, value) => value == null);

return AlfredItem(
uid: result.objectID,
title: title!,
subtitle:
level > 0 ? unescape.convert(hierarchy.values.join(' > ')) : null,
arg: result.url,
text: AlfredItemText(
largeType: title,
copy: result.url,
),
quickLookUrl: result.url,
icon: AlfredItemIcon(path: 'icon.png'),
valid: true,
);
}).toList(),
);
workflow.addItems(items.items);
} else {
final Uri url =
Uri.https('www.google.com', '/search', {'q': 'Tailwind CSS $query'});

workflow.addItem(
AlfredItem(
title: 'No matching answers found',
subtitle: 'Shall I try and search Google?',
arg: url.toString(),
text: AlfredItemText(
copy: url.toString(),
),
quickLookUrl: url.toString(),
icon: AlfredItemIcon(path: 'google.png'),
valid: true,
),
);
}
}
84 changes: 84 additions & 0 deletions bin/main_helpers.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
part of 'main.dart';

final HtmlUnescape _unescape = HtmlUnescape();

final AlfredWorkflow _workflow = AlfredWorkflow();

final AlfredUpdater _updater = AlfredUpdater(
githubRepositoryUrl: Uri.parse(Env.githubRepositoryUrl),
currentVersion: Env.appVersion,
updateInterval: Duration(days: 7),
);

const updateItem = AlfredItem(
title: 'Auto-Update available!',
subtitle: 'Press <enter> to auto-update to a new version of this workflow.',
arg: 'update:workflow',
match:
'Auto-Update available! Press <enter> to auto-update to a new version of this workflow.',
icon: AlfredItemIcon(path: 'alfredhatcog.png'),
valid: true,
);

void _showPlaceholder() {
_workflow.addItem(
const AlfredItem(
title: 'Search the Tailwind CSS docs...',
icon: AlfredItemIcon(path: 'icon.png'),
),
);
}

Future<void> _performSearch(String query, {String? version}) async {
final AlgoliaQuerySnapshot snapshot = await AlgoliaSearch.query(
query,
version: version,
);

if (snapshot.nbHits > 0) {
final AlfredItems items = AlfredItems(
snapshot.hits
.map((snapshot) => SearchResult.fromJson(snapshot.data))
.map((result) {
final int level = int.tryParse(result.type.substring(3)) ?? 0;
final String? title = result.hierarchy.getLevel(level);
final Map<String, String?> hierarchy = result.hierarchy.toJson()
..removeWhere((_, value) => value == null);

return AlfredItem(
uid: result.objectID,
title: title!,
subtitle: level > 0
? _unescape.convert(hierarchy.values.join(' > '))
: null,
arg: result.url,
text: AlfredItemText(
largeType: title,
copy: result.url,
),
quickLookUrl: result.url,
icon: AlfredItemIcon(path: 'icon.png'),
valid: true,
);
}).toList(),
);
_workflow.addItems(items.items);
} else {
final Uri url =
Uri.https('www.google.com', '/search', {'q': 'Tailwind CSS $query'});

_workflow.addItem(
AlfredItem(
title: 'No matching answers found',
subtitle: 'Shall I try and search Google?',
arg: url.toString(),
text: AlfredItemText(
copy: url.toString(),
),
quickLookUrl: url.toString(),
icon: AlfredItemIcon(path: 'google.png'),
valid: true,
),
);
}
}
12 changes: 0 additions & 12 deletions bin/src/constants/config.dart

This file was deleted.

2 changes: 2 additions & 0 deletions bin/src/env/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.g.dart
!.gitignore
26 changes: 26 additions & 0 deletions bin/src/env/env.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import 'package:envied/envied.dart';

part 'env.g.dart';

@Envied(path: '.env')
abstract class Env {
@EnviedField(varName: 'APP_VERSION')
static const String appVersion = _Env.appVersion;

@EnviedField(varName: 'GITHUB_REPOSITORY_URL')
static const String githubRepositoryUrl = _Env.githubRepositoryUrl;

@EnviedField(varName: 'ALGOLIA_APPLICATION_ID', obfuscate: true)
static final String algoliaApplicationId = _Env.algoliaApplicationId;

@EnviedField(varName: 'ALGOLIA_SEARCH_ONLY_API_KEY', obfuscate: true)
static final String algoliaSearchOnlyApiKey = _Env.algoliaSearchOnlyApiKey;

@EnviedField(varName: 'ALGOLIA_SEARCH_INDEX', obfuscate: true)
static final String algoliaSearchIndex = _Env.algoliaSearchIndex;

@EnviedField(varName: 'SUPPORTED_VERSIONS')
static const String _supportedVersions = _Env._supportedVersions;

static final List<String> supportedVersions = _supportedVersions.split(',');
}
Loading

0 comments on commit 8ee2a9e

Please sign in to comment.