GithubHelp home page GithubHelp logo

narrowspark / http-emitter Goto Github PK

View Code? Open in Web Editor NEW
33.0 5.0 10.0 265 KB

:satellite: Emitting psr-7 responses.

License: MIT License

PHP 92.81% Dockerfile 4.51% JavaScript 2.68%
psr-7 http emitter stream sapi swoole http-emitter php library narrowspark

http-emitter's Introduction



Narrowspark is a PHP framework for large, robust web applications and a superb combination of simplicity, elegance, reusable PHP components with expressive, elegant syntax. Narrowspark attempts to take the pain out of development by easing common tasks.

  • Powerful dependency injection container.
  • Multiple back-ends for session, filesystem and cache storage.
  • A powerful console "cerebro" based on Symfony Console
  • Simple, fast and with support for psr-15 middleware routing engine.
  • Powerful encryption and hashing.

Documentation

The Narrowspark documentation is thorough, complete, and makes it a breeze to get started learning the framework. You need more information's take a look on Narrowspark website.

Community

  • Get Narrowspark support on Stack Overflow, Gitter, etc.
  • Follow us on GitHub.

Contributing

If you would like to help take a look at the list of issues and check our Contributing guild.

Note: Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.

Security Vulnerabilities

If you discover a security vulnerability within Narrowspark, please send an e-mail to Daniel Bannert at [email protected]. All security vulnerabilities will be promptly addressed.

License

The Narrowspark framework is open-sourced software licensed under the MIT license

http-emitter's People

Contributors

dependabot-preview[bot] avatar github-actions[bot] avatar mindplay-dk avatar prisis avatar renovate-bot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

http-emitter's Issues

Dependabot can't resolve your PHP dependency files

Dependabot can't resolve your PHP dependency files.

As a result, Dependabot couldn't update your dependencies.

The error Dependabot encountered was:

Your requirements could not be resolved to an installable set of packages.
  Problem 1
    - symfony/console v4.3.3 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.3.2 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.3.1 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.3.0 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.2.9 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.2.8 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.2.7 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.2.6 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.2.5 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.2.4 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.2.3 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.2.2 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.2.11 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.2.10 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.2.1 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.2.0 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.1.9 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.1.8 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.1.7 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.1.6 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.1.5 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.1.4 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.1.3 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.1.2 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.1.12 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.1.11 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.1.10 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.1.1 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.1.0 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.0.9 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.0.8 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.0.7 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.0.6 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.0.5 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.0.4 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.0.3 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.0.2 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.0.15 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.0.14 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.0.13 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.0.12 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.0.11 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.0.10 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.0.1 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - symfony/console v4.0.0 requires php ^7.1.3 -> your PHP version (7.3.8-1+ubuntu18.04.1+deb.sury.org+1) overridden by "config.platform.php" version (7.1) does not satisfy that requirement.
    - narrowspark/coding-standard 1.4.0 requires jwage/changelog-generator ^0.0.7 -> satisfiable by jwage/changelog-generator[0.0.7].
    - jwage/changelog-generator 0.0.7 requires symfony/console ^4.0 -> satisfiable by symfony/console[v4.0.0, v4.0.1, v4.0.10, v4.0.11, v4.0.12, v4.0.13, v4.0.14, v4.0.15, v4.0.2, v4.0.3, v4.0.4, v4.0.5, v4.0.6, v4.0.7, v4.0.8, v4.0.9, v4.1.0, v4.1.1, v4.1.10, v4.1.11, v4.1.12, v4.1.2, v4.1.3, v4.1.4, v4.1.5, v4.1.6, v4.1.7, v4.1.8, v4.1.9, v4.2.0, v4.2.1, v4.2.10, v4.2.11, v4.2.2, v4.2.3, v4.2.4, v4.2.5, v4.2.6, v4.2.7, v4.2.8, v4.2.9, v4.3.0, v4.3.1, v4.3.2, v4.3.3].
    - Installation request for narrowspark/coding-standard ^1.4.0 -> satisfiable by narrowspark/coding-standard[1.4.0].

If you think the above is an error on Dependabot's side please don't hesitate to get in touch - we'll do whatever we can to fix it.

You can mention @dependabot in the comments below to contact the Dependabot team.

Caching issue

I'm unsure if this belongs in an emitter library or not, but figured I'd bring it up for discussion.

The issue is cache headers - or rather, the absence of cache headers.

I've personally always relied on PHP to send a no-cache pragma by default - if you don't send any cache headers yourself.

I recently discovered that this isn't being emitted by default anymore.

It turns out, what I've actually been relying on, is session.auto_start and the default session.cache_limiter setting, which is what actually causes PHP to emit the no-cache headers by default.

We don't use PHP's session-module at all anymore, so we're no longer getting this behavior. (and I imagine a lot of pure PSR-7-based projects avoid the session-library as well, since it hampers testing for one.)

I guess I thought this was just built-into the language - PHP pages are dynamic, which is why I would have thought this made sense: suppress caching for dynamic pages by default, unless the script itself specifies something else. No risk of end users seeing stale content.

I've only recently become aware of "heuristic caching" in Chrome, which kicks in when you don't have any cache-headers in the response at all - and only recently realized that this is actually causing cache problems for some of our users.

Bottom line: PHP pages are dynamic and probably shouldn't be cached by default.

I can solve this for our own stack easily - either hard code it into the stack, or add a middleware that populates the cache-headers with defaults.

But it seems like this could easily become a pain point for anyone working with a PSR-7 based stack, which makes me wonder if this should really just be built into the emitter?

Why should you have to be learn about this problem the hard way and find an appropriate middleware and everything, just to get an app that "just works" by default?

Maybe this made sense in the past, but it seems like the landscape has changed a bit with Chrome introducing this new "heuristic" caching behavior for pages with no cache-headers.

It seems like you just shouldn't be serving pages without cache-headers anymore, period. The behavior is unpredictable and there's likely nothing won by assuming pages can be cached - most dynamic pages, in my experience, either can't or shouldn't be, so it's not really a useful default.

Am I wrong? What do you think?

Disparity between SwooleEmitter and SapiEmitters?

I think there may be a slight disparity between SwooleEmitter and the SAPI emitters.

In terms of dependency injection, all emitters are behind EmitterInterface, which is good.

But the SwooleEmitter has a constructor-dependency on SwooleResponse, which implies a different life-cycle - whereas the SAPI emitters can be safely reused across multiple requests, the Swoole emitter (being designed for use in long-running apps) needs to be recreated for every request.

You may have intended for all emitters to be created and then destroyed for every request?

But it's not necessary, and it doesn't really seem to provide any benefit.

Of course, I could just ignore the interface and register them as separate components with explicit dependencies on the implementations - which might make sense anyway, since the Swoole emitter has implicit dependency on Swoole and an event-loop and so on.

I wonder if the interface is actually meaningful or just misleading?

You can't actually plug a Swoole emitter into a normal stack and get something that works - similarly, you can't plug a SAPI emitter into a Swoole-based stack and get something that works.

The interface seems to imply a some kind of meaninful of abstraction, but... is it meaningful?

If not, perhaps we might consider a simpler abstraction that treats the emitters as an implementation detail, and instead provides a higher-level "host" abstraction based on PSR-15 handlers:

use Psr\Http\Server\RequestHandlerInterface;

interface Host
{
    public function run(RequestHandlerInterface $handler): void;
}

With this abstraction, a SapiHost would run the $handler once (e.g. from an index.php script) while the SwooleHost would actually implement the event-loop and dispatch the $handler repeatedly; something that's currently left up to the consumer.

Also missing from this package is something to convert from a Swoole Request to a PSR-7 Request - this could be built into the Swoole host as well.

Thoughts?

Close HTTP connections after emit

As we discussed on twitter, I'm opening an issue to explicitly define the requirements for a PR that adds support for closing HTTP connections after emit.

To others who aren't aware of this discussion: the reason for this feature is it provides the ability to defer minor tasks (such as sending an email or flushing a log-buffer to a database) until after the user receives the response - this increases perceived responsiveness of the app by not blocking the closing of the connection unnecessarily.

This feature also prevents accidental output after you've emitted the complete response body, which in some cases can end up corrupting the response.

This should also improve parity with the SwooleEmitter, which I believe already does this. (@prisis perhaps you can confirm this? SwooleServer does have a close method, though from the description of end() I'd assume this is implicitly called?)

The implementation details in SapiEmitter and SapiStreamEmitter are a bit different, so I'd propose adding a protected method to AbstractSapiEmitter and calling it as needed in the two super-classes.

I'm referencing these lines from narrowspark/skeleton-generators, so the addition to AbstractSapiEmitter would look like this:

protected function closeConnection(): void
{
    if (function_exists('fastcgi_finish_request')) {
        fastcgi_finish_request();
    } elseif (!\in_array(PHP_SAPI, ['cli', 'phpdbg'], true)) {
        EmitterUtil::closeOutputBuffers(0, true);
    }
}

This would then get called after this line in SapiEmitter, after this statement and this statement in SapiStreamEmitter.

@prisis dose that sound workable?

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Rate-Limited

These updates are currently rate-limited. Click on a checkbox below to force their creation now.

  • chore(deps): update actions/cache action to v3
  • chore(deps): update actions/checkout action to v3
  • chore(deps): update actions/download-artifact action to v3
  • chore(deps): update actions/stale action to v5
  • chore(deps): update actions/stale action to v6
  • chore(deps): update actions/upload-artifact action to v3
  • chore(deps): update codecov/codecov-action action to v3
  • chore(deps): update node.js to v18
  • ๐Ÿ” Create all rate-limited PRs at once ๐Ÿ”

Edited/Blocked

These updates have been manually edited so Renovate will no longer make changes. To discard all commits and start over, click on a checkbox.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

composer
composer.json
  • php ^8.0
  • psr/http-message ^1.0
  • thecodingmachine/safe ^1.3.3
  • laminas/laminas-diactoros ^2.5.0
  • mockery/mockery ^1.4.2
  • narrowspark/coding-standard ^5.2.2
  • phpunit/phpunit ^9.5.2
  • psalm/plugin-mockery ^0.7.0
  • thecodingmachine/phpstan-safe-rule ^1.0.1
docker-compose
.github/workflows/composer-normalize.yml
docker-compose.yml
dockerfile
.docker/php/Dockerfile
github-actions
.github/workflows/coding-standard.yml
  • actions/checkout v2
  • shivammathur/cache-extensions v1
  • actions/cache v2
  • shivammathur/setup-php v2
  • ramsey/composer-install v1
.github/workflows/composer-normalize.yml
  • actions/checkout v2
  • stefanzweifel/git-auto-commit-action v4.0.0
.github/workflows/continuous-integration.yml
  • actions/checkout v2
  • shivammathur/cache-extensions v1
  • actions/cache v2
  • shivammathur/setup-php v2
  • ramsey/composer-install v1
  • actions/upload-artifact v2
  • actions/checkout v2
  • shivammathur/cache-extensions v1
  • actions/cache v2
  • shivammathur/setup-php v2
  • ramsey/composer-install v1
  • actions/upload-artifact v2
  • actions/checkout v2
  • actions/download-artifact v2
  • codecov/codecov-action v1
.github/workflows/greetings.yml
  • actions/first-interaction v1
.github/workflows/license-update.yml
  • actions/checkout v2
  • shivammathur/cache-extensions v1
  • actions/cache v2
  • shivammathur/setup-php v2
  • ramsey/composer-install v1
  • stefanzweifel/git-auto-commit-action v4.9.1
.github/workflows/markdown-lint.yml
  • actions/checkout v2
  • actions/setup-node v2
  • actions/cache v2
.github/workflows/mutation.yml
  • actions/checkout v2
  • shivammathur/cache-extensions v1
  • actions/cache v2
  • shivammathur/setup-php v2
  • ramsey/composer-install v1
.github/workflows/rector-ci.yml
  • actions/checkout v2
  • shivammathur/cache-extensions v1
  • actions/cache v2
  • shivammathur/setup-php v2
  • ramsey/composer-install v1
.github/workflows/semantic-release.yml
  • actions/checkout v2
  • shivammathur/cache-extensions v1
  • actions/cache v2
  • shivammathur/setup-php v2
  • ramsey/composer-install v1
  • actions/checkout v2
  • cycjimmy/semantic-release-action v2
.github/workflows/stale-issues.yml
  • actions/stale v3
  • actions/stale v3
  • actions/stale v3
  • actions/stale v3
.github/workflows/static-analyze.yml
  • actions/checkout v2
  • shivammathur/cache-extensions v1
  • actions/cache v2
  • shivammathur/setup-php v2
  • ramsey/composer-install v1
  • actions/checkout v2
  • shivammathur/cache-extensions v1
  • actions/cache v2
  • shivammathur/setup-php v2
  • ramsey/composer-install v1
.github/workflows/template-sync.yml
  • actions/checkout v2
  • narrowspark/template-sync-action v1.0.0-alpha.9
.github/workflows/yaml-lint.yml
  • actions/checkout v2
  • ibiqlik/action-yamllint v3
npm
package.json
  • @anolilab/textlint-config ^2.0.0
nvm
.nvmrc
  • node 14.18.1

  • Check this box to trigger a request for Renovate to run again on this repository

SapiStreamEmitter that does not consider Content-Range

Is your feature request related to a problem? Please describe.

SapiStreamEmitter::emit considers the header Content-Range and emits only the relevant range when only a single range is requested and the range unit is bytes. This seems very nice and convenient at first glance.

If the application wants to support multi-range requests or range units other than bytes, however, populating the response with the correct content range(s) must be done by the application, and SapiStreamEmitter will emit the entire provided response body.

This seems very asymmetrical to me. Who should actually be in charge of ensuring that the response body is correct? The one who populates the response body or the one who emits it?

My application would have to populate the final response body in the case of multi-range or non-byte unit, but populate the entire file into the response body in the case of single byte range, and then let SapiStreamEmitter handle the range-stuff.

Describe the solution you'd like

I would like the option to let SapiStreamEmitter just output the whole response body that I have provided, regardless of the Content-Range range header.

I actually don't think the Content-Range functionality has anything to do in the emitter, so I would prefer to just remove it. But such a change in functionality might warrant a new major version. The behavior could also be set in a constructor argument. Or there could be a separate class.

If the Content-Range functionality has anything to do in the emitter, why isn't it also a part of the SapiEmitter. In my opinion, exchanging the one for the other should not lead to different output.

Describe alternatives you've considered

Teachability, Documentation, Adoption, Migration Strategy

Multi-byte string assumption in SapiStreamEmitter::emitBodyRange() ?

Are you deliberately using multi-byte string functions to deal with ranged emits?

Looks like you referenced zend for this bit?

If they were using multi-byte functions at the time, they've since corrected this.

The Content-Range header specified bytes, not character points - so this looks like a bug, and likely a missing test-case to prove that emitting binary data actually works?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.