Skip to content

Commit

Permalink
Merge branch 'main' of github.com:dart-lang/dart-pad into workspace
Browse files Browse the repository at this point in the history
  • Loading branch information
johnpryan committed Jan 14, 2025
2 parents b1b7a84 + 0c2868d commit c6fe61e
Show file tree
Hide file tree
Showing 54 changed files with 1,211 additions and 1,544 deletions.
2 changes: 1 addition & 1 deletion .cloud_build/dart_pad.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
steps:
- name: gcr.io/$PROJECT_ID/flutter:main
args: ['build', 'web']
args: ['build', 'web', '--wasm']
dir: pkgs/dartpad_ui
- name: gcr.io/$PROJECT_ID/firebase
args: ['deploy', '--project=$PROJECT_ID', '--only', 'hosting:dartpad']
Expand Down
1 change: 0 additions & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
**/pubspec.lock linguist-generated=true
pkgs/dart_services/lib/src/shared/** linguist-generated=true
pkgs/dartpad_ui/lib/samples.g.dart linguist-generated=true
pkgs/dartpad_ui/web/codemirror/** linguist-generated=true
4 changes: 2 additions & 2 deletions .github/workflows/dart_services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ jobs:
matrix:
sdk: [stable, beta, main]
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: subosito/flutter-action@74af56c5ed2697ba4621264652728e8d217e53d3
with:
channel: ${{ matrix.sdk }}
- run: flutter --version
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/dartpad_shared.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ jobs:
working-directory: pkgs/dartpad_shared/

steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94

- name: Install dart dependencies
run: dart pub get
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/dartpad_ui.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ jobs:
run:
working-directory: pkgs/dartpad_ui/
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: subosito/flutter-action@74af56c5ed2697ba4621264652728e8d217e53d3
with:
channel: main
- run: flutter --version
Expand Down
14 changes: 14 additions & 0 deletions .github/workflows/health.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: Health
on:
pull_request:
branches: [ main ]
types: [opened, synchronize, reopened, labeled, unlabeled]

jobs:
health:
uses: dart-lang/ecosystem/.github/workflows/health.yaml@main
with:
ignore_license: "**.g.dart"
sdk: dev
permissions:
pull-requests: write
16 changes: 16 additions & 0 deletions .github/workflows/post_summaries.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: Comment on the pull request

on:
# Trigger this workflow after the Health workflow completes. This workflow will have permissions to
# do things like create comments on the PR, even if the original workflow couldn't.
workflow_run:
workflows:
- Health
types:
- completed

jobs:
upload:
uses: dart-lang/ecosystem/.github/workflows/post_summaries.yaml@main
permissions:
pull-requests: write
4 changes: 2 additions & 2 deletions .github/workflows/samples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ jobs:
run:
working-directory: pkgs/samples/
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
- uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: subosito/flutter-action@74af56c5ed2697ba4621264652728e8d217e53d3
- run: flutter pub get
- run: flutter analyze
- run: dart format --set-exit-if-changed .
Expand Down
8 changes: 2 additions & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,6 @@ Contributions made by corporations are covered by a different agreement than the

## How to run DartPad locally

To run the server, see https://github.com/dart-lang/dart-pad/blob/main/pkgs/dart_services/README.md.
To run the server, see the [dart_services readme](https://github.com/dart-lang/dart-pad/blob/main/pkgs/dart_services/README.md).

To run the front-end, from the `pkg/dart-pad` directory, run:

```
dart tool/grind.dart serve
```
To run the front-end, see the [dartpad_ui readme](https://github.com/dart-lang/dart-pad/blob/main/pkgs/dartpad_ui/README.md).
3 changes: 3 additions & 0 deletions pkgs/dart_services/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,6 @@ config.properties
.vscode/

bin/server

# Any local environment variable configuration
.env
30 changes: 23 additions & 7 deletions pkgs/dart_services/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,22 @@ To run tests:

`dart test`

### Re-generating source
### Building storage artifacts

To rebuild the shelf router, run:
Dart services pre-compiles `.dill` files for the Dart SDK and Flutter Web SDK, which
are uploaded to Cloud Storage automatically. These files are located in the
`artifacts/` directory.

If you need to re-generate these files, run the following command.

```
dart run build_runner build --delete-conflicting-outputs
grind build-storage-artifacts
```

Or, if you don't have `grind` on your PATH:

```
dart tool/grind.dart build-storage-artifacts
```

### Modifying supported packages
Expand All @@ -58,11 +68,17 @@ that the dependencies resolve and update the pinned versions specified in the
grind build-project-templates
```

3. Run `pub upgrade` in the Dart or Flutter project in `project_templates/`
4. Run `grind update-pub-dependencies` to overwrite the
Or, if you don't have `grind` on your PATH:
```
dart tool/grind.dart build-project-templates
```
4. Run `pub upgrade` in the Dart or Flutter project in `project_templates/`
5. Run `grind update-pub-dependencies` to overwrite the
`tool/dependencies/pub_dependencies_<CHANNEL>.yaml` file for your current
channel.
5. Repeat the above steps for the latest version of each Flutter channel
channel. Or, if you don't have `grind` on your PATH, `dart tool/grind.dart update-pub-dependencies`
6. Repeat the above steps for the latest version of each Flutter channel
(`main`, `beta` and `stable`)

## Redis
Expand Down
108 changes: 32 additions & 76 deletions pkgs/dart_services/lib/src/common_server.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import 'dart:convert';
import 'dart:io';

import 'package:dartpad_shared/model.dart' as api;
import 'package:google_generative_ai/google_generative_ai.dart' as google_ai;
import 'package:http/http.dart' as http;
import 'package:logging/logging.dart';
import 'package:shelf/shelf.dart';
Expand All @@ -22,8 +21,6 @@ import 'sdk.dart';
import 'shelf_cors.dart' as shelf_cors;
import 'utils.dart';

part 'common_server.g.dart';

const jsonContentType = 'application/json; charset=utf-8';

const apiPrefix = '/api/<apiVersion>';
Expand Down Expand Up @@ -69,17 +66,38 @@ class CommonServerApi {
final CommonServerImpl impl;
final TaskScheduler scheduler = TaskScheduler();

/// The (lazily-constructed) router.
late final Router router = _$CommonServerApiRouter(this);
/// The shelf router.
late final Router router = () {
final router = Router();

// general requests (GET)
router.get(r'/api/<apiVersion>/version', handleVersion);

// general requests (POST)
router.post(r'/api/<apiVersion>/analyze', handleAnalyze);
router.post(r'/api/<apiVersion>/compile', handleCompile);
router.post(r'/api/<apiVersion>/compileDDC', handleCompileDDC);
router.post(r'/api/<apiVersion>/complete', handleComplete);
router.post(r'/api/<apiVersion>/fixes', handleFixes);
router.post(r'/api/<apiVersion>/format', handleFormat);
router.post(r'/api/<apiVersion>/document', handleDocument);
router.post(r'/api/<apiVersion>/openInIDX', handleOpenInIdx);
return router;
}();

CommonServerApi(this.impl);

Future<void> init() => impl.init();

Future<void> shutdown() => impl.shutdown();

@Route.post('$apiPrefix/analyze')
Future<Response> analyze(Request request, String apiVersion) async {
Future<Response> handleVersion(Request request, String apiVersion) async {
if (apiVersion != api3) return unhandledVersion(apiVersion);

return ok(version().toJson());
}

Future<Response> handleAnalyze(Request request, String apiVersion) async {
if (apiVersion != api3) return unhandledVersion(apiVersion);

final sourceRequest =
Expand All @@ -92,8 +110,7 @@ class CommonServerApi {
return ok(result.toJson());
}

@Route.post('$apiPrefix/compile')
Future<Response> compile(Request request, String apiVersion) async {
Future<Response> handleCompile(Request request, String apiVersion) async {
if (apiVersion != api3) return unhandledVersion(apiVersion);

final sourceRequest =
Expand All @@ -110,8 +127,7 @@ class CommonServerApi {
}
}

@Route.post('$apiPrefix/compileDDC')
Future<Response> compileDDC(Request request, String apiVersion) async {
Future<Response> handleCompileDDC(Request request, String apiVersion) async {
if (apiVersion != api3) return unhandledVersion(apiVersion);

final sourceRequest =
Expand All @@ -135,8 +151,7 @@ class CommonServerApi {
}
}

@Route.post('$apiPrefix/complete')
Future<Response> complete(Request request, String apiVersion) async {
Future<Response> handleComplete(Request request, String apiVersion) async {
if (apiVersion != api3) return unhandledVersion(apiVersion);

final sourceRequest =
Expand All @@ -148,8 +163,7 @@ class CommonServerApi {
return ok(result.toJson());
}

@Route.post('$apiPrefix/fixes')
Future<Response> fixes(Request request, String apiVersion) async {
Future<Response> handleFixes(Request request, String apiVersion) async {
if (apiVersion != api3) return unhandledVersion(apiVersion);

final sourceRequest =
Expand All @@ -161,8 +175,7 @@ class CommonServerApi {
return ok(result.toJson());
}

@Route.post('$apiPrefix/format')
Future<Response> format(Request request, String apiVersion) async {
Future<Response> handleFormat(Request request, String apiVersion) async {
if (apiVersion != api3) return unhandledVersion(apiVersion);

final sourceRequest =
Expand All @@ -178,8 +191,7 @@ class CommonServerApi {
return ok(result.toJson());
}

@Route.post('$apiPrefix/document')
Future<Response> document(Request request, String apiVersion) async {
Future<Response> handleDocument(Request request, String apiVersion) async {
if (apiVersion != api3) return unhandledVersion(apiVersion);

final sourceRequest =
Expand All @@ -195,15 +207,7 @@ class CommonServerApi {
return ok(result.toJson());
}

@Route.get('$apiPrefix/version')
Future<Response> versionGet(Request request, String apiVersion) async {
if (apiVersion != api3) return unhandledVersion(apiVersion);

return ok(version().toJson());
}

@Route.post('$apiPrefix/openInIDX')
Future<Response> openInIdx(Request request, String apiVersion) async {
Future<Response> handleOpenInIdx(Request request, String apiVersion) async {
final code = api.OpenInIdxRequest.fromJson(await request.readAsJson()).code;
final idxUrl = Uri.parse('https://idx.google.com/run.api');

Expand Down Expand Up @@ -232,50 +236,6 @@ class CommonServerApi {
}
}

static final String? geminiApiKey = Platform.environment['GEMINI_API_KEY'];
http.Client? geminiHttpClient;

@Route.post('$apiPrefix/_gemini')
Future<Response> gemini(Request request, String apiVersion) async {
if (apiVersion != api3) return unhandledVersion(apiVersion);

// Read the api key from env variables (populated on the server).
final apiKey = geminiApiKey;
if (apiKey == null) {
return Response.internalServerError(
body: 'gemini key not configured on server');
}

// Only allow the call from dartpad.dev.
final origin = request.origin;
if (origin != 'https://dartpad.dev') {
return Response.badRequest(
body: 'Gemini calls only allowed from the DartPad front-end');
}

final sourceRequest =
api.SourceRequest.fromJson(await request.readAsJson());

geminiHttpClient ??= http.Client();

final model = google_ai.GenerativeModel(
model: 'models/gemini-1.5-flash-latest',
apiKey: apiKey,
httpClient: geminiHttpClient,
);

final result = await serialize(() async {
// call gemini
final result = await model.generateContent([
google_ai.Content.text(sourceRequest.source),
]);

return api.GeminiResponse(response: result.text!);
});

return ok(result.toJson());
}

Response ok(Map<String, dynamic> json) {
return Response.ok(
_jsonEncoder.convert(json),
Expand Down Expand Up @@ -403,7 +363,3 @@ String _formatMessage(

return message;
}

extension on Request {
String? get origin => headers['origin'];
}
Loading

0 comments on commit c6fe61e

Please sign in to comment.