Compare commits

...

141 Commits

Author SHA1 Message Date
Steven
ad436313e1 Publish Stable
- @vercel/build-utils@3.1.1
 - vercel@24.2.5
 - @vercel/client@11.0.4
 - @vercel/frameworks@1.0.0
 - @vercel/go@1.4.4
 - @vercel/next@2.9.0
 - @vercel/node@1.15.4
 - @vercel/python@2.3.4
 - @vercel/redwood@0.8.4
 - @vercel/remix@0.0.2
 - @vercel/ruby@1.3.7
 - @vercel/static-build@0.26.0
2022-05-31 10:44:36 -04:00
Lee Robinson
c414288b2f [examples] Update SvelteKit example with latest boilerplate (#7892)
Replaces https://github.com/vercel/vercel/pull/7674 with the latest SvelteKit boilerplate.
2022-05-30 07:57:46 +00:00
Steven
b07ff7431f [tests] Bump turbo to 1.2.14 (#7887)
This should fix the caching problem

https://github.com/vercel/turborepo/releases/tag/v1.2.14
2022-05-27 23:46:38 +00:00
Steven
79fde4475c [build-utils][go][next][redwood][static-build] Fix path delimiter on windows (#7881)
This PR fixes an issue where the path delimiter was incorrect for windows and caused yarn (and other global CLIs) to no longer be found.

https://github.com/vercel/vercel/runs/6602572000?check_suite_focus=true#step:13:1357
2022-05-27 22:59:28 +00:00
Nathan Rajlich
855197c699 [node] Remove mkdirp-promise dependency (#7878)
There's no need to use this module since Node.js has `recursive: true` since Node v10.

Co-authored-by: Steven <steven@ceriously.com>
2022-05-26 15:07:09 -04:00
Nathan Rajlich
fbd9080859 [tests] Add vc build integration test (#7876)
[cli] Add `vc build` integration test

Adds a `vc build` integration test to ensure the ncc'd CLI works as
expected to supplement the unit tests from #7869.

Co-authored-by: Steven <steven@ceriously.com>
2022-05-26 15:05:31 -04:00
Steven
b5c5b7b82c [tests] Fix tests with promises (#7880)
These tests are asynchronous and would sometimes fail if the second call started before the first call finished. This PR fixes the usage since the function returns a promise.
2022-05-26 10:28:49 -04:00
Gal Schlezinger
0a072ee850 Publish Canary
- vercel@24.2.5-canary.3
 - @vercel/next@2.8.67-canary.3
2022-05-26 09:20:12 +03:00
Dalpat Rathore
0b56caba45 [docs] Fix CONTRIBUTING.md grammar (#7575)
Fix: CONTRIBUTING.md grammar

Co-authored-by: Steven <steven@ceriously.com>
2022-05-25 17:44:41 -04:00
Steven
ab3db60824 [tests] Conditionally set env vars (#7874)
This PR is a follow up to #7873 which didn't work as intended
2022-05-25 17:36:20 -04:00
Steven
f2f2ff2c67 [tests] Skip env vars for forks (#7873)
This fixes an issue when an external contributor submits a PR and the remote cache is not accessible 

```
$ turbo run build
 ERROR No caches are enabled. You can try "turbo login", "turbo link", or ensuring you are not passing --remote-only to enable caching:  <nil>
• Packages in scope: @vercel/build-utils, @vercel/client, @vercel/frameworks, @vercel/go, @vercel/next, @vercel/node, @vercel/node-bridge, @vercel/python, @vercel/redwood, @vercel/remix, @vercel/routing-utils, @vercel/ruby, @vercel/static-build, @vercel/static-config, vercel
```
2022-05-25 16:54:35 -04:00
Gal Schlezinger
ba7dafff71 [next] Allow edge api endpoints in Next.js (#7855)
Co-authored-by: JJ Kasper <jj@jjsweb.site>
2022-05-25 15:19:14 +03:00
JJ Kasper
987fb4d4f7 [next] Ensure test-next-local is run in CI (#7868)
* Ensure test-next-local is run in CI

* update turbo config

* update timeout

* update flakey test
2022-05-24 14:22:40 -05:00
Nathan Rajlich
be74f79fa0 Publish Canary
- @vercel/build-utils@3.1.1-canary.2
 - vercel@24.2.5-canary.2
 - @vercel/client@11.0.4-canary.2
 - @vercel/go@1.4.4-canary.2
 - @vercel/next@2.8.67-canary.2
 - @vercel/node@1.15.4-canary.2
 - @vercel/python@2.3.4-canary.2
 - @vercel/redwood@0.8.4-canary.2
 - @vercel/remix@0.0.2-canary.2
 - @vercel/ruby@1.3.7-canary.2
 - @vercel/static-build@0.25.3-canary.2
2022-05-24 09:14:29 -07:00
Andrew Gadzik
86886e6b60 [build-utils] Add getWorkspaces helper function (#7775)
```ts
/*

  Example 1:
	
  my-repo
    |-- packages
    |    |-- api-1
    |    |-- api-2
    |-- package.json
    |-- pnpm-workspaces.yaml // packages: ["packages/*"]
	
  getWorkspaces("my-repo") => [
    {
      implementation: "pnpm",
      rootPath: "https://github.com/.../my-repo"
    }
  ]
  
  Example 2:
	
  my-repo
    |-- backend
    |    |-- api-1
    |    |-- api-2
    |    |-- package.json // workspaces: ["api-1", "api-2"]
    |-- frontend
    |    |-- nextjs-app
    |    |-- gatsby-app
    |    |-- package.json
    |    |-- pnpm-workspaces.yaml // packages: ["nextjs-app", "gatsby-app"]
	
  getWorkspaces("my-repo") => [
    {
      implementation: "yarn",
      rootPath: "https://github.com/.../my-repo/backend"
    }, 
    {
      implementation: "pnpm",
      rootPath: "https://github.com/.../my-repo/frontend"
    }
  ]

 */
type Workspace = {
  implementation: "yarn" | "npm" | "pnpm" 
  rootPath: string // the path to the root of the workspace
}

function getWorkspaces(fs: DetectorFilesystem): Workspace[]
```

### Related Issues

> Closes https://github.com/vercel/vercel/issues/7730

### 📋 Checklist

<!--
  Please keep your PR as a Draft until the checklist is complete
-->

#### Tests

- [x] The code changed/added as part of this PR has been covered with tests
- [x] All tests pass locally with `yarn test-unit`

#### Code Review

- [x] This PR has a concise title and thorough description useful to a reviewer
- [x] Issue from task tracker has a link to this PR
2022-05-24 14:28:32 +00:00
Nathan Rajlich
e8a9000137 [cli] Symlink @now/build-utils when installing builders in "vc build" (#7844)
To support legacy Builders like `@frontity/now` which still depends on the old `@now/build-utils` package name, create a symlink to `@vercel/build-utils` to make import the package work transparently.

Depends on #7842 being merged first.
2022-05-24 05:36:34 +00:00
Nathan Rajlich
75ea68d445 [cli] Convert DevServer "Unit" suite tests to "Dev" suite tests (#7845)
The `DevServer` class as it's currently implement is not really suitable for unit testing, since it calls `process.exit()` when shutting down the server. This causes Jest to exit prematurely, and prevents tests after these one from running. This was in fact hiding some failing tests. So these tests were ported over to be "Dev" suite tests which spawn a child process of `vc dev` rather than running them in-process, so that the `process.exit()` doesn't exit Jest.
2022-05-23 23:38:02 +00:00
Sean Massa
a5a990995c [tests] improve error message when a deploy fails (#7864)
improve error message
2022-05-23 17:02:29 -05:00
Sean Massa
cd7dcc6731 [tests] bump node version to 14 (#7863) 2022-05-23 16:00:03 -05:00
Sean Massa
c4bd462b85 [tests] update fixture path (#7862)
It looks like the fixture location was shifted and these references to it were not updated. The crashing `dev` tests were hiding these failures.
2022-05-23 20:31:24 +00:00
Steven
5fc266bd8a [next][node] Bump @vercel/nft to 0.19.1 (#7860)
Bump `@vercel/nft` to 0.19.1 https://github.com/vercel/nft/releases/tag/0.19.1
2022-05-23 17:30:29 +00:00
JJ Kasper
08b04d0bda Publish Canary
- @vercel/build-utils@3.1.1-canary.1
 - vercel@24.2.5-canary.1
 - @vercel/client@11.0.4-canary.1
 - @vercel/frameworks@0.9.2-canary.0
 - @vercel/go@1.4.4-canary.1
 - @vercel/next@2.8.67-canary.1
 - @vercel/node@1.15.4-canary.1
 - @vercel/python@2.3.4-canary.1
 - @vercel/redwood@0.8.4-canary.1
 - @vercel/remix@0.0.2-canary.1
 - @vercel/ruby@1.3.7-canary.1
 - @vercel/static-build@0.25.3-canary.1
2022-05-23 10:38:42 -05:00
Nathan Rajlich
92ae51c6a6 [examples] Add missing semi to "solidstart" vite config (#7858) 2022-05-22 19:24:45 -05:00
JJ Kasper
909c493d1e [next][build-utils] Update to re-use build result type from build-utils (#7857)
### Related Issues

We were previously using a custom type in Next.js for the build result although there is an existing type for this in the build-utils package which we can centralize around. 

x-ref: https://github.com/vercel/vercel/pull/7854#issuecomment-1133934764

### 📋 Checklist

<!--
  Please keep your PR as a Draft until the checklist is complete
-->

#### Tests

- [ ] The code changed/added as part of this PR has been covered with tests
- [ ] All tests pass locally with `yarn test-unit`

#### Code Review

- [ ] This PR has a concise title and thorough description useful to a reviewer
- [ ] Issue from task tracker has a link to this PR
2022-05-22 21:11:33 +00:00
Gal Schlezinger
98b54ff61f [next] Remove unused middleware definition (#7854)
Remove unused middleware definition in Next.js builder

Co-authored-by: JJ Kasper <jj@jjsweb.site>
2022-05-22 20:46:49 +03:00
JJ Kasper
3defd0b2fd [next] Fix middleware order and add e2e test (#7847)
Fix middleware order and add e2e test
2022-05-22 11:25:56 -05:00
Nathan Rajlich
5a7851a7f7 [tests] Revert "update CI to use node@14 and drop support for node@12 (#7819)" (#7853)
Revert "[tests] update CI to use node@14 and drop support for node@12 (#7819)"

This reverts commit 89b5aad367.
2022-05-21 20:11:08 -07:00
Nathan Rajlich
7f0caa7dec [examples] Add vercel.json file back to "remix" template for now (#7851)
This file was removed prematurely in #7831.
2022-05-21 20:03:06 -07:00
Sean Massa
89b5aad367 [tests] update CI to use node@14 and drop support for node@12 (#7819)
Node 12 is EOL and we're starting to reference packages that don't install on node lower than 14, such as nuxt@3 and remix. Let's update to 14 for now.
2022-05-21 05:20:43 +00:00
Nathan Rajlich
c13775ba07 [frameworks] Remove defaultHeaders / defaultRedirects / defaultRewrites / getFsOutputDir() (#7832)
These properties are leftover from the previous iteration of `vc build` / File System API v2, and are no longer in use.
2022-05-20 20:24:51 +00:00
Nathan Rajlich
cc3c1d1eeb [cli] Refactor vc build installBuilders() logic to not use a loop (#7842)
This will prevent the possibility of an infinite loop occurring when importing builders that throw a `MODULE_NOT_FOUND` error. Instead, we'll just try to import the builders, then run yarn if necessary, and then try to import the builders a second time when needed. If that fails then we'll throw the original error.
2022-05-20 19:53:54 +00:00
Sean Massa
3aa2fbbb53 [static-build] Support subset of Build Output API v2 (#7808)
* Revert "Revert "[static-build] Support subset of Build Output API v2" (#7803)"

This reverts commit dfb6ef949b.

* more specific v2 detection

* use nuxt@3.0.0-rc.3 to make sure the incident is resolved

* set test timeout to see if this works in CI

* update CI node version to 14

* add node_modules because it was taking too long to install in CI

* remove timeout

* remove node modules

* remove the nuxt@3 dependency

* finish update to node 14

* blank yarn.lock

* revert node version update

* fix revert

* remove newline
2022-05-20 12:27:14 -07:00
Nathan Rajlich
3a8b8aa03a [cli] Hard-code VERCEL: 1 env var for "vc build" (#7843)
This env var should normally come from the `.env` file that is created from `vc pull`, but let's just be extra sure and hard-code it directly in to `vc build` command as well.

SvelteKit `adapter-vercel` depends on this env var being set for its detection logic.
2022-05-20 18:53:55 +00:00
Nathan Rajlich
d008617c0b [frameworks] Use @vercel/remix Builder for "remix" preset (#7831)
Specify the `useRuntimes` property for the "remix" framework
to use the `@vercel/remix` Builder.

The `ENABLE_FILE_SYSTEM_API` env var is no longer necessary so the
`vercel.json` file from the Remix template has also been deleted.
2022-05-20 11:41:36 -05:00
Steven
8aecb99447 [cli] Recommend vc env instead of vc secrets (#6217)
We no longer need `vercel secrets` command. The former use cases can be solved with `vercel env`.

This adds a note recommending to use `vc env` as an alternative.

<img width="544" alt="Screen Shot 2021-08-11 at 1 38 18 PM" src="https://user-images.githubusercontent.com/71256/129101031-73e915dd-8253-4901-8e34-4b37d9516100.png">
<img width="565" alt="Screen Shot 2021-08-11 at 1 41 06 PM" src="https://user-images.githubusercontent.com/71256/129101036-2ed053dc-3de6-4fc1-8071-1bf9206323c9.png">
2022-05-20 15:43:20 +00:00
Andrew Gadzik
1793fa643f Add list of supported monorepo managers (#7760)
This file will mimic the structure of `vercel/frameworks/frameworks.ts` in the sense that it defines the list of supported monorepo managers.  These are the ones were targeting for the initial launch,

- Turborepo

```ts
export const monorepoManagers = [
  {
    name: "Turborepo",
    slug: "turbo",
    detectors: {
      every: [
        {
          path: 'turbo.json'
        },
      ],
    },
  },
]
```

### Related Issues

> Closes https://github.com/vercel/vercel/issues/7757

### 📋 Checklist

<!--
  Please keep your PR as a Draft until the checklist is complete
-->

#### Tests

- [x] The code changed/added as part of this PR has been covered with tests
- [x] All tests pass locally with `yarn test-unit`

#### Code Review

- [x] This PR has a concise title and thorough description useful to a reviewer
- [x] Issue from task tracker has a link to this PR
2022-05-20 15:20:50 +00:00
Nathan Rajlich
913683a8e6 [next] Use substring() instead of substr() (#7839)
Fixes linting warnings, i.e.:

> packages/next/src/server-build.ts#L858
>
> substr() is deprecated, use slice() or substring() instead
2022-05-20 14:58:39 +00:00
Nathan Rajlich
0d1dc23d0d [cli] Don't use tree-kill for shutting down startDevServer() process in vc dev (#7830)
Follow-up to #7824 since using `tree-kill` here seems to make a CLI test hang forever.
2022-05-19 18:16:09 -07:00
Nathan Rajlich
e829ce47c3 Publish Canary
- @vercel/build-utils@3.1.1-canary.0
 - vercel@24.2.5-canary.0
 - @vercel/client@11.0.4-canary.0
 - @vercel/go@1.4.4-canary.0
 - @vercel/next@2.8.67-canary.0
 - @vercel/node@1.15.4-canary.0
 - @vercel/python@2.3.4-canary.0
 - @vercel/redwood@0.8.4-canary.0
 - @vercel/remix@0.0.2-canary.0
 - @vercel/ruby@1.3.7-canary.0
 - @vercel/static-build@0.25.3-canary.0
2022-05-19 16:56:36 -07:00
Nathan Rajlich
474770e9b0 [remix] Add @vercel/remix Builder (#7814)
Adds a new Builder for the Remix framework. This Builder has support for a few different configurations of Remix including the "just the basics" Remix server as well as the "vercel" server build target configuration. If the project does not have the `@remix-run/vercel` runtime adapter as a dependency in package.json then this Builder will implicitly add it when generating the SSR serverless function.

In a follow-up PR, we can make this Builder be used in the frameworks configuration so that it is executed when `remix` framework is selected for the project, and we can update the remix example template in this repo to no longer require the `ENABLE_FILE_SYSTEM_API` env var.
2022-05-19 22:54:00 +00:00
Nathan Rajlich
e762d8d4e8 [cli] Add vercel build command (#7673)
This PR adds the latest iteration of the `vc build` command which invokes the Builders that a Project depends on locally and serializes the output into the `.vercel/output` directory.
2022-05-19 22:11:07 +00:00
Steven
6e8935883b Publish Stable
- @vercel/build-utils@3.1.0
 - vercel@24.2.4
 - @vercel/client@11.0.3
 - @vercel/frameworks@0.9.1
 - @vercel/go@1.4.3
 - @vercel/next@2.8.66
 - @vercel/node-bridge@2.2.2
 - @vercel/node@1.15.3
 - @vercel/python@2.3.3
 - @vercel/redwood@0.8.3
 - @vercel/routing-utils@1.13.3
 - @vercel/ruby@1.3.6
 - @vercel/static-build@0.25.2
 - @vercel/static-config@1.0.1
2022-05-19 16:30:30 -04:00
Steven
1c3497dc74 Publish Canary
- vercel@24.2.4-canary.1
 - @vercel/next@2.8.66-canary.1
 - @vercel/node@1.15.3-canary.1
 - @vercel/redwood@0.8.3-canary.1
2022-05-19 16:18:29 -04:00
JJ Kasper
9836fdb5ca [next][node][redwood] Update to latest version of @vercel/nft (#7827)
### Related Issues

x-ref: https://github.com/vercel/nft/releases/tag/0.19.0

### 📋 Checklist

<!--
  Please keep your PR as a Draft until the checklist is complete
-->

#### Tests

- [ ] The code changed/added as part of this PR has been covered with tests
- [ ] All tests pass locally with `yarn test-unit`

#### Code Review

- [ ] This PR has a concise title and thorough description useful to a reviewer
- [ ] Issue from task tracker has a link to this PR
2022-05-19 19:49:48 +00:00
JJ Kasper
d6f88f019f [next] Fix loading next launcher with type: module in package.json (#7828)
### Related Issues

Currently if you have a `package.json` with `type: 'module'` the launcher will fail to load as it is not using ESM and isn't using the `.cjs` extension. This corrects the extension per the below error message. 

```sh
ReferenceError: exports is not defined in ES module scope
This file is being treated as an ES module because it has a '.js' file extension and '/var/task/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.
```

x-ref: https://github.com/vercel/next.js/issues/36903

### 📋 Checklist

<!--
  Please keep your PR as a Draft until the checklist is complete
-->

#### Tests

- [ ] The code changed/added as part of this PR has been covered with tests
- [ ] All tests pass locally with `yarn test-unit`

#### Code Review

- [ ] This PR has a concise title and thorough description useful to a reviewer
- [ ] Issue from task tracker has a link to this PR
2022-05-19 19:23:29 +00:00
JJ Kasper
0f720472c4 [cli] Migrate Dev tests from ava to jest (#7822)
* Migrate ava cli dev tests to jest

* remove outdated test

* update tests

* Update utils

* update stdio to fix stalling

* test stdio tests

* add debug logs

* more logs

* use strip ansi

* update

* add exit flag and fix next dev test

* update timeout for mac ci

* update cancel

* update cancel tests.yml -> test.yml

* update other ids -> names

* remove outdated test

* de-dupe scripts

* remove redwood dev test due to size
2022-05-19 14:01:13 -05:00
JJ Kasper
8d0c5114e4 Update to latest version of turbo (#7829) 2022-05-19 13:35:26 -05:00
Nathan Rajlich
e3c4435606 [cli] Fix "now-dev-next" and "now-dev-static-build-routing" unit tests (#7824)
These two tests have been problematic on MacOS for a long time,
but now that we've re-introduced `@vercel/next` into this repo,
they've started to fail on Linux/Windows as well.

So the idea is to use the `devCommand` property so that
`@vercel/next` Builder doesn't get invoked at all.

Since the `devCommand` property was not yet being unit tested,
some logic in `vc build` needed to be adjusted in order to properly
shut down the dev command (via `tree-kill` module) when the
process was being stopped in order to cleanly shut down.
2022-05-19 09:27:51 -07:00
Steven
234c4dfa84 [tests] Update codeowners (#7825) 2022-05-19 11:43:27 -04:00
Nathan Rajlich
acd756436c [node] Fix 11-symlinks integration test fixture (#7823)
The `symlink` symlink wasn't being persisted through Turbo's cache,
so this test was failing. So move the symlink directly into the git repo
since there's no need to create it at build-time (git can store symlinks
just fine).

Additionally, the test itself was not testing that the symlink was indeed
re-created as a symlink from within the lambda environment (it actually
wasn't, due to the upload code not considering symlinks), so the test
has been updated to test for that as well.
2022-05-18 22:04:58 -07:00
Nathan Rajlich
f26858b735 Publish Canary
- @vercel/build-utils@3.0.2-canary.0
 - vercel@24.2.4-canary.0
 - @vercel/client@11.0.3-canary.0
 - @vercel/frameworks@0.9.1-canary.0
 - @vercel/go@1.4.3-canary.0
 - @vercel/next@2.8.66-canary.0
 - @vercel/node-bridge@2.2.2-canary.0
 - @vercel/node@1.15.3-canary.0
 - @vercel/python@2.3.3-canary.0
 - @vercel/redwood@0.8.3-canary.0
 - @vercel/routing-utils@1.13.3-canary.0
 - @vercel/ruby@1.3.6-canary.0
 - @vercel/static-build@0.25.2-canary.0
 - @vercel/static-config@1.0.1-canary.0
2022-05-18 16:54:08 -07:00
Nathan Rajlich
623e43f865 [next] Add @vercel/next Builder (#7793) 2022-05-18 23:51:48 +00:00
Sean Massa
3e696513a2 [examples] add .output to .vercelignore (#7817)
When running `nuxi build` locally, you'll end up with a `.output` directory. This is not used to produce a vercel deployment and can cause confusion with Build Output API v2 (which also expects a `.output` directory). It's better to leave this ignored.
2022-05-18 21:35:15 +00:00
JJ Kasper
285f62c9d0 Remove un-needed use of secret for team as it mangles logs (#7818)
### Related Issues

This removes the secret for turbo team as it filters anywhere vercel is printed in the logs and it doesn't really need to be secret. 

x-ref: https://github.com/vercel/vercel/runs/6496893033?check_suite_focus=true

### 📋 Checklist

<!--
  Please keep your PR as a Draft until the checklist is complete
-->

#### Tests

- [ ] The code changed/added as part of this PR has been covered with tests
- [ ] All tests pass locally with `yarn test-unit`

#### Code Review

- [ ] This PR has a concise title and thorough description useful to a reviewer
- [ ] Issue from task tracker has a link to this PR
2022-05-18 21:02:36 +00:00
JJ Kasper
c43db1788c [tests] Add cross platform chunked testing and leverage turbo more (#7795)
* [tests] Use `turbo` for unit tests

* .

* .

* Revert "."

This reverts commit 3d6204fef3fda3c7b4bf08955a186fe806d7c597.

* Add "src/util/constants.ts" to outputs

* .

* Add `@vercel/node-bridge` outputs

* .

* Mac and Windows

* .

* Node 14

* .

* .

* Add templates to CLI output

* Run only selected test files

* Add cross platform testing

* make test paths relative and have minimum per chunk

* add install arg

* update shell

* bump cache key

* use backslashes on windows

* pass tests as arg

* update script name

* update turbo config

* forward turbo args correctly

* dont use backslashes

* chunk integration tests instead

* update env

* separate static-build tests

* ensure unit test turbo cache is saved

* ensure turbo cache is saved for dev/cli

* fix cache key and update timeout

* Increase static-build unit test timeout

* Leverage turbo remote caching instead of actions/cache

* apply suggestions and test chunking itself

* update other ci jobs

* fix test collecting

Co-authored-by: Nathan Rajlich <n@n8.io>
2022-05-18 13:27:20 -07:00
haitrungle
fc2eb1a30d [examples] Fix typo in SolidStart link (#7589) 2022-05-18 10:42:24 -07:00
Sean Massa
ecf194b7c1 [tests] improve platform-based skips (#7802)
Co-authored-by: Steven <steven@ceriously.com>
2022-05-17 12:12:47 -05:00
Steven
c14e5689f1 [tests] Skip broken go test (#7809)
This test was added several years ago, before the monorepo in https://github.com/vercel/vercel/pull/2812 but it was never working correctly due to the way zero config behaves differently than the test with `builds` in vercel.json

We can fix it in a follow up PR
2022-05-16 14:44:09 -04:00
Steven
54dfe747e2 [build-utils] Deprecate Node.js 12.x with warning (#7779)
Node.js 12 reached EOL April 2022 so its time to notify customers.

This PR will warn starting today and then error once the discontinue date is reached in a couple months.
2022-05-16 16:06:39 +00:00
Steven
2afc8db8e7 Publish Stable
- vercel@24.2.3
 - @vercel/static-build@0.25.1
2022-05-13 18:30:15 -04:00
Steven
cc628dd9fb Publish Canary
- vercel@24.2.3-canary.0
 - @vercel/static-build@0.25.1-canary.0
2022-05-13 18:20:41 -04:00
Steven
dfb6ef949b Revert "[static-build] Support subset of Build Output API v2" (#7803)
Revert "[static-build] Support subset of Build Output API v2 (#7690)"

This reverts commit 05243fb6e9.
2022-05-13 18:19:38 -04:00
Sean Massa
cd4799b5d5 [cli] distinguish error messages (#7794)
* distinguish error messages

* use correct response and assertion

* remove check for APIError because getUser does not always throw those
2022-05-13 12:49:36 -05:00
Steven
5e66d4b2cc Publish Stable
- @vercel/build-utils@3.0.1
 - vercel@24.2.2
 - @vercel/client@11.0.2
 - @vercel/go@1.4.2
 - @vercel/node@1.15.2
 - @vercel/python@2.3.2
 - @vercel/redwood@0.8.2
 - @vercel/ruby@1.3.5
 - @vercel/static-build@0.25.0
2022-05-12 17:19:06 -04:00
Ethan Arrowood
44d7473e7c Publish Canary
- @vercel/redwood@0.8.2-canary.2
 - @vercel/static-build@0.24.2-canary.2
2022-05-12 13:48:21 -06:00
Ethan Arrowood
fddec1286c [redwood][static-build] move path logic up so both commands get pnpm7 (#7792)
move path logic up so both commands get pnpm7
2022-05-12 13:47:09 -06:00
Ethan Arrowood
6e5e700e8d Publish Canary
- vercel@24.2.2-canary.2
 - @vercel/node@1.15.2-canary.1
 - @vercel/redwood@0.8.2-canary.1
 - @vercel/static-build@0.24.2-canary.1
2022-05-12 09:04:20 -06:00
Ryan Carniato
b6e8609b83 [examples] Update SolidStart to Build Output API v3 (#7790) 2022-05-11 23:12:53 -07:00
Ethan Arrowood
78b7bd5ec8 [redwood][static-build] add pnpm7 detection logic to builders (#7787)
add pnpm7 detection logic to builders
2022-05-11 19:37:01 -04:00
Steven
4104a45c2d [tests] Fix node tests (#7786)
Since we released Node.js 16, these tests now resolve `engines` differently
2022-05-11 23:36:18 +00:00
Ethan Arrowood
4c20218e05 Publish Canary
- @vercel/build-utils@3.0.1-canary.1
 - vercel@24.2.2-canary.1
 - @vercel/client@11.0.2-canary.0
 - @vercel/go@1.4.2-canary.0
 - @vercel/node@1.15.2-canary.0
 - @vercel/python@2.3.2-canary.0
 - @vercel/redwood@0.8.2-canary.0
 - @vercel/ruby@1.3.5-canary.0
 - @vercel/static-build@0.24.2-canary.0
2022-05-11 15:47:48 -06:00
Ethan Arrowood
02a0004719 [build-utils] Fix pnpm 7 path setting (#7785)
### Related Issues

Fixes pnpm 7 support. Now uses a yarn installed version and drops an unnecessary check for node version.

### 📋 Checklist

<!--
  Please keep your PR as a Draft until the checklist is complete
-->

#### Tests

- [ ] The code changed/added as part of this PR has been covered with tests
- [ ] All tests pass locally with `yarn test-unit`

#### Code Review

- [ ] This PR has a concise title and thorough description useful to a reviewer
- [ ] Issue from task tracker has a link to this PR
2022-05-11 21:37:44 +00:00
Steven
123bffb776 [examples] Pin Ember to 14.x (#7782) 2022-05-10 14:34:46 -04:00
Steven
074535f27c [build-utils] Downgrade remix and solidstart to Node.js 14 (fsapi) (#7781)
These frameworks (remix and solidstart) use the legacy file system api (v2) so they can't support Node.js 16.x so we change engines to pin to Node.js 14.x

I also added the missing `ENABLE_FILE_SYSTEM_API=1` env var to solidstart to match remix.

https://vercel.com/docs/file-system-api/v2
2022-05-10 13:20:07 -04:00
Sean Massa
05243fb6e9 [static-build] Support subset of Build Output API v2 (#7690) 2022-05-09 14:01:26 -07:00
Sean Massa
097725580c [tests] skip flakey test (#7777)
Skips two flakey tests on Mac OS only. The error often looks like:

<img width="1453" alt="Screen Shot 2022-05-09 at 2 26 52 PM" src="https://user-images.githubusercontent.com/41545/167483088-49498f69-5470-4c1a-98f5-96ca811b838b.png">

Created internal tracking card to dig deeper. Skipping this for now will unclog other work.
2022-05-09 21:00:49 +00:00
Andrew Gadzik
4b09c89e7d [build-utils] Fix version mismatch (#7776)
Fixes 3a1eede63b
2022-05-09 14:51:04 -04:00
agadzik
3a1eede63b Publish Canary
- @vercel/build-utils@3.0.1-canary.0
 - vercel@24.2.2-canary.0
2022-05-09 13:51:37 -04:00
agadzik
9cee0dd5d7 BREAKING CHANGE: updating build-utils to version 3 for DetectorFilesystem changes 2022-05-09 13:47:11 -04:00
John Pham
b801c6e593 [cli] Track source of getting decrypted environment variables (#7754)
* Track source of getting decrypted environment variables

* Add source as a query param

* Revert lock file changes

* Change source from strings to type

* Differential between pull and env pull
2022-05-09 10:24:43 -07:00
Andrew Gadzik
505050b923 [build-utils] Add readdir and chdir functions to DetectorFilesystem (#7751)
In order to support various `fs` operations for monorepo detection, the team needs to add two new abstract functions to `DetectorFilesystem` in order to traverse down into children directories

* readdir
* chdir

```ts
interface Stat {
  name: string
  path: string
  type: "file" | "dir"
}

export abstract class DetectorFilesystem {
  ...
  /**
   * Returns a list of Stat objects from the current working directory.
   * 
   * @example
   * 
   * const url = "https://github.com/vercel/front"
   * const fs = new GitDetectorFilesystem(...) // based on url
   *
   * // calls "https://api.github.com/repos/vercel/front/contents" behind the scenes
   * await fs.readdir() => [
   *    { name: "docs", path: "docs", type: "dir" },
   *    { name: "front", path: "front", type: "dir" },
   *    ...,
   *    { name: "package.json", path: "package.json", type: "file" },
   * ]
   */
   protected abstract _readdir(name: string): Promise<Stat[]>;

 /**
   * Changes the current directory to the specified path and returns a new instance of DetectorFilesystem.
   * 
   * @example
   * 
   * my-repo
   * |-- backend
   * |    |-- api-1
   * |    |-- api-2
   * |    |-- package.json // workspaces: ["api-1", "api-2"]
   * |    |-- yarn.lock
   * |-- frontend
   * |    |-- nextjs-app
   * |    |-- gatsby-app
   * |    |-- package.json
   * |    |-- pnpm-workspaces.yaml // packages: ["nextjs-app", "gatsby-app"]
   * 
   * const fs = new (...) // based on "my-repo" as the root
   * const backendFs = fs.chdir("backend")
   * const frontendFs = fs.chdir("frontend")
   * 
   * const backendWorkspaceManager = detectFramework({ fs: backendFs, frameworkList: workspaceManagers }) // "yarn"
   * const frontendWorkspaceManager = detectFramework({ fs: frontendFs, frameworkList: workspaceManagers }) // "pnpm"
   */
   protected abstract _chdir(name: string): DetectorFilesystem
   ...
}
```

### Related Issues

> Related to https://github.com/vercel/vercel/issues/7750

### 📋 Checklist

<!--
  Please keep your PR as a Draft until the checklist is complete
-->

#### Tests

- [x] The code changed/added as part of this PR has been covered with tests
- [x] All tests pass locally with `yarn test-unit`

#### Code Review

- [x] This PR has a concise title and thorough description useful to a reviewer
- [x] Issue from task tracker has a link to this PR
2022-05-09 17:12:30 +00:00
Steven
15c7ad241a Publish Stable
- @vercel/build-utils@2.17.0
 - vercel@24.2.1
 - @vercel/client@11.0.1
 - @vercel/frameworks@0.9.0
 - @vercel/go@1.4.1
 - @vercel/node@1.15.1
 - @vercel/python@2.3.1
 - @vercel/redwood@0.8.1
 - @vercel/ruby@1.3.4
 - @vercel/static-build@0.24.1
2022-05-09 10:41:56 -04:00
Steven
ec57654b5b Publish Canary
- @vercel/build-utils@2.16.1-canary.4
 - vercel@24.2.1-canary.4
 - @vercel/client@11.0.1-canary.4
 - @vercel/go@1.4.1-canary.4
 - @vercel/node@1.15.1-canary.4
 - @vercel/python@2.3.1-canary.4
 - @vercel/redwood@0.8.1-canary.4
 - @vercel/ruby@1.3.4-canary.4
 - @vercel/static-build@0.24.1-canary.4
2022-05-09 10:13:58 -04:00
Steven
3b9a9878bc [build-utils] Add Node.js 16.x (#7772)
Add support for Node.js 16

- Related to https://github.com/aws/aws-lambda-base-images/issues/14#issuecomment-1120864028
2022-05-09 10:13:11 -04:00
Nathan Rajlich
70b7db1a15 [node] Move @types/jest to "devDependencies" (#7768)
This should be a dev dep.
2022-05-09 09:23:10 -04:00
Nathan Rajlich
41d6666139 Publish Canary
- @vercel/build-utils@2.16.1-canary.3
 - vercel@24.2.1-canary.3
 - @vercel/client@11.0.1-canary.3
 - @vercel/frameworks@0.8.1-canary.1
 - @vercel/go@1.4.1-canary.3
 - @vercel/node@1.15.1-canary.3
 - @vercel/python@2.3.1-canary.3
 - @vercel/redwood@0.8.1-canary.3
 - @vercel/ruby@1.3.4-canary.3
 - @vercel/static-build@0.24.1-canary.3
2022-05-07 16:08:08 -07:00
Nathan Rajlich
2857219f89 Fix "astro" slug 2022-05-07 11:57:14 -07:00
Tony Sullivan
246c2a0f5d [frameworks] Add Astro (#7747) 2022-05-06 16:51:42 -07:00
Ethan Arrowood
d91bca7d6b Publish Canary
- @vercel/build-utils@2.16.1-canary.2
 - vercel@24.2.1-canary.2
 - @vercel/client@11.0.1-canary.2
 - @vercel/frameworks@0.8.1-canary.0
 - @vercel/go@1.4.1-canary.2
 - @vercel/node@1.15.1-canary.2
 - @vercel/python@2.3.1-canary.2
 - @vercel/redwood@0.8.1-canary.2
 - @vercel/ruby@1.3.4-canary.2
 - @vercel/static-build@0.24.1-canary.2
2022-05-06 14:16:00 -06:00
Ethan Arrowood
be54fce67b [build-utils] add pnpm7 to path when lockfile v5.4 is detected (#7758)
### Related Issues

Adds support for `pnpm@7` using a similar lock file detection and path setting method that `npm@7` uses

### 📋 Checklist

<!--
  Please keep your PR as a Draft until the checklist is complete
-->

#### Tests

- [x] The code changed/added as part of this PR has been covered with tests
- [x] All tests pass locally with `yarn test-unit`

#### Code Review

- [x] This PR has a concise title and thorough description useful to a reviewer
- [ ] Issue from task tracker has a link to this PR
2022-05-06 19:47:41 +00:00
Sean Massa
7753bb8d89 [cli] check prebuilt target env against deploy target env (#7748)
This check prevents a user from creating a build output targeting one environment (like `preview`) and deploying targeting another environment (like `production`). It checks `.vercel/output/builds.json` for the `target` property to decide this. If that file is missing, the check is not run.
2022-05-06 07:06:07 +00:00
Logan McAnsh
ce17ac5c35 [frameworks] Update Remix detection to check for "remix.config.js" (#7761)
The "remix" magic package is no longer preferred by Remix,
so anyone who is using a modern template won't have it installed.

Checking for `remix.config.js` is safer detection logic.
2022-05-05 19:13:44 -07:00
Sean Massa
8006fc32b8 [cli] require non-TTY uses of pull to also pass --yes (#7700)
Checks for `TTY` input to decide to handle the command or not. If the input is not TTY and the user did not pass the `--yes` option, the CLi will exit with the message:

> Command `vercel pull` requires confirmation. Use option "--yes" to confirm.
2022-05-05 22:40:26 +00:00
Nathan Rajlich
8038a90db1 [node] Use TypeScript for unit tests (#7756)
Random change I had in my working directory.
2022-05-05 19:13:01 +00:00
agadzik
f88c862e9d Publish Canary
- @vercel/build-utils@2.16.1-canary.1
 - vercel@24.2.1-canary.1
 - @vercel/client@11.0.1-canary.1
 - @vercel/go@1.4.1-canary.1
 - @vercel/node@1.15.1-canary.1
 - @vercel/python@2.3.1-canary.1
 - @vercel/redwood@0.8.1-canary.1
 - @vercel/ruby@1.3.4-canary.1
 - @vercel/static-build@0.24.1-canary.1
2022-05-05 14:11:13 -04:00
Nathan Rajlich
9170820371 [build-utils] Add ShouldServe type (#7755)
Version 3 Builders can define a `shouldServe()` function that is used in `vercel dev`, so add the proper type for that.
2022-05-05 17:06:20 +00:00
Andrew Gadzik
c881546e0e [build-utils] Add supported list of workspace managers (#7737)
In order to support monorepo detection, we need to build out the list of supported workspace managers so that our helper functions and API endpoints can utilize the same `detectFramework` function / logic to detect a workspace manager for a given git repository.

### Related Issues

- Closes https://github.com/vercel/vercel/issues/7731

### 📋 Checklist

<!--
  Please keep your PR as a Draft until the checklist is complete
-->

#### Tests

- [x] The code changed/added as part of this PR has been covered with tests
- [x] All tests pass locally with `yarn test-unit`

#### Code Review

- [x] This PR has a concise title and thorough description useful to a reviewer
- [x] Issue from task tracker has a link to this PR
2022-05-05 14:44:34 +00:00
Nathan Rajlich
fa21db98e4 [cli] Revert "Use @vercel/fetch-retry in CLI integration tests" (#7738)
This reverts commit 03a8fbd3a7 (#7360).
2022-05-04 17:15:54 +00:00
Ethan Arrowood
8eabbfc666 Publish Canary
- @vercel/build-utils@2.16.1-canary.0
 - vercel@24.2.1-canary.0
 - @vercel/client@11.0.1-canary.0
 - @vercel/go@1.4.1-canary.0
 - @vercel/node@1.15.1-canary.0
 - @vercel/python@2.3.1-canary.0
 - @vercel/redwood@0.8.1-canary.0
 - @vercel/ruby@1.3.4-canary.0
 - @vercel/static-build@0.24.1-canary.0
2022-05-02 11:33:22 -06:00
Ethan Arrowood
6783f7afc9 [build-utils] Fix package manager auto detection precedence (#7733)
### Related Issues

improves package manager auto detection so that when multiple lock files are found, the highest priority one is selected rather than defaulting to yarn. 

### 📋 Checklist

<!--
  Please keep your PR as a Draft until the checklist is complete
-->

#### Tests

- [x] The code changed/added as part of this PR has been covered with tests
- [ ] All tests pass locally with `yarn test-unit`

#### Code Review

- [ ] This PR has a concise title and thorough description useful to a reviewer
- [ ] Issue from task tracker has a link to this PR
2022-05-02 17:22:01 +00:00
Steven
a400b9b29d Publish Stable
- @vercel/build-utils@2.16.0
 - vercel@24.2.0
 - @vercel/client@11.0.0
 - @vercel/frameworks@0.8.0
 - @vercel/go@1.4.0
 - @vercel/node-bridge@2.2.1
 - @vercel/node@1.15.0
 - @vercel/python@2.3.0
 - @vercel/redwood@0.8.0
 - @vercel/routing-utils@1.13.2
 - @vercel/ruby@1.3.3
 - @vercel/static-build@0.24.0
 - @vercel/static-config@1.0.0
2022-04-29 14:11:32 -04:00
Steven
b549c37149 [build-utils][static-build] Replace 00a0 with space (#7732) 2022-04-28 22:25:24 -04:00
Nathan Rajlich
30d5e64291 Publish Canary
- @vercel/build-utils@2.15.2-canary.6
 - vercel@24.1.1-canary.8
 - @vercel/client@10.4.2-canary.7
 - @vercel/go@1.3.3-canary.6
 - @vercel/node@1.14.2-canary.7
 - @vercel/python@2.2.3-canary.6
 - @vercel/redwood@0.7.1-canary.6
 - @vercel/ruby@1.3.3-canary.6
 - @vercel/static-build@0.23.2-canary.6
2022-04-28 17:50:59 -07:00
Nathan Rajlich
47c2c361d2 [build-utils] Update "yazl" dependency (#7734)
The older version of "yazl" was using `new Buffer()` which causes
deprecation warnings to be printed. The latest version avoids that.
2022-04-28 17:47:10 -07:00
Nathan Rajlich
438576fc7c Publish Canary
- @vercel/build-utils@2.15.2-canary.5
 - vercel@24.1.1-canary.7
 - @vercel/client@10.4.2-canary.6
 - @vercel/frameworks@0.7.2-canary.1
 - @vercel/go@1.3.3-canary.5
 - @vercel/node@1.14.2-canary.6
 - @vercel/python@2.2.3-canary.5
 - @vercel/redwood@0.7.1-canary.5
 - @vercel/ruby@1.3.3-canary.5
 - @vercel/static-build@0.23.2-canary.5
 - @vercel/static-config@1.0.0-canary.1
2022-04-28 11:53:39 -07:00
Steven
b30343ef7b [tests] Bump dependencies for jest/eslint/prettier/turbo/etc (#7727) 2022-04-28 14:52:46 -04:00
Ethan Arrowood
2dc0dfa572 [node][static-build][redwood] Add root path pattern to prepareCache() (#7710) 2022-04-27 21:17:44 -07:00
Steven
9ee54b3dd6 [static-build] Resolve git.io links (#7722)
https://github.blog/changelog/2022-04-25-git-io-deprecation/
2022-04-26 21:57:12 -04:00
Steven
9d67e0bc06 [python] Add discontinue date for Python 3.6 (#7709)
This PR does a few things:
- Changes the existing warning message for Python 3.6 to print a discontinue date
- Will automatically fail new Python 3.6 deployments created after that date
- Consolidates logic to make Python version selection work in a similar manner to Node.js version selection
- Changes tests from JS to TS
2022-04-26 15:49:19 -04:00
Steven
466135cf84 Publish Canary
- @vercel/build-utils@2.15.2-canary.4
 - vercel@24.1.1-canary.6
 - @vercel/client@10.4.2-canary.5
 - @vercel/go@1.3.3-canary.4
 - @vercel/node@1.14.2-canary.5
 - @vercel/python@2.2.3-canary.4
 - @vercel/redwood@0.7.1-canary.4
 - @vercel/ruby@1.3.3-canary.4
 - @vercel/static-build@0.23.2-canary.4
2022-04-25 12:49:34 -04:00
Steven
eab2e229dc [build-utils] Add warning for experimental Node.js (#7717) 2022-04-25 12:49:04 -04:00
Steven
698b89a2ba Publish Canary
- @vercel/build-utils@2.15.2-canary.3
 - vercel@24.1.1-canary.5
 - @vercel/client@10.4.2-canary.4
 - @vercel/frameworks@0.7.2-canary.0
 - @vercel/go@1.3.3-canary.3
 - @vercel/node@1.14.2-canary.4
 - @vercel/python@2.2.3-canary.3
 - @vercel/redwood@0.7.1-canary.3
 - @vercel/ruby@1.3.3-canary.3
 - @vercel/static-build@0.23.2-canary.3
2022-04-25 12:02:13 -04:00
Steven
bae2a2e4df [python] Upgrade tests (#7711)
* [python] Upgrade tests

* Fix latest sanic asgi

* Bump flask

* Change requirements.txt to Pipfile

* Fix dev test

* Use verbose requirements.txt

* Flip requirements
2022-04-25 12:01:49 -04:00
Steven
57916bb712 [build-utils] Add env var ENABLE_EXPERIMENTAL_NODE16 (#7489)
This PR uses an environment variable since this feature is not available to all accounts yet.
2022-04-25 11:07:16 -04:00
Sean Massa
12bbd4e8eb [cli] Update language of prebuilt error (#7702) 2022-04-22 09:55:27 -07:00
Aaron Morris
4e4c7023dc [frameworks] Add opt-in darkModeLogo to Framework in packages/frameworks (#7693)
Supply light mode logos over the frameworks API to be consumed by front

### Related Issues

### 📋 Checklist

<!--
  Please keep your PR as a Draft until the checklist is complete
-->

#### Tests

- [ ] The code changed/added as part of this PR has been covered with tests
- [ ] All tests pass locally with `yarn test-unit`

#### Code Review

- [x] This PR has a concise title and thorough description useful to a reviewer
- [ ] Issue from task tracker has a link to this PR
2022-04-22 16:49:39 +00:00
Nathan Rajlich
41805790e7 [static-build] Support Build Output API v3 cache property in prepareCache() (#7704)
When a framework that outputs Build Output API v3 specifies the `cache`
property in the `config.json` file then static-build will include those
files in the `prepareCache()` function result.
2022-04-21 18:04:21 -07:00
Ethan Arrowood
6ad77ae8e1 Publish Canary
- vercel@24.1.1-canary.4
 - @vercel/client@10.4.2-canary.3
2022-04-21 16:01:41 -06:00
Ethan Arrowood
e8daf36cd7 only revert override feature (#7701) 2022-04-21 15:59:55 -06:00
Nathan Rajlich
c319a2c499 [client] Remove single file deployment root path / route (#7699)
This is strange behavior, and also inconsistent compared to how a Git deployment is created. Let's remove it.
2022-04-21 00:35:25 +00:00
Sean Massa
a410baa797 [cli] check for prebuilt directory (#7697)
When using `vc deploy --prebuilt`, we need to check for an actual ".vercel/output" before attempting to deploy. This PR adds a a check for that. Now...

In a directory without `.vercel/output`:

```
$ vc deploy --prebuilt
Error! Option `--prebuilt` was used, but no prebuilt deploy found in ".vercel/output"
```

In a direcotry with `.vercel/output` (where I've not linked it yet):

```
$ vc deploy --prebuilt
? Set up and deploy “~/source/vercel/examples/build-output-api/serverless-function”? [Y/n]
```
2022-04-20 19:54:47 +00:00
Dominik Ferber
625568e659 fix ts-eager (#7677)
Switches await import() to require().default so that ts-eager understands them.

closes #7676
2022-04-20 10:30:48 -07:00
Nathan Rajlich
41868c1fe0 [cli] Ensure .vercel directory is created in vc pull (#7695)
When the `.vercel` directory does not exist and the env vars
(`VERCEL_PROJECT_ID`/`VERCEL_ORG_ID`) are used for project
linking, the `vercel pull` command was throwing an error:

```
$ VERCEL_PROJECT_ID=xxxxxxxx VERCEL_ORG_ID=xxxxxxxxxx vercel pull
Vercel CLI 24.1.1-canary.3 — https://vercel.com/feedback
Downloading "development" Environment Variables for Project t
Error! ENOENT: no such file or directory, open '/Code/t/.vercel/.env.development.local'
```
2022-04-19 20:49:44 -07:00
Steven
1b644f1218 [docs] Update available runtimes (#7692) 2022-04-19 12:08:46 -04:00
Sean Massa
29ea0fb06b [examples] Remove amp example (#7686) 2022-04-17 19:29:56 -04:00
Ethan Arrowood
b61f049f11 Publish Canary
- @vercel/build-utils@2.15.2-canary.2
 - vercel@24.1.1-canary.3
 - @vercel/client@10.4.2-canary.2
 - @vercel/go@1.3.3-canary.2
 - @vercel/node@1.14.2-canary.3
 - @vercel/python@2.2.3-canary.2
 - @vercel/redwood@0.7.1-canary.2
 - @vercel/ruby@1.3.3-canary.2
 - @vercel/static-build@0.23.2-canary.2
2022-04-15 15:26:55 -06:00
Ethan Arrowood
16e28f326b [cli] Allow projectSettings override in vercel.json (#7619)
This PR adds the required changes to the CLI to support overridable `vercel.json` `projectSettings` values. This PR is linked with changes on the API side too.

- The core changes are in `packages/cli/src/commands/deploy/index.ts`
- An unused code path was removed from `packages/client/src/create-deployment.ts`, `packages/cli/src/util/deploy/process-deployment.ts` and `packages/cli/src/util/index.ts`.

This will only work for *existing* deployment (not *new* ones). This is implemented by checking the `status` of the deployment (is it linked or not). An error is thrown if the user attempts to send overrided settings to a new project. 

A warning is outputted when overrided settings are discovered and shares what settings are being overridden.

### 📋 Checklist

<!--
  Please keep your PR as a Draft until the checklist is complete
-->

#### Tests

- [x] The code changed/added as part of this PR has been covered with tests
- [x] All tests pass locally with `yarn test-unit`

#### Code Review

- [x] This PR has a concise title and thorough description useful to a reviewer
- [ ] Issue from task tracker has a link to this PR
2022-04-15 21:20:00 +00:00
Sean Massa
276397c940 [examples] fixed vercel deploy link (#7684) 2022-04-15 13:55:42 -05:00
Nathan Rajlich
85d7311199 [static-build] Misc TypeScript cleanup (#7682)
This was just sitting on my local checkout so might as well push it.
2022-04-15 09:42:32 -07:00
Sean Massa
b8114b8b39 [cli] set environment properly in vc pull (#7656)
This PR sets environment properly in `vc pull`. The system env vars were not respecting the target `--environment`.

Adds tests for related `vc env` logic.
2022-04-15 04:41:29 +00:00
QianyuPan
d63e8d3187 [go] Add support for version 1.18 (#7590)
Go 1.18 has been released, but I find that I can't deploy my project on Vercel when `go.mod` has `go 1.18` in it.

1.18 adds some very useful features. It would be very valuable for developers to have Vercel support 1.18.
2022-04-14 19:37:01 -04:00
JJ Kasper
11d3dd04aa Publish Canary
- vercel@24.1.1-canary.2
 - @vercel/node-bridge@2.2.1-canary.0
 - @vercel/node@1.14.2-canary.2
2022-04-14 17:04:05 -05:00
JJ Kasper
46bf95ee36 [node-bridge] Ensure content-type is always set with multi-payloads (#7681)
### Related Issues

This ensures a content-type is always set inside of each part of the multi-part payload as it's needed for proper parsing. This also ensures non-200 status codes/headers are passed back separate when they differ so that they can be handled independently without assuming they all match. 

x-ref: https://vercel.slack.com/archives/C03AYHB6MA9
x-ref: https://github.com/vercel/vercel/pull/7507

### 📋 Checklist

<!--
  Please keep your PR as a Draft until the checklist is complete
-->

#### Tests

- [ ] The code changed/added as part of this PR has been covered with tests
- [ ] All tests pass locally with `yarn test-unit`

#### Code Review

- [ ] This PR has a concise title and thorough description useful to a reviewer
- [ ] Issue from task tracker has a link to this PR
2022-04-14 22:00:10 +00:00
Nathan Rajlich
92252468c2 [tests] Add turbo.json and bump to turbo 1.2.2 (#7620)
* Add `turbo.json`

Ran `npx @turbo/codemod create-turbo-config` like the warnings have been telling us to.

* [tests] Bump `turbo` and allow `turbo.json` in `.vercelignore` (#7623)

Co-authored-by: Jared Palmer <jared@jaredpalmer.com>
Co-authored-by: Steven <steven@ceriously.com>
2022-04-13 11:09:47 -04:00
Nathan Rajlich
71b83d5587 Publish Canary
- @vercel/build-utils@2.15.2-canary.1
 - vercel@24.1.1-canary.1
 - @vercel/client@10.4.2-canary.1
 - @vercel/go@1.3.3-canary.1
 - @vercel/node@1.14.2-canary.1
 - @vercel/python@2.2.3-canary.1
 - @vercel/redwood@0.7.1-canary.1
 - @vercel/ruby@1.3.3-canary.1
 - @vercel/static-build@0.23.2-canary.1
2022-04-12 15:57:36 -07:00
Nathan Rajlich
d9e5fdc5e4 [build-utils] Move "Installing dependencies..." log to runNpmInstall() (#7672)
Follow-up to #7671. Since `runNpmInstall()` might now be de-duped, only
print "Installing dependencies..." when the dependencies are actually
being installed. This avoids printing the log message unnecessarily when
the command won't actually be run, and also removes some duplication in
the Builders' code.
2022-04-12 16:23:01 -04:00
Nathan Rajlich
58f479c603 [static-build] Add support for Build Output v3 detection (#7669)
Adds detection logic for a framework / build script outputting Build Output v3
format to the filesystem. In this case, `static-build` will simply stop processing
after the Build Command since deserialization happens in the build-container side
of things (this is different compared to the v1 output which gets handled in this
Builder. The reason for that is because the v3 output matches what `vc build`
outputs vs. v1 which is a different format).
2022-04-12 09:09:50 -07:00
Nathan Rajlich
d62461d952 [build-utils] Only allow runNpmInstall() to run once per package.json (#7671)
Adds a best-effort optimization to only run `npm install` once per
`pacakge.json` file. This will save a lot of time in the single-sandbox
build world (i.e. `vc build`).
2022-04-12 09:09:10 -07:00
Steven
e7f524defb Publish Canary
- @vercel/build-utils@2.15.2-canary.0
 - vercel@24.1.1-canary.0
 - @vercel/client@10.4.2-canary.0
 - @vercel/go@1.3.3-canary.0
 - @vercel/node@1.14.2-canary.0
 - @vercel/python@2.2.3-canary.0
 - @vercel/redwood@0.7.1-canary.0
 - @vercel/ruby@1.3.3-canary.0
 - @vercel/static-build@0.23.2-canary.0
2022-04-12 08:58:38 -04:00
Steven
bdefd0d05d [docs] Fix links to docs (#7668) 2022-04-12 07:52:12 -04:00
Ethan Arrowood
ca522fc9f1 [node][redwood] update @vercel/nft to 0.18.1 (#7670)
### Related Issues

Updates the @vercel/nft dependency across the repo to v0.18.1.

### 📋 Checklist

<!--
  Please keep your PR as a Draft until the checklist is complete
-->

#### Tests

- [ ] The code changed/added as part of this PR has been covered with tests
- [ ] All tests pass locally with `yarn test-unit`

#### Code Review

- [ ] This PR has a concise title and thorough description useful to a reviewer
- [ ] Issue from task tracker has a link to this PR
2022-04-11 22:07:45 +00:00
1509 changed files with 86224 additions and 10696 deletions

View File

@@ -19,6 +19,10 @@ packages/cli/src/util/dev/templates/*.ts
packages/client/tests/fixtures
packages/client/lib
# next
packages/next/test/integration/middleware
packages/next/test/integration/middleware-eval
# node-bridge
packages/node-bridge/bridge.js
packages/node-bridge/launcher.js

39
.github/CODEOWNERS vendored
View File

@@ -1,29 +1,26 @@
# Documentation
# https://help.github.com/en/articles/about-code-owners
* @TooTallNate
/.github/workflows @AndyBitz @styfle
/packages/frameworks @AndyBitz
/packages/cli/src/commands/build @TooTallNate @styfle @AndyBitz @gdborton @jaredpalmer
/packages/cli/src/commands/dev @TooTallNate @styfle @AndyBitz
/packages/cli/src/util/dev @TooTallNate @styfle @AndyBitz
* @TooTallNate @EndangeredMassa @styfle
/.github/workflows @TooTallNate @EndangeredMassa @styfle @ijjk
/packages/frameworks @TooTallNate @EndangeredMassa @styfle @AndyBitz
/packages/cli/src/commands/domains @javivelasco @mglagola @anatrajkovska
/packages/cli/src/commands/certs @javivelasco @mglagola @anatrajkovska
/packages/cli/src/commands/env @styfle @lucleray
/packages/client @styfle @TooTallNate
/packages/build-utils @styfle @AndyBitz @TooTallNate
/packages/client @TooTallNate @EndangeredMassa @styfle
/packages/build-utils @TooTallNate @EndangeredMassa @styfle @AndyBitz
/packages/middleware @gdborton @javivelasco
/packages/node @styfle @TooTallNate @lucleray
/packages/node-bridge @styfle @TooTallNate @lucleray
/packages/next @Timer @ijjk
/packages/go @styfle @TooTallNate
/packages/python @styfle @TooTallNate
/packages/ruby @styfle @TooTallNate
/packages/static-build @styfle @AndyBitz
/packages/routing-utils @styfle @dav-is @ijjk
/examples @mcsdevv
/packages/node @TooTallNate @EndangeredMassa @styfle
/packages/node-bridge @TooTallNate @EndangeredMassa @styfle @ijjk
/packages/next @TooTallNate @ijjk
/packages/go @TooTallNate @EndangeredMassa @styfle
/packages/python @TooTallNate @EndangeredMassa @styfle
/packages/ruby @TooTallNate @EndangeredMassa @styfle
/packages/static-build @TooTallNate @EndangeredMassa @styfle @AndyBitz
/packages/routing-utils @TooTallNate @EndangeredMassa @styfle @ijjk
/examples @leerob
/examples/create-react-app @Timer
/examples/nextjs @timneutkens @Timer
/examples/hugo @mcsdevv @styfle
/examples/jekyll @mcsdevv @styfle
/examples/zola @mcsdevv @styfle
/examples/nextjs @timneutkens @ijjk @styfle
/examples/hugo @styfle
/examples/jekyll @styfle
/examples/zola @styfle

View File

@@ -23,7 +23,7 @@ Make sure all the tests pass before making changes.
## Verifying your change
Once you are done with your changes (we even suggest doing it along the way), make sure all the test still pass by running:
Once you are done with your changes (we even suggest doing it along the way), make sure all the tests still pass by running:
```
yarn test-unit
@@ -64,7 +64,7 @@ Integration tests create deployments to your Vercel account using the `test` pro
x-now-trace=iad1]
```
In such cases you can visit the URL of the failed deployment and append `/_logs` so see the build error. In the case above, that would be https://test-8ashcdlew.vercel.app/_logs
In such cases, you can visit the URL of the failed deployment and append `/_logs` to see the build error. In the case above, that would be https://test-8ashcdlew.vercel.app/_logs
The logs of this deployment will contain the actual error which may help you to understand what went wrong.
@@ -82,11 +82,11 @@ nodeFileTrace(['path/to/entrypoint.js'], {
.then(e => console.error(e));
```
When you run this script, you'll see all imported files. If anything file is missing, the bug is in [@vercel/nft](https://github.com/vercel/nft) and not the Builder.
When you run this script, you'll see all the imported files. If anything file is missing, the bug is in [@vercel/nft](https://github.com/vercel/nft) and not the Builder.
## Deploy a Builder with existing project
Sometimes you want to test changes to a Builder against an existing project, maybe with `vercel dev` or an actual deployment. You can avoid publishing every Builder change to npm by uploading the Builder as a tarball.
Sometimes you want to test changes to a Builder against an existing project, maybe with `vercel dev` or actual deployment. You can avoid publishing every Builder change to npm by uploading the Builder as a tarball.
1. Change directory to the desired Builder `cd ./packages/node`
2. Run `yarn build` to compile typescript and other build steps

View File

@@ -13,6 +13,5 @@ jobs:
steps:
- uses: styfle/cancel-workflow-action@0.9.1
with:
workflow_id: 849295, 849296, 849297, 849298
workflow_id: test.yml, test-integration-cli.yml, test-unit.yml
access_token: ${{ github.token }}

View File

@@ -16,9 +16,15 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest]
node: [12]
node: [14]
runs-on: ${{ matrix.os }}
steps:
- name: Conditionally set remote env
if: github.event.pull_request.head.repo.full_name == github.repository
run: |
echo "TURBO_REMOTE_ONLY=true" >> $GITHUB_ENV
echo "TURBO_TEAM=vercel" >> $GITHUB_ENV
echo "TURBO_TOKEN=${{ secrets.TURBO_TOKEN }}" >> $GITHUB_ENV
- uses: actions/setup-go@v2
with:
go-version: '1.13.15'

View File

@@ -1,43 +0,0 @@
name: Dev
on:
push:
branches:
- main
tags:
- '!*'
pull_request:
jobs:
test:
name: Dev
timeout-minutes: 75
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
node: [12]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/setup-go@v2
with:
go-version: '1.13.15'
- uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node }}
- uses: actions/checkout@v2
with:
fetch-depth: 100
- run: git --version
- run: git fetch origin main --depth=100
- run: git fetch origin ${{ github.ref }} --depth=100
- run: git diff origin/main...HEAD --name-only
- name: Install Hugo
if: matrix.os == 'macos-latest'
run: curl -L -O https://github.com/gohugoio/hugo/releases/download/v0.56.0/hugo_0.56.0_macOS-64bit.tar.gz && tar -xzf hugo_0.56.0_macOS-64bit.tar.gz && mv ./hugo packages/cli/test/dev/fixtures/08-hugo/
- run: yarn install --network-timeout 1000000
- run: yarn run build
- run: yarn test-integration-dev
env:
VERCEL_TEAM_TOKEN: ${{ secrets.VERCEL_TEAM_TOKEN }}
VERCEL_REGISTRATION_URL: ${{ secrets.VERCEL_REGISTRATION_URL }}

View File

@@ -1,35 +0,0 @@
name: E2E
on:
push:
branches:
- main
tags:
- '!*'
pull_request:
jobs:
test:
name: E2E
timeout-minutes: 120
runs-on: ubuntu-latest
steps:
- uses: actions/setup-go@v2
with:
go-version: '1.13.15'
- uses: actions/setup-node@v2
with:
node-version: 12
- uses: actions/checkout@v2
with:
fetch-depth: 100
- run: git --version
- run: git fetch origin main --depth=100
- run: git fetch origin ${{ github.ref }} --depth=100
- run: git diff origin/main...HEAD --name-only
- run: yarn install --network-timeout 1000000
- run: yarn run build
- run: yarn test-integration-once
env:
VERCEL_TEAM_TOKEN: ${{ secrets.VERCEL_TEAM_TOKEN }}
VERCEL_REGISTRATION_URL: ${{ secrets.VERCEL_REGISTRATION_URL }}

View File

@@ -16,9 +16,15 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
node: [12]
node: [14]
runs-on: ${{ matrix.os }}
steps:
- name: Conditionally set remote env
if: github.event.pull_request.head.repo.full_name == github.repository
run: |
echo "TURBO_REMOTE_ONLY=true" >> $GITHUB_ENV
echo "TURBO_TEAM=vercel" >> $GITHUB_ENV
echo "TURBO_TOKEN=${{ secrets.TURBO_TOKEN }}" >> $GITHUB_ENV
- uses: actions/setup-go@v2
with:
go-version: '1.13.15'
@@ -35,9 +41,9 @@ jobs:
- run: yarn install --network-timeout 1000000
- run: yarn run build
- run: yarn run lint
if: matrix.os == 'ubuntu-latest' && matrix.node == 12 # only run lint once
if: matrix.os == 'ubuntu-latest' && matrix.node == 14 # only run lint once
- run: yarn run test-unit
- run: yarn workspace vercel run coverage
if: matrix.os == 'ubuntu-latest' && matrix.node == 12 # only run coverage once
if: matrix.os == 'ubuntu-latest' && matrix.node == 14 # only run coverage once
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

90
.github/workflows/test.yml vendored Normal file
View File

@@ -0,0 +1,90 @@
name: Tests
on:
push:
branches:
- main
tags:
- '!*'
pull_request:
env:
NODE_VERSION: '14'
jobs:
setup:
name: Find Changes
runs-on: ubuntu-latest
outputs:
tests: ${{ steps['set-tests'].outputs['tests'] }}
steps:
- uses: actions/checkout@v2
- run: git --version
- run: git fetch origin main
- uses: actions/setup-node@v2
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'yarn'
- run: yarn install --network-timeout 1000000
- id: set-tests
run: |
TESTS_ARRAY=$(node utils/chunk-tests.js $SCRIPT_NAME)
echo "Files to test:"
echo "$TESTS_ARRAY"
echo "::set-output name=tests::$TESTS_ARRAY"
test:
timeout-minutes: 120
runs-on: ${{ matrix.runner }}
name: ${{matrix.scriptName}} (${{matrix.packageName}}, ${{matrix.chunkNumber}}, ${{ matrix.runner }})
if: ${{ needs.setup.outputs['tests'] != '[]' }}
needs:
- setup
strategy:
fail-fast: false
matrix:
include: ${{ fromJson(needs.setup.outputs['tests']) }}
steps:
- name: Conditionally set remote env
if: github.event.pull_request.head.repo.full_name == github.repository
run: |
echo "TURBO_REMOTE_ONLY=true" >> $GITHUB_ENV
echo "TURBO_TEAM=vercel" >> $GITHUB_ENV
echo "TURBO_TOKEN=${{ secrets.TURBO_TOKEN }}" >> $GITHUB_ENV
- uses: actions/checkout@v2
with:
fetch-depth: 2
- uses: actions/setup-go@v2
with:
go-version: '1.13.15'
- uses: actions/setup-node@v2
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'yarn'
- name: Install Hugo
if: matrix.runner == 'macos-latest'
run: curl -L -O https://github.com/gohugoio/hugo/releases/download/v0.56.0/hugo_0.56.0_macOS-64bit.tar.gz && tar -xzf hugo_0.56.0_macOS-64bit.tar.gz && mv ./hugo packages/cli/test/dev/fixtures/08-hugo/
- run: yarn install --network-timeout 1000000
- name: Build ${{matrix.packageName}} and all its dependencies
run: yarn turbo run build --cache-dir=".turbo" --scope=${{matrix.packageName}} --include-dependencies --no-deps
env:
FORCE_COLOR: '1'
- name: Test ${{matrix.packageName}}
run: node_modules/.bin/turbo run test --cache-dir=".turbo" --scope=${{matrix.packageName}} --no-deps -- ${{ join(matrix.testPaths, ' ') }}
shell: bash
env:
VERCEL_TEAM_TOKEN: ${{ secrets.VERCEL_TEAM_TOKEN }}
VERCEL_REGISTRATION_URL: ${{ secrets.VERCEL_REGISTRATION_URL }}
FORCE_COLOR: '1'
conclusion:
needs:
- test
runs-on: ubuntu-latest
name: E2E
steps:
- name: Done
run: echo "Done."

View File

@@ -6,6 +6,7 @@
!.yarnrc
!yarn.lock
!package.json
!turbo.json
# api
!api/
@@ -14,4 +15,4 @@
# packages
!packages/
!packages/frameworks
!packages/frameworks/**
!packages/frameworks/**

View File

@@ -307,15 +307,15 @@ This is a [class](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refere
This is an abstract enumeration type that is implemented by one of the following possible `String` values:
- `nodejs14.x`
- `nodejs12.x`
- `nodejs10.x`
- `go1.x`
- `java11`
- `python3.9`
- `python3.6`
- `dotnetcore2.1`
- `ruby2.5`
- `provided`
- `dotnet6`
- `dotnetcore3.1`
- `ruby2.7`
- `provided.al2`
## `@vercel/build-utils` Helper Functions

View File

@@ -16,4 +16,4 @@ If you would not like to verify your domain, you can remove it from your account
#### Resources
- [Vercel Custom Domains Documentation](https://vercel.com/docs/v2/custom-domains)
- [Vercel Custom Domains Documentation](https://vercel.com/docs/concepts/projects/custom-domains)

View File

@@ -2,7 +2,7 @@
#### Why This Error Occurred
You ran `vercel dev` inside a project that contains a `vercel.json` file with `env` or `build.env` properties that use [Vercel Secrets](https://vercel.com/docs/v2/build-step#environment-variables).
You ran `vercel dev` inside a project that contains a `vercel.json` file with `env` or `build.env` properties that use [Vercel Secrets](https://vercel.com/docs/concepts/projects/environment-variables).
In order to use environment variables in your project locally that have values defined using the Vercel Secrets format (e.g. `@my-secret-value`), you will need to provide the value as an environment variable using a `.env`.
@@ -24,4 +24,4 @@ TEST=value
In the above example, `TEST` represents the name of the environment variable and `value` its value.
For more information on Environment Variables in development, [see the documentation](https://vercel.com/docs/v2/build-step#environment-variables).
For more information on Environment Variables in development, [see the documentation](https://vercel.com/docs/concepts/projects/environment-variables).

View File

@@ -1 +0,0 @@
.env

View File

@@ -1,19 +0,0 @@
# AMP Example
This directory is a brief example of an [AMP](https://amp.dev/) site that can be deployed to Vercel with zero configuration.
## Deploy Your Own
Deploy your own AMP project with Vercel.
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/vercel/vercel/tree/main/examples/amp)
_Live Example: https://amp-template.vercel.app_
### How We Created This Example
To get started deploying AMP with Vercel, you can use the [Vercel CLI](https://vercel.com/download) to initialize the project:
```shell
$ vercel init amp
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -1,72 +0,0 @@
<!DOCTYPE html>
<html >
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,minimum-scale=1" />
<link rel="shortcut icon" href="favicon.png">
<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
<link rel="canonical" href="index.html" />
<title>AMP Website</title>
<script async src="https://cdn.ampproject.org/v0.js"></script>
<style amp-custom>
body > * {
margin: 3rem 1rem;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
color: #525252;
}
h3 {
font-size: 2rem;
}
h4 {
margin-top: 2rem;
}
p {
font-size: 1.2rem;
line-height: 2rem;
}
.links {
display: flex;
justify-content: center;
margin-bottom: 3rem;
}
.links a {
margin: 0 10px;
font-size: 1rem;
color: #005af0;
}
</style>
</head>
<body>
<center>
<amp-img width=150 height=150 layout="fixed" class="logo" src="logo.png"></amp-img>
<h3>Welcome to your AMP page</h3>
<p>AMP is a web component framework to <br> easily create user-first websites, stories, ads and emails.</p>
<h4>Links</h4>
<div class="links">
<a href="https://amp.dev/">Homepage</a>
<a href="https://amp.dev/documentation/guides-and-tutorials/?format=websites">Tutorials</a>
<a href="https://amp.dev/documentation/examples/">Examples</a>
<a href="https://blog.amp.dev">Blog</a>
</div>
<h4>Ready to get started?</h4>
<div class="links">
<a href="https://amp.dev/documentation/guides-and-tutorials/start/create/?format=websites">Create your first AMP page</a>
</div>
<h4>Get involved</h4>
<div class="links">
<a href="https://twitter.com/amphtml">Twitter</a>
<a href="https://amphtml.slack.com">Slack</a>
<a href="https://amp.dev/events/amp-conf-2019">AMP Conf</a>
<a href="https://amp.dev/events/amp-roadshow">AMP Roadshow</a>
</div>
</center>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

20
examples/astro/.gitignore vendored Normal file
View File

@@ -0,0 +1,20 @@
# build output
dist/
.output/
# dependencies
node_modules/
# logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# environment variables
.env
.env.production
# macOS-specific files
.DS_Store

2
examples/astro/.npmrc Normal file
View File

@@ -0,0 +1,2 @@
# Expose Astro dependencies for `pnpm` users
shamefully-hoist=true

View File

@@ -0,0 +1 @@
README.md

42
examples/astro/README.md Normal file
View File

@@ -0,0 +1,42 @@
# Welcome to [Astro](https://astro.build)
[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/starter)
> 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun!
## 🚀 Project Structure
Inside of your Astro project, you'll see the following folders and files:
```
/
├── public/
│ └── favicon.ico
├── src/
│ ├── components/
│ │ └── Layout.astro
│ └── pages/
│ └── index.astro
└── package.json
```
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components or layouts.
Any static assets, like images, can be placed in the `public/` directory.
## 🧞 Commands
All commands are run from the root of the project, from a terminal:
| Command | Action |
| :---------------- | :------------------------------------------- |
| `npm install` | Installs dependencies |
| `npm run dev` | Starts local dev server at `localhost:3000` |
| `npm run build` | Build your production site to `./dist/` |
| `npm run preview` | Preview your build locally, before deploying |
## 👀 Want to learn more?
Feel free to check [our documentation](https://github.com/withastro/astro) or jump into our [Discord server](https://astro.build/chat).

View File

@@ -0,0 +1,4 @@
import { defineConfig } from 'astro/config';
// https://astro.build/config
export default defineConfig({});

View File

@@ -0,0 +1,14 @@
{
"name": "@example/basics",
"version": "0.0.1",
"private": true,
"scripts": {
"dev": "astro dev",
"start": "astro dev",
"build": "astro build",
"preview": "astro preview"
},
"devDependencies": {
"astro": "^1.0.0-beta.20"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -0,0 +1,55 @@
---
export interface Props {
title: string;
}
const { title } = Astro.props as Props;
---
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
<title>{title}</title>
</head>
<body>
<slot />
</body>
</html>
<style>
:root {
--font-size-base: clamp(1rem, 0.34vw + 0.91rem, 1.19rem);
--font-size-lg: clamp(1.2rem, 0.7vw + 1.2rem, 1.5rem);
--font-size-xl: clamp(2.44rem, 2.38vw + 1.85rem, 3.75rem);
--color-text: hsl(12, 5%, 4%);
--color-bg: hsl(10, 21%, 95%);
}
html {
font-family: system-ui, sans-serif;
font-size: var(--font-size-base);
color: var(--color-text);
background-color: var(--color-bg);
}
body {
margin: 0;
}
:global(h1) {
font-size: var(--font-size-xl);
}
:global(h2) {
font-size: var(--font-size-lg);
}
:global(code) {
font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
Bitstream Vera Sans Mono, Courier New, monospace;
}
</style>

View File

@@ -0,0 +1,174 @@
---
import Layout from '../components/Layout.astro';
---
<Layout title="Welcome to Astro.">
<main>
<h1>Welcome to <span class="text-gradient">Astro</span></h1>
<p class="instructions"><strong>Your first mission:</strong> tweak this message to try our hot module reloading. Check the <code>src/pages</code> directory!</p>
<ul role="list" class="link-card-grid">
<li class="link-card">
<a href="https://astro.build/integrations/">
<h2>Integrations <span>&rarr;</span></h2>
<p>Add component frameworks, Tailwind, Partytown, and more!</p>
</a>
</li>
<li class="link-card">
<a href="https://astro.build/themes/">
<h2>Themes <span>&rarr;</span></h2>
<p>Explore a galaxy of community-built starters.</p>
</a>
</li>
<li class="link-card">
<a href="https://docs.astro.build/">
<h2>Docs <span>&rarr;</span></h2>
<p>Learn our complete feature set and explore the API.</p>
</a>
</li>
<li class="link-card">
<a href="https://astro.build/chat/">
<h2>Chat <span>&rarr;</span></h2>
<p>
Ask, contribute, and have fun on our community Discord
<svg
class="heart"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
width="16"
height="16"
fill="currentColor"
>
<title>heart</title>
<path d="M256 448l-30.164-27.211C118.718 322.442 48 258.61 48 179.095 48 114.221 97.918 64 162.4 64c36.399 0 70.717 16.742 93.6 43.947C278.882 80.742 313.199 64 349.6 64 414.082 64 464 114.221 464 179.095c0 79.516-70.719 143.348-177.836 241.694L256 448z" />
</svg>
</p>
</a>
</li>
</ul>
</main>
</Layout>
<style>
:root {
--color-border: hsl(17, 24%, 90%);
--astro-gradient: linear-gradient(0deg,#4F39FA, #DA62C4);
--link-gradient: linear-gradient(45deg, #4F39FA, #DA62C4 30%, var(--color-border) 60%);
--night-sky-gradient: linear-gradient(0deg, #392362 -33%, #431f69 10%, #30216b 50%, #1f1638 100%);
}
h2 {
margin: 0;
transition: color 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}
h2 span {
display: inline-block;
transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}
code {
font-size: 0.875em;
border: 0.1em solid var(--color-border);
border-radius: 4px;
padding: 0.15em 0.25em;
}
main {
margin: auto;
padding: 1em;
max-width: 60ch;
}
.text-gradient {
font-weight: 900;
background-image: var(--astro-gradient);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-size: 100% 200%;
background-position-y: 100%;
border-radius: 0.4rem;
animation: pulse 4s ease-in-out infinite;
}
@keyframes pulse {
0%, 100% {
background-position-y: 0%;
}
50% {
background-position-y: 80%;
}
}
.instructions {
line-height: 1.8;
margin-bottom: 2rem;
background-image: var(--night-sky-gradient);
padding: 1.5rem;
border-radius: 0.4rem;
color: var(--color-bg);
}
.link-card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(24ch, 1fr));
gap: 1rem;
padding: 0;
}
.link-card {
list-style: none;
display: flex;
padding: 0.15rem;
background-image: var(--link-gradient);
background-size: 400%;
border-radius: 0.5rem;
background-position: 100%;
transition: background-position 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}
.link-card > a {
width: 100%;
text-decoration: none;
line-height: 1.4;
padding: 1em 1.3em;
border-radius: 0.35rem;
color: var(--text-color);
background-color: white;
opacity: 0.8;
}
.link-card:is(:hover, :focus-within) {
background-position: 0;
}
.link-card:is(:hover, :focus-within) h2 {
color: #4F39FA;
}
.link-card:is(:hover, :focus-within) h2 span {
transform: translateX(2px);
}
.heart {
display: inline-block;
color: #DA62C4;
animation: heartbeat 3s ease-in-out infinite;
}
@keyframes heartbeat {
0%,
50%,
100% {
transform: scale(1);
}
5% {
transform: scale(1.125);
}
10% {
transform: scale(1.05);
}
15% {
transform: scale(1.25);
}
}
</style>

View File

@@ -0,0 +1,15 @@
{
"compilerOptions": {
// Enable top-level await, and other modern ESM features.
"target": "ESNext",
"module": "ESNext",
// Enable node-style module resolution, for things like npm package imports.
"moduleResolution": "node",
// Enable JSON imports.
"resolveJsonModule": true,
// Enable stricter transpilation for better output.
"isolatedModules": true,
// Add type definitions for our Vite runtime.
"types": ["vite/client"]
}
}

3457
examples/astro/yarn.lock Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@ This directory is a brief example of a [Dojo](https://dojo.io) site that can be
Deploy your own Dojo project with Vercel.
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/vercel/vercel/tree/main/dojo&template=dojo)
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/vercel/vercel/tree/main/examples/dojo&template=dojo)
### How We Created This Example

View File

@@ -15,7 +15,7 @@ cache:
env:
global:
# See https://git.io/vdao3 for details.
# See https://github.com/ember-cli/ember-cli/blob/master/docs/build-concurrency.md
- JOBS=1
script:

View File

@@ -48,6 +48,6 @@
"qunit-dom": "^0.8.4"
},
"engines": {
"node": "8.* || >= 10.*"
"node": "14.x"
}
}

View File

@@ -2,3 +2,4 @@ README.md
.nuxt
node_modules
*.log
.output

View File

@@ -21,7 +21,7 @@
"typescript": "^4.1.2"
},
"engines": {
"node": ">=14"
"node": "14.x"
}
},
"node_modules/@babel/code-frame": {

View File

@@ -23,7 +23,7 @@
"typescript": "^4.1.2"
},
"engines": {
"node": ">=14"
"node": "14.x"
},
"sideEffects": false
}
}

View File

@@ -2,6 +2,7 @@ dist
worker
.solid
.vercel
.output
# dependencies
/node_modules

View File

@@ -1,6 +1,6 @@
# SolidStart
This directory is a brief example of a [SolidStart](https://github.com/ryansolid/solid-startp) site that can be deployed to Vercel with zero configuration.
This directory is a brief example of a [SolidStart](https://github.com/ryansolid/solid-start) site that can be deployed to Vercel with zero configuration.
## Deploy Your Own

View File

@@ -1,9 +0,0 @@
{
"compilerOptions": {
"jsx": "preserve",
"jsxImportSource": "solid-js",
"paths": {
"~/*": ["./src/*"]
}
}
}

View File

@@ -7,14 +7,14 @@
"type": "module",
"private": true,
"devDependencies": {
"solid-app-router": "^0.1.14",
"solid-js": "^1.2.6",
"solid-meta": "^0.27.2",
"solid-app-router": "^0.3.2",
"solid-js": "^1.3.15",
"solid-meta": "^0.27.3",
"solid-start": "next",
"solid-start-vercel": "next",
"vite": "^2.7.1"
"vite": "^2.9.9"
},
"engines": {
"node": ">=14"
"node": "16.x"
}
}

View File

@@ -0,0 +1,4 @@
import { hydrate } from "solid-js/web";
import { StartClient } from "solid-start/entry-client";
hydrate(() => <StartClient />, document);

View File

@@ -0,0 +1,7 @@
import { StartServer, createHandler, renderAsync } from "solid-start/entry-server";
import { inlineServerModules } from "solid-start/server";
export default createHandler(
inlineServerModules,
renderAsync((context) => <StartServer context={context} />)
);

View File

@@ -1,21 +0,0 @@
// @refresh reload
import { Links, Meta, Outlet, Scripts } from "solid-start/components";
export default function Root({ Start }) {
return (
<Start>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<Meta />
<Links />
</head>
<body>
<Outlet />
<Scripts />
</body>
</html>
</Start>
);
}

View File

@@ -0,0 +1,25 @@
// @refresh reload
import { Links, Meta, Routes, Scripts } from "solid-start/root";
import { ErrorBoundary } from "solid-start/error-boundary";
import { Suspense } from "solid-js";
export default function Root() {
return (
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<Meta />
<Links />
</head>
<body>
<ErrorBoundary>
<Suspense>
<Routes />
</Suspense>
</ErrorBoundary>
<Scripts />
</body>
</html>
);
}

View File

@@ -0,0 +1,16 @@
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "node",
"jsxImportSource": "solid-js",
"jsx": "preserve",
"types": ["vite/client"],
"baseUrl": "./",
"paths": {
"~/*": ["./src/*"]
}
}
}

View File

@@ -0,0 +1,7 @@
{
"build": {
"env": {
"ENABLE_VC_BUILD": "1"
}
}
}

View File

@@ -1,7 +1,7 @@
import { defineConfig } from "vite";
import solid from "solid-start";
import vercel from "solid-start-vercel"
import vercel from "solid-start-vercel";
export default defineConfig({
plugins: [solid({ adapter: vercel() })]
plugins: [solid({ adapter: vercel() })],
});

File diff suppressed because it is too large Load Diff

View File

@@ -7,3 +7,4 @@ node_modules
.env.*
!.env.example
.vercel
.output

View File

@@ -0,0 +1,13 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example
# Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml
package-lock.json
yarn.lock

View File

@@ -0,0 +1,6 @@
{
"useTabs": false,
"singleQuote": true,
"trailingComma": "none",
"printWidth": 100
}

View File

@@ -14,31 +14,29 @@ If you're seeing this, you've probably already done this step. Congrats!
```bash
# create a new project in the current directory
npm init svelte@next
npm init svelte
# create a new project in my-app
npm init svelte@next my-app
npm init svelte my-app
```
> Note: the `@next` is temporary
## Developing
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
Once you've created a project and installed dependencies with `pnpm install`, start a development server:
```bash
npm run dev
pnpm run dev
# or start the server and open the app in a new browser tab
npm run dev -- --open
pnpm run dev -- --open
```
## Building
This uses the adapter-auto for SvelteKit, which detects Vercel and runs adapter-vercel on your behalf.
To create a production version of your app:
```bash
npm run build
pnpm run build
```
> You can preview the built app with `npm run preview`, regardless of whether you installed an adapter. This should _not_ be used to serve your app in production.
You can preview the production build with `npm run preview`.

View File

@@ -1,10 +1,13 @@
{
"extends": "./.svelte-kit/tsconfig.json",
"compilerOptions": {
"baseUrl": ".",
"paths": {
"$lib": ["src/lib"],
"$lib/*": ["src/lib/*"]
}
},
"include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte"]
"allowJs": true,
"checkJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,22 +1,29 @@
{
"private": true,
"name": "sveltekit",
"version": "0.0.1",
"scripts": {
"dev": "svelte-kit dev",
"build": "svelte-kit build",
"package": "svelte-kit package",
"preview": "svelte-kit preview"
"preview": "svelte-kit preview",
"prepare": "svelte-kit sync",
"check": "svelte-check --tsconfig ./jsconfig.json",
"check:watch": "svelte-check --tsconfig ./jsconfig.json --watch",
"lint": "prettier --check --plugin-search-dir=. .",
"format": "prettier --write --plugin-search-dir=. ."
},
"devDependencies": {
"@sveltejs/adapter-auto": "next",
"@sveltejs/kit": "next",
"svelte": "^3.46.0"
"@types/cookie": "^0.4.1",
"prettier": "^2.5.1",
"prettier-plugin-svelte": "^2.5.0",
"svelte": "^3.46.0",
"svelte-check": "^2.2.6",
"typescript": "~4.6.2"
},
"type": "module",
"dependencies": {
"@fontsource/fira-mono": "^4.5.0",
"@lukeed/uuid": "^2.0.0",
"cookie": "^0.4.1"
}
}

1633
examples/sveltekit/pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,107 +1,107 @@
@import '@fontsource/fira-mono';
:root {
font-family: Arial, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu,
Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
--font-mono: 'Fira Mono', monospace;
--pure-white: #ffffff;
--primary-color: #b9c6d2;
--secondary-color: #d0dde9;
--tertiary-color: #edf0f8;
--accent-color: #ff3e00;
--heading-color: rgba(0, 0, 0, 0.7);
--text-color: #444444;
--background-without-opacity: rgba(255, 255, 255, 0.7);
--column-width: 42rem;
--column-margin-top: 4rem;
font-family: Arial, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu,
Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
--font-mono: 'Fira Mono', monospace;
--pure-white: #ffffff;
--primary-color: #b9c6d2;
--secondary-color: #d0dde9;
--tertiary-color: #edf0f8;
--accent-color: #ff3e00;
--heading-color: rgba(0, 0, 0, 0.7);
--text-color: #444444;
--background-without-opacity: rgba(255, 255, 255, 0.7);
--column-width: 42rem;
--column-margin-top: 4rem;
}
body {
min-height: 100vh;
margin: 0;
background-color: var(--primary-color);
background: linear-gradient(
180deg,
var(--primary-color) 0%,
var(--secondary-color) 10.45%,
var(--tertiary-color) 41.35%
);
min-height: 100vh;
margin: 0;
background-color: var(--primary-color);
background: linear-gradient(
180deg,
var(--primary-color) 0%,
var(--secondary-color) 10.45%,
var(--tertiary-color) 41.35%
);
}
body::before {
content: '';
width: 80vw;
height: 100vh;
position: absolute;
top: 0;
left: 10vw;
z-index: -1;
background: radial-gradient(
50% 50% at 50% 50%,
var(--pure-white) 0%,
rgba(255, 255, 255, 0) 100%
);
opacity: 0.05;
content: '';
width: 80vw;
height: 100vh;
position: absolute;
top: 0;
left: 10vw;
z-index: -1;
background: radial-gradient(
50% 50% at 50% 50%,
var(--pure-white) 0%,
rgba(255, 255, 255, 0) 100%
);
opacity: 0.05;
}
#svelte {
min-height: 100vh;
display: flex;
flex-direction: column;
min-height: 100vh;
display: flex;
flex-direction: column;
}
h1,
h2,
p {
font-weight: 400;
color: var(--heading-color);
font-weight: 400;
color: var(--heading-color);
}
p {
line-height: 1.5;
line-height: 1.5;
}
a {
color: var(--accent-color);
text-decoration: none;
color: var(--accent-color);
text-decoration: none;
}
a:hover {
text-decoration: underline;
text-decoration: underline;
}
h1 {
font-size: 2rem;
text-align: center;
font-size: 2rem;
text-align: center;
}
h2 {
font-size: 1rem;
font-size: 1rem;
}
pre {
font-size: 16px;
font-family: var(--font-mono);
background-color: rgba(255, 255, 255, 0.45);
border-radius: 3px;
box-shadow: 2px 2px 6px rgb(255 255 255 / 25%);
padding: 0.5em;
overflow-x: auto;
color: var(--text-color);
font-size: 16px;
font-family: var(--font-mono);
background-color: rgba(255, 255, 255, 0.45);
border-radius: 3px;
box-shadow: 2px 2px 6px rgb(255 255 255 / 25%);
padding: 0.5em;
overflow-x: auto;
color: var(--text-color);
}
input,
button {
font-size: inherit;
font-family: inherit;
font-size: inherit;
font-family: inherit;
}
button:focus:not(:focus-visible) {
outline: none;
outline: none;
}
@media (min-width: 720px) {
h1 {
font-size: 2.4rem;
}
h1 {
font-size: 2.4rem;
}
}

15
examples/sveltekit/src/app.d.ts vendored Normal file
View File

@@ -0,0 +1,15 @@
/// <reference types="@sveltejs/kit" />
// See https://kit.svelte.dev/docs/types#app
// for information about these interfaces
declare namespace App {
interface Locals {
userid: string;
}
// interface Platform {}
// interface Session {}
// interface Stuff {}
}

View File

@@ -1,13 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="description" content="Svelte demo app" />
<link rel="icon" href="%svelte.assets%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
%svelte.head%
</head>
<body>
<div>%svelte.body%</div>
</body>
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head%
</head>
<body>
<div>%sveltekit.body%</div>
</body>
</html>

View File

@@ -1,23 +1,23 @@
import cookie from 'cookie';
import { v4 as uuid } from '@lukeed/uuid';
import * as cookie from 'cookie';
/** @type {import('@sveltejs/kit').Handle} */
export const handle = async ({ event, resolve }) => {
const cookies = cookie.parse(event.request.headers.get('cookie') || '');
event.locals.userid = cookies.userid || uuid();
const cookies = cookie.parse(event.request.headers.get('cookie') || '');
event.locals.userid = cookies['userid'] || crypto.randomUUID();
const response = await resolve(event);
const response = await resolve(event);
if (!cookies.userid) {
// if this is the first time the user has visited this app,
// set a cookie so that we recognise them when they return
response.headers.set(
'set-cookie',
cookie.serialize('userid', event.locals.userid, {
path: '/',
httpOnly: true
})
);
}
if (!cookies['userid']) {
// if this is the first time the user has visited this app,
// set a cookie so that we recognise them when they return
response.headers.set(
'set-cookie',
cookie.serialize('userid', event.locals.userid, {
path: '/',
httpOnly: true
})
);
}
return response;
return response;
};

View File

@@ -1,102 +1,107 @@
<script>
import { spring } from 'svelte/motion';
import { spring } from 'svelte/motion';
let count = 0;
let count = 0;
const displayed_count = spring();
$: displayed_count.set(count);
$: offset = modulo($displayed_count, 1);
const displayed_count = spring();
$: displayed_count.set(count);
$: offset = modulo($displayed_count, 1);
function modulo(n, m) {
// handle negative numbers
return ((n % m) + m) % m;
}
/**
* @param {number} n
* @param {number} m
*/
function modulo(n, m) {
// handle negative numbers
return ((n % m) + m) % m;
}
</script>
<div class="counter">
<button on:click={() => (count -= 1)} aria-label="Decrease the counter by one">
<svg aria-hidden="true" viewBox="0 0 1 1">
<path d="M0,0.5 L1,0.5" />
</svg>
</button>
<button on:click={() => (count -= 1)} aria-label="Decrease the counter by one">
<svg aria-hidden="true" viewBox="0 0 1 1">
<path d="M0,0.5 L1,0.5" />
</svg>
</button>
<div class="counter-viewport">
<div class="counter-digits" style="transform: translate(0, {100 * offset}%)">
<strong class="hidden" aria-hidden="true">{Math.floor($displayed_count + 1)}</strong>
<strong>{Math.floor($displayed_count)}</strong>
</div>
</div>
<div class="counter-viewport">
<div class="counter-digits" style="transform: translate(0, {100 * offset}%)">
<strong class="hidden" aria-hidden="true">{Math.floor($displayed_count + 1)}</strong>
<strong>{Math.floor($displayed_count)}</strong>
</div>
</div>
<button on:click={() => (count += 1)} aria-label="Increase the counter by one">
<svg aria-hidden="true" viewBox="0 0 1 1">
<path d="M0,0.5 L1,0.5 M0.5,0 L0.5,1" />
</svg>
</button>
<button on:click={() => (count += 1)} aria-label="Increase the counter by one">
<svg aria-hidden="true" viewBox="0 0 1 1">
<path d="M0,0.5 L1,0.5 M0.5,0 L0.5,1" />
</svg>
</button>
</div>
<style>
.counter {
display: flex;
border-top: 1px solid rgba(0, 0, 0, 0.1);
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
margin: 1rem 0;
}
.counter {
display: flex;
border-top: 1px solid rgba(0, 0, 0, 0.1);
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
margin: 1rem 0;
}
.counter button {
width: 2em;
padding: 0;
display: flex;
align-items: center;
justify-content: center;
border: 0;
background-color: transparent;
color: var(--text-color);
font-size: 2rem;
}
.counter button {
width: 2em;
padding: 0;
display: flex;
align-items: center;
justify-content: center;
border: 0;
background-color: transparent;
touch-action: manipulation;
color: var(--text-color);
font-size: 2rem;
}
.counter button:hover {
background-color: var(--secondary-color);
}
.counter button:hover {
background-color: var(--secondary-color);
}
svg {
width: 25%;
height: 25%;
}
svg {
width: 25%;
height: 25%;
}
path {
vector-effect: non-scaling-stroke;
stroke-width: 2px;
stroke: var(--text-color);
}
path {
vector-effect: non-scaling-stroke;
stroke-width: 2px;
stroke: var(--text-color);
}
.counter-viewport {
width: 8em;
height: 4em;
overflow: hidden;
text-align: center;
position: relative;
}
.counter-viewport {
width: 8em;
height: 4em;
overflow: hidden;
text-align: center;
position: relative;
}
.counter-viewport strong {
position: absolute;
display: flex;
width: 100%;
height: 100%;
font-weight: 400;
color: var(--accent-color);
font-size: 4rem;
align-items: center;
justify-content: center;
}
.counter-viewport strong {
position: absolute;
display: flex;
width: 100%;
height: 100%;
font-weight: 400;
color: var(--accent-color);
font-size: 4rem;
align-items: center;
justify-content: center;
}
.counter-digits {
position: absolute;
width: 100%;
height: 100%;
}
.counter-digits {
position: absolute;
width: 100%;
height: 100%;
}
.hidden {
top: -100%;
user-select: none;
}
.hidden {
top: -100%;
user-select: none;
}
</style>

View File

@@ -2,54 +2,81 @@ import { invalidate } from '$app/navigation';
// this action (https://svelte.dev/tutorial/actions) allows us to
// progressively enhance a <form> that already works without JS
/**
* @param {HTMLFormElement} form
* @param {{
* pending?: ({ data, form }: { data: FormData; form: HTMLFormElement }) => void;
* error?: ({
* data,
* form,
* response,
* error
* }: {
* data: FormData;
* form: HTMLFormElement;
* response: Response | null;
* error: Error | null;
* }) => void;
* result?: ({
* data,
* form,
* response
* }: {
* data: FormData;
* response: Response;
* form: HTMLFormElement;
* }) => void;
* }} [opts]
*/
export function enhance(form, { pending, error, result } = {}) {
let current_token;
let current_token;
async function handle_submit(e) {
const token = (current_token = {});
/** @param {SubmitEvent} e */
async function handle_submit(e) {
const token = (current_token = {});
e.preventDefault();
e.preventDefault();
const data = new FormData(form);
const data = new FormData(form);
if (pending) pending({ data, form });
if (pending) pending({ data, form });
try {
const response = await fetch(form.action, {
method: form.method,
headers: {
accept: 'application/json'
},
body: data
});
try {
const response = await fetch(form.action, {
method: form.method,
headers: {
accept: 'application/json'
},
body: data
});
if (token !== current_token) return;
if (token !== current_token) return;
if (response.ok) {
if (result) result({ data, form, response });
if (response.ok) {
if (result) result({ data, form, response });
const url = new URL(form.action);
url.search = url.hash = '';
invalidate(url.href);
} else if (error) {
error({ data, form, error: null, response });
} else {
console.error(await response.text());
}
} catch (e) {
if (error) {
error({ data, form, error: e, response: null });
} else {
throw e;
}
}
}
const url = new URL(form.action);
url.search = url.hash = '';
invalidate(url.href);
} else if (error) {
error({ data, form, error: null, response });
} else {
console.error(await response.text());
}
} catch (e) {
if (error && e instanceof Error) {
error({ data, form, error: e, response: null });
} else {
throw e;
}
}
}
form.addEventListener('submit', handle_submit);
form.addEventListener('submit', handle_submit);
return {
destroy() {
form.removeEventListener('submit', handle_submit);
}
};
return {
destroy() {
form.removeEventListener('submit', handle_submit);
}
};
}

View File

@@ -1,124 +1,124 @@
<script>
import { page } from '$app/stores';
import logo from './svelte-logo.svg';
import { page } from '$app/stores';
import logo from './svelte-logo.svg';
</script>
<header>
<div class="corner">
<a href="https://kit.svelte.dev">
<img src={logo} alt="SvelteKit" />
</a>
</div>
<div class="corner">
<a href="https://kit.svelte.dev">
<img src={logo} alt="SvelteKit" />
</a>
</div>
<nav>
<svg viewBox="0 0 2 3" aria-hidden="true">
<path d="M0,0 L1,2 C1.5,3 1.5,3 2,3 L2,0 Z" />
</svg>
<ul>
<li class:active={$page.url.pathname === '/'}><a sveltekit:prefetch href="/">Home</a></li>
<li class:active={$page.url.pathname === '/about'}>
<a sveltekit:prefetch href="/about">About</a>
</li>
<li class:active={$page.url.pathname === '/todos'}>
<a sveltekit:prefetch href="/todos">Todos</a>
</li>
</ul>
<svg viewBox="0 0 2 3" aria-hidden="true">
<path d="M0,0 L0,3 C0.5,3 0.5,3 1,2 L2,0 Z" />
</svg>
</nav>
<nav>
<svg viewBox="0 0 2 3" aria-hidden="true">
<path d="M0,0 L1,2 C1.5,3 1.5,3 2,3 L2,0 Z" />
</svg>
<ul>
<li class:active={$page.url.pathname === '/'}><a sveltekit:prefetch href="/">Home</a></li>
<li class:active={$page.url.pathname === '/about'}>
<a sveltekit:prefetch href="/about">About</a>
</li>
<li class:active={$page.url.pathname === '/todos'}>
<a sveltekit:prefetch href="/todos">Todos</a>
</li>
</ul>
<svg viewBox="0 0 2 3" aria-hidden="true">
<path d="M0,0 L0,3 C0.5,3 0.5,3 1,2 L2,0 Z" />
</svg>
</nav>
<div class="corner">
<!-- TODO put something else here? github link? -->
</div>
<div class="corner">
<!-- TODO put something else here? github link? -->
</div>
</header>
<style>
header {
display: flex;
justify-content: space-between;
}
header {
display: flex;
justify-content: space-between;
}
.corner {
width: 3em;
height: 3em;
}
.corner {
width: 3em;
height: 3em;
}
.corner a {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
.corner a {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
.corner img {
width: 2em;
height: 2em;
object-fit: contain;
}
.corner img {
width: 2em;
height: 2em;
object-fit: contain;
}
nav {
display: flex;
justify-content: center;
--background: rgba(255, 255, 255, 0.7);
}
nav {
display: flex;
justify-content: center;
--background: rgba(255, 255, 255, 0.7);
}
svg {
width: 2em;
height: 3em;
display: block;
}
svg {
width: 2em;
height: 3em;
display: block;
}
path {
fill: var(--background);
}
path {
fill: var(--background);
}
ul {
position: relative;
padding: 0;
margin: 0;
height: 3em;
display: flex;
justify-content: center;
align-items: center;
list-style: none;
background: var(--background);
background-size: contain;
}
ul {
position: relative;
padding: 0;
margin: 0;
height: 3em;
display: flex;
justify-content: center;
align-items: center;
list-style: none;
background: var(--background);
background-size: contain;
}
li {
position: relative;
height: 100%;
}
li {
position: relative;
height: 100%;
}
li.active::before {
--size: 6px;
content: '';
width: 0;
height: 0;
position: absolute;
top: 0;
left: calc(50% - var(--size));
border: var(--size) solid transparent;
border-top: var(--size) solid var(--accent-color);
}
li.active::before {
--size: 6px;
content: '';
width: 0;
height: 0;
position: absolute;
top: 0;
left: calc(50% - var(--size));
border: var(--size) solid transparent;
border-top: var(--size) solid var(--accent-color);
}
nav a {
display: flex;
height: 100%;
align-items: center;
padding: 0 1em;
color: var(--heading-color);
font-weight: 700;
font-size: 0.8rem;
text-transform: uppercase;
letter-spacing: 0.1em;
text-decoration: none;
transition: color 0.2s linear;
}
nav a {
display: flex;
height: 100%;
align-items: center;
padding: 0 1em;
color: var(--heading-color);
font-weight: 700;
font-size: 0.8rem;
text-transform: uppercase;
letter-spacing: 0.1em;
text-decoration: none;
transition: color 0.2s linear;
}
a:hover {
color: var(--accent-color);
}
a:hover {
color: var(--accent-color);
}
</style>

View File

@@ -1,45 +1,45 @@
<script>
import Header from '$lib/header/Header.svelte';
import '../app.css';
import Header from '$lib/header/Header.svelte';
import '../app.css';
</script>
<Header />
<main>
<slot />
<slot />
</main>
<footer>
<p>visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to learn SvelteKit</p>
<p>visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to learn SvelteKit</p>
</footer>
<style>
main {
flex: 1;
display: flex;
flex-direction: column;
padding: 1rem;
width: 100%;
max-width: 1024px;
margin: 0 auto;
box-sizing: border-box;
}
main {
flex: 1;
display: flex;
flex-direction: column;
padding: 1rem;
width: 100%;
max-width: 1024px;
margin: 0 auto;
box-sizing: border-box;
}
footer {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 40px;
}
footer {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 40px;
}
footer a {
font-weight: bold;
}
footer a {
font-weight: bold;
}
@media (min-width: 480px) {
footer {
padding: 40px 0;
}
}
@media (min-width: 480px) {
footer {
padding: 40px 0;
}
}
</style>

View File

@@ -1,50 +1,50 @@
<script context="module">
import { browser, dev } from '$app/env';
import { browser, dev } from '$app/env';
// we don't need any JS on this page, though we'll load
// it in dev so that we get hot module replacement...
export const hydrate = dev;
// we don't need any JS on this page, though we'll load
// it in dev so that we get hot module replacement...
export const hydrate = dev;
// ...but if the client-side router is already loaded
// (i.e. we came here from elsewhere in the app), use it
export const router = browser;
// ...but if the client-side router is already loaded
// (i.e. we came here from elsewhere in the app), use it
export const router = browser;
// since there's no dynamic data here, we can prerender
// it so that it gets served as a static asset in prod
export const prerender = true;
// since there's no dynamic data here, we can prerender
// it so that it gets served as a static asset in prod
export const prerender = true;
</script>
<svelte:head>
<title>About</title>
<title>About</title>
<meta name="description" content="About this app" />
</svelte:head>
<div class="content">
<h1>About this app</h1>
<h1>About this app</h1>
<p>
This is a <a href="https://kit.svelte.dev">SvelteKit</a> app. You can make your own by typing the
following into your command line and following the prompts:
</p>
<p>
This is a <a href="https://kit.svelte.dev">SvelteKit</a> app. You can make your own by typing the
following into your command line and following the prompts:
</p>
<!-- TODO lose the @next! -->
<pre>npm init svelte@next</pre>
<pre>npm init svelte</pre>
<p>
The page you're looking at is purely static HTML, with no client-side interactivity needed.
Because of that, we don't need to load any JavaScript. Try viewing the page's source, or opening
the devtools network panel and reloading.
</p>
<p>
The page you're looking at is purely static HTML, with no client-side interactivity needed.
Because of that, we don't need to load any JavaScript. Try viewing the page's source, or opening
the devtools network panel and reloading.
</p>
<p>
The <a href="/todos">TODOs</a> page illustrates SvelteKit's data loading and form handling. Try using
it with JavaScript disabled!
</p>
<p>
The <a href="/todos">TODOs</a> page illustrates SvelteKit's data loading and form handling. Try using
it with JavaScript disabled!
</p>
</div>
<style>
.content {
width: 100%;
max-width: var(--column-width);
margin: var(--column-margin-top) auto 0 auto;
}
.content {
width: 100%;
max-width: var(--column-width);
margin: var(--column-margin-top) auto 0 auto;
}
</style>

View File

@@ -1,59 +1,60 @@
<script context="module">
export const prerender = true;
export const prerender = true;
</script>
<script>
import Counter from '$lib/Counter.svelte';
import Counter from '$lib/Counter.svelte';
</script>
<svelte:head>
<title>Home</title>
<title>Home</title>
<meta name="description" content="Svelte demo app" />
</svelte:head>
<section>
<h1>
<div class="welcome">
<picture>
<source srcset="svelte-welcome.webp" type="image/webp" />
<img src="svelte-welcome.png" alt="Welcome" />
</picture>
</div>
<h1>
<div class="welcome">
<picture>
<source srcset="svelte-welcome.webp" type="image/webp" />
<img src="svelte-welcome.png" alt="Welcome" />
</picture>
</div>
to your new<br />SvelteKit app
</h1>
to your new<br />SvelteKit app
</h1>
<h2>
try editing <strong>src/routes/index.svelte</strong>
</h2>
<h2>
try editing <strong>src/routes/index.svelte</strong>
</h2>
<Counter />
<Counter />
</section>
<style>
section {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
flex: 1;
}
section {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
flex: 1;
}
h1 {
width: 100%;
}
h1 {
width: 100%;
}
.welcome {
position: relative;
width: 100%;
height: 0;
padding: 0 0 calc(100% * 495 / 2048) 0;
}
.welcome {
position: relative;
width: 100%;
height: 0;
padding: 0 0 calc(100% * 495 / 2048) 0;
}
.welcome img {
position: absolute;
width: 100%;
height: 100%;
top: 0;
display: block;
}
.welcome img {
position: absolute;
width: 100%;
height: 100%;
top: 0;
display: block;
}
</style>

View File

@@ -11,12 +11,17 @@
const base = 'https://api.svelte.dev';
/**
* @param {string} method
* @param {string} resource
* @param {Record<string, unknown>} [data]
*/
export function api(method, resource, data) {
return fetch(`${base}/${resource}`, {
method,
headers: {
'content-type': 'application/json'
},
body: data && JSON.stringify(data)
});
return fetch(`${base}/${resource}`, {
method,
headers: {
'content-type': 'application/json'
},
body: data && JSON.stringify(data)
});
}

View File

@@ -1,66 +1,70 @@
import { api } from './_api';
/** @type {import('./__types').RequestHandler} */
export const get = async ({ locals }) => {
// locals.userid comes from src/hooks.js
const response = await api('get', `todos/${locals.userid}`);
// locals.userid comes from src/hooks.js
const response = await api('get', `todos/${locals.userid}`);
if (response.status === 404) {
// user hasn't created a todo list.
// start with an empty array
return {
body: {
todos: []
}
};
}
if (response.status === 404) {
// user hasn't created a todo list.
// start with an empty array
return {
body: {
todos: []
}
};
}
if (response.status === 200) {
return {
body: {
todos: await response.json()
}
};
}
if (response.status === 200) {
return {
body: {
todos: await response.json()
}
};
}
return {
status: response.status
};
return {
status: response.status
};
};
/** @type {import('./index').RequestHandler} */
export const post = async ({ request, locals }) => {
const form = await request.formData();
const form = await request.formData();
await api('post', `todos/${locals.userid}`, {
text: form.get('text')
});
await api('post', `todos/${locals.userid}`, {
text: form.get('text')
});
return {};
return {};
};
// If the user has JavaScript disabled, the URL will change to
// include the method override unless we redirect back to /todos
const redirect = {
status: 303,
headers: {
location: '/todos'
}
status: 303,
headers: {
location: '/todos'
}
};
/** @type {import('./index').RequestHandler} */
export const patch = async ({ request, locals }) => {
const form = await request.formData();
const form = await request.formData();
await api('patch', `todos/${locals.userid}/${form.get('uid')}`, {
text: form.has('text') ? form.get('text') : undefined,
done: form.has('done') ? !!form.get('done') : undefined
});
await api('patch', `todos/${locals.userid}/${form.get('uid')}`, {
text: form.has('text') ? form.get('text') : undefined,
done: form.has('done') ? !!form.get('done') : undefined
});
return redirect;
return redirect;
};
/** @type {import('./index').RequestHandler} */
export const del = async ({ request, locals }) => {
const form = await request.formData();
const form = await request.formData();
await api('delete', `todos/${locals.userid}/${form.get('uid')}`);
await api('delete', `todos/${locals.userid}/${form.get('uid')}`);
return redirect;
return redirect;
};

View File

@@ -1,178 +1,190 @@
<script>
import { enhance } from '$lib/form';
import { scale } from 'svelte/transition';
import { flip } from 'svelte/animate';
import { enhance } from '$lib/form';
import { scale } from 'svelte/transition';
import { flip } from 'svelte/animate';
export let todos;
/**
* @typedef {{
* uid: string;
* created_at: Date;
* text: string;
* done: boolean;
* pending_delete: boolean;
* }} Todo
*/
/** @type {Todo[]} */
export let todos;
</script>
<svelte:head>
<title>Todos</title>
<title>Todos</title>
<meta name="description" content="A todo list app" />
</svelte:head>
<div class="todos">
<h1>Todos</h1>
<h1>Todos</h1>
<form
class="new"
action="/todos"
method="post"
use:enhance={{
result: async ({ form }) => {
form.reset();
}
}}
>
<input name="text" aria-label="Add todo" placeholder="+ tap to add a todo" />
</form>
<form
class="new"
action="/todos"
method="post"
use:enhance={{
result: async ({ form }) => {
form.reset();
}
}}
>
<input name="text" aria-label="Add todo" placeholder="+ tap to add a todo" />
</form>
{#each todos as todo (todo.uid)}
<div
class="todo"
class:done={todo.done}
transition:scale|local={{ start: 0.7 }}
animate:flip={{ duration: 200 }}
>
<form
action="/todos?_method=PATCH"
method="post"
use:enhance={{
pending: ({ data }) => {
todo.done = !!data.get('done');
}
}}
>
<input type="hidden" name="uid" value={todo.uid} />
<input type="hidden" name="done" value={todo.done ? '' : 'true'} />
<button class="toggle" aria-label="Mark todo as {todo.done ? 'not done' : 'done'}" />
</form>
{#each todos as todo (todo.uid)}
<div
class="todo"
class:done={todo.done}
transition:scale|local={{ start: 0.7 }}
animate:flip={{ duration: 200 }}
>
<form
action="/todos?_method=PATCH"
method="post"
use:enhance={{
pending: ({ data }) => {
todo.done = !!data.get('done');
}
}}
>
<input type="hidden" name="uid" value={todo.uid} />
<input type="hidden" name="done" value={todo.done ? '' : 'true'} />
<button class="toggle" aria-label="Mark todo as {todo.done ? 'not done' : 'done'}" />
</form>
<form class="text" action="/todos?_method=PATCH" method="post" use:enhance>
<input type="hidden" name="uid" value={todo.uid} />
<input aria-label="Edit todo" type="text" name="text" value={todo.text} />
<button class="save" aria-label="Save todo" />
</form>
<form class="text" action="/todos?_method=PATCH" method="post" use:enhance>
<input type="hidden" name="uid" value={todo.uid} />
<input aria-label="Edit todo" type="text" name="text" value={todo.text} />
<button class="save" aria-label="Save todo" />
</form>
<form
action="/todos?_method=DELETE"
method="post"
use:enhance={{
pending: () => (todo.pending_delete = true)
}}
>
<input type="hidden" name="uid" value={todo.uid} />
<button class="delete" aria-label="Delete todo" disabled={todo.pending_delete} />
</form>
</div>
{/each}
<form
action="/todos?_method=DELETE"
method="post"
use:enhance={{
pending: () => (todo.pending_delete = true)
}}
>
<input type="hidden" name="uid" value={todo.uid} />
<button class="delete" aria-label="Delete todo" disabled={todo.pending_delete} />
</form>
</div>
{/each}
</div>
<style>
.todos {
width: 100%;
max-width: var(--column-width);
margin: var(--column-margin-top) auto 0 auto;
line-height: 1;
}
.todos {
width: 100%;
max-width: var(--column-width);
margin: var(--column-margin-top) auto 0 auto;
line-height: 1;
}
.new {
margin: 0 0 0.5rem 0;
}
.new {
margin: 0 0 0.5rem 0;
}
input {
border: 1px solid transparent;
}
input {
border: 1px solid transparent;
}
input:focus-visible {
box-shadow: inset 1px 1px 6px rgba(0, 0, 0, 0.1);
border: 1px solid #ff3e00 !important;
outline: none;
}
input:focus-visible {
box-shadow: inset 1px 1px 6px rgba(0, 0, 0, 0.1);
border: 1px solid #ff3e00 !important;
outline: none;
}
.new input {
font-size: 28px;
width: 100%;
padding: 0.5em 1em 0.3em 1em;
box-sizing: border-box;
background: rgba(255, 255, 255, 0.05);
border-radius: 8px;
text-align: center;
}
.new input {
font-size: 28px;
width: 100%;
padding: 0.5em 1em 0.3em 1em;
box-sizing: border-box;
background: rgba(255, 255, 255, 0.05);
border-radius: 8px;
text-align: center;
}
.todo {
display: grid;
grid-template-columns: 2rem 1fr 2rem;
grid-gap: 0.5rem;
align-items: center;
margin: 0 0 0.5rem 0;
padding: 0.5rem;
background-color: white;
border-radius: 8px;
filter: drop-shadow(2px 4px 6px rgba(0, 0, 0, 0.1));
transform: translate(-1px, -1px);
transition: filter 0.2s, transform 0.2s;
}
.todo {
display: grid;
grid-template-columns: 2rem 1fr 2rem;
grid-gap: 0.5rem;
align-items: center;
margin: 0 0 0.5rem 0;
padding: 0.5rem;
background-color: white;
border-radius: 8px;
filter: drop-shadow(2px 4px 6px rgba(0, 0, 0, 0.1));
transform: translate(-1px, -1px);
transition: filter 0.2s, transform 0.2s;
}
.done {
transform: none;
opacity: 0.4;
filter: drop-shadow(0 0 1px rgba(0, 0, 0, 0.1));
}
.done {
transform: none;
opacity: 0.4;
filter: drop-shadow(0 0 1px rgba(0, 0, 0, 0.1));
}
form.text {
position: relative;
display: flex;
align-items: center;
flex: 1;
}
form.text {
position: relative;
display: flex;
align-items: center;
flex: 1;
}
.todo input {
flex: 1;
padding: 0.5em 2em 0.5em 0.8em;
border-radius: 3px;
}
.todo input {
flex: 1;
padding: 0.5em 2em 0.5em 0.8em;
border-radius: 3px;
}
.todo button {
width: 2em;
height: 2em;
border: none;
background-color: transparent;
background-position: 50% 50%;
background-repeat: no-repeat;
}
.todo button {
width: 2em;
height: 2em;
border: none;
background-color: transparent;
background-position: 50% 50%;
background-repeat: no-repeat;
}
button.toggle {
border: 1px solid rgba(0, 0, 0, 0.2);
border-radius: 50%;
box-sizing: border-box;
background-size: 1em auto;
}
button.toggle {
border: 1px solid rgba(0, 0, 0, 0.2);
border-radius: 50%;
box-sizing: border-box;
background-size: 1em auto;
}
.done .toggle {
background-image: url("data:image/svg+xml,%3Csvg width='22' height='16' viewBox='0 0 22 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M20.5 1.5L7.4375 14.5L1.5 8.5909' stroke='%23676778' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.done .toggle {
background-image: url("data:image/svg+xml,%3Csvg width='22' height='16' viewBox='0 0 22 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M20.5 1.5L7.4375 14.5L1.5 8.5909' stroke='%23676778' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.delete {
background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4.5 5V22H19.5V5H4.5Z' fill='%23676778' stroke='%23676778' stroke-width='1.5' stroke-linejoin='round'/%3E%3Cpath d='M10 10V16.5' stroke='white' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M14 10V16.5' stroke='white' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M2 5H22' stroke='%23676778' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M8 5L9.6445 2H14.3885L16 5H8Z' fill='%23676778' stroke='%23676778' stroke-width='1.5' stroke-linejoin='round'/%3E%3C/svg%3E%0A");
opacity: 0.2;
}
.delete {
background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4.5 5V22H19.5V5H4.5Z' fill='%23676778' stroke='%23676778' stroke-width='1.5' stroke-linejoin='round'/%3E%3Cpath d='M10 10V16.5' stroke='white' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M14 10V16.5' stroke='white' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M2 5H22' stroke='%23676778' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M8 5L9.6445 2H14.3885L16 5H8Z' fill='%23676778' stroke='%23676778' stroke-width='1.5' stroke-linejoin='round'/%3E%3C/svg%3E%0A");
opacity: 0.2;
}
.delete:hover,
.delete:focus {
transition: opacity 0.2s;
opacity: 1;
}
.delete:hover,
.delete:focus {
transition: opacity 0.2s;
opacity: 1;
}
.save {
position: absolute;
right: 0;
opacity: 0;
background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M20.5 2H3.5C2.67158 2 2 2.67157 2 3.5V20.5C2 21.3284 2.67158 22 3.5 22H20.5C21.3284 22 22 21.3284 22 20.5V3.5C22 2.67157 21.3284 2 20.5 2Z' fill='%23676778' stroke='%23676778' stroke-width='1.5' stroke-linejoin='round'/%3E%3Cpath d='M17 2V11H7.5V2H17Z' fill='white' stroke='white' stroke-width='1.5' stroke-linejoin='round'/%3E%3Cpath d='M13.5 5.5V7.5' stroke='%23676778' stroke-width='1.5' stroke-linecap='round'/%3E%3Cpath d='M5.99844 2H18.4992' stroke='%23676778' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E%0A");
}
.save {
position: absolute;
right: 0;
opacity: 0;
background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M20.5 2H3.5C2.67158 2 2 2.67157 2 3.5V20.5C2 21.3284 2.67158 22 3.5 22H20.5C21.3284 22 22 21.3284 22 20.5V3.5C22 2.67157 21.3284 2 20.5 2Z' fill='%23676778' stroke='%23676778' stroke-width='1.5' stroke-linejoin='round'/%3E%3Cpath d='M17 2V11H7.5V2H17Z' fill='white' stroke='white' stroke-width='1.5' stroke-linejoin='round'/%3E%3Cpath d='M13.5 5.5V7.5' stroke='%23676778' stroke-width='1.5' stroke-linecap='round'/%3E%3Cpath d='M5.99844 2H18.4992' stroke='%23676778' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E%0A");
}
.todo input:focus + .save,
.save:focus {
transition: opacity 0.2s;
opacity: 1;
}
.todo input:focus + .save,
.save:focus {
transition: opacity 0.2s;
opacity: 1;
}
</style>

View File

@@ -2,14 +2,14 @@ import adapter from '@sveltejs/adapter-auto';
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
adapter: adapter(),
kit: {
adapter: adapter(),
// Override http methods in the Todo forms
methodOverride: {
allowed: ['PATCH', 'DELETE']
}
}
// Override http methods in the Todo forms
methodOverride: {
allowed: ['PATCH', 'DELETE']
}
}
};
export default config;

View File

@@ -14,37 +14,24 @@
"dependencies": {
"lerna": "3.16.4"
},
"turbo": {
"baseBranch": "origin/main",
"pipeline": {
"build": {
"dependsOn": [
"^build"
],
"outputs": [
"dist/**"
]
}
}
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "4.28.0",
"@typescript-eslint/parser": "4.28.0",
"@typescript-eslint/eslint-plugin": "5.21.0",
"@typescript-eslint/parser": "5.21.0",
"async-retry": "1.2.3",
"buffer-replace": "1.0.0",
"eslint": "7.29.0",
"eslint-config-prettier": "8.3.0",
"eslint-plugin-jest": "24.3.6",
"husky": "6.0.0",
"jest": "27.3.1",
"eslint": "8.14.0",
"eslint-config-prettier": "8.5.0",
"eslint-plugin-jest": "26.1.5",
"husky": "7.0.4",
"jest": "28.0.2",
"json5": "2.1.1",
"lint-staged": "9.2.5",
"node-fetch": "2.6.1",
"npm-package-arg": "6.1.0",
"prettier": "2.3.1",
"prettier": "2.6.2",
"ts-eager": "2.0.2",
"ts-jest": "27.0.4",
"turbo": "1.1.9"
"ts-jest": "28.0.0-next.1",
"turbo": "1.2.14"
},
"scripts": {
"lerna": "lerna",
@@ -57,10 +44,10 @@
"vercel-build": "yarn build && cd api && node -r ts-eager/register ./_lib/script/build.ts",
"pre-commit": "lint-staged",
"test": "jest --rootDir=\"test\" --testPathPattern=\"\\.test.js\"",
"test-unit": "yarn test && node utils/run.js test-unit",
"test-integration-cli": "node utils/run.js test-integration-cli",
"test-integration-once": "node utils/run.js test-integration-once",
"test-integration-dev": "node utils/run.js test-integration-dev",
"test-unit": "yarn test && turbo run test-unit",
"test-integration-cli": "turbo run test-integration-cli",
"test-integration-once": "turbo run test-integration-once",
"test-integration-dev": "turbo run test-integration-dev",
"lint": "eslint . --ext .ts,.js",
"prepare": "husky install"
},

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/build-utils",
"version": "2.15.1",
"version": "3.1.1",
"license": "MIT",
"main": "./dist/index.js",
"types": "./dist/index.d.js",
@@ -12,8 +12,9 @@
},
"scripts": {
"build": "node build",
"test-unit": "jest --env node --verbose --runInBand --bail test/unit.*test.*",
"test-integration-once": "jest --env node --verbose --runInBand --bail test/integration.test.ts",
"test": "jest --env node --verbose --runInBand --bail",
"test-unit": "yarn test test/unit.*test.*",
"test-integration-once": "yarn test test/integration.test.ts",
"prepublishOnly": "node build"
},
"devDependencies": {
@@ -23,14 +24,14 @@
"@types/end-of-stream": "^1.4.0",
"@types/fs-extra": "9.0.13",
"@types/glob": "^7.1.1",
"@types/jest": "27.0.1",
"@types/jest": "27.4.1",
"@types/js-yaml": "3.12.1",
"@types/ms": "0.7.31",
"@types/multistream": "2.1.1",
"@types/node-fetch": "^2.1.6",
"@types/semver": "6.0.0",
"@types/yazl": "^2.4.1",
"@vercel/frameworks": "0.7.1",
"@types/yazl": "2.4.2",
"@vercel/frameworks": "1.0.0",
"@vercel/ncc": "0.24.0",
"aggregate-error": "3.0.1",
"async-retry": "1.2.3",
@@ -47,6 +48,6 @@
"node-fetch": "2.6.1",
"semver": "6.1.1",
"typescript": "4.3.4",
"yazl": "2.4.3"
"yazl": "2.5.1"
}
}

View File

@@ -538,7 +538,7 @@ function getMissingBuildScriptError() {
code: 'missing_build_script',
message:
'Your `package.json` file is missing a `build` property inside the `scripts` property.' +
'\nLearn More: https://vercel.com/docs/v2/platform/frequently-asked-questions#missing-build-script',
'\nLearn More: https://vercel.link/missing-build-script',
};
}

View File

@@ -1,12 +1,17 @@
import { Framework, FrameworkDetectionItem } from '@vercel/frameworks';
import { DetectorFilesystem } from './detectors/filesystem';
export interface DetectFrameworkOptions {
fs: DetectorFilesystem;
frameworkList: readonly Framework[];
interface BaseFramework {
slug: Framework['slug'];
detectors?: Framework['detectors'];
}
async function matches(fs: DetectorFilesystem, framework: Framework) {
export interface DetectFrameworkOptions {
fs: DetectorFilesystem;
frameworkList: readonly BaseFramework[];
}
async function matches(fs: DetectorFilesystem, framework: BaseFramework) {
const { detectors } = framework;
if (!detectors) {

View File

@@ -1,3 +1,8 @@
export interface Stat {
name: string;
path: string;
type: 'file' | 'dir';
}
/**
* `DetectorFilesystem` is an abstract class that represents a virtual filesystem
* to perform read-only operations on in order to detect which framework is being
@@ -27,15 +32,19 @@ export abstract class DetectorFilesystem {
protected abstract _hasPath(name: string): Promise<boolean>;
protected abstract _readFile(name: string): Promise<Buffer>;
protected abstract _isFile(name: string): Promise<boolean>;
protected abstract _readdir(name: string): Promise<Stat[]>;
protected abstract _chdir(name: string): DetectorFilesystem;
private pathCache: Map<string, Promise<boolean>>;
private fileCache: Map<string, Promise<boolean>>;
private readFileCache: Map<string, Promise<Buffer>>;
private readdirCache: Map<string, Promise<Stat[]>>;
constructor() {
this.pathCache = new Map();
this.fileCache = new Map();
this.readFileCache = new Map();
this.readdirCache = new Map();
}
public hasPath = async (path: string): Promise<boolean> => {
@@ -64,4 +73,23 @@ export abstract class DetectorFilesystem {
}
return p;
};
/**
* Returns a list of Stat objects from the current working directory.
*/
public readdir = async (name: string): Promise<Stat[]> => {
let p = this.readdirCache.get(name);
if (!p) {
p = this._readdir(name);
this.readdirCache.set(name, p);
}
return p;
};
/**
* Changes the current directory to the specified path and returns a new instance of DetectorFilesystem.
*/
public chdir = (name: string): DetectorFilesystem => {
return this._chdir(name);
};
}

View File

@@ -4,8 +4,14 @@ import { NowBuildError } from '../errors';
import debug from '../debug';
const allOptions = [
{ major: 16, range: '16.x', runtime: 'nodejs16.x' },
{ major: 14, range: '14.x', runtime: 'nodejs14.x' },
{ major: 12, range: '12.x', runtime: 'nodejs12.x' },
{
major: 12,
range: '12.x',
runtime: 'nodejs12.x',
discontinueDate: new Date('2022-08-09'),
},
{
major: 10,
range: '10.x',

View File

@@ -1,15 +1,19 @@
import assert from 'assert';
import fs from 'fs-extra';
import path from 'path';
import debug from '../debug';
import Sema from 'async-sema';
import spawn from 'cross-spawn';
import { SpawnOptions } from 'child_process';
import { deprecate } from 'util';
import debug from '../debug';
import { NowBuildError } from '../errors';
import { Meta, PackageJson, NodeVersion, Config } from '../types';
import { getSupportedNodeVersion, getLatestNodeVersion } from './node-version';
import { readConfigFile } from './read-config-file';
// Only allow one `runNpmInstall()` invocation to run concurrently
const runNpmInstallSema = new Sema(1);
export type CliType = 'yarn' | 'npm' | 'pnpm';
export interface ScanParentDirsResult {
@@ -17,6 +21,11 @@ export interface ScanParentDirsResult {
* "yarn", "npm", or "pnpm" depending on the presence of lockfiles.
*/
cliType: CliType;
/**
* The file path of found `package.json` file, or `undefined` if none was
* found.
*/
packageJsonPath?: string;
/**
* The contents of found `package.json` file, when the `readPackageJson`
* option is enabled.
@@ -196,7 +205,9 @@ export function getSpawnOptions(
if (!meta.isDev) {
// Ensure that the selected Node version is at the beginning of the `$PATH`
opts.env.PATH = `/node${nodeVersion.major}/bin:${opts.env.PATH}`;
opts.env.PATH = `/node${nodeVersion.major}/bin${path.delimiter}${
opts.env.PATH || process.env.PATH
}`;
}
return opts;
@@ -237,12 +248,13 @@ export async function scanParentDirs(
let cliType: CliType = 'yarn';
let packageJson: PackageJson | undefined;
let packageJsonPath: string | undefined;
let currentDestPath = destPath;
let lockfileVersion: number | undefined;
// eslint-disable-next-line no-constant-condition
while (true) {
const packageJsonPath = path.join(currentDestPath, 'package.json');
packageJsonPath = path.join(currentDestPath, 'package.json');
// eslint-disable-next-line no-await-in-loop
if (await fs.pathExists(packageJsonPath)) {
// Only read the contents of the *first* `package.json` file found,
@@ -269,15 +281,17 @@ export async function scanParentDirs(
),
]);
if (packageLockJson && !hasYarnLock && !pnpmLockYaml) {
cliType = 'npm';
lockfileVersion = packageLockJson.lockfileVersion;
}
if (!packageLockJson && !hasYarnLock && pnpmLockYaml) {
// Priority order is Yarn > pnpm > npm
// - find highest priority lock file and use that
if (hasYarnLock) {
cliType = 'yarn';
} else if (pnpmLockYaml) {
cliType = 'pnpm';
// just ensure that it is read as a number and not a string
lockfileVersion = Number(pnpmLockYaml.lockfileVersion);
} else if (packageLockJson) {
cliType = 'npm';
lockfileVersion = packageLockJson.lockfileVersion;
}
// Only stop iterating if a lockfile was found, because it's possible
@@ -293,7 +307,7 @@ export async function scanParentDirs(
currentDestPath = newDestPath;
}
return { cliType, packageJson, lockfileVersion };
return { cliType, packageJson, lockfileVersion, packageJsonPath };
}
export async function walkParentDirs({
@@ -319,55 +333,87 @@ export async function walkParentDirs({
return null;
}
function isSet<T>(v: any): v is Set<T> {
return v?.constructor?.name === 'Set';
}
export async function runNpmInstall(
destPath: string,
args: string[] = [],
spawnOpts?: SpawnOptions,
meta?: Meta,
nodeVersion?: NodeVersion
) {
): Promise<boolean> {
if (meta?.isDev) {
debug('Skipping dependency installation because dev mode is enabled');
return;
return false;
}
assert(path.isAbsolute(destPath));
debug(`Installing to ${destPath}`);
const { cliType, lockfileVersion } = await scanParentDirs(destPath);
const opts: SpawnOptionsExtended = { cwd: destPath, ...spawnOpts };
const env = opts.env ? { ...opts.env } : { ...process.env };
delete env.NODE_ENV;
opts.env = getEnvForPackageManager({
cliType,
lockfileVersion,
nodeVersion,
env,
});
let commandArgs: string[];
try {
await runNpmInstallSema.acquire();
const { cliType, packageJsonPath, lockfileVersion } = await scanParentDirs(
destPath
);
if (cliType === 'npm') {
opts.prettyCommand = 'npm install';
commandArgs = args
.filter(a => a !== '--prefer-offline')
.concat(['install', '--no-audit', '--unsafe-perm']);
} else if (cliType === 'pnpm') {
// PNPM's install command is similar to NPM's but without the audit nonsense
// @see options https://pnpm.io/cli/install
opts.prettyCommand = 'pnpm install';
commandArgs = args
.filter(a => a !== '--prefer-offline')
.concat(['install', '--unsafe-perm']);
} else {
opts.prettyCommand = 'yarn install';
commandArgs = ['install', ...args];
// Only allow `runNpmInstall()` to run once per `package.json`
// when doing a default install (no additional args)
if (meta && packageJsonPath && args.length === 0) {
if (!isSet<string>(meta.runNpmInstallSet)) {
meta.runNpmInstallSet = new Set<string>();
}
if (isSet<string>(meta.runNpmInstallSet)) {
if (meta.runNpmInstallSet.has(packageJsonPath)) {
return false;
} else {
meta.runNpmInstallSet.add(packageJsonPath);
}
}
}
const installTime = Date.now();
console.log('Installing dependencies...');
debug(`Installing to ${destPath}`);
const opts: SpawnOptionsExtended = { cwd: destPath, ...spawnOpts };
const env = opts.env ? { ...opts.env } : { ...process.env };
delete env.NODE_ENV;
opts.env = getEnvForPackageManager({
cliType,
lockfileVersion,
nodeVersion,
env,
});
let commandArgs: string[];
if (cliType === 'npm') {
opts.prettyCommand = 'npm install';
commandArgs = args
.filter(a => a !== '--prefer-offline')
.concat(['install', '--no-audit', '--unsafe-perm']);
} else if (cliType === 'pnpm') {
// PNPM's install command is similar to NPM's but without the audit nonsense
// @see options https://pnpm.io/cli/install
opts.prettyCommand = 'pnpm install';
commandArgs = args
.filter(a => a !== '--prefer-offline')
.concat(['install', '--unsafe-perm']);
} else {
opts.prettyCommand = 'yarn install';
commandArgs = ['install', ...args];
}
if (process.env.NPM_ONLY_PRODUCTION) {
commandArgs.push('--production');
}
await spawnAsync(cliType, commandArgs, opts);
debug(`Install complete [${Date.now() - installTime}ms]`);
return true;
} finally {
runNpmInstallSema.release();
}
if (process.env.NPM_ONLY_PRODUCTION) {
commandArgs.push('--production');
}
return spawnAsync(cliType, commandArgs, opts);
}
export function getEnvForPackageManager({
@@ -389,9 +435,15 @@ export function getEnvForPackageManager({
(nodeVersion?.major || 0) < 16
) {
// Ensure that npm 7 is at the beginning of the `$PATH`
newEnv.PATH = `/node16/bin-npm7:${env.PATH}`;
newEnv.PATH = `/node16/bin-npm7${path.delimiter}${env.PATH}`;
console.log('Detected `package-lock.json` generated by npm 7...');
}
} else if (cliType === 'pnpm') {
if (typeof lockfileVersion === 'number' && lockfileVersion === 5.4) {
// Ensure that pnpm 7 is at the beginning of the `$PATH`
newEnv.PATH = `/pnpm7/node_modules/.bin${path.delimiter}${env.PATH}`;
console.log('Detected `pnpm-lock.yaml` generated by pnpm 7...');
}
} else {
// Yarn v2 PnP mode may be activated, so force "node-modules" linker style
if (!env.YARN_NODE_LINKER) {
@@ -502,7 +554,7 @@ export async function runPipInstall(
meta?: Meta
) {
if (meta && meta.isDev) {
debug('Skipping dependency installation because dev mode is enabled');
debug('Skipping dependency installation because dev mode is enabled');
return;
}

View File

@@ -33,7 +33,6 @@ import {
getDiscontinuedNodeVersions,
} from './fs/node-version';
import streamToBuffer from './fs/stream-to-buffer';
import shouldServe from './should-serve';
import debug from './debug';
import getIgnoreFilter from './get-ignore-filter';
import { getPlatformEnv } from './get-platform-env';
@@ -73,7 +72,6 @@ export {
getSpawnOptions,
getPlatformEnv,
streamToBuffer,
shouldServe,
debug,
isSymbolicLink,
getLambdaOptionsFromFunction,
@@ -94,6 +92,7 @@ export { DetectorFilesystem } from './detectors/filesystem';
export { readConfigFile } from './fs/read-config-file';
export { normalizePath } from './fs/normalize-path';
export * from './should-serve';
export * from './schemas';
export * from './types';
export * from './errors';
@@ -116,3 +115,7 @@ export const isOfficialRuntime = (desired: string, name?: string): boolean => {
export const isStaticRuntime = (name?: string): boolean => {
return isOfficialRuntime('static', name);
};
export { workspaceManagers } from './workspaces/workspace-managers';
export { getWorkspaces } from './workspaces/get-workspaces';
export { monorepoManagers } from './monorepos/monorepo-managers';

View File

@@ -0,0 +1,36 @@
import type { Framework } from '@vercel/frameworks';
/**
* The supported list of monorepo managers.
*
* This list is designed to work with the @see {@link detectFramework} function.
*
* @example
* import { monorepoManagers as frameworkList } from '@vercel/build-utils'
* import { detectFramework } from '@vercel/build-utils'
*
* const fs = new GitDetectorFilesystem(...)
* detectFramwork({ fs, frameworkList }) // returns the 'slug' field if detected, otherwise null
*
*/
export const monorepoManagers: Array<
Omit<Framework, 'description' | 'logo' | 'settings' | 'getOutputDirName'>
> = [
{
name: 'Turborepo',
slug: 'turbo',
detectors: {
some: [
{
path: 'turbo.json',
},
{
path: 'package.json',
matchContent: '"turbo":\\s*{[^}]*.+[^}]*}',
},
],
},
},
];
export default monorepoManagers;

View File

@@ -1,12 +1,12 @@
import { parse } from 'path';
import { ShouldServeOptions } from './types';
import FileFsRef from './file-fs-ref';
import type FileFsRef from './file-fs-ref';
import type { ShouldServe } from './types';
export default function shouldServe({
export const shouldServe: ShouldServe = ({
entrypoint,
files,
requestPath,
}: ShouldServeOptions): boolean {
}) => {
requestPath = requestPath.replace(/\/$/, ''); // sanitize trailing '/'
entrypoint = entrypoint.replace(/\\/, '/'); // windows compatibility
@@ -20,7 +20,7 @@ export default function shouldServe({
}
return false;
}
};
function hasProp(obj: { [path: string]: FileFsRef }, key: string): boolean {
return Object.hasOwnProperty.call(obj, key);

View File

@@ -327,11 +327,13 @@ export interface ProjectSettings {
buildCommand?: string | null;
outputDirectory?: string | null;
rootDirectory?: string | null;
nodeVersion?: string;
createdAt?: number;
autoExposeSystemEnvs?: boolean;
sourceFilesOutsideRootDirectory?: boolean;
directoryListing?: boolean;
gitForkProtection?: boolean;
commandForIgnoringBuildStep?: string | null;
}
export interface BuilderV2 {
@@ -344,19 +346,72 @@ export interface BuilderV3 {
version: 3;
build: BuildV3;
prepareCache?: PrepareCache;
shouldServe?: ShouldServe;
startDevServer?: StartDevServer;
}
type ImageFormat = 'image/avif' | 'image/webp';
export type RemotePattern = {
/**
* Must be `http` or `https`.
*/
protocol?: 'http' | 'https';
/**
* Can be literal or wildcard.
* Single `*` matches a single subdomain.
* Double `**` matches any number of subdomains.
*/
hostname: string;
/**
* Can be literal port such as `8080` or empty string
* meaning no port.
*/
port?: string;
/**
* Can be literal or wildcard.
* Single `*` matches a single path segment.
* Double `**` matches any number of path segments.
*/
pathname?: string;
};
export interface Images {
domains: string[];
remotePatterns?: RemotePattern[];
sizes: number[];
minimumCacheTTL?: number;
formats?: ImageFormat[];
dangerouslyAllowSVG?: boolean;
contentSecurityPolicy?: string;
}
export interface BuildResultV2 {
/**
* If a Builder ends up creating filesystem outputs conforming to
* the Build Output API, then the Builder should return this type.
*/
export interface BuildResultBuildOutput {
/**
* Version number of the Build Output API that was created.
* Currently only `3` is a valid value.
* @example 3
*/
buildOutputVersion: 3;
/**
* Filesystem path to the Build Output directory.
* @example "/path/to/.vercel/output"
*/
buildOutputPath: string;
}
/**
* When a Builder implements `version: 2`, the `build()` function is expected
* to return this type.
*/
export interface BuildResultV2Typical {
// TODO: use proper `Route` type from `routing-utils` (perhaps move types to a common package)
routes?: any[];
images?: Images;
@@ -369,6 +424,8 @@ export interface BuildResultV2 {
}>;
}
export type BuildResultV2 = BuildResultV2Typical | BuildResultBuildOutput;
export interface BuildResultV3 {
output: Lambda;
}
@@ -376,6 +433,9 @@ export interface BuildResultV3 {
export type BuildV2 = (options: BuildOptions) => Promise<BuildResultV2>;
export type BuildV3 = (options: BuildOptions) => Promise<BuildResultV3>;
export type PrepareCache = (options: PrepareCacheOptions) => Promise<Files>;
export type ShouldServe = (
options: ShouldServeOptions
) => boolean | Promise<boolean>;
export type StartDevServer = (
options: StartDevServerOptions
) => Promise<StartDevServerResult>;

View File

@@ -0,0 +1,59 @@
import path from 'path';
import { DetectorFilesystem } from '../detectors/filesystem';
import { workspaceManagers } from './workspace-managers';
import { detectFramework as detectWorkspaceManagers } from '../detect-framework';
const MAX_DEPTH_TRAVERSE = 3;
const posixPath = path.posix;
export interface GetWorkspaceOptions {
fs: DetectorFilesystem;
depth?: number;
cwd?: string;
}
export type WorkspaceType = 'yarn' | 'pnpm' | 'npm';
export type Workspace = {
type: WorkspaceType;
rootPath: string;
};
export async function getWorkspaces({
fs,
depth = MAX_DEPTH_TRAVERSE,
cwd = '/',
}: GetWorkspaceOptions): Promise<Workspace[]> {
if (depth === 0) return [];
const workspaceType = await detectWorkspaceManagers({
fs,
frameworkList: workspaceManagers,
});
if (workspaceType === null) {
const directoryContents = await fs.readdir('./');
const childDirectories = directoryContents.filter(
stat => stat.type === 'dir'
);
return (
await Promise.all(
childDirectories.map(childDirectory =>
getWorkspaces({
fs: fs.chdir(childDirectory.path),
depth: depth - 1,
cwd: posixPath.join(cwd, childDirectory.path),
})
)
)
).flat();
}
return [
{
type: workspaceType as WorkspaceType,
rootPath: cwd,
},
];
}

View File

@@ -0,0 +1,64 @@
import type { Framework } from '@vercel/frameworks';
/**
* The supported list of workspace managers.
*
* This list is designed to work with the @see {@link detectFramework} function.
*
* @example
* import { workspaceManagers as frameworkList } from '@vercel/build-utils'
* import { detectFramework } from '@vercel/build-utils'
*
* const fs = new GitDetectorFilesystem(...)
* detectFramwork({ fs, frameworkList }) // returns the 'slug' field if detected, otherwise null
*
*/
export const workspaceManagers: Array<
Omit<Framework, 'description' | 'logo' | 'settings' | 'getOutputDirName'>
> = [
{
name: 'Yarn',
slug: 'yarn',
detectors: {
every: [
{
path: 'package.json',
matchContent:
'"workspaces":\\s*(?:\\[[^\\]]*]|{[^}]*"packages":[^}]*})',
},
{
path: 'yarn.lock',
},
],
},
},
{
name: 'pnpm',
slug: 'pnpm',
detectors: {
every: [
{
path: 'pnpm-workspace.yaml',
},
],
},
},
{
name: 'npm',
slug: 'npm',
detectors: {
every: [
{
path: 'package.json',
matchContent:
'"workspaces":\\s*(?:\\[[^\\]]*]|{[^}]*"packages":[^}]*})',
},
{
path: 'package-lock.json',
},
],
},
},
];
export default workspaceManagers;

View File

@@ -0,0 +1,4 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1

View File

@@ -17,5 +17,13 @@ checkPkgOrThrow('exeggcute');
// This is to satisfy `@vercel/static-build` which needs a `dist` directory.
const { exec } = require('exeggcute');
exec('mkdir dist', __dirname);
exec('echo "node-env:RANDOMNESS_PLACEHOLDER" > dist/index.html', __dirname);
exec('mkdir dist', __dirname)
.then(() => {
exec(
'echo "node-env:RANDOMNESS_PLACEHOLDER" > dist/index.html',
__dirname
).then(() => {
console.log('Success');
});
})
.catch(console.error);

View File

@@ -6,5 +6,10 @@ const b = require('./b');
a();
b();
exec('mkdir public', __dirname);
exec('echo "Hello, World!" > public/index.html', __dirname);
exec('mkdir public', __dirname)
.then(() => {
exec('echo "Hello, World!" > public/index.html', __dirname).then(() => {
console.log('Success');
});
})
.catch(console.error);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,14 @@
{
"private": "true",
"name": "25-multiple-lock-files-yarn",
"workspaces": [
"a",
"b"
],
"scripts": {
"build": "mkdir -p public && (printf \"yarn version: \" && yarn -v) > public/index.txt"
},
"dependencies": {
"once": "^1.4.0"
}
}

View File

@@ -0,0 +1,19 @@
lockfileVersion: 5.3
specifiers:
once: ^1.4.0
dependencies:
once: 1.4.0
packages:
/once/1.4.0:
resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=}
dependencies:
wrappy: 1.0.2
dev: false
/wrappy/1.0.2:
resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=}
dev: false

View File

@@ -0,0 +1,11 @@
{
"version": 2,
"builds": [{ "src": "package.json", "use": "@vercel/static-build" }],
"probes": [
{
"path": "/",
"mustContain": "yarn version: 1",
"logMustContain": "yarn run build"
}
]
}

View File

@@ -0,0 +1,15 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
once@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
dependencies:
wrappy "1"
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=

View File

@@ -0,0 +1,44 @@
{
"name": "26-multiple-lock-files-pnpm",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "26-multiple-lock-files-pnpm",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"once": "^1.4.0"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dependencies": {
"wrappy": "1"
}
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
}
},
"dependencies": {
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"requires": {
"wrappy": "1"
}
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
}
}
}

View File

@@ -0,0 +1,14 @@
{
"private": "true",
"name": "26-multiple-lock-files-pnpm",
"workspaces": [
"a",
"b"
],
"scripts": {
"build": "mkdir -p public && (printf \"pnpm version: \" && pnpm -v) > public/index.txt"
},
"dependencies": {
"once": "^1.4.0"
}
}

View File

@@ -0,0 +1,19 @@
lockfileVersion: 5.3
specifiers:
once: ^1.4.0
dependencies:
once: 1.4.0
packages:
/once/1.4.0:
resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=}
dependencies:
wrappy: 1.0.2
dev: false
/wrappy/1.0.2:
resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=}
dev: false

View File

@@ -0,0 +1,3 @@
packages:
- 'a'
- 'b'

View File

@@ -0,0 +1,11 @@
{
"version": 2,
"builds": [{ "src": "package.json", "use": "@vercel/static-build" }],
"probes": [
{
"path": "/",
"mustContain": "pnpm version: 6",
"logMustContain": "pnpm run build"
}
]
}

View File

@@ -0,0 +1,15 @@
{
"name": "a",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"debug": "^4.3.2"
}
}

View File

@@ -0,0 +1,15 @@
{
"name": "b",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"cowsay": "^1.5.0"
}
}

Some files were not shown because too many files have changed in this diff Show More