Skip to content

Commit

Permalink
Merge pull request #664 from tighten/dts-generation
Browse files Browse the repository at this point in the history
Add type declarations and `ziggy.d.ts` generation
  • Loading branch information
bakerkretzmar authored Oct 6, 2023
2 parents cb47272 + f7b245b commit 141f00d
Show file tree
Hide file tree
Showing 19 changed files with 528 additions and 42 deletions.
26 changes: 17 additions & 9 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Contributing

Thanks for your interest in contributing to Ziggy! Contributions are **welcome** and will be fully **credited**.
Thanks for your interest in contributing to Ziggy! Contributions are welcome and will be credited.

To keep things running smoothly we ask you to follow a few guidelines when contributing. Please read and understand this contribution guide before creating an issue or pull request.

Expand All @@ -10,31 +10,39 @@ Be kind.

## Viability

If you have an idea for a feature, we'd prefer you open an issue before going to the trouble of writing code. We welcome your ideas, but we'd like to work with you to come up with solutions that work well for the project as a whole. We're usually pretty responsive, so it shouldn't take us long to figure out whether and how best to implement your idea.
If you have an idea for a feature, we'd prefer you open a discussion before going to the trouble of writing code. We welcome your ideas, but we'd like to work with you to come up with solutions that work well for the project as a whole. We're usually pretty responsive, so it shouldn't take us long to figure out whether and how best to implement your idea.

## Procedure

Before filing an issue:

- Attempt to replicate the problem, to ensure that it wasn't a coincidence
- Check to make sure your feature suggestion isn't already present within the project
- Check the pull requests tab to ensure that your feature or bugfix isn't already in progress
- Attempt to replicate the problem, to ensure that it wasn't a coincidence.
- Check to make sure your feature suggestion isn't already present within the project.
- Check the pull requests tab to ensure that your feature or bugfix isn't already in progress.

Before submitting a pull request:

- Check the codebase to ensure that your feature doesn't already exist
- Check the pull requests to ensure that another person hasn't already submitted the feature or fix
- Check the codebase to ensure that your feature doesn't already exist.
- Check the pull requests to ensure that another person hasn't already submitted the feature or fix.

## Tests

Please write tests for any fixes or new features you contribute. We use [Orchestra Testbench](http://orchestraplatform.com/docs/latest/components/testbench/) as our base PHPUnit test for PHP and [Jest](https://jestjs.io/) for testing our JavaScript.
Please write tests for any fixes or new features you contribute. We use [Orchestra Testbench](https://github.com/orchestral/testbench) as our base PHPUnit test for PHP and [Jest](https://jestjs.io/) for testing our JavaScript.

You can run PHP tests with `vendor/bin/phpunit` and JavaScript tests with `npm test`.
You can run PHP tests with `vendor/bin/phpunit` and JavaScript tests with `npm run test`.

If you need any help with this please don't hesitate to ask.

> If your filesystem uses `CRLF` instead of `LF` line endings (e.g. Windows) you may see errors related to that when running tests. To fix this you can run `git config --global core.autocrlf input` to configure Git to preserve the line endings from the repository when cloning. You may have to clone this repository again.
## Types

TypeScript types are included with Ziggy and maintained manually.

To test the type definitions, open `tests/js/types.ts` in an editor or IDE with TypeScript support. This file contains sample code using Ziggy's `route()` function, and can be used to ensure that specific examples do or don't type-check as expected. To add a test for code that should work, add the code (with a comment explaining its purpose) and verify that it doesn't create any type errors. To add a test for code that should _not_ work, and should generate a type error, add the code with a `// @ts-expect-error` annotation, and verify that without the annotation it generates a type error and with the annotation it doesn't.

See also [`tighten/ziggy-type-testing`](https://github.com/tighten/ziggy-type-testing).

## Requirements

- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](https://github.com/squizlabs/PHP_CodeSniffer).
Expand Down
40 changes: 36 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Ziggy supports all versions of Laravel from `5.4` onward, and all modern browser
- [The `route()` helper](#the-route-helper)
- [The `Router` class](#the-router-class)
- [Route-model binding](#route-model-binding)
- [TypeScript support](#typescript-support)
- [TypeScript](#typescript)
- [**Advanced Setup**](#advanced-setup)
- [JavaScript frameworks](#javascript-frameworks)
- [Vue](#vue)
Expand All @@ -31,7 +31,11 @@ Ziggy supports all versions of Laravel from `5.4` onward, and all modern browser

## Installation

Install Ziggy into your Laravel app with `composer require tightenco/ziggy`.
Install Ziggy in your Laravel app:

```bash
composer require tightenco/ziggy
```

Add the `@routes` Blade directive to your main layout (_before_ your application's JavaScript), and the `route()` helper function will now be available globally!

Expand Down Expand Up @@ -281,9 +285,37 @@ route('authors.photos.show', [{ id: 1, name: 'Jacob' }, photo]);
// 'https://ziggy.test/authors/1/photos/714b19e8-ac5e-4dab-99ba-34dc6fdd24a5'
```

#### TypeScript support
#### TypeScript

Ziggy includes TypeScript type definitions, and a helper command that can generate additional type definitions to enable route name and parameter autocompletion.

To generate the route types, run Ziggy's Artisan command with the `--types` or `--types-only` option:

```bash
php artisan ziggy:generate --types
```

To make your IDE aware that Ziggy's `route()` helper is available globally, and to type it correctly, add a declaration like this in a `.d.ts` file somewhere in your project:

```ts
import routeFn from 'ziggy-js';

declare global {
var route: typeof routeFn;
}
```

If you don't have Ziggy's NPM package installed, add the following to your `jsconfig.json` or `tsconfig.json` to load Ziggy's types from the Composer vendor directory:

Unofficial TypeScript type definitions for Ziggy are maintained by [benallfree](https://github.com/benallfree) as part of [Definitely Typed](https://github.com/DefinitelyTyped/DefinitelyTyped), and can be installed with `npm install @types/ziggy-js`.
```json
{
"compilerOptions": {
"paths": {
"ziggy-js": ["./vendor/tightenco/ziggy"]
}
}
}
```

## Advanced Setup

Expand Down
15 changes: 8 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
}
],
"files": [
"src/js",
"src/js/index.d.ts",
"dist"
],
"source": "src/js/index.js",
Expand All @@ -35,18 +35,19 @@
"browser": "dist/index.js",
"module": "dist/index.m.js",
"esmodule": "dist/index.es.js",
"types": "src/js/index.d.ts",
"repository": {
"type": "git",
"url": "https://github.com/tighten/ziggy.git"
},
"scripts": {
"build": "microbundle --name route --format modern,es,umd --external none --no-sourcemap",
"build:vue": "microbundle --entry src/js/vue.js --output dist/vue.js --name ZiggyVue --format modern,es,umd --external none --no-sourcemap",
"build:react": "microbundle --entry src/js/react.js --output dist/react.js --name ZiggyReact --format modern,es,umd --external none --no-sourcemap",
"build": "microbundle --name route --format modern,es,umd --external none --no-sourcemap --no-generateTypes",
"build:vue": "microbundle --entry src/js/vue.js --output dist/vue.js --name ZiggyVue --format modern,es,umd --external none --no-sourcemap --no-generateTypes",
"build:react": "microbundle --entry src/js/react.js --output dist/react.js --name ZiggyReact --format modern,es,umd --external none --no-sourcemap --no-generateTypes",
"watch": "npm run build watch",
"build:npm": "microbundle --name route --format modern,es,umd --no-sourcemap",
"build:npm:vue": "microbundle --entry src/js/vue.js --output dist/vue.js --name ZiggyVue --format modern,es,umd --no-sourcemap",
"build:npm:react": "microbundle --entry src/js/react.js --output dist/react.js --name ZiggyReact --format modern,es,umd --no-sourcemap",
"build:npm": "microbundle --name route --format modern,es,umd --no-sourcemap --no-generateTypes",
"build:npm:vue": "microbundle --entry src/js/vue.js --output dist/vue.js --name ZiggyVue --format modern,es,umd --no-sourcemap --no-generateTypes",
"build:npm:react": "microbundle --entry src/js/react.js --output dist/react.js --name ZiggyReact --format modern,es,umd --no-sourcemap --no-generateTypes",
"test": "jest --verbose",
"prepublishOnly": "npm run build:npm && npm run build:npm:vue && npm run build:npm:react"
},
Expand Down
35 changes: 21 additions & 14 deletions src/CommandRouteGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@

use Illuminate\Console\Command;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Str;
use Tightenco\Ziggy\Output\File;
use Tightenco\Ziggy\Output\Types;
use Tightenco\Ziggy\Ziggy;

class CommandRouteGenerator extends Command
{
protected $signature = 'ziggy:generate
{path? : Path to the generated JavaScript file. Default: `resources/js/ziggy.js`.}
{--types : Generate a TypeScript declaration file.}
{--types-only : Generate only a TypeScript declaration file.}
{--url=}
{--group=}';

Expand All @@ -27,13 +31,25 @@ public function __construct(Filesystem $files)

public function handle()
{
$path = $this->argument('path') ?? config('ziggy.output.path', 'resources/js/ziggy.js');
$generatedRoutes = $this->generate($this->option('group'));
$ziggy = new Ziggy($this->option('group'), $this->option('url') ? url($this->option('url')) : null);

$this->makeDirectory($path);
$this->files->put(base_path($path), $generatedRoutes);
$this->makeDirectory(
$path = $this->argument('path') ?? config('ziggy.output.path', 'resources/js/ziggy.js')
);

$this->info('File generated!');
if (! $this->option('types-only')) {
$output = config('ziggy.output.file', File::class);

$this->files->put(base_path($path), new $output($ziggy));
}

if ($this->option('types') || $this->option('types-only')) {
$types = config('ziggy.output.types', Types::class);

$this->files->put(base_path(Str::replaceLast('.js', '.d.ts', $path)), new $types($ziggy));
}

$this->info('Files generated!');
}

protected function makeDirectory($path)
Expand All @@ -44,13 +60,4 @@ protected function makeDirectory($path)

return $path;
}

private function generate($group = false)
{
$ziggy = (new Ziggy($group, $this->option('url') ? url($this->option('url')) : null));

$output = config('ziggy.output.file', File::class);

return (string) new $output($ziggy);
}
}
37 changes: 37 additions & 0 deletions src/Output/Types.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

namespace Tightenco\Ziggy\Output;

use Illuminate\Support\Arr;
use Stringable;
use Tightenco\Ziggy\Ziggy;

class Types implements Stringable
{
protected $ziggy;

public function __construct(Ziggy $ziggy)
{
$this->ziggy = $ziggy;
}

public function __toString(): string
{
$routes = collect($this->ziggy->toArray()['routes'])->map(function ($route) {
return collect($route['parameters'] ?? [])->map(function ($param) use ($route) {
return Arr::has($route, "bindings.{$param}")
? ['name' => $param, 'binding' => $route['bindings'][$param]]
: ['name' => $param];
});
});

return <<<JAVASCRIPT
/* This file is generated by Ziggy. */
declare module 'ziggy-js' {
interface RouteList {$routes->toJson(JSON_PRETTY_PRINT)}
}
export {};
JAVASCRIPT;
}
}
1 change: 1 addition & 0 deletions src/Ziggy.php
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ private function nameKeyedRoutes()
return $routes->map(function ($route) use ($bindings) {
return collect($route)->only(['uri', 'methods', 'wheres'])
->put('domain', $route->domain())
->put('parameters', $route->parameterNames())
->put('bindings', $bindings[$route->getName()] ?? [])
->when($middleware = config('ziggy.middleware'), function ($collection) use ($middleware, $route) {
if (is_array($middleware)) {
Expand Down
Loading

0 comments on commit 141f00d

Please sign in to comment.