Compare commits
30 commits
feature/mi
...
main
Author | SHA1 | Date | |
---|---|---|---|
|
06080c879a | ||
|
2247aae302 | ||
|
a0db187d75 | ||
|
2decae0c3d | ||
|
685419eea6 | ||
|
d466f2e776 | ||
|
42ca54ec0f | ||
|
8ee0fc607d | ||
|
58f63f0315 | ||
|
dfccf23629 | ||
|
b6c1ba243a | ||
|
0aee2f64da | ||
|
f4a7b46cbc | ||
|
08bb59f51f | ||
|
6740e55356 | ||
|
819e030a32 | ||
|
d3946f479a | ||
|
4e320b1e44 | ||
|
ab7c3dc952 | ||
|
f482f16ace | ||
|
1dce9a75c3 | ||
|
5ad3ab195d | ||
|
0010405bda | ||
|
f03bd9b3e8 | ||
|
5d1a917fac | ||
|
0bf0c487bc | ||
|
b439c90970 | ||
|
2d0082f3b0 | ||
|
ef082cb000 | ||
|
b8cbfd95ee |
92 changed files with 750 additions and 345 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -27,3 +27,4 @@ doc/api/
|
||||||
!.vscode/launch.json
|
!.vscode/launch.json
|
||||||
!.vscode/extensions.json
|
!.vscode/extensions.json
|
||||||
.metals/
|
.metals/
|
||||||
|
.DS_Store
|
1
.idea/.name
Normal file
1
.idea/.name
Normal file
|
@ -0,0 +1 @@
|
||||||
|
belatuk_common_utilities
|
19
.idea/modules.xml
Normal file
19
.idea/modules.xml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/packages/body_parser/melos_belatuk_body_parser.iml" filepath="$PROJECT_DIR$/packages/body_parser/melos_belatuk_body_parser.iml" />
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/packages/code_buffer/melos_belatuk_code_buffer.iml" filepath="$PROJECT_DIR$/packages/code_buffer/melos_belatuk_code_buffer.iml" />
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/packages/combinator/melos_belatuk_combinator.iml" filepath="$PROJECT_DIR$/packages/combinator/melos_belatuk_combinator.iml" />
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/packages/html_builder/melos_belatuk_html_builder.iml" filepath="$PROJECT_DIR$/packages/html_builder/melos_belatuk_html_builder.iml" />
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/packages/json_serializer/melos_belatuk_json_serializer.iml" filepath="$PROJECT_DIR$/packages/json_serializer/melos_belatuk_json_serializer.iml" />
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/packages/merge_map/melos_belatuk_merge_map.iml" filepath="$PROJECT_DIR$/packages/merge_map/melos_belatuk_merge_map.iml" />
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/packages/pretty_logging/melos_belatuk_pretty_logging.iml" filepath="$PROJECT_DIR$/packages/pretty_logging/melos_belatuk_pretty_logging.iml" />
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/packages/pub_sub/melos_belatuk_pub_sub.iml" filepath="$PROJECT_DIR$/packages/pub_sub/melos_belatuk_pub_sub.iml" />
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/packages/range_header/melos_belatuk_range_header.iml" filepath="$PROJECT_DIR$/packages/range_header/melos_belatuk_range_header.iml" />
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/packages/symbol_table/melos_belatuk_symbol_table.iml" filepath="$PROJECT_DIR$/packages/symbol_table/melos_belatuk_symbol_table.iml" />
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/packages/user_agent/melos_user_agent_analyzer.iml" filepath="$PROJECT_DIR$/packages/user_agent/melos_user_agent_analyzer.iml" />
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/melos_belatuk_common_utilities.iml" filepath="$PROJECT_DIR$/melos_belatuk_common_utilities.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
11
.idea/runConfigurations/melos_bootstrap.xml
Normal file
11
.idea/runConfigurations/melos_bootstrap.xml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<!-- Generated by Melos -->
|
||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Melos -> Bootstrap Workspace" type="ShConfigurationType">
|
||||||
|
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
|
||||||
|
<option name="SCRIPT_PATH" value="$USER_HOME$/.pub-cache/bin/melos" />
|
||||||
|
<option name="SCRIPT_OPTIONS" value="bootstrap" />
|
||||||
|
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="false" />
|
||||||
|
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
11
.idea/runConfigurations/melos_clean.xml
Normal file
11
.idea/runConfigurations/melos_clean.xml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<!-- Generated by Melos -->
|
||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Melos -> Clean Workspace" type="ShConfigurationType">
|
||||||
|
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
|
||||||
|
<option name="SCRIPT_PATH" value="$USER_HOME$/.pub-cache/bin/melos" />
|
||||||
|
<option name="SCRIPT_OPTIONS" value="clean" />
|
||||||
|
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="false" />
|
||||||
|
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
|
@ -18,3 +18,6 @@ This repository contains the common utility packages required for developing dar
|
||||||
* [Symbol Table](https://github.com/dart-backend/belatuk-common-utilities/tree/main/packages/symbol_table)
|
* [Symbol Table](https://github.com/dart-backend/belatuk-common-utilities/tree/main/packages/symbol_table)
|
||||||
* [User Agent](https://github.com/dart-backend/belatuk-common-utilities/tree/main/packages/user_agent)
|
* [User Agent](https://github.com/dart-backend/belatuk-common-utilities/tree/main/packages/user_agent)
|
||||||
|
|
||||||
|
## Donation & Support
|
||||||
|
|
||||||
|
If you like this project and interested in supporting its development, you can make a donation via [paypal](https://paypal.me/dukefirehawk?country.x=MY&locale.x=en_US) service.
|
||||||
|
|
4
melos.yaml
Normal file
4
melos.yaml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
name: belatuk_common_utilities
|
||||||
|
|
||||||
|
packages:
|
||||||
|
- packages/*
|
12
melos_belatuk_common_utilities.iml
Normal file
12
melos_belatuk_common_utilities.iml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="WEB_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||||
|
<exclude-output />
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
<orderEntry type="library" name="Dart SDK" level="project" />
|
||||||
|
<orderEntry type="library" name="Dart Packages" level="project" />
|
||||||
|
</component>
|
||||||
|
</module>
|
|
@ -1,5 +1,34 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 5.3.0
|
||||||
|
|
||||||
|
* Require Dart >= 3.3
|
||||||
|
* Updated `belatuk_http_server` to 4.4.0
|
||||||
|
* Updated `lints` to 4.0.0
|
||||||
|
|
||||||
|
## 5.2.0
|
||||||
|
|
||||||
|
* Updated `lints` to 3.0.0
|
||||||
|
* Updated `belatuk_http_server` to 4.2.0
|
||||||
|
|
||||||
|
## 5.1.0
|
||||||
|
|
||||||
|
* Updated `belatuk_http_server` to 4.1.1
|
||||||
|
* Updated `http` to 1.0.0
|
||||||
|
|
||||||
|
## 5.0.0
|
||||||
|
|
||||||
|
* Require Dart >= 3.0
|
||||||
|
|
||||||
|
## 5.0.0-beta.1
|
||||||
|
|
||||||
|
* Require Dart >= 3.0
|
||||||
|
* Updated `belatuk_http_server` to 4.0.0
|
||||||
|
|
||||||
|
## 4.0.1
|
||||||
|
|
||||||
|
* Updated `belatuk_http_server` to 3.0.0
|
||||||
|
|
||||||
## 4.0.0
|
## 4.0.0
|
||||||
|
|
||||||
* Require Dart >= 2.17
|
* Require Dart >= 2.17
|
||||||
|
|
|
@ -21,16 +21,14 @@ This is the request body parser powering the [Angel3 framework](https://pub.dev/
|
||||||
|
|
||||||
### About
|
### About
|
||||||
|
|
||||||
I needed something like Express.js's `body-parser` module, so I made it here. It fully supports JSON requests. x-www-form-urlencoded fully supported, as well as query strings. You can also include arrays in your query, in the same way you would for a PHP application. Full file upload support will also be present by the production 1.0.0 release.
|
This package is similar to Express.js's `body-parser` module. It fully supports JSON, x-www-form-urlencoded as well as query strings requests. You can also include arrays in your query, in the same way you would for a PHP application. A benefit of this is that primitive types are automatically deserialized correctly. As in, if you have a `hello=1.5` request, then `body['hello']` will equal `1.5` and not `'1.5'`.
|
||||||
|
|
||||||
A benefit of this is that primitive types are automatically deserialized correctly. As in, if you have a `hello=1.5` request, then `body['hello']` will equal `1.5` and not `'1.5'`. A very semantic difference, yes, but it relieves stress in my head.
|
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
|
||||||
To install Body Parser for your Dart project, simply add body_parser to your pub dependencies.
|
To install Body Parser for your Dart project, simply add body_parser to your pub dependencies.
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
belatuk_body_parser: ^4.0.0
|
belatuk_body_parser: ^5.2.0
|
||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
name: belatuk_body_parser
|
name: belatuk_body_parser
|
||||||
version: 4.0.0
|
version: 5.3.0
|
||||||
description: Parse request bodies and query strings in Dart. Supports JSON, URL-encoded, and multi-part bodies.
|
description: Parse request bodies and query strings in Dart. Supports JSON, URL-encoded, and multi-part bodies.
|
||||||
homepage: https://github.com/dart-backend/belatuk-common-utilities/tree/main/packages/body_parser
|
homepage: https://github.com/dart-backend/belatuk-common-utilities/tree/main/packages/body_parser
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=2.17.0 <3.0.0'
|
sdk: '>=3.3.0 <4.0.0'
|
||||||
dependencies:
|
dependencies:
|
||||||
http_parser: ^4.0.0
|
http_parser: ^4.0.0
|
||||||
belatuk_http_server: ^2.0.0
|
belatuk_http_server: ^4.4.0
|
||||||
mime: ^1.0.0
|
mime: ^1.0.0
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
http: ^0.13.0
|
http: ^1.0.0
|
||||||
test: ^1.17.8
|
test: ^1.24.0
|
||||||
lints: ^2.0.0
|
lints: ^4.0.0
|
|
@ -63,9 +63,7 @@ world
|
||||||
print('Response: ${response.body}');
|
print('Response: ${response.body}');
|
||||||
var jsons = json.decode(response.body);
|
var jsons = json.decode(response.body);
|
||||||
var files = jsons['files'].map((map) {
|
var files = jsons['files'].map((map) {
|
||||||
return map == null
|
return map.keys.fold<Map<String, dynamic>>(
|
||||||
? null
|
|
||||||
: map.keys.fold<Map<String, dynamic>>(
|
|
||||||
<String, dynamic>{}, (out, k) => out..[k.toString()] = map[k]);
|
<String, dynamic>{}, (out, k) => out..[k.toString()] = map[k]);
|
||||||
});
|
});
|
||||||
expect(files.length, equals(0));
|
expect(files.length, equals(0));
|
||||||
|
|
|
@ -6,7 +6,7 @@ import 'package:http/http.dart' as http;
|
||||||
import 'package:http_parser/http_parser.dart';
|
import 'package:http_parser/http_parser.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
const TOKEN =
|
const token =
|
||||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiIxMjcuMC4wLjEiLCJleHAiOi0xLCJpYXQiOiIyMDE2LTEyLTIyVDEyOjQ5OjUwLjM2MTQ0NiIsImlzcyI6ImFuZ2VsX2F1dGgiLCJzdWIiOiIxMDY2OTQ4Mzk2MDIwMjg5ODM2NTYifQ==.PYw7yUb-cFWD7N0sSLztP7eeRvO44nu1J2OgDNyT060=';
|
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiIxMjcuMC4wLjEiLCJleHAiOi0xLCJpYXQiOiIyMDE2LTEyLTIyVDEyOjQ5OjUwLjM2MTQ0NiIsImlzcyI6ImFuZ2VsX2F1dGgiLCJzdWIiOiIxMDY2OTQ4Mzk2MDIwMjg5ODM2NTYifQ==.PYw7yUb-cFWD7N0sSLztP7eeRvO44nu1J2OgDNyT060=';
|
||||||
|
|
||||||
String jsonEncodeBody(BodyParseResult result) {
|
String jsonEncodeBody(BodyParseResult result) {
|
||||||
|
@ -89,12 +89,12 @@ void main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('JWT', () async {
|
test('JWT', () async {
|
||||||
var postData = 'token=$TOKEN';
|
var postData = 'token=$token';
|
||||||
print('Body: $postData');
|
print('Body: $postData');
|
||||||
var response = await client!.get(Uri.parse('$url/?$postData'));
|
var response = await client!.get(Uri.parse('$url/?$postData'));
|
||||||
print('Response: ${response.body}');
|
print('Response: ${response.body}');
|
||||||
var query = json.decode(response.body)['query'];
|
var query = json.decode(response.body)['query'];
|
||||||
expect(query['token'], equals(TOKEN));
|
expect(query['token'], equals(token));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -129,11 +129,11 @@ void main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('JWT', () async {
|
test('JWT', () async {
|
||||||
var postData = 'token=$TOKEN';
|
var postData = 'token=$token';
|
||||||
var response =
|
var response =
|
||||||
await client!.post(Uri.parse(url!), headers: headers, body: postData);
|
await client!.post(Uri.parse(url!), headers: headers, body: postData);
|
||||||
var body = json.decode(response.body)['body'];
|
var body = json.decode(response.body)['body'];
|
||||||
expect(body['token'], equals(TOKEN));
|
expect(body['token'], equals(token));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,22 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 5.2.0
|
||||||
|
|
||||||
|
* Require Dart >= 3.3
|
||||||
|
* Updated `lints` to 4.0.0
|
||||||
|
|
||||||
|
## 5.1.0
|
||||||
|
|
||||||
|
* Updated `lints` to 3.0.0
|
||||||
|
|
||||||
|
## 5.0.0
|
||||||
|
|
||||||
|
* Require Dart >= 3.0
|
||||||
|
|
||||||
|
## 5.0.0-beta.1
|
||||||
|
|
||||||
|
* Require Dart >= 3.0
|
||||||
|
|
||||||
## 4.0.0
|
## 4.0.0
|
||||||
|
|
||||||
* Require Dart >= 2.17
|
* Require Dart >= 2.17
|
||||||
|
|
|
@ -14,7 +14,7 @@ In your `pubspec.yaml`:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
dependencies:
|
dependencies:
|
||||||
belatuk_code_buffer: ^4.0.0
|
belatuk_code_buffer: ^5.1.0
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
name: belatuk_code_buffer
|
name: belatuk_code_buffer
|
||||||
version: 4.0.0
|
version: 5.2.0
|
||||||
description: An advanced StringBuffer geared toward generating code, and source maps.
|
description: An advanced StringBuffer geared toward generating code, and source maps.
|
||||||
homepage: https://github.com/dart-backend/belatuk-common-utilities/tree/main/packages/code_buffer
|
homepage: https://github.com/dart-backend/belatuk-common-utilities/tree/main/packages/code_buffer
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=2.17.0 <3.0.0'
|
sdk: '>=3.3.0 <4.0.0'
|
||||||
dependencies:
|
dependencies:
|
||||||
charcode: ^1.2.0
|
charcode: ^1.2.0
|
||||||
source_span: ^1.8.1
|
source_span: ^1.8.1
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
test: ^1.17.3
|
test: ^1.24.0
|
||||||
lints: ^2.0.0
|
lints: ^4.0.0
|
||||||
|
|
|
@ -1,5 +1,24 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 5.2.0
|
||||||
|
|
||||||
|
* Require Dart >= 3.3
|
||||||
|
* Updated `lints` to 4.0.0
|
||||||
|
|
||||||
|
## 5.1.0
|
||||||
|
|
||||||
|
* Updated `lints` to 3.0.0
|
||||||
|
* Fixed lints warnings
|
||||||
|
|
||||||
|
## 5.0.0
|
||||||
|
|
||||||
|
* Require Dart >= 3.0
|
||||||
|
|
||||||
|
## 5.0.0-beta.1
|
||||||
|
|
||||||
|
* Require Dart >= 3.0
|
||||||
|
* Updated `belatuk_code_buffer` to 5.0.0
|
||||||
|
|
||||||
## 4.0.0
|
## 4.0.0
|
||||||
|
|
||||||
* Require Dart >= 2.17
|
* Require Dart >= 2.17
|
||||||
|
|
|
@ -9,8 +9,7 @@
|
||||||
Packrat parser combinators that support static typing, generics, file spans, memoization, and more.
|
Packrat parser combinators that support static typing, generics, file spans, memoization, and more.
|
||||||
|
|
||||||
**RECOMMENDED:**
|
**RECOMMENDED:**
|
||||||
Check `example/` for examples.
|
Check `example/` for examples. The examples contain examples of using:
|
||||||
The examples contain examples of using:
|
|
||||||
|
|
||||||
* Generic typing
|
* Generic typing
|
||||||
* Reading `FileSpan` from `ParseResult`
|
* Reading `FileSpan` from `ParseResult`
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
part of lex.src.combinator;
|
part of 'combinator.dart';
|
||||||
|
|
||||||
class _Advance<T> extends Parser<T> {
|
class _Advance<T> extends Parser<T> {
|
||||||
final Parser<T> parser;
|
final Parser<T> parser;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
part of lex.src.combinator;
|
part of 'combinator.dart';
|
||||||
|
|
||||||
/// Matches any one of the given [parsers].
|
/// Matches any one of the given [parsers].
|
||||||
///
|
///
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
part of lex.src.combinator;
|
part of 'combinator.dart';
|
||||||
|
|
||||||
class _Cache<T> extends Parser<T> {
|
class _Cache<T> extends Parser<T> {
|
||||||
final Map<int, ParseResult<T>> _cache = {};
|
final Map<int, ParseResult<T>> _cache = {};
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
part of lex.src.combinator;
|
part of 'combinator.dart';
|
||||||
|
|
||||||
class _Cast<T, U extends T> extends Parser<U> {
|
class _Cast<T, U extends T> extends Parser<U> {
|
||||||
final Parser<T> parser;
|
final Parser<T> parser;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
part of lex.src.combinator;
|
part of 'combinator.dart';
|
||||||
|
|
||||||
/// Expects to parse a sequence of [parsers].
|
/// Expects to parse a sequence of [parsers].
|
||||||
///
|
///
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
part of lex.src.combinator;
|
part of 'combinator.dart';
|
||||||
|
|
||||||
class _Check<T> extends Parser<T> {
|
class _Check<T> extends Parser<T> {
|
||||||
final Parser<T> parser;
|
final Parser<T> parser;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
part of lex.src.combinator;
|
part of 'combinator.dart';
|
||||||
|
|
||||||
class _Compare<T> extends ListParser<T> {
|
class _Compare<T> extends ListParser<T> {
|
||||||
final ListParser<T> parser;
|
final ListParser<T> parser;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
part of lex.src.combinator;
|
part of 'combinator.dart';
|
||||||
|
|
||||||
class _FoldErrors<T> extends Parser<T> {
|
class _FoldErrors<T> extends Parser<T> {
|
||||||
final Parser<T> parser;
|
final Parser<T> parser;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
part of lex.src.combinator;
|
part of 'combinator.dart';
|
||||||
|
|
||||||
class _Index<T> extends Parser<T> {
|
class _Index<T> extends Parser<T> {
|
||||||
final ListParser<T> parser;
|
final ListParser<T> parser;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
part of lex.src.combinator;
|
part of 'combinator.dart';
|
||||||
|
|
||||||
/// Matches any one of the given [parsers].
|
/// Matches any one of the given [parsers].
|
||||||
///
|
///
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
part of lex.src.combinator;
|
part of 'combinator.dart';
|
||||||
|
|
||||||
class _Map<T, U> extends Parser<U> {
|
class _Map<T, U> extends Parser<U> {
|
||||||
final Parser<T> parser;
|
final Parser<T> parser;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
part of lex.src.combinator;
|
part of 'combinator.dart';
|
||||||
|
|
||||||
/// Expects to match a given [pattern]. If it is not matched, you can provide a custom [errorMessage].
|
/// Expects to match a given [pattern]. If it is not matched, you can provide a custom [errorMessage].
|
||||||
Parser<T> match<T>(Pattern pattern,
|
Parser<T> match<T>(Pattern pattern,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
part of lex.src.combinator;
|
part of 'combinator.dart';
|
||||||
|
|
||||||
class _MaxDepth<T> extends Parser<T> {
|
class _MaxDepth<T> extends Parser<T> {
|
||||||
final Parser<T> parser;
|
final Parser<T> parser;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
part of lex.src.combinator;
|
part of 'combinator.dart';
|
||||||
|
|
||||||
class _Negate<T> extends Parser<T> {
|
class _Negate<T> extends Parser<T> {
|
||||||
final Parser<T> parser;
|
final Parser<T> parser;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
part of lex.src.combinator;
|
part of 'combinator.dart';
|
||||||
|
|
||||||
class _Opt<T> extends Parser<T> {
|
class _Opt<T> extends Parser<T> {
|
||||||
final Parser<T> parser;
|
final Parser<T> parser;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
part of lex.src.combinator;
|
part of 'combinator.dart';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
/// Handles left recursion in a grammar using the Pratt algorithm.
|
/// Handles left recursion in a grammar using the Pratt algorithm.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
part of lex.src.combinator;
|
part of 'combinator.dart';
|
||||||
|
|
||||||
class _Reduce<T> extends Parser<T> {
|
class _Reduce<T> extends Parser<T> {
|
||||||
final ListParser<T> parser;
|
final ListParser<T> parser;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
part of lex.src.combinator;
|
part of 'combinator.dart';
|
||||||
|
|
||||||
Reference<T> reference<T>() => Reference<T>._();
|
Reference<T> reference<T>() => Reference<T>._();
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
part of lex.src.combinator;
|
part of 'combinator.dart';
|
||||||
|
|
||||||
class _Repeat<T> extends ListParser<T> {
|
class _Repeat<T> extends ListParser<T> {
|
||||||
final Parser<T> parser;
|
final Parser<T> parser;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
part of lex.src.combinator;
|
part of 'combinator.dart';
|
||||||
|
|
||||||
class _Safe<T> extends Parser<T> {
|
class _Safe<T> extends Parser<T> {
|
||||||
final Parser<T> parser;
|
final Parser<T> parser;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
part of lex.src.combinator;
|
part of 'combinator.dart';
|
||||||
|
|
||||||
class _ToList<T> extends ListParser<T> {
|
class _ToList<T> extends ListParser<T> {
|
||||||
final Parser<T> parser;
|
final Parser<T> parser;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
part of lex.src.combinator;
|
part of 'combinator.dart';
|
||||||
|
|
||||||
/// A typed parser that parses a sequence of 2 values of different types.
|
/// A typed parser that parses a sequence of 2 values of different types.
|
||||||
Parser<Tuple2<A, B>> tuple2<A, B>(Parser<A> a, Parser<B> b) {
|
Parser<Tuple2<A, B>> tuple2<A, B>(Parser<A> a, Parser<B> b) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
part of lex.src.combinator;
|
part of 'combinator.dart';
|
||||||
|
|
||||||
class _Value<T> extends Parser<T> {
|
class _Value<T> extends Parser<T> {
|
||||||
final Parser<T> parser;
|
final Parser<T> parser;
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
name: belatuk_combinator
|
name: belatuk_combinator
|
||||||
version: 4.0.0
|
version: 5.2.0
|
||||||
description: Packrat parser combinators that support static typing, generics, file spans, memoization, and more.
|
description: Packrat parser combinators that support static typing, generics, file spans, memoization, and more.
|
||||||
homepage: https://github.com/dart-backend/belatuk-common-utilities/tree/main/packages/combinator
|
homepage: https://github.com/dart-backend/belatuk-common-utilities/tree/main/packages/combinator
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=2.17.0 <3.0.0'
|
sdk: '>=3.3.0 <4.0.0'
|
||||||
dependencies:
|
dependencies:
|
||||||
belatuk_code_buffer: ^4.0.0
|
belatuk_code_buffer: ^5.0.0
|
||||||
matcher: ^0.12.10
|
matcher: ^0.12.10
|
||||||
source_span: ^1.8.1
|
source_span: ^1.8.1
|
||||||
string_scanner: ^1.1.0
|
string_scanner: ^1.1.0
|
||||||
tuple: ^2.0.0
|
tuple: ^2.0.0
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
test: ^1.17.4
|
test: ^1.24.0
|
||||||
lints: ^2.0.0
|
lints: ^4.0.0
|
4
packages/combinator/pubspec_overrides.yaml
Normal file
4
packages/combinator/pubspec_overrides.yaml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# melos_managed_dependency_overrides: belatuk_code_buffer
|
||||||
|
#dependency_overrides:
|
||||||
|
# belatuk_code_buffer:
|
||||||
|
# path: ../code_buffer
|
|
@ -1,5 +1,22 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 5.2.0
|
||||||
|
|
||||||
|
* Require Dart >= 3.3
|
||||||
|
* Updated `lints` to 4.0.0
|
||||||
|
|
||||||
|
## 5.1.0
|
||||||
|
|
||||||
|
* Updated `lints` to 3.0.0
|
||||||
|
|
||||||
|
## 5.0.0
|
||||||
|
|
||||||
|
* Require Dart >= 3.0
|
||||||
|
|
||||||
|
## 5.0.0-beta.1
|
||||||
|
|
||||||
|
* Require Dart >= 3.0
|
||||||
|
|
||||||
## 4.0.0
|
## 4.0.0
|
||||||
|
|
||||||
* Require Dart >= 2.17
|
* Require Dart >= 2.17
|
||||||
|
|
|
@ -8,17 +8,13 @@
|
||||||
|
|
||||||
This package builds HTML AST's and renders them to HTML. It can be used as an internal DSL, i.e. for a templating engine.
|
This package builds HTML AST's and renders them to HTML. It can be used as an internal DSL, i.e. for a templating engine.
|
||||||
|
|
||||||
## Requirements
|
|
||||||
|
|
||||||
* Dart SDK: 2.17.x or later
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
In your `pubspec.yaml`:
|
In your `pubspec.yaml`:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
dependencies:
|
dependencies:
|
||||||
belatuk_html_builder: ^4.0.0
|
belatuk_html_builder: ^5.1.0
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
|
@ -12,9 +12,9 @@ Node Function(Node) rebuild(NodeBuilder Function(NodeBuilder) transform,
|
||||||
///
|
///
|
||||||
/// Use this alongside [rebuild].
|
/// Use this alongside [rebuild].
|
||||||
Node Function(Node) rebuildRecursive(Node Function(Node) f) {
|
Node Function(Node) rebuildRecursive(Node Function(Node) f) {
|
||||||
Node _build(Node node) {
|
Node build(Node node) {
|
||||||
return NodeBuilder.from(f(node)).mapChildren(_build).build();
|
return NodeBuilder.from(f(node)).mapChildren(build).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
return _build;
|
return build;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,8 @@ class SelfClosingNode extends Node {
|
||||||
@override
|
@override
|
||||||
List<Node> get children => List<Node>.unmodifiable([]);
|
List<Node> get children => List<Node>.unmodifiable([]);
|
||||||
|
|
||||||
SelfClosingNode(tagName, [Map<String, dynamic> attributes = const {}])
|
// ignore: use_super_parameters
|
||||||
|
SelfClosingNode(String tagName, [Map<String, dynamic> attributes = const {}])
|
||||||
: super._selfClosing(tagName, attributes);
|
: super._selfClosing(tagName, attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
name: belatuk_html_builder
|
name: belatuk_html_builder
|
||||||
version: 4.0.0
|
version: 5.2.0
|
||||||
description: Build HTML AST's and render them to HTML. This can be used as an internal DSL, i.e. for a templating engine.
|
description: Build HTML AST's and render them to HTML. This can be used as an internal DSL, i.e. for a templating engine.
|
||||||
homepage: https://github.com/dart-backend/belatuk-common-utilities/tree/main/packages/html_builder
|
homepage: https://github.com/dart-backend/belatuk-common-utilities/tree/main/packages/html_builder
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=2.17.0 <3.0.0'
|
sdk: '>=3.3.0 <4.0.0'
|
||||||
dependencies:
|
dependencies:
|
||||||
collection: ^1.15.0
|
collection: ^1.17.0
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
html: ^0.15.0
|
html: ^0.15.0
|
||||||
test: ^1.17.4
|
test: ^1.24.0
|
||||||
lints: ^2.0.0
|
lints: ^4.0.0
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import 'package:html/parser.dart' as html5;
|
import 'package:html/parser.dart' as html5;
|
||||||
import 'package:belatuk_html_builder/elements.dart';
|
import 'package:belatuk_html_builder/elements.dart';
|
||||||
import 'package:belatuk_html_builder/belatuk_html_builder.dart';
|
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
|
@ -1,5 +1,27 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 7.2.0
|
||||||
|
|
||||||
|
* Require Dart >= 3.3
|
||||||
|
* Updated `lints` to 4.0.0
|
||||||
|
|
||||||
|
## 7.1.0
|
||||||
|
|
||||||
|
* Updated `lints` to 3.0.0
|
||||||
|
* Fixed lints warnings
|
||||||
|
|
||||||
|
## 7.0.0
|
||||||
|
|
||||||
|
* Require Dart >= 3.0
|
||||||
|
|
||||||
|
## 7.0.0-beta.1
|
||||||
|
|
||||||
|
* Require Dart >= 3.0
|
||||||
|
|
||||||
|
## 6.0.1
|
||||||
|
|
||||||
|
* Updated README
|
||||||
|
|
||||||
## 6.0.0
|
## 6.0.0
|
||||||
|
|
||||||
* Require Dart >= 2.17
|
* Require Dart >= 2.17
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Belatuk JSON Serializer
|
# Belatuk JSON Serializer
|
||||||
|
|
||||||
![Pub Version (including pre-releases)](https://img.shields.io/pub/v/json_serializer?include_prereleases)
|
![Pub Version (including pre-releases)](https://img.shields.io/pub/v/belatuk_json_serializer?include_prereleases)
|
||||||
[![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety)
|
[![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety)
|
||||||
[![Gitter](https://img.shields.io/gitter/room/angel_dart/discussion)](https://gitter.im/angel_dart/discussion)
|
[![Gitter](https://img.shields.io/gitter/room/angel_dart/discussion)](https://gitter.im/angel_dart/discussion)
|
||||||
[![License](https://img.shields.io/github/license/dart-backend/belatuk-common-utilities)](https://github.com/dart-backend/belatuk-common-utilities/blob/main/packages/json_serializer/LICENSE)
|
[![License](https://img.shields.io/github/license/dart-backend/belatuk-common-utilities)](https://github.com/dart-backend/belatuk-common-utilities/blob/main/packages/json_serializer/LICENSE)
|
||||||
|
@ -11,8 +11,10 @@ The ***new and improved*** definitive solution for JSON in Dart. It supports syn
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
```yaml
|
||||||
dependencies:
|
dependencies:
|
||||||
belatuk_json_serializer: ^6.0.0
|
belatuk_json_serializer: ^7.1.0
|
||||||
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
part of belatuk_json_serializer;
|
part of '../belatuk_json_serializer.dart';
|
||||||
|
|
||||||
/// Deserializes a JSON string into a Dart datum.
|
/// Deserializes a JSON string into a Dart datum.
|
||||||
///
|
///
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
part of belatuk_json_serializer;
|
part of '../belatuk_json_serializer.dart';
|
||||||
|
|
||||||
/// Serializes any arbitrary Dart datum to JSON. Supports schema validation.
|
/// Serializes any arbitrary Dart datum to JSON. Supports schema validation.
|
||||||
String serialize(value) {
|
String serialize(value) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
part of belatuk_json_serializer;
|
part of '../belatuk_json_serializer.dart';
|
||||||
|
|
||||||
bool _isPrimitive(value) {
|
bool _isPrimitive(value) {
|
||||||
return value is num || value is bool || value is String || value == null;
|
return value is num || value is bool || value is String || value == null;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
part of belatuk_json_serializer;
|
part of '../belatuk_json_serializer.dart';
|
||||||
|
|
||||||
/// Thrown when schema validation fails.
|
/// Thrown when schema validation fails.
|
||||||
class JsonValidationError implements Exception {
|
class JsonValidationError implements Exception {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
name: belatuk_json_serializer
|
name: belatuk_json_serializer
|
||||||
version: 6.0.0
|
version: 7.2.0
|
||||||
description: Easy JSON to Object serialization and deserialization in Dart.
|
description: Easy JSON to Object serialization and deserialization in Dart.
|
||||||
homepage: https://github.com/dart-backend/belatuk-common-utilities/tree/main/packages/json_serializer
|
homepage: https://github.com/dart-backend/belatuk-common-utilities/tree/main/packages/json_serializer
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=2.17.0 <3.0.0'
|
sdk: '>=3.3.0 <4.0.0'
|
||||||
dependencies:
|
dependencies:
|
||||||
logging: ^1.0.1
|
logging: ^1.0.1
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
stack_trace: ^1.10.0
|
stack_trace: ^1.10.0
|
||||||
test: ^1.17.4
|
test: ^1.24.0
|
||||||
lints: ^2.0.0
|
lints: ^4.0.0
|
|
@ -105,11 +105,11 @@ testDeserializationWithSchemaValidation() async {
|
||||||
god.deserialize(babelRcJson, outputType: BabelRc) as BabelRc;
|
god.deserialize(babelRcJson, outputType: BabelRc) as BabelRc;
|
||||||
|
|
||||||
print(deserialized.presets.runtimeType);
|
print(deserialized.presets.runtimeType);
|
||||||
expect(deserialized.presets is List, equals(true));
|
//expect(deserialized.presets is List, equals(true));
|
||||||
expect(deserialized.presets.length, equals(2));
|
expect(deserialized.presets.length, equals(2));
|
||||||
expect(deserialized.presets[0], equals('es2015'));
|
expect(deserialized.presets[0], equals('es2015'));
|
||||||
expect(deserialized.presets[1], equals('stage-0'));
|
expect(deserialized.presets[1], equals('stage-0'));
|
||||||
expect(deserialized.plugins is List, equals(true));
|
//expect(deserialized.plugins is List, equals(true));
|
||||||
expect(deserialized.plugins.length, equals(1));
|
expect(deserialized.plugins.length, equals(1));
|
||||||
expect(deserialized.plugins[0], equals('add-module-exports'));
|
expect(deserialized.plugins[0], equals('add-module-exports'));
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,14 +11,14 @@ void printRecord(LogRecord rec) {
|
||||||
class SampleNestedClass {
|
class SampleNestedClass {
|
||||||
String? bar;
|
String? bar;
|
||||||
|
|
||||||
SampleNestedClass([String? this.bar]);
|
SampleNestedClass([this.bar]);
|
||||||
}
|
}
|
||||||
|
|
||||||
class SampleClass {
|
class SampleClass {
|
||||||
String? hello;
|
String? hello;
|
||||||
List<SampleNestedClass> nested = [];
|
List<SampleNestedClass> nested = [];
|
||||||
|
|
||||||
SampleClass([String? this.hello]);
|
SampleClass([this.hello]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@WithSchemaUrl(
|
@WithSchemaUrl(
|
||||||
|
@ -27,25 +27,23 @@ class BabelRc {
|
||||||
List<String> presets;
|
List<String> presets;
|
||||||
List<String> plugins;
|
List<String> plugins;
|
||||||
|
|
||||||
BabelRc(
|
BabelRc({this.presets = const [], this.plugins = const []});
|
||||||
{List<String> this.presets: const [],
|
|
||||||
List<String> this.plugins: const []});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@WithSchema(const {
|
@WithSchema({
|
||||||
r"$schema": "http://json-schema.org/draft-04/schema#",
|
r"$schema": "http://json-schema.org/draft-04/schema#",
|
||||||
"title": "Validated Sample Class",
|
"title": "Validated Sample Class",
|
||||||
"description": "Sample schema for validation via JSON God",
|
"description": "Sample schema for validation via JSON God",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"hello": const {"description": "A friendly greeting.", "type": "string"},
|
"hello": {"description": "A friendly greeting.", "type": "string"},
|
||||||
"nested": const {
|
"nested": {
|
||||||
"description": "A list of NestedSampleClass items within this instance.",
|
"description": "A list of NestedSampleClass items within this instance.",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": const {
|
"items": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"bar": const {"description": "Filler text", "type": "string"}
|
"bar": {"description": "Filler text", "type": "string"}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": const ["hello", "nested"]
|
"required": ["hello", "nested"]
|
||||||
})
|
})
|
||||||
class ValidatedSampleClass {}
|
class ValidatedSampleClass {}
|
||||||
|
|
|
@ -8,7 +8,7 @@ main() {
|
||||||
test('fromJson', () {
|
test('fromJson', () {
|
||||||
var foo = god.deserialize('{"bar":"baz"}', outputType: Foo) as Foo;
|
var foo = god.deserialize('{"bar":"baz"}', outputType: Foo) as Foo;
|
||||||
|
|
||||||
expect(foo is Foo, true);
|
//expect(foo is Foo, true);
|
||||||
expect(foo.text, equals('baz'));
|
expect(foo.text, equals('baz'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,22 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 5.2.0
|
||||||
|
|
||||||
|
* Require Dart >= 3.3
|
||||||
|
* Updated `lints` to 4.0.0
|
||||||
|
|
||||||
|
## 5.1.0
|
||||||
|
|
||||||
|
* Updated `lints` to 3.0.0
|
||||||
|
|
||||||
|
## 5.0.0
|
||||||
|
|
||||||
|
* Require Dart >= 3.0
|
||||||
|
|
||||||
|
## 5.0.0-beta.1
|
||||||
|
|
||||||
|
* Require Dart >= 3.0
|
||||||
|
|
||||||
## 4.0.0
|
## 4.0.0
|
||||||
|
|
||||||
* Require Dart >= 2.17
|
* Require Dart >= 2.17
|
||||||
|
|
|
@ -7,8 +7,7 @@
|
||||||
**Replacement of `package:merge_map` with breaking changes to support NNBD.**
|
**Replacement of `package:merge_map` with breaking changes to support NNBD.**
|
||||||
|
|
||||||
Combine multiple Maps into one. Equivalent to
|
Combine multiple Maps into one. Equivalent to
|
||||||
[Object.assign](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
|
[Object.assign](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) in JS.
|
||||||
in JS.
|
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
name: belatuk_merge_map
|
name: belatuk_merge_map
|
||||||
version: 4.0.0
|
version: 5.2.0
|
||||||
description: Combine multiple Maps into one. Equivalent to Object.assign in JS.
|
description: Combine multiple Maps into one. Equivalent to Object.assign in JS.
|
||||||
homepage: https://github.com/dart-backend/belatuk-common-utilities/tree/main/packages/merge_map
|
homepage: https://github.com/dart-backend/belatuk-common-utilities/tree/main/packages/merge_map
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=2.17.0 <3.0.0'
|
sdk: '>=3.3.0 <4.0.0'
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
test: ^1.17.4
|
test: ^1.24.0
|
||||||
lints: ^2.0.0
|
lints: ^4.0.0
|
||||||
|
|
|
@ -3,8 +3,7 @@ Primary Authors
|
||||||
|
|
||||||
* __[Thomas Hii](dukefirehawk.apps@gmail.com)__
|
* __[Thomas Hii](dukefirehawk.apps@gmail.com)__
|
||||||
|
|
||||||
Thomas is the current maintainer of the code base. He has refactored and migrated the
|
Thomas is the current maintainer of the code base. He has refactored and migrated the code base to support NNBD.
|
||||||
code base to support NNBD.
|
|
||||||
|
|
||||||
* __[Tobe O](thosakwe@gmail.com)__
|
* __[Tobe O](thosakwe@gmail.com)__
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,22 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 6.2.0
|
||||||
|
|
||||||
|
* Require Dart >= 3.3
|
||||||
|
* Updated `lints` to 4.0.0
|
||||||
|
|
||||||
|
## 6.1.0
|
||||||
|
|
||||||
|
* Updated `lints` to 3.0.0
|
||||||
|
|
||||||
|
## 6.0.0
|
||||||
|
|
||||||
|
* Require Dart >= 3.0
|
||||||
|
|
||||||
|
## 6.0.0-beta.1
|
||||||
|
|
||||||
|
* Require Dart >= 3.0
|
||||||
|
|
||||||
## 5.0.0
|
## 5.0.0
|
||||||
|
|
||||||
* Require Dart >= 2.17
|
* Require Dart >= 2.17
|
||||||
|
|
|
@ -15,7 +15,7 @@ In your `pubspec.yaml`:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
dependencies:
|
dependencies:
|
||||||
belatuk_pretty_logging: ^5.0.0
|
belatuk_pretty_logging: ^6.1.0
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
name: belatuk_pretty_logging
|
name: belatuk_pretty_logging
|
||||||
version: 5.0.0
|
version: 6.2.0
|
||||||
description: Standalone helper for colorful logging output, using pkg:io AnsiCode.
|
description: Standalone helper for colorful logging output, using pkg:io AnsiCode.
|
||||||
homepage: https://github.com/dart-backend/belatuk-common-utilities/tree/main/packages/pretty_logging
|
homepage: https://github.com/dart-backend/belatuk-common-utilities/tree/main/packages/pretty_logging
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=2.17.0 <3.0.0'
|
sdk: '>=3.3.0 <4.0.0'
|
||||||
dependencies:
|
dependencies:
|
||||||
io: ^1.0.0
|
io: ^1.0.0
|
||||||
logging: ^1.0.1
|
logging: ^1.0.1
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
lints: ^2.0.0
|
test: ^1.24.0
|
||||||
|
lints: ^4.0.0
|
||||||
|
|
8
packages/pretty_logging/test/all_test.dart
Normal file
8
packages/pretty_logging/test/all_test.dart
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
test('test', () {
|
||||||
|
var message = "Testing";
|
||||||
|
expect(message, equals('Testing'));
|
||||||
|
});
|
||||||
|
}
|
|
@ -1,5 +1,27 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 6.3.0
|
||||||
|
|
||||||
|
* Require Dart >= 3.3
|
||||||
|
* Updated `lints` to 4.0.0
|
||||||
|
|
||||||
|
## 6.2.0
|
||||||
|
|
||||||
|
* Updated `lints` to 3.0.0
|
||||||
|
* Refactored encode/decode message handling into `MessageHandler`
|
||||||
|
|
||||||
|
## 6.1.0
|
||||||
|
|
||||||
|
* Updated `uuid` to 4.0.0
|
||||||
|
|
||||||
|
## 6.0.0
|
||||||
|
|
||||||
|
* Require Dart >= 3.0
|
||||||
|
|
||||||
|
## 6.0.0-beta.1
|
||||||
|
|
||||||
|
* Require Dart >= 3.0
|
||||||
|
|
||||||
## 5.0.0
|
## 5.0.0
|
||||||
|
|
||||||
* Require Dart >= 2.17
|
* Require Dart >= 2.17
|
||||||
|
|
|
@ -14,25 +14,21 @@ Add `belatuk_pub_sub` as a dependency in your `pubspec.yaml` file:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
dependencies:
|
dependencies:
|
||||||
belatuk_pub_sub: ^5.0.0
|
belatuk_pub_sub: ^6.2.0
|
||||||
```
|
```
|
||||||
|
|
||||||
Then, be sure to run `pub get` in your terminal.
|
Then, be sure to run `dart pub get` in your terminal.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
`belatuk_pub_sub` is your typical pub/sub API. However, `belatuk_pub_sub` enforces authentication of every
|
`belatuk_pub_sub` is your typical pub/sub API. However, `belatuk_pub_sub` enforces authentication of every
|
||||||
request. It is very possible that `belatuk_pub_sub` will run on both servers and in the browser,
|
request. It is very possible that `belatuk_pub_sub` will run on both server and in the browser,
|
||||||
or on a platform belatuk_pub_sublike Flutter. Thus, there are provisions available to limit
|
or on a platform like Flutter.
|
||||||
access.
|
|
||||||
|
|
||||||
**Be careful to not leak any `belatuk_pub_sub` client ID's if operating over a network.**
|
**Be careful to not leak any `belatuk_pub_sub` client ID's if operating over a network.**
|
||||||
If you do, you risk malicious users injecting events into your application, which
|
If you do, you run the risk of malicious users injecting events into your application.
|
||||||
could ultimately spell *disaster*.
|
|
||||||
|
|
||||||
A `belatuk_pub_sub` server can operate across multiple *adapters*, which take care of interfacing data over different
|
A `belatuk_pub_sub` server can operate across multiple *adapters*, which take care of interfacing data over different media. For example, a single server can handle pub/sub between multiple Isolates and TCP Sockets, as well as WebSockets, simultaneously.
|
||||||
media. For example, a single server can handle pub/sub between multiple Isolates and TCP Sockets, as well as
|
|
||||||
WebSockets, simultaneously.
|
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
import 'package:belatuk_pub_sub/belatuk_pub_sub.dart' as pub_sub;
|
import 'package:belatuk_pub_sub/belatuk_pub_sub.dart' as pub_sub;
|
||||||
|
@ -52,13 +48,7 @@ main() async {
|
||||||
|
|
||||||
### Trusted Clients
|
### Trusted Clients
|
||||||
|
|
||||||
You can use `package:belatuk_pub_sub` without explicitly registering
|
You can use `package:belatuk_pub_sub` without explicitly registering clients, *if and only if* those clients come from trusted sources. Clients via `Isolate` are always trusted. Clients via `package:json_rpc_2` must be explicitly marked as trusted (i.e. using an IP whitelist mechanism):
|
||||||
clients, *if and only if* those clients come from trusted sources.
|
|
||||||
|
|
||||||
Clients via `Isolate` are always trusted.
|
|
||||||
|
|
||||||
Clients via `package:json_rpc_2` must be explicitly marked
|
|
||||||
as trusted (i.e. using an IP whitelist mechanism):
|
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
JsonRpc2Adapter(..., isTrusted: false);
|
JsonRpc2Adapter(..., isTrusted: false);
|
||||||
|
@ -70,9 +60,7 @@ pub_sub.IsolateClient(null);
|
||||||
### Access Control
|
### Access Control
|
||||||
|
|
||||||
The ID's of all *untrusted* clients who will connect to the server must be known at start-up time.
|
The ID's of all *untrusted* clients who will connect to the server must be known at start-up time.
|
||||||
You may not register new clients after the server has started. This is mostly a security consideration;
|
You may not register new clients after the server has started. This is mostly a security consideration, to make it impossible to register new clients, thus preventing malicious users from granting themselves additional privileges within the system.
|
||||||
if it is impossible to register new clients, then malicious users cannot grant themselves additional
|
|
||||||
privileges within the system.
|
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
import 'package:belatuk_pub_sub/belatuk_pub_sub.dart' as pub_sub;
|
import 'package:belatuk_pub_sub/belatuk_pub_sub.dart' as pub_sub;
|
||||||
|
@ -96,10 +84,7 @@ void main() async {
|
||||||
|
|
||||||
### Isolates
|
### Isolates
|
||||||
|
|
||||||
If you are just running multiple instances of a server,
|
If you are just running multiple instances of a server, use `package:belatuk_pub_sub/isolate.dart`. You'll need one isolate to be the master. Typically this is the first isolate you create.
|
||||||
use `package:belatuk_pub_sub/isolate.dart`.
|
|
||||||
|
|
||||||
You'll need one isolate to be the master. Typically this is the first isolate you create.
|
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
@ -157,9 +142,7 @@ Check out `test/json_rpc_2_test.dart` for an example of serving `belatuk_pub_sub
|
||||||
|
|
||||||
## Protocol
|
## Protocol
|
||||||
|
|
||||||
`belatuk_pub_sub` is built upon a simple RPC, and this package includes
|
`belatuk_pub_sub` is built upon a simple RPC, and this package includes an implementation that runs via `SendPort`s and `ReceivePort`s, as well as one that runs on any `StreamChannel<String>`.
|
||||||
an implementation that runs via `SendPort`s and `ReceivePort`s, as
|
|
||||||
well as one that runs on any `StreamChannel<String>`.
|
|
||||||
|
|
||||||
Data sent over the wire looks like the following:
|
Data sent over the wire looks like the following:
|
||||||
|
|
||||||
|
@ -219,14 +202,11 @@ In the case of Isolate clients/servers, events will be simply sent as Lists:
|
||||||
['<event-name>', value]
|
['<event-name>', value]
|
||||||
```
|
```
|
||||||
|
|
||||||
Clients can send the following (3) methods:
|
Clients can send with the following 3 methods:
|
||||||
|
|
||||||
* `subscribe` (`event_name`:string): Subscribe to an event.
|
* `subscribe` (`event_name`:string): Subscribe to an event.
|
||||||
* `unsubscribe` (`subscription_id`:string): Unsubscribe from an event you previously subscribed to.
|
* `unsubscribe` (`subscription_id`:string): Unsubscribe from an event you previously subscribed to.
|
||||||
* `publish` (`event_name`:string, `value`:any): Publish an event to all other clients who are subscribed.
|
* `publish` (`event_name`:string, `value`:any): Publish an event to all other clients who are subscribed.
|
||||||
|
|
||||||
The client and server in `package:belatuk_pub_sub/isolate.dart` must make extra
|
The client and server in `package:belatuk_pub_sub/isolate.dart` must make extra provisions to keep track of client ID's. Since `SendPort`s and `ReceivePort`s do not have any sort of guaranteed-unique ID's, new clients must send their `SendPort` to the server before sending any requests. The server then responds
|
||||||
provisions to keep track of client ID's. Since `SendPort`s and `ReceivePort`s
|
|
||||||
do not have any sort of guaranteed-unique ID's, new clients must send their
|
|
||||||
`SendPort` to the server before sending any requests. The server then responds
|
|
||||||
with an `id` that must be used to identify a `SendPort` to send a response to.
|
with an `id` that must be used to identify a `SendPort` to send a response to.
|
||||||
|
|
|
@ -1,19 +1,20 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:isolate';
|
import 'dart:isolate';
|
||||||
import 'package:belatuk_pub_sub/isolate.dart' as pub_sub;
|
import 'package:belatuk_pub_sub/isolate.dart';
|
||||||
import 'package:belatuk_pub_sub/belatuk_pub_sub.dart' as pub_sub;
|
import 'package:belatuk_pub_sub/belatuk_pub_sub.dart';
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
// Easily bring up a server.
|
// Easily bring up a server.
|
||||||
var adapter = pub_sub.IsolateAdapter();
|
var adapter = IsolateAdapter();
|
||||||
var server = pub_sub.Server([adapter]);
|
var server = Server([adapter]);
|
||||||
|
|
||||||
// You then need to create a client that will connect to the adapter.
|
// You then need to create a client that will connect to the adapter.
|
||||||
// Every untrusted client in your application should be pre-registered.
|
// Every untrusted client in your application should be pre-registered.
|
||||||
//
|
//
|
||||||
// In the case of Isolates, however, those are always implicitly trusted.
|
// In the case of Isolates, however, those are always implicitly trusted.
|
||||||
|
print("Register Client");
|
||||||
for (var i = 0; i < Platform.numberOfProcessors - 1; i++) {
|
for (var i = 0; i < Platform.numberOfProcessors - 1; i++) {
|
||||||
server.registerClient(pub_sub.ClientInfo('client$i'));
|
server.registerClient(ClientInfo('client$i'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the server.
|
// Start the server.
|
||||||
|
@ -22,6 +23,7 @@ void main() async {
|
||||||
// Next, let's start isolates that interact with the server.
|
// Next, let's start isolates that interact with the server.
|
||||||
//
|
//
|
||||||
// Fortunately, we can send SendPorts over Isolates, so this is no hassle.
|
// Fortunately, we can send SendPorts over Isolates, so this is no hassle.
|
||||||
|
print("Create Isolate");
|
||||||
for (var i = 0; i < Platform.numberOfProcessors - 1; i++) {
|
for (var i = 0; i < Platform.numberOfProcessors - 1; i++) {
|
||||||
await Isolate.spawn(isolateMain, [i, adapter.receivePort.sendPort]);
|
await Isolate.spawn(isolateMain, [i, adapter.receivePort.sendPort]);
|
||||||
}
|
}
|
||||||
|
@ -32,7 +34,7 @@ void main() async {
|
||||||
|
|
||||||
void isolateMain(List args) {
|
void isolateMain(List args) {
|
||||||
// Isolates are always trusted, so technically we don't need to pass a client iD.
|
// Isolates are always trusted, so technically we don't need to pass a client iD.
|
||||||
var client = pub_sub.IsolateClient('client${args[0]}', args[1] as SendPort);
|
var client = IsolateClient('client${args[0]}', args[1] as SendPort);
|
||||||
|
|
||||||
// The client will connect automatically. In the meantime, we can start subscribing to events.
|
// The client will connect automatically. In the meantime, we can start subscribing to events.
|
||||||
client.subscribe('user::logged_in').then((sub) {
|
client.subscribe('user::logged_in').then((sub) {
|
||||||
|
|
|
@ -2,7 +2,9 @@ import 'dart:async';
|
||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
import 'dart:isolate';
|
import 'dart:isolate';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
import '../../belatuk_pub_sub.dart';
|
|
||||||
|
import '../protocol/protocol.dart';
|
||||||
|
import 'shared.dart';
|
||||||
|
|
||||||
/// A [Client] implementation that communicates via [SendPort]s and [ReceivePort]s.
|
/// A [Client] implementation that communicates via [SendPort]s and [ReceivePort]s.
|
||||||
class IsolateClient extends Client {
|
class IsolateClient extends Client {
|
||||||
|
@ -29,33 +31,39 @@ class IsolateClient extends Client {
|
||||||
IsolateClient(String? clientId, this.serverSendPort) {
|
IsolateClient(String? clientId, this.serverSendPort) {
|
||||||
_clientId = clientId;
|
_clientId = clientId;
|
||||||
receivePort.listen((data) {
|
receivePort.listen((data) {
|
||||||
if (data is Map && data['request_id'] is String) {
|
if (data is Map<String, Object?>) {
|
||||||
var requestId = data['request_id'] as String?;
|
var (status, id, requestId, result, errorMessage) =
|
||||||
|
MessageHandler().decodeResponseMessage(data);
|
||||||
|
|
||||||
|
if (requestId != null) {
|
||||||
|
//var requestId = data['request_id'] as String?;
|
||||||
var c = _requests.remove(requestId);
|
var c = _requests.remove(requestId);
|
||||||
|
|
||||||
if (c != null && !c.isCompleted) {
|
if (c != null && !c.isCompleted) {
|
||||||
if (data['status'] is! bool) {
|
//if (data['status'] is! bool) {
|
||||||
c.completeError(
|
// c.completeError(
|
||||||
FormatException('The server sent an invalid response.'));
|
// FormatException('The server sent an invalid response.'));
|
||||||
} else if (!(data['status'] as bool)) {
|
//} else if (!(data['status'] as bool)) {
|
||||||
c.completeError(PubSubException(data['error_message']?.toString() ??
|
if (!status) {
|
||||||
|
c.completeError(PubSubException(errorMessage ??
|
||||||
'The server sent a failure response, but did not provide an error message.'));
|
'The server sent a failure response, but did not provide an error message.'));
|
||||||
} else if (data['result'] is! Map) {
|
} else if (result is! Map) {
|
||||||
c.completeError(FormatException(
|
c.completeError(FormatException(
|
||||||
'The server sent a success response, but did not include a result.'));
|
'The server sent a success response, but did not include a result.'));
|
||||||
} else {
|
} else {
|
||||||
c.complete(data['result'] as Map?);
|
c.complete(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (data is Map && data['id'] is String && _id == null) {
|
} else if (id != null && _id == null) {
|
||||||
_id = data['id'] as String?;
|
_id = id;
|
||||||
|
|
||||||
for (var c in _onConnect) {
|
for (var c in _onConnect) {
|
||||||
if (!c.isCompleted) c.complete(_id);
|
if (!c.isCompleted) c.complete(_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onConnect.clear();
|
_onConnect.clear();
|
||||||
} else if (data is List && data.length == 2 && data[0] is String) {
|
}
|
||||||
|
} else if (data is List) {
|
||||||
var eventName = data[0] as String;
|
var eventName = data[0] as String;
|
||||||
var event = data[1];
|
var event = data[1];
|
||||||
for (var s in _subscriptions.where((s) => s.eventName == eventName)) {
|
for (var s in _subscriptions.where((s) => s.eventName == eventName)) {
|
||||||
|
@ -82,18 +90,13 @@ class IsolateClient extends Client {
|
||||||
var c = Completer<Map>();
|
var c = Completer<Map>();
|
||||||
var requestId = _uuid.v4();
|
var requestId = _uuid.v4();
|
||||||
_requests[requestId] = c;
|
_requests[requestId] = c;
|
||||||
serverSendPort.send({
|
serverSendPort.send(MessageHandler().encodePublishRequestMessage(
|
||||||
'id': _id,
|
_id, requestId, clientId, eventName, value));
|
||||||
'request_id': requestId,
|
|
||||||
'method': 'publish',
|
|
||||||
'params': {
|
|
||||||
'client_id': clientId,
|
|
||||||
'event_name': eventName,
|
|
||||||
'value': value
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return c.future.then((result) {
|
return c.future.then((result) {
|
||||||
_clientId = result['client_id'] as String?;
|
var (_, clientId) = MessageHandler()
|
||||||
|
.decodePublishResponseMessage(result as Map<String, Object?>);
|
||||||
|
_clientId = clientId;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -104,16 +107,14 @@ class IsolateClient extends Client {
|
||||||
var c = Completer<Map>();
|
var c = Completer<Map>();
|
||||||
var requestId = _uuid.v4();
|
var requestId = _uuid.v4();
|
||||||
_requests[requestId] = c;
|
_requests[requestId] = c;
|
||||||
serverSendPort.send({
|
serverSendPort.send(MessageHandler().encodeSubscriptionRequestMessage(
|
||||||
'id': _id,
|
_id, requestId, clientId, eventName));
|
||||||
'request_id': requestId,
|
|
||||||
'method': 'subscribe',
|
|
||||||
'params': {'client_id': clientId, 'event_name': eventName}
|
|
||||||
});
|
|
||||||
return c.future.then<ClientSubscription>((result) {
|
return c.future.then<ClientSubscription>((result) {
|
||||||
_clientId = result['client_id'] as String?;
|
var (subcriptionId, clientId) = MessageHandler()
|
||||||
var s = _IsolateClientSubscription(
|
.decodeSubscriptionResponseMessage(result as Map<String, Object?>);
|
||||||
eventName, result['subscription_id'] as String?, this);
|
_clientId = clientId;
|
||||||
|
var s = _IsolateClientSubscription(eventName, subcriptionId, this);
|
||||||
_subscriptions.add(s);
|
_subscriptions.add(s);
|
||||||
return s;
|
return s;
|
||||||
});
|
});
|
||||||
|
@ -171,14 +172,11 @@ class _IsolateClientSubscription extends ClientSubscription {
|
||||||
var c = Completer<Map>();
|
var c = Completer<Map>();
|
||||||
var requestId = client._uuid.v4();
|
var requestId = client._uuid.v4();
|
||||||
client._requests[requestId] = c;
|
client._requests[requestId] = c;
|
||||||
client.serverSendPort.send({
|
client.serverSendPort.send(MessageHandler()
|
||||||
'id': client._id,
|
.encodeUnsubscriptionRequestMessage(
|
||||||
'request_id': requestId,
|
client._id, requestId, client.clientId, id));
|
||||||
'method': 'unsubscribe',
|
|
||||||
'params': {'client_id': client.clientId, 'subscription_id': id}
|
|
||||||
});
|
|
||||||
|
|
||||||
return c.future.then((_) {
|
return c.future.then((result) {
|
||||||
_close();
|
_close();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:isolate';
|
import 'dart:isolate';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
import '../../belatuk_pub_sub.dart';
|
import '../protocol/protocol.dart';
|
||||||
|
import 'shared.dart';
|
||||||
|
|
||||||
/// A [Adapter] implementation that communicates via [SendPort]s and [ReceivePort]s.
|
/// A [Adapter] implementation that communicates via [SendPort]s and [ReceivePort]s.
|
||||||
class IsolateAdapter extends Adapter {
|
class IsolateAdapter extends Adapter {
|
||||||
|
@ -42,81 +43,50 @@ class IsolateAdapter extends Adapter {
|
||||||
if (data is SendPort) {
|
if (data is SendPort) {
|
||||||
var id = _uuid.v4();
|
var id = _uuid.v4();
|
||||||
_clients[id] = data;
|
_clients[id] = data;
|
||||||
data.send({'status': true, 'id': id});
|
data.send(MessageHandler().encodeSendPortResponseMessage(id));
|
||||||
} else if (data is Map &&
|
} else if (data is Map<String, Object?>) {
|
||||||
data['id'] is String &&
|
var (id, method, requestId, params) =
|
||||||
data['request_id'] is String &&
|
MessageHandler().decodeRequestMessage(data);
|
||||||
data['method'] is String &&
|
var (clientId, eventName, subscriptionId, value) =
|
||||||
data['params'] is Map) {
|
MessageHandler().decodeRequestParams(params);
|
||||||
var id = data['id'] as String?,
|
|
||||||
requestId = data['request_id'] as String?,
|
|
||||||
method = data['method'] as String?;
|
|
||||||
var params = data['params'] as Map?;
|
|
||||||
var sp = _clients[id!];
|
|
||||||
|
|
||||||
|
var sp = _clients[id];
|
||||||
if (sp == null) {
|
if (sp == null) {
|
||||||
// There's nobody to respond to, so don't send anything to anyone. Oops.
|
// There's nobody to respond to, so don't send anything to anyone
|
||||||
} else if (method == 'publish') {
|
return;
|
||||||
if (_isValidClientId(params!['client_id']) &&
|
}
|
||||||
params['event_name'] is String &&
|
|
||||||
params.containsKey('value')) {
|
if (method == 'publish') {
|
||||||
var clientId = params['client_id'] as String?,
|
if (eventName == null || value == null) {
|
||||||
eventName = params['event_name'] as String?;
|
sp.send(MessageHandler().encodePublishResponseError(requestId));
|
||||||
var value = params['value'];
|
}
|
||||||
var rq = _IsolatePublishRequestImpl(
|
var rq = _IsolatePublishRequestImpl(
|
||||||
requestId, clientId, eventName, value, sp);
|
requestId, clientId, eventName, value, sp);
|
||||||
_onPublish.add(rq);
|
_onPublish.add(rq);
|
||||||
} else {
|
|
||||||
sp.send({
|
|
||||||
'status': false,
|
|
||||||
'request_id': requestId,
|
|
||||||
'error_message': 'Expected client_id, event_name, and value.'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else if (method == 'subscribe') {
|
} else if (method == 'subscribe') {
|
||||||
if (_isValidClientId(params!['client_id']) &&
|
if (eventName == null) {
|
||||||
params['event_name'] is String) {
|
sp.send(
|
||||||
var clientId = params['client_id'] as String?,
|
MessageHandler().encodeSubscriptionResponseError(requestId));
|
||||||
eventName = params['event_name'] as String?;
|
}
|
||||||
var rq = _IsolateSubscriptionRequestImpl(
|
var rq = _IsolateSubscriptionRequestImpl(
|
||||||
clientId, eventName, sp, requestId, _uuid);
|
clientId, eventName, sp, requestId, _uuid);
|
||||||
_onSubscribe.add(rq);
|
_onSubscribe.add(rq);
|
||||||
} else {
|
|
||||||
sp.send({
|
|
||||||
'status': false,
|
|
||||||
'request_id': requestId,
|
|
||||||
'error_message': 'Expected client_id, and event_name.'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else if (method == 'unsubscribe') {
|
} else if (method == 'unsubscribe') {
|
||||||
if (_isValidClientId(params!['client_id']) &&
|
if (subscriptionId == null) {
|
||||||
params['subscription_id'] is String) {
|
sp.send(
|
||||||
var clientId = params['client_id'] as String?,
|
MessageHandler().encodeUnsubscriptionResponseError(requestId));
|
||||||
subscriptionId = params['subscription_id'] as String?;
|
}
|
||||||
var rq = _IsolateUnsubscriptionRequestImpl(
|
var rq = _IsolateUnsubscriptionRequestImpl(
|
||||||
clientId, subscriptionId, sp, requestId);
|
clientId, subscriptionId, sp, requestId);
|
||||||
_onUnsubscribe.add(rq);
|
_onUnsubscribe.add(rq);
|
||||||
} else {
|
} else {
|
||||||
sp.send({
|
sp.send(MessageHandler()
|
||||||
'status': false,
|
.encodeUnknownMethodResponseError(requestId, method));
|
||||||
'request_id': requestId,
|
|
||||||
'error_message': 'Expected client_id, and subscription_id.'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sp.send({
|
|
||||||
'status': false,
|
|
||||||
'request_id': requestId,
|
|
||||||
'error_message':
|
|
||||||
'Unrecognized method "$method". Or, you omitted id, request_id, method, or params.'
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _isValidClientId(id) => id == null || id is String;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool isTrustedPublishRequest(PublishRequest request) {
|
bool isTrustedPublishRequest(PublishRequest request) {
|
||||||
// Isolate clients are considered trusted, because they are
|
// Isolate clients are considered trusted, because they are
|
||||||
|
@ -138,7 +108,7 @@ class _IsolatePublishRequestImpl extends PublishRequest {
|
||||||
final String? eventName;
|
final String? eventName;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final dynamic value;
|
final Object? value;
|
||||||
|
|
||||||
final SendPort sendPort;
|
final SendPort sendPort;
|
||||||
|
|
||||||
|
@ -148,24 +118,15 @@ class _IsolatePublishRequestImpl extends PublishRequest {
|
||||||
this.requestId, this.clientId, this.eventName, this.value, this.sendPort);
|
this.requestId, this.clientId, this.eventName, this.value, this.sendPort);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void accept(PublishResponse response) {
|
void reject(String errorMessage) {
|
||||||
sendPort.send({
|
sendPort.send(MessageHandler()
|
||||||
'status': true,
|
.encodePublishResponseError(requestId, errorMessage: errorMessage));
|
||||||
'request_id': requestId,
|
|
||||||
'result': {
|
|
||||||
'listeners': response.listeners,
|
|
||||||
'client_id': response.clientId
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void reject(String errorMessage) {
|
void accept(PublishResponse response) {
|
||||||
sendPort.send({
|
sendPort.send(MessageHandler().encodePublishResponseMessage2(
|
||||||
'status': false,
|
requestId, response.listeners, response.clientId));
|
||||||
'request_id': requestId,
|
|
||||||
'error_message': errorMessage
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,21 +148,15 @@ class _IsolateSubscriptionRequestImpl extends SubscriptionRequest {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void reject(String errorMessage) {
|
void reject(String errorMessage) {
|
||||||
sendPort.send({
|
sendPort.send(MessageHandler().encodeSubscriptionResponseError(requestId,
|
||||||
'status': false,
|
errorMessage: errorMessage));
|
||||||
'request_id': requestId,
|
|
||||||
'error_message': errorMessage
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureOr<Subscription> accept(String? clientId) {
|
FutureOr<Subscription> accept(String? clientId) {
|
||||||
var id = _uuid.v4();
|
var id = _uuid.v4();
|
||||||
sendPort.send({
|
sendPort.send(MessageHandler()
|
||||||
'status': true,
|
.encodeSubscriptionResponseMessage(requestId, id, clientId));
|
||||||
'request_id': requestId,
|
|
||||||
'result': {'subscription_id': id, 'client_id': clientId}
|
|
||||||
});
|
|
||||||
return _IsolateSubscriptionImpl(clientId, id, eventName, sendPort);
|
return _IsolateSubscriptionImpl(clientId, id, eventName, sendPort);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -239,15 +194,13 @@ class _IsolateUnsubscriptionRequestImpl extends UnsubscriptionRequest {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void reject(String errorMessage) {
|
void reject(String errorMessage) {
|
||||||
sendPort.send({
|
sendPort.send(MessageHandler().encodeUnsubscriptionResponseError(requestId,
|
||||||
'status': false,
|
errorMessage: errorMessage));
|
||||||
'request_id': requestId,
|
|
||||||
'error_message': errorMessage
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void accept() {
|
void accept() {
|
||||||
sendPort.send({'status': true, 'request_id': requestId, 'result': {}});
|
sendPort
|
||||||
|
.send(MessageHandler().encodeUnsubscriptionResponseMessage(requestId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
183
packages/pub_sub/lib/src/isolate/shared.dart
Normal file
183
packages/pub_sub/lib/src/isolate/shared.dart
Normal file
|
@ -0,0 +1,183 @@
|
||||||
|
/// A message handler class that handles the encoding/decoding of messages send
|
||||||
|
/// between isolate [Client] and [Server].
|
||||||
|
class MessageHandler {
|
||||||
|
static const _requestId = 'request_id';
|
||||||
|
static const _method = 'method';
|
||||||
|
static const _clientId = 'client_id';
|
||||||
|
static const _eventName = 'event_name';
|
||||||
|
static const _subscriptionId = 'subscription_id';
|
||||||
|
static const _errorMessage = 'error_message';
|
||||||
|
static const _value = 'value';
|
||||||
|
static const _id = 'id';
|
||||||
|
static const _params = 'params';
|
||||||
|
static const _status = 'status';
|
||||||
|
static const _result = 'result';
|
||||||
|
static const _listeners = 'listeners';
|
||||||
|
|
||||||
|
static const _publishErrorMsg = 'Expected client_id, event_name, and value';
|
||||||
|
static const _subscribeErrorMsg = 'Expected client_id, and event_name';
|
||||||
|
static const _unsubscribeErrorMsg = 'Expected client_id, and subscription_id';
|
||||||
|
|
||||||
|
const MessageHandler();
|
||||||
|
|
||||||
|
Map<String, dynamic> encodePublishResponseError(String? requestId,
|
||||||
|
{String errorMessage = _publishErrorMsg}) {
|
||||||
|
return _encodeResponseError(requestId, errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> encodeSubscriptionResponseError(String? requestId,
|
||||||
|
{String errorMessage = _subscribeErrorMsg}) {
|
||||||
|
return _encodeResponseError(requestId, errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> encodeUnsubscriptionResponseError(String? requestId,
|
||||||
|
{String errorMessage = _unsubscribeErrorMsg}) {
|
||||||
|
return _encodeResponseError(requestId, errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> encodeUnknownMethodResponseError(
|
||||||
|
String? requestId, String method) {
|
||||||
|
var unknownMethodErrorMsg =
|
||||||
|
'Unrecognized method "$method" or you have omitted id, request_id, method, or params';
|
||||||
|
|
||||||
|
return _encodeResponseError(requestId, unknownMethodErrorMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> _encodeResponseError(String? requestId, String message) {
|
||||||
|
return {
|
||||||
|
_status: false,
|
||||||
|
_requestId: requestId ?? '',
|
||||||
|
_errorMessage: message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> encodeEventMessage(String? requestId, Object message) {
|
||||||
|
return {_status: true, _requestId: requestId ?? '', _result: message};
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> encodeSubscriptionResponseMessage(
|
||||||
|
String? requestId, String? subscriptionId, String? clientId) {
|
||||||
|
return {
|
||||||
|
_status: true,
|
||||||
|
_requestId: requestId ?? '',
|
||||||
|
_result: {_subscriptionId: subscriptionId, _clientId: clientId}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
(String?, String?) decodeSubscriptionResponseMessage(
|
||||||
|
Map<String, Object?> message) {
|
||||||
|
var subscriptionId = message[_subscriptionId] as String?;
|
||||||
|
var clientId = message[_clientId] as String?;
|
||||||
|
|
||||||
|
return (subscriptionId, clientId);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> encodeUnsubscriptionResponseMessage(String? requestId) {
|
||||||
|
return {_status: true, _requestId: requestId, _result: {}};
|
||||||
|
}
|
||||||
|
|
||||||
|
(bool, String?, Object?, String?) decodeUnsubscriptionResponseMessage(
|
||||||
|
Map<String, Object?> message) {
|
||||||
|
var status = message[_status] as bool? ?? false;
|
||||||
|
var requestId = message[_requestId] as String?;
|
||||||
|
var result = message[_result];
|
||||||
|
var errorMessage = message[_errorMessage] as String?;
|
||||||
|
|
||||||
|
return (status, requestId, result, errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object?> encodePublishResponseMessage2(
|
||||||
|
String? requestId, int listeners, String? clientId) {
|
||||||
|
return {
|
||||||
|
_status: true,
|
||||||
|
_requestId: requestId,
|
||||||
|
_result: {_listeners: listeners, _clientId: clientId}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
(int, String?) decodePublishResponseMessage(Map<String, Object?> message) {
|
||||||
|
var listeners = message[_listeners] as int;
|
||||||
|
var clientId = message[_clientId] as String?;
|
||||||
|
|
||||||
|
return (listeners, clientId);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object?> encodePublishResponseMessage(String? id,
|
||||||
|
String? requestId, String? clientId, String? eventName, Object? value) {
|
||||||
|
return {
|
||||||
|
_id: id,
|
||||||
|
_requestId: requestId,
|
||||||
|
_method: 'publish',
|
||||||
|
_params: {_clientId: clientId, _eventName: eventName, _value: value}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> encodeResponseMessage(
|
||||||
|
String? requestId, Object message) {
|
||||||
|
return {_status: true, _requestId: requestId ?? '', _result: message};
|
||||||
|
}
|
||||||
|
|
||||||
|
(bool, String?, String?, Object?, String?) decodeResponseMessage(
|
||||||
|
Map<String, Object?> message) {
|
||||||
|
var id = message[_id] as String?;
|
||||||
|
var status = message[_status] as bool? ?? false;
|
||||||
|
var requestId = message[_requestId] as String?;
|
||||||
|
var result = message[_result];
|
||||||
|
var errorMessage = message[_errorMessage] as String?;
|
||||||
|
|
||||||
|
return (status, id, requestId, result, errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
(String, String, String, Map<String, Object?>) decodeRequestMessage(
|
||||||
|
Map<String, Object?> message) {
|
||||||
|
var id = message[_id] as String? ?? '';
|
||||||
|
var method = message[_method] as String? ?? '';
|
||||||
|
var requestId = message[_requestId] as String? ?? '';
|
||||||
|
var params = message[_params] as Map<String, Object?>? ?? {};
|
||||||
|
|
||||||
|
return (id, method, requestId, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object?> encodeSubscriptionRequestMessage(
|
||||||
|
String? id, String? requestId, String? clientId, String? eventName) {
|
||||||
|
return {
|
||||||
|
_id: id,
|
||||||
|
_requestId: requestId,
|
||||||
|
_method: 'subscribe',
|
||||||
|
_params: {_clientId: clientId, _eventName: eventName}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object?> encodeUnsubscriptionRequestMessage(
|
||||||
|
String? id, String? requestId, String? clientId, String? subscriptionId) {
|
||||||
|
return {
|
||||||
|
_id: id,
|
||||||
|
_requestId: requestId,
|
||||||
|
_method: 'unsubscribe',
|
||||||
|
_params: {_clientId: clientId, _subscriptionId: subscriptionId}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object?> encodePublishRequestMessage(String? id,
|
||||||
|
String? requestId, String? clientId, String? eventName, Object? value) {
|
||||||
|
return {
|
||||||
|
_id: id,
|
||||||
|
_requestId: requestId,
|
||||||
|
_method: 'publish',
|
||||||
|
_params: {_clientId: clientId, _eventName: eventName, _value: value}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
(String?, String?, String?, Object?) decodeRequestParams(
|
||||||
|
Map<String, Object?> params) {
|
||||||
|
var clientId = params[_clientId] as String?;
|
||||||
|
var eventName = params[_eventName] as String?;
|
||||||
|
var value = params[_value];
|
||||||
|
var subscriptionId = params[_subscriptionId] as String?;
|
||||||
|
return (clientId, eventName, subscriptionId, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> encodeSendPortResponseMessage(String id) {
|
||||||
|
return {_status: true, _id: id};
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ abstract class PublishRequest {
|
||||||
String? get eventName;
|
String? get eventName;
|
||||||
|
|
||||||
/// The value to be published as an event.
|
/// The value to be published as an event.
|
||||||
dynamic get value;
|
Object? get value;
|
||||||
|
|
||||||
/// Accept the request, with a response.
|
/// Accept the request, with a response.
|
||||||
void accept(PublishResponse response);
|
void accept(PublishResponse response);
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
name: belatuk_pub_sub
|
name: belatuk_pub_sub
|
||||||
version: 5.0.0
|
version: 6.3.0
|
||||||
description: Keep application instances in sync with a simple pub/sub API.
|
description: Keep application instances in sync with a simple pub/sub API.
|
||||||
homepage: https://github.com/dart-backend/belatuk-common-utilities/tree/main/packages/pub_sub
|
homepage: https://github.com/dart-backend/belatuk-common-utilities/tree/main/packages/pub_sub
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=2.17.0 <3.0.0'
|
sdk: '>=3.3.0 <4.0.0'
|
||||||
dependencies:
|
dependencies:
|
||||||
json_rpc_2: ^3.0.0
|
json_rpc_2: ^3.0.0
|
||||||
stream_channel: ^2.1.0
|
stream_channel: ^2.1.0
|
||||||
uuid: ^3.0.4
|
uuid: ^4.0.0
|
||||||
collection: ^1.15.0
|
collection: ^1.17.0
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
lints: ^2.0.0
|
test: ^1.24.0
|
||||||
test: ^1.17.4
|
lints: ^4.0.0
|
||||||
|
|
|
@ -157,7 +157,7 @@ class _SocketStreamChannel extends StreamChannelMixin<List<int>> {
|
||||||
Stream<List<int>> get stream => socket;
|
Stream<List<int>> get stream => socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
class _SocketSink extends StreamSink<List<int>> {
|
class _SocketSink implements StreamSink<List<int>> {
|
||||||
final Socket socket;
|
final Socket socket;
|
||||||
|
|
||||||
_SocketSink(this.socket);
|
_SocketSink(this.socket);
|
||||||
|
|
|
@ -1,5 +1,27 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 6.3.0
|
||||||
|
|
||||||
|
* Require Dart >= 3.3
|
||||||
|
* Updated `lints` to 4.0.0
|
||||||
|
|
||||||
|
## 6.2.0
|
||||||
|
|
||||||
|
* Updated `lints` to 3.0.0
|
||||||
|
|
||||||
|
## 6.1.0
|
||||||
|
|
||||||
|
* Updated `file` to 7.0.0
|
||||||
|
|
||||||
|
## 6.0.0
|
||||||
|
|
||||||
|
* Require Dart >= 3.0
|
||||||
|
* Updated all dependencies to latest
|
||||||
|
|
||||||
|
## 6.0.0-beta.1
|
||||||
|
|
||||||
|
* Require Dart >= 3.0
|
||||||
|
|
||||||
## 5.0.0
|
## 5.0.0
|
||||||
|
|
||||||
* Require Dart >= 2.17
|
* Require Dart >= 2.17
|
||||||
|
|
|
@ -14,7 +14,7 @@ In your `pubspec.yaml`:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
dependencies:
|
dependencies:
|
||||||
belatuk_range_header: ^5.0.0
|
belatuk_range_header: ^6.2.0
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
|
@ -15,7 +15,9 @@ void handleRequest(HttpRequest request) async {
|
||||||
// Get info
|
// Get info
|
||||||
header.items;
|
header.items;
|
||||||
header.rangeUnit;
|
header.rangeUnit;
|
||||||
header.items.forEach((item) => item.toContentRange(400));
|
for (var item in header.items) {
|
||||||
|
item.toContentRange(400);
|
||||||
|
}
|
||||||
|
|
||||||
// Serve the file
|
// Serve the file
|
||||||
var transformer =
|
var transformer =
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io' show BytesBuilder;
|
//import 'dart:io' hide BytesBuilder;
|
||||||
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
import 'package:async/async.dart';
|
import 'package:async/async.dart';
|
||||||
import 'package:charcode/ascii.dart';
|
import 'package:charcode/ascii.dart';
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
class RangeHeaderParseException extends FormatException {
|
class RangeHeaderParseException extends FormatException {
|
||||||
@override
|
//@override
|
||||||
final String message;
|
//final String message;
|
||||||
|
|
||||||
RangeHeaderParseException(this.message);
|
RangeHeaderParseException(super.message);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'Range header parse exception: $message';
|
String toString() => 'Range header parse exception: $message';
|
||||||
|
|
|
@ -9,7 +9,7 @@ import 'range_header_item.dart';
|
||||||
final RegExp _rgxInt = RegExp(r'[0-9]+');
|
final RegExp _rgxInt = RegExp(r'[0-9]+');
|
||||||
final RegExp _rgxWs = RegExp(r'[ \n\r\t]');
|
final RegExp _rgxWs = RegExp(r'[ \n\r\t]');
|
||||||
|
|
||||||
enum TokenType { RANGE_UNIT, COMMA, INT, DASH, EQUALS }
|
enum TokenType { rangeUnit, comma, int, dash, equals }
|
||||||
|
|
||||||
class Token {
|
class Token {
|
||||||
final TokenType type;
|
final TokenType type;
|
||||||
|
@ -27,19 +27,19 @@ List<Token> scan(String text, List<String> allowedRangeUnits) {
|
||||||
scanner.scan(_rgxWs);
|
scanner.scan(_rgxWs);
|
||||||
|
|
||||||
if (scanner.scanChar($comma)) {
|
if (scanner.scanChar($comma)) {
|
||||||
tokens.add(Token(TokenType.COMMA, scanner.lastSpan));
|
tokens.add(Token(TokenType.comma, scanner.lastSpan));
|
||||||
} else if (scanner.scanChar($dash)) {
|
} else if (scanner.scanChar($dash)) {
|
||||||
tokens.add(Token(TokenType.DASH, scanner.lastSpan));
|
tokens.add(Token(TokenType.dash, scanner.lastSpan));
|
||||||
} else if (scanner.scan(_rgxInt)) {
|
} else if (scanner.scan(_rgxInt)) {
|
||||||
tokens.add(Token(TokenType.INT, scanner.lastSpan));
|
tokens.add(Token(TokenType.int, scanner.lastSpan));
|
||||||
} else if (scanner.scanChar($equal)) {
|
} else if (scanner.scanChar($equal)) {
|
||||||
tokens.add(Token(TokenType.EQUALS, scanner.lastSpan));
|
tokens.add(Token(TokenType.equals, scanner.lastSpan));
|
||||||
} else {
|
} else {
|
||||||
var matched = false;
|
var matched = false;
|
||||||
|
|
||||||
for (var unit in allowedRangeUnits) {
|
for (var unit in allowedRangeUnits) {
|
||||||
if (scanner.scan(unit)) {
|
if (scanner.scan(unit)) {
|
||||||
tokens.add(Token(TokenType.RANGE_UNIT, scanner.lastSpan));
|
tokens.add(Token(TokenType.rangeUnit, scanner.lastSpan));
|
||||||
matched = true;
|
matched = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -98,9 +98,9 @@ class Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
RangeHeader? parseRangeHeader() {
|
RangeHeader? parseRangeHeader() {
|
||||||
if (next(TokenType.RANGE_UNIT)) {
|
if (next(TokenType.rangeUnit)) {
|
||||||
var unit = current!.span!.text;
|
var unit = current!.span!.text;
|
||||||
next(TokenType.EQUALS); // Consume =, if any.
|
next(TokenType.equals); // Consume =, if any.
|
||||||
|
|
||||||
var items = <RangeHeaderItem>[];
|
var items = <RangeHeaderItem>[];
|
||||||
var item = parseHeaderItem();
|
var item = parseHeaderItem();
|
||||||
|
@ -108,7 +108,7 @@ class Parser {
|
||||||
while (item != null) {
|
while (item != null) {
|
||||||
items.add(item);
|
items.add(item);
|
||||||
// Parse comma
|
// Parse comma
|
||||||
if (next(TokenType.COMMA)) {
|
if (next(TokenType.comma)) {
|
||||||
item = parseHeaderItem();
|
item = parseHeaderItem();
|
||||||
} else {
|
} else {
|
||||||
item = null;
|
item = null;
|
||||||
|
@ -126,11 +126,11 @@ class Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
RangeHeaderItem? parseHeaderItem() {
|
RangeHeaderItem? parseHeaderItem() {
|
||||||
if (next(TokenType.INT)) {
|
if (next(TokenType.int)) {
|
||||||
// i.e 500-544, or 600-
|
// i.e 500-544, or 600-
|
||||||
var start = int.parse(current!.span!.text);
|
var start = int.parse(current!.span!.text);
|
||||||
if (next(TokenType.DASH)) {
|
if (next(TokenType.dash)) {
|
||||||
if (next(TokenType.INT)) {
|
if (next(TokenType.int)) {
|
||||||
return RangeHeaderItem(start, int.parse(current!.span!.text));
|
return RangeHeaderItem(start, int.parse(current!.span!.text));
|
||||||
} else {
|
} else {
|
||||||
return RangeHeaderItem(start);
|
return RangeHeaderItem(start);
|
||||||
|
@ -138,9 +138,9 @@ class Parser {
|
||||||
} else {
|
} else {
|
||||||
throw _expected('"-"');
|
throw _expected('"-"');
|
||||||
}
|
}
|
||||||
} else if (next(TokenType.DASH)) {
|
} else if (next(TokenType.dash)) {
|
||||||
// i.e. -599
|
// i.e. -599
|
||||||
if (next(TokenType.INT)) {
|
if (next(TokenType.int)) {
|
||||||
return RangeHeaderItem(-1, int.parse(current!.span!.text));
|
return RangeHeaderItem(-1, int.parse(current!.span!.text));
|
||||||
} else {
|
} else {
|
||||||
throw _expected('integer');
|
throw _expected('integer');
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
name: belatuk_range_header
|
name: belatuk_range_header
|
||||||
version: 5.0.0
|
version: 6.3.0
|
||||||
description: Range header parser for Dart. Beyond parsing, a stream transformer is included.
|
description: Range header parser for Dart. Beyond parsing, a stream transformer is included.
|
||||||
homepage: https://github.com/dart-backend/belatuk-common-utilities/tree/main/packages/range_header
|
homepage: https://github.com/dart-backend/belatuk-common-utilities/tree/main/packages/range_header
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=2.17.0 <3.0.0'
|
sdk: '>=3.3.0 <4.0.0'
|
||||||
dependencies:
|
dependencies:
|
||||||
async: ^2.6.0
|
async: ^2.11.0
|
||||||
charcode: ^1.2.0
|
charcode: ^1.3.0
|
||||||
quiver: ^3.0.1
|
quiver: ^3.2.0
|
||||||
source_span: ^1.8.1
|
source_span: ^1.10.0
|
||||||
string_scanner: ^1.1.0
|
string_scanner: ^1.2.0
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
file: ^6.1.0
|
file: ^7.0.0
|
||||||
http_parser: ^4.0.0
|
http_parser: ^4.0.0
|
||||||
logging: ^1.0.1
|
logging: ^1.0.1
|
||||||
test: ^1.17.8
|
test: ^1.24.0
|
||||||
lints: ^2.0.0
|
lints: ^4.0.0
|
||||||
|
|
|
@ -1,5 +1,23 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 5.2.0
|
||||||
|
|
||||||
|
* Require Dart >= 3.3
|
||||||
|
* Updated `lints` to 4.0.0
|
||||||
|
|
||||||
|
## 5.1.0
|
||||||
|
|
||||||
|
* Updated `lints` to 3.0.0
|
||||||
|
* Fixed lints warnings
|
||||||
|
|
||||||
|
## 5.0.0
|
||||||
|
|
||||||
|
* Require Dart >= 3.0
|
||||||
|
|
||||||
|
## 5.0.0-beta.1
|
||||||
|
|
||||||
|
* Require Dart >= 3.0
|
||||||
|
|
||||||
## 4.0.0
|
## 4.0.0
|
||||||
|
|
||||||
* Require Dart >= 2.17
|
* Require Dart >= 2.17
|
||||||
|
|
|
@ -12,8 +12,7 @@ and utilize basic memoization to speed up repeated lookups.
|
||||||
|
|
||||||
## Variables
|
## Variables
|
||||||
|
|
||||||
To represent a symbol, use `Variable`. I opted for the name
|
To represent a symbol, use `Variable`. I opted for the name `Variable` to avoid conflict with the Dart primitive `Symbol`.
|
||||||
`Variable` to avoid conflict with the Dart primitive `Symbol`.
|
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
var foo = Variable<String>('foo');
|
var foo = Variable<String>('foo');
|
||||||
|
@ -31,8 +30,7 @@ foo.value = 'baz'; // Also throws a StateError - Once a variable is locked, it c
|
||||||
|
|
||||||
## Visibility
|
## Visibility
|
||||||
|
|
||||||
Variables are *public* by default, but can also be marked as *private* or *protected*. This can be helpful if you are trying
|
Variables are *public* by default, but can also be marked as *private* or *protected*. This can be helpful if you are trying to determine which symbols should be exported from a library or class.
|
||||||
to determine which symbols should be exported from a library or class.
|
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
myVariable.visibility = Visibility.protected;
|
myVariable.visibility = Visibility.protected;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
part of symbol_table;
|
part of 'symbol_table.dart';
|
||||||
|
|
||||||
/// Holds a symbol, the value of which may change or be marked immutable.
|
/// Holds a symbol, the value of which may change or be marked immutable.
|
||||||
class Variable<T> {
|
class Variable<T> {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
part of symbol_table;
|
part of 'symbol_table.dart';
|
||||||
|
|
||||||
/// Represents the visibility of a symbol.
|
/// Represents the visibility of a symbol.
|
||||||
///
|
///
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
name: belatuk_symbol_table
|
name: belatuk_symbol_table
|
||||||
version: 4.0.0
|
version: 5.2.0
|
||||||
description: A generic symbol table implementation in Dart, with support for scopes and constants.
|
description: A generic symbol table implementation in Dart, with support for scopes and constants.
|
||||||
homepage: https://github.com/dart-backend/belatuk-common-utilities/tree/main/packages/symbol_table
|
homepage: https://github.com/dart-backend/belatuk-common-utilities/tree/main/packages/symbol_table
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=2.17.0 <3.0.0'
|
sdk: '>=3.3.0 <4.0.0'
|
||||||
dependencies:
|
dependencies:
|
||||||
collection: ^1.15.0
|
collection: ^1.17.0
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
test: ^1.17.4
|
test: ^1.24.0
|
||||||
lints: ^2.0.0
|
lints: ^4.0.0
|
||||||
|
|
|
@ -1,5 +1,22 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 5.2.0
|
||||||
|
|
||||||
|
* Require Dart >= 3.3
|
||||||
|
* Updated `lints` to 4.0.0
|
||||||
|
|
||||||
|
## 5.1.0
|
||||||
|
|
||||||
|
* Updated `lints` to 3.0.0
|
||||||
|
|
||||||
|
## 5.0.0
|
||||||
|
|
||||||
|
* Require Dart >= 3.0
|
||||||
|
|
||||||
|
## 5.0.0-beta.1
|
||||||
|
|
||||||
|
* Require Dart >= 3.0
|
||||||
|
|
||||||
## 4.0.0
|
## 4.0.0
|
||||||
|
|
||||||
* Require Dart >= 2.17
|
* Require Dart >= 2.17
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
name: user_agent_analyzer
|
name: user_agent_analyzer
|
||||||
version: 4.0.0
|
version: 5.2.0
|
||||||
description: A library to identify the type of devices and web browsers based on User-Agent string.
|
description: A library to identify the type of devices and web browsers based on User-Agent string.
|
||||||
homepage: https://github.com/dart-backend/belatuk-common-utilities/tree/main/packages/user_agent
|
homepage: https://github.com/dart-backend/belatuk-common-utilities/tree/main/packages/user_agent
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=2.17.0 <3.0.0'
|
sdk: '>=3.3.0 <4.0.0'
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
test: ^1.17.8
|
test: ^1.24.0
|
||||||
lints: ^2.0.0
|
lints: ^4.0.0
|
||||||
|
|
6
pubspec.yaml
Normal file
6
pubspec.yaml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
name: belatuk_common_utilities_workspace
|
||||||
|
|
||||||
|
environment:
|
||||||
|
sdk: '>=3.3.0 <4.0.0'
|
||||||
|
dev_dependencies:
|
||||||
|
melos: ^6.0.0
|
Loading…
Reference in a new issue