Coder Social home page Coder Social logo

socketsupply / tonic Goto Github PK

View Code? Open in Web Editor NEW
843.0 19.0 25.0 666 KB

A Low Profile Component Framework – Stable, minimal, easy to audit, zero-dependencies and build-tool-free.

Home Page: http://tonicframework.dev

License: MIT License

JavaScript 100.00%
components react cba ui-components user-interface minimalist jamstack jam tonic framework

tonic's Introduction

tonic

https://tonicframework.dev



Tonic is a low profile component framework for the web. It's one file, less than 3kb gzipped and has no dependencies. It's designed to be used with modern Javascript and is compatible with all modern browsers and built on top of the Web Components.

Installation

npm install @socketsupply/tonic

Usage

import Tonic from '@socketsupply/tonic'

class MyGreeting extends Tonic {
  render () {
    return this.html`<div>Hello, World.</div>`
  }
}

Tonic.add(MyGreeting, 'my-greeting')

After adding your Javascript to your HTML, you can use your component anywhere.

<html>
  <head>
    <script src="my-greeting.js"></script>
  </head>
  <body>
    <my-greeting></my-greeting>
  </body>
</html>

Useful links

Copyright (c) 2023 Socket Supply Co.

MIT License

tonic's People

Contributors

achou11 avatar aprile avatar bcomnes avatar chicoxyzzy avatar dependabot[bot] avatar dominictarr avatar heapwolf avatar joemccann avatar jwerle avatar nichoth avatar raynos 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  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  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  avatar

Watchers

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

tonic's Issues

Mangling error fixed with Terser, not UglifyJS

https://github.com/optoolco/tonic/blob/master/HELP.md under the heading "Webpack 4+ Mangling Error" suggests that a "Mangling" error in the console when using webpack is fixable by adding the keep_fnames option to the UglifyJS config in your webpack config. However, Webpack now comes with TerserPlugin out of the box, and it's that that's mangling the names by default; it may be worth adding to those docs to suggest making a change as follows:

...
    optimization: {
        minimizer: [ // needed for Tonic
            new TerserPlugin({
                terserOptions: {
                    keep_fnames: true
                }
            })
        ]
    }
...

to the webpack configuration. (This is exactly what's there already, except for Terser, not UglifyJS).

This isn't a PR because there may be other better Tonic-ish options that should also be set for Terser and I don't know what they would be.

Home page has no links to the code or examples

The tonic home page is very informative, but it’s a dead end — there are no links (that I could find), so to find the source code or examples you have to do some web-searching. Awkward.

similarly, the examples page doesn’t link to the code either. Neither does the blog post.

Component composition?

This library looks really nice!

One of the stated goals is "React-like component composition." I'm looking through the examples in the docs and I'm struggling to find any examples of nested component composition. Every component seems to go one level deep and I don't see anything that looks parallel to React's notion of child elements. I may have missed something though! Is there anything I missed/any plan to implement this type of feature?

For clarity, this is the type of API I am imagining:

class Parent extends Tonic {
  render () {
    return `
      <div class="parent">
        ${this.props.children.render()}
      </div>
    `
  }
}

Tonic.add(Parent)

class Child extends Tonic {
  render () {
    return `
      <div class="child">
        ${this.props.value}
      </div>
    `
  }
}

Tonic.add(Child)
<parent>
  <child value="hello world" />
</parent>

Which would render...

<div class="parent">
  <div class="child">hello world</div>
</div>

Thanks

SSR docs

current docs are here: https://tonicframework.dev/#ssr

It would be good to make an example of SSR. The site says to look at the docs website. I see there is a prerender function call.

However, when I make an example using prerender, it throws an error

demonstration main % node ./ssr/greeting.js 
/Users/nick/code/demonstration/node_modules/tonic-ssr/node_modules/@socketsupply/tonic/index.js:47
      const html = this.outerHTML.replace(this.innerHTML, '...')
                                  ^

TypeError: Cannot read properties of undefined (reading 'replace')
    at MyGreeting._checkId (/Users/nick/code/demonstration/node_modules/tonic-ssr/node_modules/@socketsupply/tonic/index.js:47:35)
    at MyGreeting.get state [as state] (/Users/nick/code/demonstration/node_modules/tonic-ssr/node_modules/@socketsupply/tonic/index.js:54:18)
    at new MyGreeting (/Users/nick/code/demonstration/ssr/greeting.js:9:14)
    at main (/Users/nick/code/demonstration/ssr/greeting.js:30:22)
    at Object.<anonymous> (/Users/nick/code/demonstration/ssr/greeting.js:35:1)
    at Module._compile (node:internal/modules/cjs/loader:1126:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1180:10)
    at Module.load (node:internal/modules/cjs/loader:1004:32)
    at Function.Module._load (node:internal/modules/cjs/loader:839:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)

The docs website I think is a little too complex for example purposes.

Numbers and booleans aren’t replaced correctly

Describe the bug

When passing a boolean or number, I am seeing the variable type in the rendered output, i.e.

1__number
false__boolean

Steps To Reproduce
See https://jsfiddle.net/fev3zko2/
with the following code:

<my-component></my-component>
import Tonic from 'https://cdn.jsdelivr.net/npm/@socketsupply/[email protected]/+esm'

const numberValue = 1;
const booleanValue = true;
const stringValue = 'lorem ipsum';

class MyComponent extends Tonic {
	render() {
  	return this.html`<ul>
    	<li>Number ${numberValue}</li>
      <li>Boolean ${booleanValue}</li>
      <li>String ${stringValue}</li>
    </ul>`;
  }
}

Tonic.add(MyComponent);

This seems to happen in every browser that I tested with.

Composition Issues

Hi Everyone!

I'm facing an strange issue with Tonic, today!

I do have the following codes

class LabPage extends Tonic {
  render(){
    return this.html`<div class="page-content-wrapper py-3">${this.children}</div>`;
  }
}
Tonic.add(LabPage)
<lab-page id="pageAbout">
  <div class="container">
    <div class="card position-relative shadow-sm">
      <img class="card-img-top" src="/img/labelle/famille-colorc3a9e.png" alt="">
    </div>
  </div>
  <div class="container">
    <div class="card mb-3">
      <h5 class="mb-3">Write to us</h5>
      <div class="contact-form">
        <form action="#">
          <div class="form-group mb-3">
            <input class="form-control" type="text" placeholder="Your name" name="sender_name">
          </div>
          <div class="form-group mb-3">
            <input class="form-control" type="text" placeholder="Your email" name="sender_email">
          </div>
          <div class="form-group mb-3">
            <textarea class="form-control" name="sender_message" cols="30" rows="10" placeholder="Your message"></textarea>
          </div>
          <button class="btn btn-primary w-100">Send</button>
        </form>
      </div>
    </div>
  </div>
</lab-page>

On my DOM, I'm expecting, it to render as

<lab-page id="pageAbout">
  <div class="page-content-wrapper py-3">
  <div class="container">
    <div class="card position-relative shadow-sm">
      <img class="card-img-top" src="/img/labelle/famille-colorc3a9e.png" alt="">
    </div>
  </div>
  <div class="container">
    <div class="card mb-3">
      <h5 class="mb-3">Write to us</h5>
      <div class="contact-form">
        <form action="#">
          <div class="form-group mb-3">
            <input class="form-control" type="text" placeholder="Your name" name="sender_name">
          </div>
          <div class="form-group mb-3">
            <input class="form-control" type="text" placeholder="Your email" name="sender_email">
          </div>
          <div class="form-group mb-3">
            <textarea class="form-control" name="sender_message" cols="30" rows="10" placeholder="Your message"></textarea>
          </div>
          <button class="btn btn-primary w-100">Send</button>
        </form>
      </div>
    </div>
  </div>
  </div>
</lab-page>

But instead Tonic is rendering

<lab-page id="pageAbout">
  <div class="page-content-wrapper py-3"></div>
  <div class="container">
    <div class="card position-relative shadow-sm">
      <img class="card-img-top" src="/img/labelle/famille-colorc3a9e.png" alt="">
    </div>
  </div>
  <div class="container">
    <div class="card mb-3">
      <h5 class="mb-3">Write to us</h5>
      <div class="contact-form">
        <form action="#">
          <div class="form-group mb-3">
            <input class="form-control" type="text" placeholder="Your name" name="sender_name">
          </div>
          <div class="form-group mb-3">
            <input class="form-control" type="text" placeholder="Your email" name="sender_email">
          </div>
          <div class="form-group mb-3">
            <textarea class="form-control" name="sender_message" cols="30" rows="10" placeholder="Your message"></textarea>
          </div>
          <button class="btn btn-primary w-100">Send</button>
        </form>
      </div>
    </div>
  </div>
</lab-page>

Note that the childrens aren't beeing rendered on the properly place

`Tonic.matches` is not defined

Do you want to request a feature or report a bug?

Bug

Describe the bug

The bottom of the event docs describe a Tonic.matches function:

Tonic also provides a helper function which checks if the element matches the selector, and if not, tries to find the closest match.
Tonic.matches(el, 'selector')
Here, when a particular element inside a child component is clicked, we intercept the click event and pass along some data to the parent component.

Steps To Reproduce

Try to use Tonic.matches.

Expected behavior

Tonic.matches is a function that does element/event target matching. Or the docs are updated to remove this tidbit, not sure.

Actual behavior

Tonic.matches is undefined.

[Question] FAQ? How to use?

First of all, good job for creating something like this, thanks :)

Secondly, please pardon my ignorance / lack of knowledge,
does something like this:

import Tonic from '@optoolco/tonic'

work without bundler inside modern browser?

Or, is it that simple to use?

(Assuming I'm willing to commit to abandoning end-user
without a modern enough browser.)

Last thing, please open the discussion tabs, I personally dislike having to login
to yet another chat site / slack to ask simple questions that other user with
more experience can answer.

Github discussions is good enough, and people don't have to open a non-issue issue.

Cheers.

Uncaught TypeError: can't assign to property "bar" on 1: not an object

NodeJS: 12.13.1
Tonic: 13.1.2

Do you want to request a feature or report a bug?

bug

Describe the bug

When attempting to attach data to the event as events bubble, an error is thrown

Uncaught TypeError: can't assign to property "bar" on 1: not an object

The e.detail property is already set to 1 and can not be reset.

Steps To Reproduce

Steps to reproduce the behavior:

Using the example from the Events section of the docs can trigger this error

class ChildElement extends Tonic {
  click (e) {
    e.detail.bar = true
  }
  render () {
    return this.html`
      Click Me
    `
  }
}

class ParentElement extends Tonic {
  click (e) {
    if (e.target.matches('child-element')) {
      console.log(e.detail.bar)
    }
  }
  render () {
    return this.html`
      <child-element>
      </child-element>
    `
  }
}

Tonic.add(ChildElement)
Tonic.add(ParentElement

Expected behavior
In the ChildElement click handler, the e.detail property should be able to be set to some custom value.

Actual behavior

A clear and concise description of what actually happened.

When clicking the ChildElement and error is thrown Uncaught TypeError: can't assign to property "bar" on 1: not an object`

Screenshots

If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: Windows

  • Browser: Firefox

  • Version 83

  • Browser: Chrome

  • Version: 87.0.4280.66

Additional context

I am also not sure if this is related but when using e.target.matches on child elements that return a tonic component, the target element is not the component but an inner element.

class ChildElement extends Tonic {
  render() {
    return this.html`
      <tonic-button>click me</tonic-button>
    `
  }
  click(e) {
    console.log(e.target.matches('child-element') // false
    console.log(e.target.matches('tonic-button') // false
    console.log(e.target.matches('button') // true
  }
}

What is the expected behavior here? Is it possible to match on a custom element that uses sub-components?

Async functions are stringified

Bug report

Link to a working example, because we pass a function that is synchronous: https://jsfiddle.net/k3prLfcd/

Passing an async function results in the function being stringified. It should be usable as a function. Link to example demonstrating the issue: https://jsfiddle.net/ope5y79f/1/

Steps To Reproduce

Steps to reproduce the behavior:

  1. Go to https://jsfiddle.net/ope5y79f/1/
  2. Click on the button
  3. See error

Expected behavior
Should be able to call async methods

Actual behavior
Async functions are stringified

Screenshots

image

Desktop (please complete the following information):

  • Browser chrome
  • Version 117.0.5938.149 (Official Build) (arm64)

docs in README.md

Make this README the source of truth for docs? A benefit is the docs are located near the source code, and installed with this package. Also, no deploy & update process for a docs website, so it can't be out of sync. And less time investment to writing/deploying docs.

Then how does the website work? Ideally it could be generated from this README

V11 not yet pushed to npm

Main issue here is that the latest published version of tonic is not compatible with the latest version of components

Docs request — Can render a component assigned to a variable?

question / docs request

The scenario: I'm making a single page app, and I get a child component client side, from a 'router' module.

class MyApp extends Tonic {
  render () {
    const child = router.match('/example')
    return this.html`<div>
      // how to render `child` here?
      <${child></${child}>
    </div>`
  }
}

How to make this work? Normally in this scenario you would just return html with the child component's class/tag name?

render () {
  return this.html`<my-child>example</my-child>`
}

this.children gets overwritten by Tonic changes

When using this.children inside a Tonic component, I thought it would refer to the original elements that were inside the component HTML when it was first created. This is true when the component starts. However, once it's been rendered, the new rendered content is now written into this.children and the original content is lost. Can that original content be retrieved somehow? this.children is an HTMLCollection, so I can't simply save a reference to it in willConnect() (because it is a NodeList and so is dynamically updated) and if I make an array from it (this.state.savedChildren = Array.from(this.children) in willConnect()) Tonic doesn't like me passing it an Array to render in this.html (stored elements seem to toString() as something like placehold:tonic0:tonic1__.)

An example:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
    <click-to-show id="c">
        <p>I am a child of the click-to-show component!</p>
        <p>So am I!</p>
    </click-to-show>

<script type="module">
/*jshint esversion: 10 */

import Tonic from "./node_modules/@optoolco/tonic/index.esm.js";

class ClickToShow extends Tonic {
    click (e) {
        if (e.target.nodeName.toLowerCase() == "button") {
            console.log("you have clicked the button!");
            this.state.clicked = true;
            this.reRender();
        }
    }
    render() {
        if (this.state.clicked) {
            return this.html`<div>
                <h1>Here should be the original content of this element!</h1>
                <p>(but actually, it's been overwritten, never to return)</p>
                <div style="border: 1px solid black; padding: 1em;">
                ${this.children}
                </div>
            </div>`;
        } else {
            return this.html`<button>Click to show content!</button>`;
        }
    }
}
Tonic.add(ClickToShow);
</script>
</body>
</html>

I would have expected this.children to always be the two paragraph elements. However, those are lost entirely when the component renders its button. What's the best way to keep the original content around so that it can be used?

Congratulations!

Hi All, first of all my congratulations around Tonic!

This was exactly the kind of framework I was looking for my daily development to avoid React, Preact, Vue, Angular, cause to me simplicity matters, and Tonic, is the simplest tonic needed to bust up daily development!

Secondly, I want to know how to contribute to the Brazilian-Portuguese of Tonic website? I think, I'm not the unique Brazilian, that will fall in love, with this such amazing framework!

When rerending, input focus is lost

First of all, thank you for the great framework, nice work! :)
When trying it out with simple examples, I just found out inputs lose focus on reRendering.

Here is a : small example

You will notice that if you focus on the input start typing, as soon as the counter increments, the input element clears its value and the input loses focus.

It would be expected to have the input retain its value and focus.

Any idea why that might be or what I am doing wrong?

Thanks!

Slots

I like it, very nice an light.

Is there an example of using slots from a page?

"Uncaught DOMException: Operation is not supported" when assigning id in the constructor

Do you want to request a feature or report a bug?

Bug

Reproduce with the following snippet

const Tonic = require('@optoolco/tonic')
const bundle = require('@optoolco/components')

bundle(Tonic)

class MyApp extends Tonic {
  constructor(){
    super()
    this.id = 'my-app'
  }
}
<head>
  <script src="bundle.js"></script>
</head>
<body>
  <my-app></my-app>
</body>

Describe the bug

When assigning an element id in the constructor, and error is thrown: Uncaught DOMException: Operation is not supported.

This seems to only happen for the root element as assigning an in child elements seems to work fine.

Expected behavior
When assigning an id attribute in the root element constructor, the id should be assigned to the element.

Actual behavior
When assigning an attribute in the root element constructor, and uncaught exception is thrown: Uncaught DOMException: Operation is not supported

Desktop (please complete the following information):

  • OS: Windows
  • Browser: Firefox
  • Version: 83

Provide pre built bundles

I think it'd be nice and help with adoption if we could provide pre-polyfilled bundles maybe even provide it via cdnjs

Browser support?

Which browsers are supported and would you recommend using this in production for an embeddable widget?

Revise public/private methods

Should make any private methods use _ as a prefix on method name


What is the purpose of these? They are not called in the source code, so must be a public method. Should add to docs

  • this.disconnectedCallback
  • this.connectedCallback

Should revise API docs

  • disconnected — this is called in the source, but not implemented. Should this be in the section METHODS IMPLEMENTED BY THE COMPONENT DEVELOPER? Or should this be implemented?

Add to docs:

  • static getTagName

Cannot pass a `Map` instance as a property

When I pass an object as a property it works like I would expect.

If however i pass a Map instance as a property, the tonic component gets "[object Map]" instead of the actual map instance, it looks like the html method only understands object literals and not different builtin types.

It would be nice to support Map / Set / WeakMap and have them behave the same object literals.

Author regression tests against examples

We had a regression bug in tonic that was not caught by our tests.

Our tests are very unit focused.

Having examples and being able to write integration tests against example apps that consist of multiple components working together should get us decent regression tests.

This depends upon #10

Installing from a package manager?

The readme for this (and the components repo) has npm install instructions but that package doesn't appear to exist. As there plans to publish this to npm anytime soon? The project seems to be shaping up pretty nicely and I was considering trying it for a side project in the very near future.

Any blockers?

How to share information between multiple screens ?

I'm building a multi-step wizard. Each step can impact the next step.

For example in step 2 the user chooses whether to create a bucket or use an existing bucket. Then in step 3 we want to render different form components based on the previous choice.

Currently each step in the multi-step wizard is it's own page and thus it's own Tonic component.

What would be a good way of sharing information between these two sibling components ?

Suggested approach

Allow passing a reference of a parent component to a child component. For example

class Foo extends Tonic {
  render() {
    return this.html`<step-2-page wizard=${this}></step-2-page>`
  }
}

class Step2Page extends Tonic {
  connected() {
    this.wizard = this.props.wizard
  }
}

With this approach you can pass a reference to the parent component down to the child component. This allows the child component to notify the parent about anything it wants by invoking methods.

For example this.wizard.confirmBucketChoice('existing')

Alternative approach

Force state to be serialized somewhere. The state of the wizard could be persisted to localStorage or it could be persisted to a seperate WizardStateApi that everyone has a reference to. It could also be persisted in the URL and you could use some form of router component to extract the state from the URL.

npm install fails

Describe the bug

npm install fails

Steps To Reproduce

Steps to reproduce the behavior:

  1. Clone the tonic repo
  2. type npm i in the directory

Expected behavior

npm install works

Desktop (please complete the following information):

  • OS: mac OS Monterey 12.5.1

Additional context

tonic master % npm i
npm WARN deprecated [email protected]: Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)
npm WARN deprecated [email protected]: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.
npm WARN deprecated [email protected]: This package is unmaintained and deprecated. See the GH Issue 259.
npm ERR! code 1
npm ERR! path /Users/nick/code/tonic/node_modules/electron
npm ERR! command failed
npm ERR! command sh /var/folders/wc/j7p9ktnx3d99v5xm95s9h2480000gn/T/postinstall-ea3b8960.sh
npm ERR! node:internal/process/promises:279
npm ERR!             triggerUncaughtException(err, true /* fromPromise */);
npm ERR!             ^
npm ERR! 
npm ERR! GotError [HTTPError]: Response code 404 (Not Found) for https://github.com/electron/electron/releases/download/v7.3.3/electron-v7.3.3-darwin-arm64.zip
npm ERR!     at EventEmitter.<anonymous> (/Users/nick/code/tonic/node_modules/got/source/as-stream.js:35:24)
npm ERR!     at EventEmitter.emit (node:events:513:28)
npm ERR!     at module.exports (/Users/nick/code/tonic/node_modules/got/source/get-response.js:22:10)
npm ERR!     at ClientRequest.handleResponse (/Users/nick/code/tonic/node_modules/got/source/request-as-event-emitter.js:155:5)
npm ERR!     at Object.onceWrapper (node:events:628:26)
npm ERR!     at ClientRequest.emit (node:events:525:35)
npm ERR!     at ClientRequest.origin.emit (/Users/nick/code/tonic/node_modules/@szmarczak/http-timer/source/index.js:37:11)
npm ERR!     at HTTPParser.parserOnIncomingClient [as onIncoming] (node:_http_client:674:27)
npm ERR!     at HTTPParser.parserOnHeadersComplete (node:_http_common:128:17)
npm ERR!     at TLSSocket.socketOnData (node:_http_client:521:22) {
npm ERR!   host: 'github.com',
npm ERR!   hostname: 'github.com',
npm ERR!   method: 'GET',
npm ERR!   path: '/electron/electron/releases/download/v7.3.3/electron-v7.3.3-darwin-arm64.zip',
npm ERR!   socketPath: undefined,
npm ERR!   protocol: 'https:',
npm ERR!   url: 'https://github.com/electron/electron/releases/download/v7.3.3/electron-v7.3.3-darwin-arm64.zip',
npm ERR!   gotOptions: {
npm ERR!     path: '/electron/electron/releases/download/v7.3.3/electron-v7.3.3-darwin-arm64.zip',
npm ERR!     protocol: 'https:',
npm ERR!     slashes: true,
npm ERR!     auth: null,
npm ERR!     host: 'github.com',
npm ERR!     port: null,
npm ERR!     hostname: 'github.com',
npm ERR!     hash: null,
npm ERR!     search: null,
npm ERR!     query: null,
npm ERR!     pathname: '/electron/electron/releases/download/v7.3.3/electron-v7.3.3-darwin-arm64.zip',
npm ERR!     href: 'https://github.com/electron/electron/releases/download/v7.3.3/electron-v7.3.3-darwin-arm64.zip',
npm ERR!     retry: {
npm ERR!       retries: [Function (anonymous)],
npm ERR!       methods: Set(6) { 'GET', 'PUT', 'HEAD', 'DELETE', 'OPTIONS', 'TRACE' },
npm ERR!       statusCodes: Set(7) { 408, 413, 429, 500, 502, 503, 504 },
npm ERR!       errorCodes: Set(8) {
npm ERR!         'ETIMEDOUT',
npm ERR!         'ECONNRESET',
npm ERR!         'EADDRINUSE',
npm ERR!         'ECONNREFUSED',
npm ERR!         'EPIPE',
npm ERR!         'ENOTFOUND',
npm ERR!         'ENETUNREACH',
npm ERR!         'EAI_AGAIN'
npm ERR!       }
npm ERR!     },
npm ERR!     headers: {
npm ERR!       'user-agent': 'got/9.6.0 (https://github.com/sindresorhus/got)',
npm ERR!       'accept-encoding': 'gzip, deflate'
npm ERR!     },
npm ERR!     hooks: {
npm ERR!       beforeRequest: [],
npm ERR!       beforeRedirect: [],
npm ERR!       beforeRetry: [],
npm ERR!       afterResponse: [],
npm ERR!       beforeError: [],
npm ERR!       init: []
npm ERR!     },
npm ERR!     decompress: true,
npm ERR!     throwHttpErrors: true,
npm ERR!     followRedirect: true,
npm ERR!     stream: true,
npm ERR!     form: false,
npm ERR!     json: false,
npm ERR!     cache: false,
npm ERR!     useElectronNet: false,
npm ERR!     method: 'GET'
npm ERR!   },
npm ERR!   statusCode: 404,
npm ERR!   statusMessage: 'Not Found',
npm ERR!   headers: {
npm ERR!     server: 'GitHub.com',
npm ERR!     date: 'Wed, 21 Sep 2022 02:48:48 GMT',
npm ERR!     'content-type': 'text/plain; charset=utf-8',
npm ERR!     vary: 'X-PJAX, X-PJAX-Container, Turbo-Visit, Turbo-Frame, Accept-Encoding, Accept, X-Requested-With',
npm ERR!     'cache-control': 'no-cache',
npm ERR!     'strict-transport-security': 'max-age=31536000; includeSubdomains; preload',
npm ERR!     'x-frame-options': 'deny',
npm ERR!     'x-content-type-options': 'nosniff',
npm ERR!     'x-xss-protection': '0',
npm ERR!     'referrer-policy': 'no-referrer-when-downgrade',
npm ERR!     'expect-ct': 'max-age=2592000, report-uri="https://api.github.com/_private/browser/errors"',
npm ERR!     'content-security-policy': "default-src 'none'; base-uri 'self'; connect-src 'self'; form-action 'self'; img-src 'self' data:; script-src 'self'; style-src 'unsafe-inline'",
npm ERR!     'content-encoding': 'gzip',
npm ERR!     'content-length': '29',
npm ERR!     'x-github-request-id': '8A0C:6CB1:2A99BF:2CF81F:632A7BAB',
npm ERR!     connection: 'close'
npm ERR!   },
npm ERR!   body: undefined
npm ERR! }

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/nick/.npm/_logs/2022-09-21T02_49_05_593Z-debug-0.log

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.