{"_id":"@asemirsk/psh","_rev":"18-745b7cf35e4ffe746d384668df58aad3","time":{"created":"2022-04-04T11:44:52.620Z","1.0.0-alpha-3.9.0":"2022-03-15T12:56:35.847Z","modified":"2022-05-25T09:17:50.353Z","1.0.0-alpha-3.1.0":"2022-03-15T13:54:13.664Z","1.0.0-beta.2":"2022-03-15T14:25:09.170Z","1.0.0-beta.3":"2022-03-15T14:37:38.288Z","1.0.0":"2022-03-15T14:40:35.831Z","1.0.1-beta.0":"2022-03-15T14:44:43.608Z","1.0.0-alpha-5.3.0":"2022-03-15T16:03:36.776Z","1.0.0-alpha.0":"2022-04-04T11:44:52.883Z","1.0.0-beta.5":"2022-04-04T13:57:35.791Z","1.0.0-beta.6":"2022-04-08T20:00:49.338Z","1.0.1-beta.6":"2022-04-08T20:05:00.892Z","1.0.1":"2022-04-08T20:09:42.150Z","1.0.2-beta.0":"2022-04-08T20:19:08.852Z","1.0.2":"2022-04-08T20:22:20.222Z","1.1.0":"2022-04-19T15:07:08.683Z","1.0.0-canary-24-22.0":"2022-05-25T08:46:19.959Z","1.0.0-canary-24-23.0":"2022-05-25T09:07:53.061Z","1.0.0-canary-24-24.0":"2022-05-25T09:17:50.277Z"},"name":"@asemirsk/psh","dist-tags":{"alpha":"1.0.0-alpha.0","latest":"1.1.0","next":"1.0.2-beta.0","canary-24":"1.0.0-canary-24-24.0"},"versions":{"1.0.0-alpha.0":{"name":"@asemirsk/psh","version":"1.0.0-alpha.0","description":"Provides cli tool for initializing a bodiless project on platform.sh","author":{"name":"Chris Oden","email":"coden@its.jnj.com"},"homepage":"https://github.com/johnsonandjohnson/bodiless-js#readme","license":"Apache-2.0","bin":{"bodiless-psh-init":"lib/bodiless-psh-init.js"},"scripts":{"build":"tsc --version && tsc -p ./tsconfig.json ","build:watch":"npm run build -- --watch","clean":"rimraf \"lib/*\" && rimraf tsconfig.tsbuildinfo"},"directories":{"lib":"lib"},"repository":{"type":"git","url":"git+https://github.com/johnsonandjohnson/bodiless-js.git"},"publishConfig":{"access":"public"},"dependencies":{"copyfiles":"^2.1.1","js-yaml":"^3.13.1","lodash":"^4.17.19","rimraf":"^2.6.3"},"devDependencies":{"@types/copyfiles":"^2.1.1"},"gitHead":"28ce15a6b1c49e6f984d59ff1db29bac050fe78d","bugs":{"url":"https://github.com/johnsonandjohnson/bodiless-js/issues"},"_id":"@asemirsk/psh@1.0.0-alpha.0","_nodeVersion":"16.13.2","_npmVersion":"lerna/4.0.0/node@v16.13.2+x64 (linux)","dist":{"integrity":"sha512-e8fibA42jlF+1h2jjN2JNVtGPY2rmLG9hs9msMVTk5rRYX1MTMwcOulU0iPbz2ncJ6A4VjAgtxQF8kEPu8FzAg==","shasum":"f5ee9ae476fd29a2e69fcd3347a62c4a4b48f06a","tarball":"https://registry.npmjs.org/@asemirsk/psh/-/psh-1.0.0-alpha.0.tgz","fileCount":14,"unpackedSize":65365,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDuO5NpJuKS3vtNNgJcfhS4zdvC0AwynN+NobqrzIPvkAiEAxVNANeR3etPiboFT29XK0j9Ort9z8B8HNHDuBdfSZuc="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiSto0ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmolww/7BHxyEim6a1PFa99+OF2XR9pm+mgdQpwFAYKvDW0DZ2GVIioq\r\nz4u/u1KeJ7CWzBWUfeHyxW/mCgsSCS27NZruFJgVOm6XCUq9LeOnOk3fGrWG\r\niYZswvC3w9DZ69qIlqjadftyOEpUbIj6j6N39hhAvR6rE+4HeXZ8bK9NOl8p\r\nOBr1yUWnJ0JPihpf8R32c9mhpuAmxLiAij8LTOVg9ch0ZXAPDVsgUPoHK5k5\r\nXu6VNZ+kV+wlwLukDdmRCaiUTH0OLa9+U+9iQDn++bvRCq1hXkc9k+73a7AJ\r\nXSxWhFXH+JDaIy+O02DLIAFEWIsdZavx2pPmhhzh0dXfZnBiPAHx4j9nyLOh\r\n+tx+anF9LN/4HxAVMnEQrVbK3UPMwmEQyGfYhJOKXOmN3mw6/L1AP+1BkvX7\r\n1/dZ2/Q0IHg8uPCNy7EW/IkVCRRetLDokZcoIdj/lKoD9QULgK6UahXTw3iB\r\nLXATPbtCKKny39lfemkS2XChB89VVt2FIc5nwS/eb0KEkOuFXZWqiBDv8WLS\r\nPPa+TxPLzO7VrSx9V3eWm1u/6SyI9FCJ6WlnhX+cidtt+/D6dsPokIPQW0nO\r\ns8mrkO6ny5UaIfw2371VexJgajj5tnBGeTDdEF/0JibDrrEA9hBGQrOn1Yxy\r\nBsbh5/nyF1V6DhGiC11CZZDCwCiIIgsl1XI=\r\n=VNAM\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"asemirsk","email":"al.semirski@gmail.com"},"maintainers":[{"name":"asemirsk","email":"al.semirski@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/psh_1.0.0-alpha.0_1649072692692_0.19117956135353498"},"_hasShrinkwrap":false},"1.0.0-beta.5":{"name":"@asemirsk/psh","version":"1.0.0-beta.5","description":"Provides cli tool for initializing a bodiless project on platform.sh","author":{"name":"Chris Oden","email":"coden@its.jnj.com"},"homepage":"https://github.com/johnsonandjohnson/bodiless-js#readme","license":"Apache-2.0","bin":{"bodiless-psh-init":"lib/bodiless-psh-init.js"},"scripts":{"build":"tsc --version && tsc -p ./tsconfig.json ","build:watch":"npm run build -- --watch","clean":"rimraf \"lib/*\" && rimraf tsconfig.tsbuildinfo"},"directories":{"lib":"lib"},"repository":{"type":"git","url":"git+https://github.com/johnsonandjohnson/bodiless-js.git"},"publishConfig":{"access":"public"},"dependencies":{"copyfiles":"^2.1.1","js-yaml":"^3.13.1","lodash":"^4.17.19","rimraf":"^2.6.3"},"devDependencies":{"@types/copyfiles":"^2.1.1"},"gitHead":"e6beb3c3e2c8fcff324e0e741ec5746fc55ec312","readme":"# Bodiless integration with platform.sh\n\nThis package provides standard configuration files and helper scripts which\nmake it easy for a bodiless site to be deployed to platform.sh.\n\n## Setting up your project\n\n### Pre-requisites\n\n- Admin access to a [platform.sh](https://platform.sh/) project.\n- A service user with *admin access* to a repository in a Bitbucket Server instance.\n- The [platform.sh cli](https://docs.platform.sh/gettingstarted/cli.html)\n\n### Step 1. Gather required information\n\nTo continue, you will need the following:\n\n#### The platform.sh project key\n- Log in via the platform.sh cli.  From your local machine execute:\n  ```\n  platform login\n  ```\n  You will be directed to log in via a web browser\n- Execute\n  ```\n  platform project:list\n  ```\n  You should see a list of all projects you have access to, something like:\n  ```\n    Your projects are:\n  +---------------+-------------------------+-----------------------------------------------------+\n  | ID            | Title                   | URL                                                 |\n  +---------------+-------------------------+-----------------------------------------------------+\n  | abcdefghijklm | project_a               | https://console.platform.sh/webalerts/abcdefghijklm |\n  | lmnopqrstuvwx | project_b               | https://console.platform.sh/webalerts/lmnopqrstuvwx |\n  +---------------+-------------------------+-----------------------------------------------------+`\n  ```\n- Take note of the project ID for your project. This is the value you will use below.\n\n### Step 2. Initialize your project configuration files\n\nPlatform.sh requires several configuration files to be in place\nin your repository. This package contains default versions of these\nfiles for a BodilessJS.  To install or update them:\n\n1. Add this package as a dependency of your project:\n  ```\n  npm i --save-dev @bodiless/psh\n  ```\n2. Add the following to your `package.json` scripts:\n  ```\n  \"init-psh\": \"bodiless-psh-init\"\n  ```\n3. Install or update the configuration files:\n  ```\n  npm run init-psh\n  ```\n> When `@bodiless/psh` is installing its' files it will try to merge `static` and `edit` `*.platform.app.yaml` files based on the whitelisted keys from `packages/bodiless-psh/resources/.platform/platform.whitelist.yaml`. Only the keys that are specified in `platform.whitelist.yaml` will be merged. Merging will be performed by using the recursive algorithm to preserve any keys that are not in default `.platform.app.yaml`. Non-whitelisted keys will be ignored, and a warning message will be printed to the console.\n\n4. Commit the added configuration files to your repository.  These include\n   ```\n   static.platform.sh\n   .platform.app.yaml\n   .platform/*\n   edit/*\n   ```\n\n### Step 3. Create platform.sh environment variables.\n\nFirst, configure your local install to connect to your platform.sh project. From\nwithin your project root, execute\n```\nplatform project:set-remote {project id}\n```\nwhere {project id} is the platform.sh project id you acquired above.\n\nAll variables below should be set at the project level using the platform.sh command\nline, as described in [the platform.sh documentation](https://docs.platform.sh/development/variables.html#project-variables), and all should be visible at both build time and run time.\n\nAdd the following variables:\n\n- env:APP_GIT_REMOTE_URL -- The URL of your upstream Git repository\n- env:APP_GIT_USER -- The user to access your upstream Git repository.\n- env:APP_GIT_USER_EMAIL -- THe user email for your upstream Git repository.\n- env:APP_GIT_PW -- The user password for your upstream Git repository.\n\n\n> Be sure to specify `--sensitive true` for all credentials.\n\nExample:\n```\n$ platform variable:create\n* Level (--level)\nThe level at which to set the variable\n  [project    ] Project-wide\n  [environment] Environment-specific\n> project\n\n* Name (--name)\nThe variable name\n> APP_GIT_USER_EMAIL\n\n* Value (--value)\nThe variable's value\n> email@your.service.account\n\nJSON (--json)\nIs the value JSON-formatted? [y|N] N\n\nSensitive (--sensitive)\nIs the value sensitive? [y|N] N\n\nPrefix (--prefix)\nThe variable name's prefix\nDefault: none\n  [none] No prefix: The variable will be part of $PLATFORM_VARIABLES.\n  [env:] env: The variable will be exposed directly, e.g. as $APP_GIT_USER_EMAIL.\n> env:\n\nVisible at build time (--visible-build)\nShould the variable be available at build time? [Y|n] Y\n\nVisible at runtime (--visible-runtime)\nShould the variable be available at runtime? [Y|n] Y\n\nCreating variable env:APP_GIT_USER_EMAIL on the project...\n```\n\nYou can verify that the variable was created properly by executing, eg:\n  ```\n  platform variable:get env:APP_GIT_USER_EMAIL\n  ```\n  You should see something like:\n  ```\n  $ platform variable:get env:APP_NPM_AUTH\n  +-----------------+---------------------------+\n  | Property        | Value                     |\n  +-----------------+---------------------------+\n  | id              | env:APP_GIT_USER_EMAL     |\n  | created_at      | 2019-08-09T06:48:52-04:00 |\n  | updated_at      | 2019-08-09T06:48:52-04:00 |\n  | name            | env:APP_GIT_USER_EMAIL    |\n  | attributes      | {  }                      |\n  | is_json         | false                     |\n  | is_sensitive    | false                     |\n  | visible_build   | true                      |\n  | visible_runtime | true                      |\n  | level           | project                   |\n  +-----------------+---------------------------+\n  ```\n\n#### Optional: Configure an NPM Private Registry\n\nIf you wish to install packages from a private registry, you may do so. The\npackages to be installed must be namespaced. Set the following 3 environment\nvariables on p.sh. All variables should be visible at both build and run time:\n- `env:APP_NPM_REGISTRY`: the full path to your registry, eg\n  `//my-artifactory.com/api/npm/my-registry/`.\n- `env:APP_NPM_AUTH`: Ypur NPM authentication token. This should be marked as sensitive.\n  To obtain your token:\n  1. Login to your registry:\n     ```\n     npm login --registry=https://url/of/your/private/registry\n     ```\n     Follow the prompts with the username/password/email of the account you wish\n     to use for p.sh automation.\n  2. Examine your `.npmrc` file (usually located in your home directory). You\n     should see something like\n     ```\n     //url/of/your/privateregistry/:_authToken={token}\n     ```\n  3. Copy the token value to the `env:APP_NPM_AUTH` variable in your p.sh project.\n\n- `env:APP_NPM_NAMESPACE`: The namespace of the packages in your private\n  regsitry, eg `@mynamespace`.\n\n### Step 4. Configure the platform.sh Git Service integration.\n\nPlatform.sh provides out-of-the-box integrations with many popular Git service providers.\nWe have tested with Bitbucket Server and GitHub.\n\nNote that you must have admin access to the repository in order to configure the integration.\n\n#### GitHub\n\nFrom your project root, execute `platform integration:add` and follow\nthe prompts, as:\n\n```\n$ platform integration:add\n* Integration type (--type)\nEnter a number to choose:\n  [0] bitbucket\n  [1] bitbucket_server\n  [2] github\n  [3] gitlab\n  [4] hipchat\n  [5] webhook\n  [6] health.email\n  [7] health.pagerduty\n  [8] health.slack\n  [9] health.webhook\n> 2\n\n* Token (--token)\nAn access token for the integration\n> {your GitHub personal access token}\n\n* Repository (--repository)\nThe repository (e.g. 'foo/bar')\n> johnsonandjohnson/Bodiless-JS\n\nBuild pull requests (--build-pull-requests)\nBuild every pull request as an environment? [Y|n] Y\n\nBuild pull requests post-merge (--build-pull-requests-post-merge)\nBuild pull requests based on their post-merge state? [y|N] y\n\nClone data for pull requests (--pull-requests-clone-parent-data)\nClone the parent environment's data for pull requests? [Y|n] n\n\nFetch branches (--fetch-branches)\nFetch all branches from the remote (as inactive environments)? [Y|n] y\n\nPrune branches (--prune-branches)\nDelete branches that do not exist on the remote? [Y|n] y\n\nWarning: adding a 'github' integration will automatically synchronize code from the external Git repository.\nThis means it can overwrite all the code in your project.\n\nAre you sure you want to continue? [y/N] y\nChecking webhook configuration on the repository: johnsonandjohnson/Bodiless-JS\n  Creating new webhook\n  Webhook created successfully\nCreated integration xxxxxxxx (type: github)\n+---------------------------+--------------------------------------------------------------------+\n| Property                  | Value                                                              |\n+---------------------------+--------------------------------------------------------------------+\n| id                        | xxxxxxx                                                            |\n| type                      | github                                                             |\n| token                     | ******                                                             |\n| base_url                  |                                                                    |\n| repository                | foo/bar                                                            |\n| fetch_branches            | true                                                               |\n| prune_branches            | true                                                               |\n| build_pull_requests       | true                                                               |\n| build_pull_requests_post_ | true                                                               |\n| merge                     |                                                                    |\n| pull_requests_clone_paren | false                                                              |\n| t_data                    |                                                                    |\n| hook_url                  | https://us-2.platform.sh/api/projects/jvaff4bu65vgm/integrations/4 |\n|                           | 4zqv2kqqfcgq/hook                                                  |\n+---------------------------+--------------------------------------------------------------------+\n```\n\n#### Bitbucket Server\n\nFrom your project root, execute `platform integration:add` and follow\nthe prompts, as:\n\n```bash\n$ platform integration:add\n* Integration type (--type)\nEnter a number to choose:\n  [0] bitbucket\n  [1] bitbucket_server\n  [2] github\n  [3] gitlab\n  [4] hipchat\n  [5] webhook\n  [6] health.email\n  [7] health.pagerduty\n  [8] health.slack\n> 1\n\n* Username (--username)\nThe Bitbucket Server username\n> {bitbukcet service username}\n\n* Token (--token)\nAn access token for the integration\n> {bitbucket service user password}\n\n* Repository (--repository)\nThe repository (e.g. 'foo/bar')\n> {project/repository, eg: foo/bar}\n\nBuild pull requests (--build-pull-requests)\nBuild every pull request as an environment? [Y|n] N\n\nClone data for pull requests (--pull-requests-clone-parent-data)\nClone the parent environments data for pull requests? [Y|n] Y\n\nFetch branches (--fetch-branches)\nFetch all branches from the remote (as inactive environments)? [Y|n] Y\n\nPrune branches (--prune-branches)\nDelete branches that do not exist on the remote? [Y|n] Y\n\nWarning: adding a 'bitbucket_server' integration will automatically synchronize code from the external Git repository.\nThis means it can overwrite all the code in your project.\n\nAre you sure you want to continue? [y/N] y\n```\n\n##### Verify the integration\n\n##### GitHub\n- Visit the \"webhooks\" section of your bitbucket repository settings, eg\n  ```\n  https://github.com/project/repo/settings/hooks\n  ```\n  and verify that a webhook to platform.sh has been added. Note you will need admin access\n  to the project in order to view the webhooks.\n- Activate a branch in your project (as described below) and validate that an environment\n  is created and deployed to platform.sh. *Note you must first push the branch to bitbucket*.\n- Issue a PR to your repository and verify that the PR branch is deployed.\n\n##### Bitbucket Server\n- Visit the \"webhooks\" section of your bitbucket repository settings, eg\n  ```\n  https://domain/plugins/servlet/webhooks/projects/{project-key}/repos/{repo-name}\n  ```\n  and verify that a webhook to platform.sh has been added. Note you will need admin access\n  to the project in order to view the webhooks.\n- Activate a branch in your project (as described below) and validate that an environment\n  is created and deployed to platform.sh. *Note you must first push the branch to bitbucket*.\n- Issue a PR to your repository and verify that the PR branch is deployed (note that only\n  the static environment will be build for PR's on Bitbucket).\n\n### Customizing Hook Implementations\n\nThis package includes default implementations of platform.sh\n[build and deploy hooks](https://docs.platform.sh/configuration/app/build.html#hooks) which\nshould work for most Bodiless sites.  However, should your site have special needs, you can\ncustomize by creating a `platform.custom.sh` or `static.platform.custom.sh` script and placing\nit alongside the appropriate `.platform.app.yaml` file (at the root of your repository for the\nstatic site, or in the `/edit` directory for the edit app).  In this script, you can define for\neach platform.sh hook one of the following functions:\n\n- `prepare_{hook} ()` - Run before the default implementation of the hook.\n- `hook ()` - Replaces the default implementation of the hook.\n- `finalize_{hook} ()` - Run after the default implementation of the hook.\n\nIf you wish to extend the default implementation, you can do so by calling it from your function.\nTo do this safely (ie to avoid errors if the default implementation doesn't exist) always use the\n`invoke` helper:\n\n```bash\nprepare_deploy () {\n  invoke default_prepare_deploy\n  # Your custom logic here...\n}\n```\n\n## Building and Deploying\n\n### Continuous Integration\n\nIf you configured platform.sh to build pull requests, then every PR to your repository will be\ndeployed to its own environment. Be aware of the following:\n- It is easy to reach your quota of development environments with this enabled, so use cautiously.\n- Edit environments for pull requests are currently only supported on GitHub -- and pushing changes\n  from the edit environment is not supported even there.\n- On Bitbucket Server, pull requests from *forks* will not automatically rebuild when new commits\n  are added.  This limitation does not apply to GitHub.\n- On both GitHub and Bitbucket, changes pushed to code outside the `/edit` directory will\n  not automatically be deployed to the edit environment.  You must manually update the\n  edit environment as described under [Pushing Changes](#pushing-changes) below.\n- Pull request environments will be automatically deleted when the PR is merged or declined.\n- If you manually delete a PR environment, it will not be recreated when the PR is\n  updated.\n- PR environments are named simply `pr-{pr#}` (eg `pr-123`).  You can easily run platform cli\n  commands against them using the `-e pr-xxx` option.\n- A link to the p.sh environment will be posted to the PR:\n  - **GitHub**: Expand the \"Show All Checks\" link next to the section on the \"Conversations\"\n    tab, and click the \"details\" link next to the platform.sh build.\n  - **Bitbucket Server**: Click the build status icon next to the PR title, and then click the\n    \"platform.sh\" link.\n\n### Manual Deployments\n\n#### Pre-requisites\n\n- Access to a [platform.sh](https://platform.sh/) project.\n- The [platform.sh cli](https://docs.platform.sh/gettingstarted/cli.html)\n\n#### Local setup\n\n- Obtain the project key of the project you wish to deploy: see\n  [The platform.sh project key](#the-platform.sh-project-key), above.\n- Connect your local repository to the correct platform.sh remote. From within the repository root:\n  ```\n  platform project:set-remote {project id}\n  ```\n\n#### Initial deployment of a new branch\n\n- Ensure you are on the correct branch locally.\n- Push the branch to bitbucket.\n  ```\n  git push origin <branch>\n  ```\n- Execute\n    ```\n    platform env:activate\n    ```\n  Note - you may have to wait a few moments after pushing the branch to\n  bitbucket before activating the environment, in order to allow the branch to\n  sync to p.sh. If, when you try to activate, you are asked for an \"Environment\n  ID\", wait a bit and try again.\n- The public URL of the new environment will be printed to the console.\n- You can display (and open) the public URLs for your site by checking out the\n  corresponding branch and executing `platform url`.\n\n##### Basic Authentication\n\nNote that basic authentication may be configured for your environment by\ndefault, and this may prevent access via your browser. To verify, use the\nplatform cli:\n```\nplatform env:http-access\n```\n\nYou can also use this command to enable or disable authentication, and to\nadd/remove credentials.\n```\nplatform help env:http-access\n```\nto learn more.\n\n#### Pushing changes\n\nOnce a new branch is created, changes pushed to Bitbucket will be automatically\ndeployed to the static site on platform.sh. You can run `platform activity:log`\nto see the current build status, or visit [console.platform.sh](https://console.platform.sh),\nlocate your build, and click \"View Logs\".\n\nChanges are *not* automatically deployed to an edit environment; you must manually\ntrigger an update of the edit environment by executing:\n  ```\n  platform ssh -e <env-id> 'bash platform.sh deploy'\n  ```\n\n  You may omit the \"-e <env-id>\" if you have the active branch checked out locally.\n\n#### Deleting an environment\n\nThe platform.sh environment will be deleted when you remove the corresponding\nbranch from bitbucket. *Please delete obsolete branches*.\n\nYou can also remove an environment without deleting your branch by checking\nout the branch locally and executing `platform env:delete -y`.\n\n#### Merging to main\n\nWhen you merge a feature branch to main, the updated main branch will be automatically deployed\nto the static environment on platform.sh.  To deploy changes to the edit environment, you must follow the same process as in [Pushing Changes](#pushing-changes) above.\n\n\n## Handling Redirect with Routes\n\n### Overview\nIn HTTP, URL redirecting is a technique to forward one URL to a different URL. It is commonly used for handling cases like URL shortening, preventing broken links when pages removed, pointing multiple domain addresses to a single URL address, etc. It is also critical to preserve page SEO value when there are URL changes.\n\nRedirection can be implemented on a client page with [Refresh Meta Tag](https://en.wikipedia.org/wiki/Meta_refresh) or JavaScript, but the preferred way is to manage redirect rules with server configuration.\n\nYou can configure redirects on Platform.sh with route yaml in project environments. A route describes how an incoming HTTP request is processed by Platform.sh, which includes URL redirect. The routes are defined inside .platform/routes.yaml file.\n\nAn example of redirect using routes.yaml:\n```\n\"https://www.{default}/\":\n  type: redirect\n  to: \"https://my-host.{default}/\"\n```\n\nHere, the URL https://www.example.com/ will be redirected to https://my-host.example.com/\n\n### Whole-route vs Partial redirects\nPlatform.sh offers two different ways to implement redirect rules, **Whole-route redirects** and **Partial redirects**\n\n* Whole-route redirects on host level. A typical use case for this kind of route is adding or removing a www. prefix to domain,\n\n  .platform/routes.yaml\n  ```\n  https://{default}/:\n    type: redirect\n    to: https://www.{default}/\n  ```\n\n  Here, https://example.com/ will be redirected to https://www.example.com/. This approach can be used to redirect vanity domains to their destination URLs.\n\n* Partial redirects allows redirect rules to be added to existing routes,\n\n  .platform/routes.yaml\n  ```\n      https://{default}/:\n        # [...]\n        redirects:\n          expires: 1d\n          paths:\n            '/from':\n              to: 'https://example.com/'\n              code: 301\n  ```\n\n  Here, \"https://[domain name]/from\" will be redirected to https://www.example.com/.\n\n  Note:\n  * the default response code is 302, in order to use a different response code, mostly commonly 301, add \"code: 301\" as configurable option.\n  * \"expires\" param is optional, it specifies duration the redirect will be cached. Examples of valid values include 3600s, 1d, 2w, 3m.\n\n\n  **Examples**\n\n  file .platform/routes.yaml\n\n  1. Redirect path \"/foo/bar\" to a different site \"https://example.com/\".\n\n      ```\n      https://{default}/:\n        type: upstream\n        redirects:\n          paths:\n            '/foo/bar':\n              to: 'https://example.com/'\n      ```\n\n  1.  Using Regular Expression to redirect path that matches \"/foo/(.*)/bar\" pattern.\n\n      ```\n      https://{default}/:\n        type: upstream\n        redirects:\n          paths:\n            '/foo/(.*)/bar':\n              to: '/$1'\n              regexp: true\n      ```\n\n      In this case, path \"/foo/cards/bar\" will be redirected to \"/cards\".\n\n  1. Redirect with prefix.\n\n      ```\n      https://{default}/:\n        type: upstream\n        redirects:\n          paths:\n            '/foo/bar':\n              to: '/new'\n              prefix: true\n\n      ```\n\n      Path \"/foo/bar\" will be redirected to \"/new\". And path \"/foo/bar/to/my/path\" will be redirected to \"/new/to/my/path\" where both the path and all its children included. If \"prefix\" set to false, only \"/foo/bar\" will be redirected to \"/new\".\n\n\n  1. Carry over suffix path with append_suffix option.\n\n      ```\n        https://{default}/:\n          type: upstream\n          redirects:\n            paths:\n              '/foo/bar':\n                to: 'https://{default}/new'\n                append_suffix: false\n\n      ```\n\n      If append_suffix is set to false, \"/foo/bar/to/my/path\" will be redirected to \"/new\". Otherwise, \"/foo/bar/to/my/path\" will be redirects to \"/new/to/my/path\". append_suffix is ignored if 'prefix' is false or 'regexp' is true.\n\n\n### HTTP vs HTTPS\n\nPlatform.sh recommends using HTTPS requests for all sites exclusively. Specifying HTTPS in route.yaml will automatically redirect any requests for an HTTP URL to HTTPS. While specifying only HTTP routes will result in duplicate HTTPS routes being created automatically, allowing the site to be served from both HTTP and HTTPS without redirects.\n\nAlthough it is not recommended, HTTPS requests can be redirected to HTTP explicitly to serve the site over HTTP only using route.yaml:\n\n```\n\"https://{default}/\":\n  type: redirect\n  to: \"http://{default}/\"\n```\n\n### Avoid redirect chains\n\nA redirect chain is a series of redirects between the initial URL and the destination URL. The redirect chain could be built over time of development or due to a combination of redirect between different protocol, host name or trailing slash processing etc. Redirect chain causes page loss authority value in search result. It also increases page load time and decreases the overall quality of site.\n\nIn order to avoid redirect chains, pay attention on destination path protocol and host name. For example, if the site is running under https and host www, specify destination \"to\" in route.yaml as:\n```\n  to: \"https://www.{default}/path/to/destination/\"\n```\n\nThe trailing slash should be appended to the configure item if platform environment adds trailing slash to url by default.\nsee [Platform.sh Documentation Redirects](https://docs.platform.sh/configuration/routes/redirects.html)\n\n### Generate redirect rules for migration sites\n\nBodilessJS [Site Migration Tool](https://github.com/johnsonandjohnson/Bodiless-JS/tree/main/packages/bodiless-migration-tool) package comes with a feature that allows user to export site redirection into file. See [Tools/Migration](/#/Tools/Migration?id=configuration) for configuration.\n\nUser can apply these exported redirect rules to routers.yaml before deploying to platform.sh.\n\n```yaml\n\"https://{default}/\":\n    type: upstream\n    upstream: \"static:http\"\n    redirects:\n      paths:\n        /image/redirect.png:\n          to: /image/placeholder.png\n          code: 301\n        /page2:\n          to: /page3\n          code: 301\n```\n\n## Using Fastly CDN\n\nPlatform.sh integrates with Fastly via EZ platform for Fastly.  \n\n1. Obtain your Fastly Service ID & Key from Fastly.   \n1. Once Fastly Service ID & Key is obtained, these variables can be set at Main environment.\n    ```\n    platform variable:create -e main --level environment env:HTTPCACHE_PURGE_TYPE --value 'fastly'\n    platform variable:create -e main --level environment env:FASTLY_SERVICE_ID --value 'YOUR_ID_HERE'\n    platform variable:create -e main --level environment env:FASTLY_KEY --value 'YOUR_ID_HERE'\n    ```\n1. Verify or Update your `routes.yaml` to enable caching for your site by setting `enabled: true`\n    ```\n        cache:\n            enabled: true\n            cookies: []\n    ```\n1. Verify or Update your `.platform.app.yaml` expiration time for your files.\n    ```\n    web:\n        locations:\n            '/':\n                expires: 6h  \n    ```\n\nOnce completed, the main env deployed on Platform.sh should be on Fastly CDN.  You may have to fine tune the expires setting for your static resources and set certain ones (ones identify not to change often such as font files) to longer to leverage browser caching.\n\nPlatform.sh References:\n* [Set Fastly Credentials on Platform.sh](https://docs.platform.sh/frameworks/ibexa/fastly.html#set-credentials-on-platformsh)\n* [HTTP Cache](https://docs.platform.sh/configuration/routes/cache.html)\n* [Router Cache](https://docs.platform.sh/languages/php/tuning.html#ensure-that-the-router-cache-is-properly-configured)\n* [Expires](https://docs.platform.sh/configuration/app/web.html#locations)\n* [How to Guide: How to configure caching for static assets](https://community.platform.sh/t/how-to-configure-caching-for-static-assets/187)\n\n\nIf there are issues or you need to troubleshoot, here are some good resources:\n* [Checking Fastly Cache](https://docs.fastly.com/en/guides/checking-cache)\n\n    ``` curl -svo /dev/null -H \"Fastly-Debug:1\" www.example.com/index.html ```\n* [Purging Fastly Cache](https://docs.fastly.com/api/purge)\n\n    ``` curl -X PURGE www.example.com/index.html ```\n\n## How to load environment specific html snippets\n\nWhen you want to inject different html snippets depending on your environment type, you can use Server Side Includes (SSI) mechanism.\n### Activate SSI\n\n* Activate SSI for your route(s) in your routes.yaml file. See: https://docs.platform.sh/configuration/routes/ssi.html\n* Use SSI_ENV enviroment variable to specify type of your environment. Default value is 'dev'.\n* Ensure ssi configs are loaded to psh container and set SSI_CONF_PATH environment variable to path to json file containing SSI configs.\n* Ensure your .platform.app.yaml contains invocation of generate-ssi-files.js node scripts. The script should be invoked during build and deploy phases. PSH phase (build or deploy) should be passed as an argument to the script.\n* Ensure the files of you app, that will be served by psh, contain SSI directives.\n* Ensure a writable volume is mounted to your app.\n\n### SSI config format\n\nSSI configuration file should be in json format.\n\n```\n{\n  key1: {\n    pragma: \"<!--# ssi data should go here -->\",\n    env1: {\n      file: \"key1.env1.html\"\n    }\n    ...\n    envN: {\n      file: \"key1.envN.html\"\n    }\n  }\n  ...\n  keyN: {\n    pragma: \"<!--# ssi data should go here -->\",\n    ...\n    env1: {\n      file: \"keyN.envN.html\"\n    }\n    ...\n    envN: {\n      file: \"keyN.envN.html\"\n    }\n  }\n}\n```\n### How it works\n\n* during build phase, generate-ssi-files reads SSI configs and for each key it creates symlink from PLATFORM_DOCUMENT_ROOT/filename.html into APP_VOLUME/filename.html. Filename is generated based on key. There is an opportunity to improve this logic. We can read and parse pragma field, exract filename from it. But it makes the things more complicated and in addition, pragma may not have files at all.\n* during deploy phase, generate-ssi-files reads SSI configs and SSI_ENV and for each key it copies the file defined in conf.{key}.{env}.{file} to APP_VOLUME/filename.html that was created during build phase.\n\n## How to replace your site prod url with psh environment url in a public file\n\nIf you want to make urls in a particular public file match psh environment url, you can leverage psh-url-replacer node script. For instance, your site sitemap.xml, which is generated during build time, contains production urls and you want to replace the production url with psh environment url, to which your website is deployed to.\n\n### Why\n\nPlatform.sh does not allow to expose environment level environment variables to the application build stage.\n\n### How it works\n\non psh build stage:\n\n- it moves your source file from public dir to a tmp directory\n- then it creates a symlink from a writable volume file to the source public file\n\non psh deploy stage:\n\n- it copies the file from the tmp directory to the writable volume file\n- then it replaces production url with psh environment url in the file\n\n### How to activate this feature\n\nBy default, the feature is activated for sitemap.xml and robots.txt. If you want to activate the feature for some other files or if you have custom installation of sitemap.xml or robots.txt, please follow the following steps:\n\n1. ensure writable volume mounting is configured for your app\n\n1. export environment variables and invoke psh-url-replacer in build section of your psh app .platform.app.yaml\n\n```bash\n\nhooks:\n    build: |\n        export PSH_URL_REPLACER_SRC_FILE=/path/to/your/src/public/file\n        export PSH_URL_REPLACER_TMP_FILE=/path/to/a/tmp/file\n        export PSH_URL_REPLACER_TARGET_FILE=/path/to/writable/volume/file\n        node /path/to/psh-url-replacer.js build\n\n```\n\n1. export environment variables and invoke psh-url-replacer in deploy section of your psh app .platform.app.yaml\n\n```bash\n\nhooks:\n    deploy: |\n        export PSH_URL_REPLACER_TMP_FILE=/path/to/the/tmp/file/you/saved/during/build/phase\n        export PSH_URL_REPLACER_TARGET_FILE=/path/to/writable/volume/file\n        export PSH_URL_REPLACER_SRC_URL=https://your-site-production-url.com\n        export PSH_URL_REPLACER_TARGET_URL=https://your-psh-env.url.site\n        export PSH_URL_REPLACER_PROD_ENV='0' # set to '1' if you want to disable the replacement\n        node /path/to/psh-url-replacer.js deploy\n```\n\n## Known limitations\n\n### General\n- PR Branches and Feature branches created in bitbucket will always inherit from\n  main. This means that you must manually configure basic authentication for\n  these branches if you want them protected from the public internet.\n- There is a 64-character limit on hostnames for TLS, and platform.sh uses 43 of\n  them. Since hostnames are created based on branch names, and since the edit\n  environment uses an additional 5 (\"edit.\"), your branch names should be\n  limited to a maximum of 16 characters to avoid certificate warnings.\n- When you create a bitbucket integration, a webhook is added to your bitbucket\n  repository. However, deleting the integration does not remove the webhook, you\n  must do this manually.\n### Environment memory\nOn development environments, the `edit` site environment can use a large amount\nof memory when running, which might cause out-of-memory issues when building \npages. This is caused by webpack's caching system, and there are two ways\nto circumvent the issue:\n\n#### Increasing container memory\nUse [Large development containers](https://docs.platform.sh/overview/pricing.html#development)\nto increase the total memory available to containers. This is the preferred way \nto solve this problem, as it's easier and faster. Note that this will increase costs.\n\n#### Disable build cache\nDisabling webpack's cache will drastically reduce memory consumption, but\nwill also increase build times. This might be specially noticeable when doing\nsimple operations like creating, cloning or moving pages.\n\nTo disable a site's cache, add `cache: false` to its webpack configuration. This\nis done in the `gatsby-node.js` file on the site root. Read [Gatsby's documentation](https://www.gatsbyjs.com/docs/how-to/custom-configuration/add-custom-webpack-config/#examples)\nfor an example, and refer to [Webpacks's documentation](https://webpack.js.org/configuration/cache/)\nif you want to understand how its caching system works.\n## Troubleshooting\n\n### Viewing Logs\n\nBuild, deploy and application logs for an environment are available using the\nplatform cli. If you want logs for an environment other than the currently\nchecked-out branch (e.g. for a pull request), you must use the `-e` flag. You\ncan first get a list of all available environments by running\n```\nplatform env:list\n```\nYou can then use the identifier from the first column in the commands below.\nIf you want logs from the environment associated with your current local\nbranch, you can omit the `-e` flag.\n\n- Tail/print most recent build log (this now includes deploy log):\n  ```\n  platform activity:log -e <env-id>\n  ```\n  Note that you may have to wait a few moments after performing\n  a git push in order for the new p.sh deployment to begin.\n- Print deploy logs for all builds to the edit environment:\n  ```\n  platform log -e <env-id> -A edit deploy <--lines n>\n  ```\n  (where n is the number of lines.)\n- View or tail application logs for the edit environment\n  ```\n  platform log -e <env-id> -A edit app <--lines n> <--tail>\n  ```\n\nAlternatively, you can visit [the platform.sh console](https://console.platform.sh/webalerts/abcdefghi) and locate\nyour build to view the build log (deployment and application logs\nare only available from the command line).\n\n### Hints\n\n- If the `platform` command is not found, you probably have to run\n  `source .bashrc` to ensure it is in your path.\n- For all deployments in which the app is restarted, the environment may not be\n  fully available for up to a minute after the deployment is complete.\n- You may see errors in the application log relating to insufficient file\n  watchers. This is a known issue. Currently the only workaround is to reduce\n  the number of active environments.\n- Public URLs for an environment are available by running\n  ```\n  platform url -e <env-id>\n  ```\n- There are many other useful platform cli subcommands.  Run `platform list`\n  to see them all.\n\n## Deploying bodiless packages from a private registry\n\nBy default the public regisry will be used to download bodiless packages: //registry.npmjs.org/\n\nIn order to switch to a private registry follow Step 3 (Create platform.sh environment variables.) of this doc.\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/johnsonandjohnson/bodiless-js/issues"},"_id":"@asemirsk/psh@1.0.0-beta.5","_nodeVersion":"16.13.2","_npmVersion":"lerna/4.0.0/node@v16.13.2+x64 (linux)","dist":{"integrity":"sha512-A53FRGSeF75at8kKwedNIiGP2iZPBtHBwZg0vqux82O+Qh4g+HkX+F2MgvsWWONNNqImPapoYZsdXnKJj8MBkA==","shasum":"7c44fd44697101a44060ddbcd6144af9687e2629","tarball":"https://registry.npmjs.org/@asemirsk/psh/-/psh-1.0.0-beta.5.tgz","fileCount":14,"unpackedSize":65356,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCXgQyySpA0o6r/hKeJE0/GZ5Lcp3vVehOZp3bKpYulygIgXihBgrtbIdtN0+Xbaj8YXzhZ9YP+XIaTh4MJN3k5dc0="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiSvlPACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmq60g/+LMuMwhgKkfOXrByPzE1S3WfWqIihJXOwQaCfb8/Zl4sBCvLD\r\n9Yw9jGdsha2iniw1fd0+e1RNx/Iz9E8ruKGFax1frxkelSp6GonStfC6qceG\r\nhfEf/XHTDSxkgc3hYmPekiSU3pVoip99RxtoRGcYY9ZVDtDePGQammwgj3AR\r\n4ROBWOFtSQ1aEG21YG+6HthRTAqmCjcb7CL4ksIReuUjELEi41eFnoutAkI8\r\nZCIYDbr0Z824fiSIXK7CSbMj0uZXgohH0IjoVoqUZbYetTAZBvslfWrXm1Sa\r\nnTQLOphDJGBIMorF2ChSNWrJvq7EtIB3gK7G5Y8F+fojlhcvYVUHnPf0IlA7\r\nh5U1r1gbUCqo2yYBRARQ0BEYkWubvfHAkRJa9sj/0uzn3z774x25okRb1EhO\r\n8jYNlAfNQ0gu25B9riXniwenheOhM5TvWGnt6XOxTtts72vVzs9yoXRIJsEp\r\nl4ElVoTbLgCUFr1RXo5sEgjca3rLDywqwRzLNFFg/5Ur12MdGret+7OFaxvP\r\nHLHWtK9ellGvwarX6+FGEptpUu9xccjEX+xsVdOa3JGFW9dVe7JyvXFReh2+\r\nCMtiC6D6+0NdJtovz3LQ4zFaxbwUhrc3z5MoDVgG0v/V9RJHm4kG7PvcYR+4\r\nTIh6Kz7q3rx0r+PG3U2Mhll8lzqBKX6ecUE=\r\n=gbeC\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"asemirsk","email":"al.semirski@gmail.com"},"maintainers":[{"name":"asemirsk","email":"al.semirski@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/psh_1.0.0-beta.5_1649080655649_0.08559246506812412"},"_hasShrinkwrap":false},"1.0.0-beta.6":{"name":"@asemirsk/psh","version":"1.0.0-beta.6","description":"Provides cli tool for initializing a bodiless project on platform.sh","author":{"name":"Chris Oden","email":"coden@its.jnj.com"},"homepage":"https://github.com/johnsonandjohnson/bodiless-js#readme","license":"Apache-2.0","bin":{"bodiless-psh-init":"lib/bodiless-psh-init.js"},"scripts":{"build":"tsc --version && tsc -p ./tsconfig.json ","build:watch":"npm run build -- --watch","clean":"rimraf \"lib/*\" && rimraf tsconfig.tsbuildinfo"},"directories":{"lib":"lib"},"repository":{"type":"git","url":"git+https://github.com/johnsonandjohnson/bodiless-js.git"},"publishConfig":{"access":"public"},"dependencies":{"@asemirsk/cli":"^1.0.0-beta.6","copyfiles":"^2.1.1","js-yaml":"^3.13.1","lodash":"^4.17.19","rimraf":"^2.6.3"},"devDependencies":{"@types/copyfiles":"^2.1.1"},"gitHead":"cbd97725152f2362bb86e6d4bba02043e3c4570e","readme":"# Bodiless integration with platform.sh\n\nThis package provides standard configuration files and helper scripts which\nmake it easy for a bodiless site to be deployed to platform.sh.\n\n## Setting up your project\n\n### Pre-requisites\n\n- Admin access to a [platform.sh](https://platform.sh/) project.\n- A service user with *admin access* to a repository in a Bitbucket Server instance.\n- The [platform.sh cli](https://docs.platform.sh/gettingstarted/cli.html)\n\n### Step 1. Gather required information\n\nTo continue, you will need the following:\n\n#### The platform.sh project key\n- Log in via the platform.sh cli.  From your local machine execute:\n  ```\n  platform login\n  ```\n  You will be directed to log in via a web browser\n- Execute\n  ```\n  platform project:list\n  ```\n  You should see a list of all projects you have access to, something like:\n  ```\n    Your projects are:\n  +---------------+-------------------------+-----------------------------------------------------+\n  | ID            | Title                   | URL                                                 |\n  +---------------+-------------------------+-----------------------------------------------------+\n  | abcdefghijklm | project_a               | https://console.platform.sh/webalerts/abcdefghijklm |\n  | lmnopqrstuvwx | project_b               | https://console.platform.sh/webalerts/lmnopqrstuvwx |\n  +---------------+-------------------------+-----------------------------------------------------+`\n  ```\n- Take note of the project ID for your project. This is the value you will use below.\n\n### Step 2. Initialize your project configuration files\n\nPlatform.sh requires several configuration files to be in place\nin your repository. This package contains default versions of these\nfiles for a BodilessJS.  To install or update them:\n\n1. Add this package as a dependency of your project:\n  ```\n  npm i --save-dev @bodiless/psh\n  ```\n2. Add the following to your `package.json` scripts:\n  ```\n  \"init-psh\": \"bodiless-psh-init\"\n  ```\n3. Install or update the configuration files:\n  ```\n  npm run init-psh\n  ```\n> When `@bodiless/psh` is installing its' files it will try to merge `static` and `edit` `*.platform.app.yaml` files based on the whitelisted keys from `packages/bodiless-psh/resources/.platform/platform.whitelist.yaml`. Only the keys that are specified in `platform.whitelist.yaml` will be merged. Merging will be performed by using the recursive algorithm to preserve any keys that are not in default `.platform.app.yaml`. Non-whitelisted keys will be ignored, and a warning message will be printed to the console.\n\n4. Commit the added configuration files to your repository.  These include\n   ```\n   static.platform.sh\n   .platform.app.yaml\n   .platform/*\n   edit/*\n   ```\n\n### Step 3. Create platform.sh environment variables.\n\nFirst, configure your local install to connect to your platform.sh project. From\nwithin your project root, execute\n```\nplatform project:set-remote {project id}\n```\nwhere {project id} is the platform.sh project id you acquired above.\n\nAll variables below should be set at the project level using the platform.sh command\nline, as described in [the platform.sh documentation](https://docs.platform.sh/development/variables.html#project-variables), and all should be visible at both build time and run time.\n\nAdd the following variables:\n\n- env:APP_GIT_REMOTE_URL -- The URL of your upstream Git repository\n- env:APP_GIT_USER -- The user to access your upstream Git repository.\n- env:APP_GIT_USER_EMAIL -- THe user email for your upstream Git repository.\n- env:APP_GIT_PW -- The user password for your upstream Git repository.\n\n\n> Be sure to specify `--sensitive true` for all credentials.\n\nExample:\n```\n$ platform variable:create\n* Level (--level)\nThe level at which to set the variable\n  [project    ] Project-wide\n  [environment] Environment-specific\n> project\n\n* Name (--name)\nThe variable name\n> APP_GIT_USER_EMAIL\n\n* Value (--value)\nThe variable's value\n> email@your.service.account\n\nJSON (--json)\nIs the value JSON-formatted? [y|N] N\n\nSensitive (--sensitive)\nIs the value sensitive? [y|N] N\n\nPrefix (--prefix)\nThe variable name's prefix\nDefault: none\n  [none] No prefix: The variable will be part of $PLATFORM_VARIABLES.\n  [env:] env: The variable will be exposed directly, e.g. as $APP_GIT_USER_EMAIL.\n> env:\n\nVisible at build time (--visible-build)\nShould the variable be available at build time? [Y|n] Y\n\nVisible at runtime (--visible-runtime)\nShould the variable be available at runtime? [Y|n] Y\n\nCreating variable env:APP_GIT_USER_EMAIL on the project...\n```\n\nYou can verify that the variable was created properly by executing, eg:\n  ```\n  platform variable:get env:APP_GIT_USER_EMAIL\n  ```\n  You should see something like:\n  ```\n  $ platform variable:get env:APP_NPM_AUTH\n  +-----------------+---------------------------+\n  | Property        | Value                     |\n  +-----------------+---------------------------+\n  | id              | env:APP_GIT_USER_EMAL     |\n  | created_at      | 2019-08-09T06:48:52-04:00 |\n  | updated_at      | 2019-08-09T06:48:52-04:00 |\n  | name            | env:APP_GIT_USER_EMAIL    |\n  | attributes      | {  }                      |\n  | is_json         | false                     |\n  | is_sensitive    | false                     |\n  | visible_build   | true                      |\n  | visible_runtime | true                      |\n  | level           | project                   |\n  +-----------------+---------------------------+\n  ```\n\n#### Optional: Configure an NPM Private Registry\n\nIf you wish to install packages from a private registry, you may do so. The\npackages to be installed must be namespaced. Set the following 3 environment\nvariables on p.sh. All variables should be visible at both build and run time:\n- `env:APP_NPM_REGISTRY`: the full path to your registry, eg\n  `//my-artifactory.com/api/npm/my-registry/`.\n- `env:APP_NPM_AUTH`: Ypur NPM authentication token. This should be marked as sensitive.\n  To obtain your token:\n  1. Login to your registry:\n     ```\n     npm login --registry=https://url/of/your/private/registry\n     ```\n     Follow the prompts with the username/password/email of the account you wish\n     to use for p.sh automation.\n  2. Examine your `.npmrc` file (usually located in your home directory). You\n     should see something like\n     ```\n     //url/of/your/privateregistry/:_authToken={token}\n     ```\n  3. Copy the token value to the `env:APP_NPM_AUTH` variable in your p.sh project.\n\n- `env:APP_NPM_NAMESPACE`: The namespace of the packages in your private\n  regsitry, eg `@mynamespace`.\n\n### Step 4. Configure the platform.sh Git Service integration.\n\nPlatform.sh provides out-of-the-box integrations with many popular Git service providers.\nWe have tested with Bitbucket Server and GitHub.\n\nNote that you must have admin access to the repository in order to configure the integration.\n\n#### GitHub\n\nFrom your project root, execute `platform integration:add` and follow\nthe prompts, as:\n\n```\n$ platform integration:add\n* Integration type (--type)\nEnter a number to choose:\n  [0] bitbucket\n  [1] bitbucket_server\n  [2] github\n  [3] gitlab\n  [4] hipchat\n  [5] webhook\n  [6] health.email\n  [7] health.pagerduty\n  [8] health.slack\n  [9] health.webhook\n> 2\n\n* Token (--token)\nAn access token for the integration\n> {your GitHub personal access token}\n\n* Repository (--repository)\nThe repository (e.g. 'foo/bar')\n> johnsonandjohnson/Bodiless-JS\n\nBuild pull requests (--build-pull-requests)\nBuild every pull request as an environment? [Y|n] Y\n\nBuild pull requests post-merge (--build-pull-requests-post-merge)\nBuild pull requests based on their post-merge state? [y|N] y\n\nClone data for pull requests (--pull-requests-clone-parent-data)\nClone the parent environment's data for pull requests? [Y|n] n\n\nFetch branches (--fetch-branches)\nFetch all branches from the remote (as inactive environments)? [Y|n] y\n\nPrune branches (--prune-branches)\nDelete branches that do not exist on the remote? [Y|n] y\n\nWarning: adding a 'github' integration will automatically synchronize code from the external Git repository.\nThis means it can overwrite all the code in your project.\n\nAre you sure you want to continue? [y/N] y\nChecking webhook configuration on the repository: johnsonandjohnson/Bodiless-JS\n  Creating new webhook\n  Webhook created successfully\nCreated integration xxxxxxxx (type: github)\n+---------------------------+--------------------------------------------------------------------+\n| Property                  | Value                                                              |\n+---------------------------+--------------------------------------------------------------------+\n| id                        | xxxxxxx                                                            |\n| type                      | github                                                             |\n| token                     | ******                                                             |\n| base_url                  |                                                                    |\n| repository                | foo/bar                                                            |\n| fetch_branches            | true                                                               |\n| prune_branches            | true                                                               |\n| build_pull_requests       | true                                                               |\n| build_pull_requests_post_ | true                                                               |\n| merge                     |                                                                    |\n| pull_requests_clone_paren | false                                                              |\n| t_data                    |                                                                    |\n| hook_url                  | https://us-2.platform.sh/api/projects/jvaff4bu65vgm/integrations/4 |\n|                           | 4zqv2kqqfcgq/hook                                                  |\n+---------------------------+--------------------------------------------------------------------+\n```\n\n#### Bitbucket Server\n\nFrom your project root, execute `platform integration:add` and follow\nthe prompts, as:\n\n```bash\n$ platform integration:add\n* Integration type (--type)\nEnter a number to choose:\n  [0] bitbucket\n  [1] bitbucket_server\n  [2] github\n  [3] gitlab\n  [4] hipchat\n  [5] webhook\n  [6] health.email\n  [7] health.pagerduty\n  [8] health.slack\n> 1\n\n* Username (--username)\nThe Bitbucket Server username\n> {bitbukcet service username}\n\n* Token (--token)\nAn access token for the integration\n> {bitbucket service user password}\n\n* Repository (--repository)\nThe repository (e.g. 'foo/bar')\n> {project/repository, eg: foo/bar}\n\nBuild pull requests (--build-pull-requests)\nBuild every pull request as an environment? [Y|n] N\n\nClone data for pull requests (--pull-requests-clone-parent-data)\nClone the parent environments data for pull requests? [Y|n] Y\n\nFetch branches (--fetch-branches)\nFetch all branches from the remote (as inactive environments)? [Y|n] Y\n\nPrune branches (--prune-branches)\nDelete branches that do not exist on the remote? [Y|n] Y\n\nWarning: adding a 'bitbucket_server' integration will automatically synchronize code from the external Git repository.\nThis means it can overwrite all the code in your project.\n\nAre you sure you want to continue? [y/N] y\n```\n\n##### Verify the integration\n\n##### GitHub\n- Visit the \"webhooks\" section of your bitbucket repository settings, eg\n  ```\n  https://github.com/project/repo/settings/hooks\n  ```\n  and verify that a webhook to platform.sh has been added. Note you will need admin access\n  to the project in order to view the webhooks.\n- Activate a branch in your project (as described below) and validate that an environment\n  is created and deployed to platform.sh. *Note you must first push the branch to bitbucket*.\n- Issue a PR to your repository and verify that the PR branch is deployed.\n\n##### Bitbucket Server\n- Visit the \"webhooks\" section of your bitbucket repository settings, eg\n  ```\n  https://domain/plugins/servlet/webhooks/projects/{project-key}/repos/{repo-name}\n  ```\n  and verify that a webhook to platform.sh has been added. Note you will need admin access\n  to the project in order to view the webhooks.\n- Activate a branch in your project (as described below) and validate that an environment\n  is created and deployed to platform.sh. *Note you must first push the branch to bitbucket*.\n- Issue a PR to your repository and verify that the PR branch is deployed (note that only\n  the static environment will be build for PR's on Bitbucket).\n\n### Customizing Hook Implementations\n\nThis package includes default implementations of platform.sh\n[build and deploy hooks](https://docs.platform.sh/configuration/app/build.html#hooks) which\nshould work for most Bodiless sites.  However, should your site have special needs, you can\ncustomize by creating a `platform.custom.sh` or `static.platform.custom.sh` script and placing\nit alongside the appropriate `.platform.app.yaml` file (at the root of your repository for the\nstatic site, or in the `/edit` directory for the edit app).  In this script, you can define for\neach platform.sh hook one of the following functions:\n\n- `prepare_{hook} ()` - Run before the default implementation of the hook.\n- `hook ()` - Replaces the default implementation of the hook.\n- `finalize_{hook} ()` - Run after the default implementation of the hook.\n\nIf you wish to extend the default implementation, you can do so by calling it from your function.\nTo do this safely (ie to avoid errors if the default implementation doesn't exist) always use the\n`invoke` helper:\n\n```bash\nprepare_deploy () {\n  invoke default_prepare_deploy\n  # Your custom logic here...\n}\n```\n\n## Building and Deploying\n\n### Continuous Integration\n\nIf you configured platform.sh to build pull requests, then every PR to your repository will be\ndeployed to its own environment. Be aware of the following:\n- It is easy to reach your quota of development environments with this enabled, so use cautiously.\n- Edit environments for pull requests are currently only supported on GitHub -- and pushing changes\n  from the edit environment is not supported even there.\n- On Bitbucket Server, pull requests from *forks* will not automatically rebuild when new commits\n  are added.  This limitation does not apply to GitHub.\n- On both GitHub and Bitbucket, changes pushed to code outside the `/edit` directory will\n  not automatically be deployed to the edit environment.  You must manually update the\n  edit environment as described under [Pushing Changes](#pushing-changes) below.\n- Pull request environments will be automatically deleted when the PR is merged or declined.\n- If you manually delete a PR environment, it will not be recreated when the PR is\n  updated.\n- PR environments are named simply `pr-{pr#}` (eg `pr-123`).  You can easily run platform cli\n  commands against them using the `-e pr-xxx` option.\n- A link to the p.sh environment will be posted to the PR:\n  - **GitHub**: Expand the \"Show All Checks\" link next to the section on the \"Conversations\"\n    tab, and click the \"details\" link next to the platform.sh build.\n  - **Bitbucket Server**: Click the build status icon next to the PR title, and then click the\n    \"platform.sh\" link.\n\n### Manual Deployments\n\n#### Pre-requisites\n\n- Access to a [platform.sh](https://platform.sh/) project.\n- The [platform.sh cli](https://docs.platform.sh/gettingstarted/cli.html)\n\n#### Local setup\n\n- Obtain the project key of the project you wish to deploy: see\n  [The platform.sh project key](#the-platform.sh-project-key), above.\n- Connect your local repository to the correct platform.sh remote. From within the repository root:\n  ```\n  platform project:set-remote {project id}\n  ```\n\n#### Initial deployment of a new branch\n\n- Ensure you are on the correct branch locally.\n- Push the branch to bitbucket.\n  ```\n  git push origin <branch>\n  ```\n- Execute\n    ```\n    platform env:activate\n    ```\n  Note - you may have to wait a few moments after pushing the branch to\n  bitbucket before activating the environment, in order to allow the branch to\n  sync to p.sh. If, when you try to activate, you are asked for an \"Environment\n  ID\", wait a bit and try again.\n- The public URL of the new environment will be printed to the console.\n- You can display (and open) the public URLs for your site by checking out the\n  corresponding branch and executing `platform url`.\n\n##### Basic Authentication\n\nNote that basic authentication may be configured for your environment by\ndefault, and this may prevent access via your browser. To verify, use the\nplatform cli:\n```\nplatform env:http-access\n```\n\nYou can also use this command to enable or disable authentication, and to\nadd/remove credentials.\n```\nplatform help env:http-access\n```\nto learn more.\n\n#### Pushing changes\n\nOnce a new branch is created, changes pushed to Bitbucket will be automatically\ndeployed to the static site on platform.sh. You can run `platform activity:log`\nto see the current build status, or visit [console.platform.sh](https://console.platform.sh),\nlocate your build, and click \"View Logs\".\n\nChanges are *not* automatically deployed to an edit environment; you must manually\ntrigger an update of the edit environment by executing:\n  ```\n  platform ssh -e <env-id> 'bash platform.sh deploy'\n  ```\n\n  You may omit the \"-e <env-id>\" if you have the active branch checked out locally.\n\n#### Deleting an environment\n\nThe platform.sh environment will be deleted when you remove the corresponding\nbranch from bitbucket. *Please delete obsolete branches*.\n\nYou can also remove an environment without deleting your branch by checking\nout the branch locally and executing `platform env:delete -y`.\n\n#### Merging to main\n\nWhen you merge a feature branch to main, the updated main branch will be automatically deployed\nto the static environment on platform.sh.  To deploy changes to the edit environment, you must follow the same process as in [Pushing Changes](#pushing-changes) above.\n\n\n## Handling Redirect with Routes\n\n### Overview\nIn HTTP, URL redirecting is a technique to forward one URL to a different URL. It is commonly used for handling cases like URL shortening, preventing broken links when pages removed, pointing multiple domain addresses to a single URL address, etc. It is also critical to preserve page SEO value when there are URL changes.\n\nRedirection can be implemented on a client page with [Refresh Meta Tag](https://en.wikipedia.org/wiki/Meta_refresh) or JavaScript, but the preferred way is to manage redirect rules with server configuration.\n\nYou can configure redirects on Platform.sh with route yaml in project environments. A route describes how an incoming HTTP request is processed by Platform.sh, which includes URL redirect. The routes are defined inside .platform/routes.yaml file.\n\nAn example of redirect using routes.yaml:\n```\n\"https://www.{default}/\":\n  type: redirect\n  to: \"https://my-host.{default}/\"\n```\n\nHere, the URL https://www.example.com/ will be redirected to https://my-host.example.com/\n\n### Whole-route vs Partial redirects\nPlatform.sh offers two different ways to implement redirect rules, **Whole-route redirects** and **Partial redirects**\n\n* Whole-route redirects on host level. A typical use case for this kind of route is adding or removing a www. prefix to domain,\n\n  .platform/routes.yaml\n  ```\n  https://{default}/:\n    type: redirect\n    to: https://www.{default}/\n  ```\n\n  Here, https://example.com/ will be redirected to https://www.example.com/. This approach can be used to redirect vanity domains to their destination URLs.\n\n* Partial redirects allows redirect rules to be added to existing routes,\n\n  .platform/routes.yaml\n  ```\n      https://{default}/:\n        # [...]\n        redirects:\n          expires: 1d\n          paths:\n            '/from':\n              to: 'https://example.com/'\n              code: 301\n  ```\n\n  Here, \"https://[domain name]/from\" will be redirected to https://www.example.com/.\n\n  Note:\n  * the default response code is 302, in order to use a different response code, mostly commonly 301, add \"code: 301\" as configurable option.\n  * \"expires\" param is optional, it specifies duration the redirect will be cached. Examples of valid values include 3600s, 1d, 2w, 3m.\n\n\n  **Examples**\n\n  file .platform/routes.yaml\n\n  1. Redirect path \"/foo/bar\" to a different site \"https://example.com/\".\n\n      ```\n      https://{default}/:\n        type: upstream\n        redirects:\n          paths:\n            '/foo/bar':\n              to: 'https://example.com/'\n      ```\n\n  1.  Using Regular Expression to redirect path that matches \"/foo/(.*)/bar\" pattern.\n\n      ```\n      https://{default}/:\n        type: upstream\n        redirects:\n          paths:\n            '/foo/(.*)/bar':\n              to: '/$1'\n              regexp: true\n      ```\n\n      In this case, path \"/foo/cards/bar\" will be redirected to \"/cards\".\n\n  1. Redirect with prefix.\n\n      ```\n      https://{default}/:\n        type: upstream\n        redirects:\n          paths:\n            '/foo/bar':\n              to: '/new'\n              prefix: true\n\n      ```\n\n      Path \"/foo/bar\" will be redirected to \"/new\". And path \"/foo/bar/to/my/path\" will be redirected to \"/new/to/my/path\" where both the path and all its children included. If \"prefix\" set to false, only \"/foo/bar\" will be redirected to \"/new\".\n\n\n  1. Carry over suffix path with append_suffix option.\n\n      ```\n        https://{default}/:\n          type: upstream\n          redirects:\n            paths:\n              '/foo/bar':\n                to: 'https://{default}/new'\n                append_suffix: false\n\n      ```\n\n      If append_suffix is set to false, \"/foo/bar/to/my/path\" will be redirected to \"/new\". Otherwise, \"/foo/bar/to/my/path\" will be redirects to \"/new/to/my/path\". append_suffix is ignored if 'prefix' is false or 'regexp' is true.\n\n\n### HTTP vs HTTPS\n\nPlatform.sh recommends using HTTPS requests for all sites exclusively. Specifying HTTPS in route.yaml will automatically redirect any requests for an HTTP URL to HTTPS. While specifying only HTTP routes will result in duplicate HTTPS routes being created automatically, allowing the site to be served from both HTTP and HTTPS without redirects.\n\nAlthough it is not recommended, HTTPS requests can be redirected to HTTP explicitly to serve the site over HTTP only using route.yaml:\n\n```\n\"https://{default}/\":\n  type: redirect\n  to: \"http://{default}/\"\n```\n\n### Avoid redirect chains\n\nA redirect chain is a series of redirects between the initial URL and the destination URL. The redirect chain could be built over time of development or due to a combination of redirect between different protocol, host name or trailing slash processing etc. Redirect chain causes page loss authority value in search result. It also increases page load time and decreases the overall quality of site.\n\nIn order to avoid redirect chains, pay attention on destination path protocol and host name. For example, if the site is running under https and host www, specify destination \"to\" in route.yaml as:\n```\n  to: \"https://www.{default}/path/to/destination/\"\n```\n\nThe trailing slash should be appended to the configure item if platform environment adds trailing slash to url by default.\nsee [Platform.sh Documentation Redirects](https://docs.platform.sh/configuration/routes/redirects.html)\n\n### Generate redirect rules for migration sites\n\nBodilessJS [Site Migration Tool](https://github.com/johnsonandjohnson/Bodiless-JS/tree/main/packages/bodiless-migration-tool) package comes with a feature that allows user to export site redirection into file. See [Tools/Migration](/#/Tools/Migration?id=configuration) for configuration.\n\nUser can apply these exported redirect rules to routers.yaml before deploying to platform.sh.\n\n```yaml\n\"https://{default}/\":\n    type: upstream\n    upstream: \"static:http\"\n    redirects:\n      paths:\n        /image/redirect.png:\n          to: /image/placeholder.png\n          code: 301\n        /page2:\n          to: /page3\n          code: 301\n```\n\n## Using Fastly CDN\n\nPlatform.sh integrates with Fastly via EZ platform for Fastly.  \n\n1. Obtain your Fastly Service ID & Key from Fastly.   \n1. Once Fastly Service ID & Key is obtained, these variables can be set at Main environment.\n    ```\n    platform variable:create -e main --level environment env:HTTPCACHE_PURGE_TYPE --value 'fastly'\n    platform variable:create -e main --level environment env:FASTLY_SERVICE_ID --value 'YOUR_ID_HERE'\n    platform variable:create -e main --level environment env:FASTLY_KEY --value 'YOUR_ID_HERE'\n    ```\n1. Verify or Update your `routes.yaml` to enable caching for your site by setting `enabled: true`\n    ```\n        cache:\n            enabled: true\n            cookies: []\n    ```\n1. Verify or Update your `.platform.app.yaml` expiration time for your files.\n    ```\n    web:\n        locations:\n            '/':\n                expires: 6h  \n    ```\n\nOnce completed, the main env deployed on Platform.sh should be on Fastly CDN.  You may have to fine tune the expires setting for your static resources and set certain ones (ones identify not to change often such as font files) to longer to leverage browser caching.\n\nPlatform.sh References:\n* [Set Fastly Credentials on Platform.sh](https://docs.platform.sh/frameworks/ibexa/fastly.html#set-credentials-on-platformsh)\n* [HTTP Cache](https://docs.platform.sh/configuration/routes/cache.html)\n* [Router Cache](https://docs.platform.sh/languages/php/tuning.html#ensure-that-the-router-cache-is-properly-configured)\n* [Expires](https://docs.platform.sh/configuration/app/web.html#locations)\n* [How to Guide: How to configure caching for static assets](https://community.platform.sh/t/how-to-configure-caching-for-static-assets/187)\n\n\nIf there are issues or you need to troubleshoot, here are some good resources:\n* [Checking Fastly Cache](https://docs.fastly.com/en/guides/checking-cache)\n\n    ``` curl -svo /dev/null -H \"Fastly-Debug:1\" www.example.com/index.html ```\n* [Purging Fastly Cache](https://docs.fastly.com/api/purge)\n\n    ``` curl -X PURGE www.example.com/index.html ```\n\n## How to load environment specific html snippets\n\nWhen you want to inject different html snippets depending on your environment type, you can use Server Side Includes (SSI) mechanism.\n### Activate SSI\n\n* Activate SSI for your route(s) in your routes.yaml file. See: https://docs.platform.sh/configuration/routes/ssi.html\n* Use SSI_ENV enviroment variable to specify type of your environment. Default value is 'dev'.\n* Ensure ssi configs are loaded to psh container and set SSI_CONF_PATH environment variable to path to json file containing SSI configs.\n* Ensure your .platform.app.yaml contains invocation of generate-ssi-files.js node scripts. The script should be invoked during build and deploy phases. PSH phase (build or deploy) should be passed as an argument to the script.\n* Ensure the files of you app, that will be served by psh, contain SSI directives.\n* Ensure a writable volume is mounted to your app.\n\n### SSI config format\n\nSSI configuration file should be in json format.\n\n```\n{\n  key1: {\n    pragma: \"<!--# ssi data should go here -->\",\n    env1: {\n      file: \"key1.env1.html\"\n    }\n    ...\n    envN: {\n      file: \"key1.envN.html\"\n    }\n  }\n  ...\n  keyN: {\n    pragma: \"<!--# ssi data should go here -->\",\n    ...\n    env1: {\n      file: \"keyN.envN.html\"\n    }\n    ...\n    envN: {\n      file: \"keyN.envN.html\"\n    }\n  }\n}\n```\n### How it works\n\n* during build phase, generate-ssi-files reads SSI configs and for each key it creates symlink from PLATFORM_DOCUMENT_ROOT/filename.html into APP_VOLUME/filename.html. Filename is generated based on key. There is an opportunity to improve this logic. We can read and parse pragma field, exract filename from it. But it makes the things more complicated and in addition, pragma may not have files at all.\n* during deploy phase, generate-ssi-files reads SSI configs and SSI_ENV and for each key it copies the file defined in conf.{key}.{env}.{file} to APP_VOLUME/filename.html that was created during build phase.\n\n## How to replace your site prod url with psh environment url in a public file\n\nIf you want to make urls in a particular public file match psh environment url, you can leverage psh-url-replacer node script. For instance, your site sitemap.xml, which is generated during build time, contains production urls and you want to replace the production url with psh environment url, to which your website is deployed to.\n\n### Why\n\nPlatform.sh does not allow to expose environment level environment variables to the application build stage.\n\n### How it works\n\non psh build stage:\n\n- it moves your source file from public dir to a tmp directory\n- then it creates a symlink from a writable volume file to the source public file\n\non psh deploy stage:\n\n- it copies the file from the tmp directory to the writable volume file\n- then it replaces production url with psh environment url in the file\n\n### How to activate this feature\n\nBy default, the feature is activated for sitemap.xml and robots.txt. If you want to activate the feature for some other files or if you have custom installation of sitemap.xml or robots.txt, please follow the following steps:\n\n1. ensure writable volume mounting is configured for your app\n\n1. export environment variables and invoke psh-url-replacer in build section of your psh app .platform.app.yaml\n\n```bash\n\nhooks:\n    build: |\n        export PSH_URL_REPLACER_SRC_FILE=/path/to/your/src/public/file\n        export PSH_URL_REPLACER_TMP_FILE=/path/to/a/tmp/file\n        export PSH_URL_REPLACER_TARGET_FILE=/path/to/writable/volume/file\n        node /path/to/psh-url-replacer.js build\n\n```\n\n1. export environment variables and invoke psh-url-replacer in deploy section of your psh app .platform.app.yaml\n\n```bash\n\nhooks:\n    deploy: |\n        export PSH_URL_REPLACER_TMP_FILE=/path/to/the/tmp/file/you/saved/during/build/phase\n        export PSH_URL_REPLACER_TARGET_FILE=/path/to/writable/volume/file\n        export PSH_URL_REPLACER_SRC_URL=https://your-site-production-url.com\n        export PSH_URL_REPLACER_TARGET_URL=https://your-psh-env.url.site\n        export PSH_URL_REPLACER_PROD_ENV='0' # set to '1' if you want to disable the replacement\n        node /path/to/psh-url-replacer.js deploy\n```\n\n## Known limitations\n\n### General\n- PR Branches and Feature branches created in bitbucket will always inherit from\n  main. This means that you must manually configure basic authentication for\n  these branches if you want them protected from the public internet.\n- There is a 64-character limit on hostnames for TLS, and platform.sh uses 43 of\n  them. Since hostnames are created based on branch names, and since the edit\n  environment uses an additional 5 (\"edit.\"), your branch names should be\n  limited to a maximum of 16 characters to avoid certificate warnings.\n- When you create a bitbucket integration, a webhook is added to your bitbucket\n  repository. However, deleting the integration does not remove the webhook, you\n  must do this manually.\n### Environment memory\nOn development environments, the `edit` site environment can use a large amount\nof memory when running, which might cause out-of-memory issues when building \npages. This is caused by webpack's caching system, and there are two ways\nto circumvent the issue:\n\n#### Increasing container memory\nUse [Large development containers](https://docs.platform.sh/overview/pricing.html#development)\nto increase the total memory available to containers. This is the preferred way \nto solve this problem, as it's easier and faster. Note that this will increase costs.\n\n#### Disable build cache\nDisabling webpack's cache will drastically reduce memory consumption, but\nwill also increase build times. This might be specially noticeable when doing\nsimple operations like creating, cloning or moving pages.\n\nTo disable a site's cache, add `cache: false` to its webpack configuration. This\nis done in the `gatsby-node.js` file on the site root. Read [Gatsby's documentation](https://www.gatsbyjs.com/docs/how-to/custom-configuration/add-custom-webpack-config/#examples)\nfor an example, and refer to [Webpacks's documentation](https://webpack.js.org/configuration/cache/)\nif you want to understand how its caching system works.\n## Troubleshooting\n\n### Viewing Logs\n\nBuild, deploy and application logs for an environment are available using the\nplatform cli. If you want logs for an environment other than the currently\nchecked-out branch (e.g. for a pull request), you must use the `-e` flag. You\ncan first get a list of all available environments by running\n```\nplatform env:list\n```\nYou can then use the identifier from the first column in the commands below.\nIf you want logs from the environment associated with your current local\nbranch, you can omit the `-e` flag.\n\n- Tail/print most recent build log (this now includes deploy log):\n  ```\n  platform activity:log -e <env-id>\n  ```\n  Note that you may have to wait a few moments after performing\n  a git push in order for the new p.sh deployment to begin.\n- Print deploy logs for all builds to the edit environment:\n  ```\n  platform log -e <env-id> -A edit deploy <--lines n>\n  ```\n  (where n is the number of lines.)\n- View or tail application logs for the edit environment\n  ```\n  platform log -e <env-id> -A edit app <--lines n> <--tail>\n  ```\n\nAlternatively, you can visit [the platform.sh console](https://console.platform.sh/webalerts/abcdefghi) and locate\nyour build to view the build log (deployment and application logs\nare only available from the command line).\n\n### Hints\n\n- If the `platform` command is not found, you probably have to run\n  `source .bashrc` to ensure it is in your path.\n- For all deployments in which the app is restarted, the environment may not be\n  fully available for up to a minute after the deployment is complete.\n- You may see errors in the application log relating to insufficient file\n  watchers. This is a known issue. Currently the only workaround is to reduce\n  the number of active environments.\n- Public URLs for an environment are available by running\n  ```\n  platform url -e <env-id>\n  ```\n- There are many other useful platform cli subcommands.  Run `platform list`\n  to see them all.\n\n## Deploying bodiless packages from a private registry\n\nBy default the public regisry will be used to download bodiless packages: //registry.npmjs.org/\n\nIn order to switch to a private registry follow Step 3 (Create platform.sh environment variables.) of this doc.\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/johnsonandjohnson/bodiless-js/issues"},"_id":"@asemirsk/psh@1.0.0-beta.6","_nodeVersion":"16.13.2","_npmVersion":"lerna/4.0.0/node@v16.13.2+x64 (linux)","dist":{"integrity":"sha512-VcGzFdV5xaTDJfwjhVOcnHlKwykUE0S0fFfWm8vfrc6o5HuiD4JpwXgDcoQPVSX6nCv6tFqbLim7VAkfiRZfkA==","shasum":"671323ad0ad9b2e4d64001bf5bf8da39f5c61215","tarball":"https://registry.npmjs.org/@asemirsk/psh/-/psh-1.0.0-beta.6.tgz","fileCount":14,"unpackedSize":65394,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD9iyAnXitCFXrSkEwTQw/eFd3pMKstFEsKgQtC+6nTpgIhAIFSKWcu3sYBU5Xs+5F+ssLGXsMrb2MRnErqZTZpoQW/"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiUJRxACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmopoQ//S/PYDHKDKkuGpiJXGLie9rGlZQ7TgA0LpttSFyrRy2uCeDua\r\nSQ0rxXa9YVu2iXvtAKji7UxlnNZcPz2y4HbN7hwhyzjyBL44vzDvo/4VOGUg\r\n59gsBWO9ehWlbJFR4Hm1Ms4JorC15lAWfLO/oevKVNBos7dB9+wMKdLj0OEt\r\nuDi3UbFOCiRfO6EER37zYgCN0xNofGgO8tEXNV2BH7kl0ogn4k1n9GDLZXO4\r\nW6IU+WOctw/Y9zBgbGHrHyClEzO4atzv7cZJWZ/PzSWWzjKI8LmfTIb4/X7n\r\n+XzZLGOJv8ZSsRhpj4JHUkV4aqiSejgKufzFPOvfXsH4scgb/U2CnQWquLnr\r\nAYREaT5L85cAXRh2TvJ4aqTU3VxSxx/ph6ktjyrK9BMdKYsYXHAU4XPEqHhT\r\nMjiCgtNCsnSv2NzciD2byiVgqapO/0LMXx1FFA4oKsDsVQLSPV2bX7O8SJhn\r\n+ixNif0eABpo5407HheFvgx51aq8AJnypNvaCw2RecIAWCF/vxVdYZnukRYW\r\nMVAOzsS162z58I6tuw1EeKXnZdXcMpJYI1Nmm6hf50JLX1gQBMwEuPtuLLOb\r\nYSI1gj5RD8C33F/qh5spuJT0N3HyA3cIja42gzFNY+rACS5+o8LFSdOKGJtY\r\nJwfzjyMtFHoV1Owg4A57SJD9+B+iDCzjtcQ=\r\n=rILP\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"asemirsk","email":"al.semirski@gmail.com"},"maintainers":[{"name":"asemirsk","email":"al.semirski@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/psh_1.0.0-beta.6_1649448049191_0.5872280370537206"},"_hasShrinkwrap":false},"1.0.1-beta.6":{"name":"@asemirsk/psh","version":"1.0.1-beta.6","description":"Provides cli tool for initializing a bodiless project on platform.sh","author":{"name":"Chris Oden","email":"coden@its.jnj.com"},"homepage":"https://github.com/johnsonandjohnson/bodiless-js#readme","license":"Apache-2.0","bin":{"bodiless-psh-init":"lib/bodiless-psh-init.js"},"scripts":{"build":"tsc --version && tsc -p ./tsconfig.json ","build:watch":"npm run build -- --watch","clean":"rimraf \"lib/*\" && rimraf tsconfig.tsbuildinfo"},"directories":{"lib":"lib"},"repository":{"type":"git","url":"git+https://github.com/johnsonandjohnson/bodiless-js.git"},"publishConfig":{"access":"public"},"dependencies":{"@asemirsk/cli":"^1.0.1-beta.6","copyfiles":"^2.1.1","js-yaml":"^3.13.1","lodash":"^4.17.19","rimraf":"^2.6.3"},"devDependencies":{"@types/copyfiles":"^2.1.1"},"gitHead":"dfbcb3dab592c76bd48c138c275c1e27fbd9ca1d","readme":"# Bodiless integration with platform.sh\n\nThis package provides standard configuration files and helper scripts which\nmake it easy for a bodiless site to be deployed to platform.sh.\n\n## Setting up your project\n\n### Pre-requisites\n\n- Admin access to a [platform.sh](https://platform.sh/) project.\n- A service user with *admin access* to a repository in a Bitbucket Server instance.\n- The [platform.sh cli](https://docs.platform.sh/gettingstarted/cli.html)\n\n### Step 1. Gather required information\n\nTo continue, you will need the following:\n\n#### The platform.sh project key\n- Log in via the platform.sh cli.  From your local machine execute:\n  ```\n  platform login\n  ```\n  You will be directed to log in via a web browser\n- Execute\n  ```\n  platform project:list\n  ```\n  You should see a list of all projects you have access to, something like:\n  ```\n    Your projects are:\n  +---------------+-------------------------+-----------------------------------------------------+\n  | ID            | Title                   | URL                                                 |\n  +---------------+-------------------------+-----------------------------------------------------+\n  | abcdefghijklm | project_a               | https://console.platform.sh/webalerts/abcdefghijklm |\n  | lmnopqrstuvwx | project_b               | https://console.platform.sh/webalerts/lmnopqrstuvwx |\n  +---------------+-------------------------+-----------------------------------------------------+`\n  ```\n- Take note of the project ID for your project. This is the value you will use below.\n\n### Step 2. Initialize your project configuration files\n\nPlatform.sh requires several configuration files to be in place\nin your repository. This package contains default versions of these\nfiles for a BodilessJS.  To install or update them:\n\n1. Add this package as a dependency of your project:\n  ```\n  npm i --save-dev @bodiless/psh\n  ```\n2. Add the following to your `package.json` scripts:\n  ```\n  \"init-psh\": \"bodiless-psh-init\"\n  ```\n3. Install or update the configuration files:\n  ```\n  npm run init-psh\n  ```\n> When `@bodiless/psh` is installing its' files it will try to merge `static` and `edit` `*.platform.app.yaml` files based on the whitelisted keys from `packages/bodiless-psh/resources/.platform/platform.whitelist.yaml`. Only the keys that are specified in `platform.whitelist.yaml` will be merged. Merging will be performed by using the recursive algorithm to preserve any keys that are not in default `.platform.app.yaml`. Non-whitelisted keys will be ignored, and a warning message will be printed to the console.\n\n4. Commit the added configuration files to your repository.  These include\n   ```\n   static.platform.sh\n   .platform.app.yaml\n   .platform/*\n   edit/*\n   ```\n\n### Step 3. Create platform.sh environment variables.\n\nFirst, configure your local install to connect to your platform.sh project. From\nwithin your project root, execute\n```\nplatform project:set-remote {project id}\n```\nwhere {project id} is the platform.sh project id you acquired above.\n\nAll variables below should be set at the project level using the platform.sh command\nline, as described in [the platform.sh documentation](https://docs.platform.sh/development/variables.html#project-variables), and all should be visible at both build time and run time.\n\nAdd the following variables:\n\n- env:APP_GIT_REMOTE_URL -- The URL of your upstream Git repository\n- env:APP_GIT_USER -- The user to access your upstream Git repository.\n- env:APP_GIT_USER_EMAIL -- THe user email for your upstream Git repository.\n- env:APP_GIT_PW -- The user password for your upstream Git repository.\n\n\n> Be sure to specify `--sensitive true` for all credentials.\n\nExample:\n```\n$ platform variable:create\n* Level (--level)\nThe level at which to set the variable\n  [project    ] Project-wide\n  [environment] Environment-specific\n> project\n\n* Name (--name)\nThe variable name\n> APP_GIT_USER_EMAIL\n\n* Value (--value)\nThe variable's value\n> email@your.service.account\n\nJSON (--json)\nIs the value JSON-formatted? [y|N] N\n\nSensitive (--sensitive)\nIs the value sensitive? [y|N] N\n\nPrefix (--prefix)\nThe variable name's prefix\nDefault: none\n  [none] No prefix: The variable will be part of $PLATFORM_VARIABLES.\n  [env:] env: The variable will be exposed directly, e.g. as $APP_GIT_USER_EMAIL.\n> env:\n\nVisible at build time (--visible-build)\nShould the variable be available at build time? [Y|n] Y\n\nVisible at runtime (--visible-runtime)\nShould the variable be available at runtime? [Y|n] Y\n\nCreating variable env:APP_GIT_USER_EMAIL on the project...\n```\n\nYou can verify that the variable was created properly by executing, eg:\n  ```\n  platform variable:get env:APP_GIT_USER_EMAIL\n  ```\n  You should see something like:\n  ```\n  $ platform variable:get env:APP_NPM_AUTH\n  +-----------------+---------------------------+\n  | Property        | Value                     |\n  +-----------------+---------------------------+\n  | id              | env:APP_GIT_USER_EMAL     |\n  | created_at      | 2019-08-09T06:48:52-04:00 |\n  | updated_at      | 2019-08-09T06:48:52-04:00 |\n  | name            | env:APP_GIT_USER_EMAIL    |\n  | attributes      | {  }                      |\n  | is_json         | false                     |\n  | is_sensitive    | false                     |\n  | visible_build   | true                      |\n  | visible_runtime | true                      |\n  | level           | project                   |\n  +-----------------+---------------------------+\n  ```\n\n#### Optional: Configure an NPM Private Registry\n\nIf you wish to install packages from a private registry, you may do so. The\npackages to be installed must be namespaced. Set the following 3 environment\nvariables on p.sh. All variables should be visible at both build and run time:\n- `env:APP_NPM_REGISTRY`: the full path to your registry, eg\n  `//my-artifactory.com/api/npm/my-registry/`.\n- `env:APP_NPM_AUTH`: Ypur NPM authentication token. This should be marked as sensitive.\n  To obtain your token:\n  1. Login to your registry:\n     ```\n     npm login --registry=https://url/of/your/private/registry\n     ```\n     Follow the prompts with the username/password/email of the account you wish\n     to use for p.sh automation.\n  2. Examine your `.npmrc` file (usually located in your home directory). You\n     should see something like\n     ```\n     //url/of/your/privateregistry/:_authToken={token}\n     ```\n  3. Copy the token value to the `env:APP_NPM_AUTH` variable in your p.sh project.\n\n- `env:APP_NPM_NAMESPACE`: The namespace of the packages in your private\n  regsitry, eg `@mynamespace`.\n\n### Step 4. Configure the platform.sh Git Service integration.\n\nPlatform.sh provides out-of-the-box integrations with many popular Git service providers.\nWe have tested with Bitbucket Server and GitHub.\n\nNote that you must have admin access to the repository in order to configure the integration.\n\n#### GitHub\n\nFrom your project root, execute `platform integration:add` and follow\nthe prompts, as:\n\n```\n$ platform integration:add\n* Integration type (--type)\nEnter a number to choose:\n  [0] bitbucket\n  [1] bitbucket_server\n  [2] github\n  [3] gitlab\n  [4] hipchat\n  [5] webhook\n  [6] health.email\n  [7] health.pagerduty\n  [8] health.slack\n  [9] health.webhook\n> 2\n\n* Token (--token)\nAn access token for the integration\n> {your GitHub personal access token}\n\n* Repository (--repository)\nThe repository (e.g. 'foo/bar')\n> johnsonandjohnson/Bodiless-JS\n\nBuild pull requests (--build-pull-requests)\nBuild every pull request as an environment? [Y|n] Y\n\nBuild pull requests post-merge (--build-pull-requests-post-merge)\nBuild pull requests based on their post-merge state? [y|N] y\n\nClone data for pull requests (--pull-requests-clone-parent-data)\nClone the parent environment's data for pull requests? [Y|n] n\n\nFetch branches (--fetch-branches)\nFetch all branches from the remote (as inactive environments)? [Y|n] y\n\nPrune branches (--prune-branches)\nDelete branches that do not exist on the remote? [Y|n] y\n\nWarning: adding a 'github' integration will automatically synchronize code from the external Git repository.\nThis means it can overwrite all the code in your project.\n\nAre you sure you want to continue? [y/N] y\nChecking webhook configuration on the repository: johnsonandjohnson/Bodiless-JS\n  Creating new webhook\n  Webhook created successfully\nCreated integration xxxxxxxx (type: github)\n+---------------------------+--------------------------------------------------------------------+\n| Property                  | Value                                                              |\n+---------------------------+--------------------------------------------------------------------+\n| id                        | xxxxxxx                                                            |\n| type                      | github                                                             |\n| token                     | ******                                                             |\n| base_url                  |                                                                    |\n| repository                | foo/bar                                                            |\n| fetch_branches            | true                                                               |\n| prune_branches            | true                                                               |\n| build_pull_requests       | true                                                               |\n| build_pull_requests_post_ | true                                                               |\n| merge                     |                                                                    |\n| pull_requests_clone_paren | false                                                              |\n| t_data                    |                                                                    |\n| hook_url                  | https://us-2.platform.sh/api/projects/jvaff4bu65vgm/integrations/4 |\n|                           | 4zqv2kqqfcgq/hook                                                  |\n+---------------------------+--------------------------------------------------------------------+\n```\n\n#### Bitbucket Server\n\nFrom your project root, execute `platform integration:add` and follow\nthe prompts, as:\n\n```bash\n$ platform integration:add\n* Integration type (--type)\nEnter a number to choose:\n  [0] bitbucket\n  [1] bitbucket_server\n  [2] github\n  [3] gitlab\n  [4] hipchat\n  [5] webhook\n  [6] health.email\n  [7] health.pagerduty\n  [8] health.slack\n> 1\n\n* Username (--username)\nThe Bitbucket Server username\n> {bitbukcet service username}\n\n* Token (--token)\nAn access token for the integration\n> {bitbucket service user password}\n\n* Repository (--repository)\nThe repository (e.g. 'foo/bar')\n> {project/repository, eg: foo/bar}\n\nBuild pull requests (--build-pull-requests)\nBuild every pull request as an environment? [Y|n] N\n\nClone data for pull requests (--pull-requests-clone-parent-data)\nClone the parent environments data for pull requests? [Y|n] Y\n\nFetch branches (--fetch-branches)\nFetch all branches from the remote (as inactive environments)? [Y|n] Y\n\nPrune branches (--prune-branches)\nDelete branches that do not exist on the remote? [Y|n] Y\n\nWarning: adding a 'bitbucket_server' integration will automatically synchronize code from the external Git repository.\nThis means it can overwrite all the code in your project.\n\nAre you sure you want to continue? [y/N] y\n```\n\n##### Verify the integration\n\n##### GitHub\n- Visit the \"webhooks\" section of your bitbucket repository settings, eg\n  ```\n  https://github.com/project/repo/settings/hooks\n  ```\n  and verify that a webhook to platform.sh has been added. Note you will need admin access\n  to the project in order to view the webhooks.\n- Activate a branch in your project (as described below) and validate that an environment\n  is created and deployed to platform.sh. *Note you must first push the branch to bitbucket*.\n- Issue a PR to your repository and verify that the PR branch is deployed.\n\n##### Bitbucket Server\n- Visit the \"webhooks\" section of your bitbucket repository settings, eg\n  ```\n  https://domain/plugins/servlet/webhooks/projects/{project-key}/repos/{repo-name}\n  ```\n  and verify that a webhook to platform.sh has been added. Note you will need admin access\n  to the project in order to view the webhooks.\n- Activate a branch in your project (as described below) and validate that an environment\n  is created and deployed to platform.sh. *Note you must first push the branch to bitbucket*.\n- Issue a PR to your repository and verify that the PR branch is deployed (note that only\n  the static environment will be build for PR's on Bitbucket).\n\n### Customizing Hook Implementations\n\nThis package includes default implementations of platform.sh\n[build and deploy hooks](https://docs.platform.sh/configuration/app/build.html#hooks) which\nshould work for most Bodiless sites.  However, should your site have special needs, you can\ncustomize by creating a `platform.custom.sh` or `static.platform.custom.sh` script and placing\nit alongside the appropriate `.platform.app.yaml` file (at the root of your repository for the\nstatic site, or in the `/edit` directory for the edit app).  In this script, you can define for\neach platform.sh hook one of the following functions:\n\n- `prepare_{hook} ()` - Run before the default implementation of the hook.\n- `hook ()` - Replaces the default implementation of the hook.\n- `finalize_{hook} ()` - Run after the default implementation of the hook.\n\nIf you wish to extend the default implementation, you can do so by calling it from your function.\nTo do this safely (ie to avoid errors if the default implementation doesn't exist) always use the\n`invoke` helper:\n\n```bash\nprepare_deploy () {\n  invoke default_prepare_deploy\n  # Your custom logic here...\n}\n```\n\n## Building and Deploying\n\n### Continuous Integration\n\nIf you configured platform.sh to build pull requests, then every PR to your repository will be\ndeployed to its own environment. Be aware of the following:\n- It is easy to reach your quota of development environments with this enabled, so use cautiously.\n- Edit environments for pull requests are currently only supported on GitHub -- and pushing changes\n  from the edit environment is not supported even there.\n- On Bitbucket Server, pull requests from *forks* will not automatically rebuild when new commits\n  are added.  This limitation does not apply to GitHub.\n- On both GitHub and Bitbucket, changes pushed to code outside the `/edit` directory will\n  not automatically be deployed to the edit environment.  You must manually update the\n  edit environment as described under [Pushing Changes](#pushing-changes) below.\n- Pull request environments will be automatically deleted when the PR is merged or declined.\n- If you manually delete a PR environment, it will not be recreated when the PR is\n  updated.\n- PR environments are named simply `pr-{pr#}` (eg `pr-123`).  You can easily run platform cli\n  commands against them using the `-e pr-xxx` option.\n- A link to the p.sh environment will be posted to the PR:\n  - **GitHub**: Expand the \"Show All Checks\" link next to the section on the \"Conversations\"\n    tab, and click the \"details\" link next to the platform.sh build.\n  - **Bitbucket Server**: Click the build status icon next to the PR title, and then click the\n    \"platform.sh\" link.\n\n### Manual Deployments\n\n#### Pre-requisites\n\n- Access to a [platform.sh](https://platform.sh/) project.\n- The [platform.sh cli](https://docs.platform.sh/gettingstarted/cli.html)\n\n#### Local setup\n\n- Obtain the project key of the project you wish to deploy: see\n  [The platform.sh project key](#the-platform.sh-project-key), above.\n- Connect your local repository to the correct platform.sh remote. From within the repository root:\n  ```\n  platform project:set-remote {project id}\n  ```\n\n#### Initial deployment of a new branch\n\n- Ensure you are on the correct branch locally.\n- Push the branch to bitbucket.\n  ```\n  git push origin <branch>\n  ```\n- Execute\n    ```\n    platform env:activate\n    ```\n  Note - you may have to wait a few moments after pushing the branch to\n  bitbucket before activating the environment, in order to allow the branch to\n  sync to p.sh. If, when you try to activate, you are asked for an \"Environment\n  ID\", wait a bit and try again.\n- The public URL of the new environment will be printed to the console.\n- You can display (and open) the public URLs for your site by checking out the\n  corresponding branch and executing `platform url`.\n\n##### Basic Authentication\n\nNote that basic authentication may be configured for your environment by\ndefault, and this may prevent access via your browser. To verify, use the\nplatform cli:\n```\nplatform env:http-access\n```\n\nYou can also use this command to enable or disable authentication, and to\nadd/remove credentials.\n```\nplatform help env:http-access\n```\nto learn more.\n\n#### Pushing changes\n\nOnce a new branch is created, changes pushed to Bitbucket will be automatically\ndeployed to the static site on platform.sh. You can run `platform activity:log`\nto see the current build status, or visit [console.platform.sh](https://console.platform.sh),\nlocate your build, and click \"View Logs\".\n\nChanges are *not* automatically deployed to an edit environment; you must manually\ntrigger an update of the edit environment by executing:\n  ```\n  platform ssh -e <env-id> 'bash platform.sh deploy'\n  ```\n\n  You may omit the \"-e <env-id>\" if you have the active branch checked out locally.\n\n#### Deleting an environment\n\nThe platform.sh environment will be deleted when you remove the corresponding\nbranch from bitbucket. *Please delete obsolete branches*.\n\nYou can also remove an environment without deleting your branch by checking\nout the branch locally and executing `platform env:delete -y`.\n\n#### Merging to main\n\nWhen you merge a feature branch to main, the updated main branch will be automatically deployed\nto the static environment on platform.sh.  To deploy changes to the edit environment, you must follow the same process as in [Pushing Changes](#pushing-changes) above.\n\n\n## Handling Redirect with Routes\n\n### Overview\nIn HTTP, URL redirecting is a technique to forward one URL to a different URL. It is commonly used for handling cases like URL shortening, preventing broken links when pages removed, pointing multiple domain addresses to a single URL address, etc. It is also critical to preserve page SEO value when there are URL changes.\n\nRedirection can be implemented on a client page with [Refresh Meta Tag](https://en.wikipedia.org/wiki/Meta_refresh) or JavaScript, but the preferred way is to manage redirect rules with server configuration.\n\nYou can configure redirects on Platform.sh with route yaml in project environments. A route describes how an incoming HTTP request is processed by Platform.sh, which includes URL redirect. The routes are defined inside .platform/routes.yaml file.\n\nAn example of redirect using routes.yaml:\n```\n\"https://www.{default}/\":\n  type: redirect\n  to: \"https://my-host.{default}/\"\n```\n\nHere, the URL https://www.example.com/ will be redirected to https://my-host.example.com/\n\n### Whole-route vs Partial redirects\nPlatform.sh offers two different ways to implement redirect rules, **Whole-route redirects** and **Partial redirects**\n\n* Whole-route redirects on host level. A typical use case for this kind of route is adding or removing a www. prefix to domain,\n\n  .platform/routes.yaml\n  ```\n  https://{default}/:\n    type: redirect\n    to: https://www.{default}/\n  ```\n\n  Here, https://example.com/ will be redirected to https://www.example.com/. This approach can be used to redirect vanity domains to their destination URLs.\n\n* Partial redirects allows redirect rules to be added to existing routes,\n\n  .platform/routes.yaml\n  ```\n      https://{default}/:\n        # [...]\n        redirects:\n          expires: 1d\n          paths:\n            '/from':\n              to: 'https://example.com/'\n              code: 301\n  ```\n\n  Here, \"https://[domain name]/from\" will be redirected to https://www.example.com/.\n\n  Note:\n  * the default response code is 302, in order to use a different response code, mostly commonly 301, add \"code: 301\" as configurable option.\n  * \"expires\" param is optional, it specifies duration the redirect will be cached. Examples of valid values include 3600s, 1d, 2w, 3m.\n\n\n  **Examples**\n\n  file .platform/routes.yaml\n\n  1. Redirect path \"/foo/bar\" to a different site \"https://example.com/\".\n\n      ```\n      https://{default}/:\n        type: upstream\n        redirects:\n          paths:\n            '/foo/bar':\n              to: 'https://example.com/'\n      ```\n\n  1.  Using Regular Expression to redirect path that matches \"/foo/(.*)/bar\" pattern.\n\n      ```\n      https://{default}/:\n        type: upstream\n        redirects:\n          paths:\n            '/foo/(.*)/bar':\n              to: '/$1'\n              regexp: true\n      ```\n\n      In this case, path \"/foo/cards/bar\" will be redirected to \"/cards\".\n\n  1. Redirect with prefix.\n\n      ```\n      https://{default}/:\n        type: upstream\n        redirects:\n          paths:\n            '/foo/bar':\n              to: '/new'\n              prefix: true\n\n      ```\n\n      Path \"/foo/bar\" will be redirected to \"/new\". And path \"/foo/bar/to/my/path\" will be redirected to \"/new/to/my/path\" where both the path and all its children included. If \"prefix\" set to false, only \"/foo/bar\" will be redirected to \"/new\".\n\n\n  1. Carry over suffix path with append_suffix option.\n\n      ```\n        https://{default}/:\n          type: upstream\n          redirects:\n            paths:\n              '/foo/bar':\n                to: 'https://{default}/new'\n                append_suffix: false\n\n      ```\n\n      If append_suffix is set to false, \"/foo/bar/to/my/path\" will be redirected to \"/new\". Otherwise, \"/foo/bar/to/my/path\" will be redirects to \"/new/to/my/path\". append_suffix is ignored if 'prefix' is false or 'regexp' is true.\n\n\n### HTTP vs HTTPS\n\nPlatform.sh recommends using HTTPS requests for all sites exclusively. Specifying HTTPS in route.yaml will automatically redirect any requests for an HTTP URL to HTTPS. While specifying only HTTP routes will result in duplicate HTTPS routes being created automatically, allowing the site to be served from both HTTP and HTTPS without redirects.\n\nAlthough it is not recommended, HTTPS requests can be redirected to HTTP explicitly to serve the site over HTTP only using route.yaml:\n\n```\n\"https://{default}/\":\n  type: redirect\n  to: \"http://{default}/\"\n```\n\n### Avoid redirect chains\n\nA redirect chain is a series of redirects between the initial URL and the destination URL. The redirect chain could be built over time of development or due to a combination of redirect between different protocol, host name or trailing slash processing etc. Redirect chain causes page loss authority value in search result. It also increases page load time and decreases the overall quality of site.\n\nIn order to avoid redirect chains, pay attention on destination path protocol and host name. For example, if the site is running under https and host www, specify destination \"to\" in route.yaml as:\n```\n  to: \"https://www.{default}/path/to/destination/\"\n```\n\nThe trailing slash should be appended to the configure item if platform environment adds trailing slash to url by default.\nsee [Platform.sh Documentation Redirects](https://docs.platform.sh/configuration/routes/redirects.html)\n\n### Generate redirect rules for migration sites\n\nBodilessJS [Site Migration Tool](https://github.com/johnsonandjohnson/Bodiless-JS/tree/main/packages/bodiless-migration-tool) package comes with a feature that allows user to export site redirection into file. See [Tools/Migration](/#/Tools/Migration?id=configuration) for configuration.\n\nUser can apply these exported redirect rules to routers.yaml before deploying to platform.sh.\n\n```yaml\n\"https://{default}/\":\n    type: upstream\n    upstream: \"static:http\"\n    redirects:\n      paths:\n        /image/redirect.png:\n          to: /image/placeholder.png\n          code: 301\n        /page2:\n          to: /page3\n          code: 301\n```\n\n## Using Fastly CDN\n\nPlatform.sh integrates with Fastly via EZ platform for Fastly.  \n\n1. Obtain your Fastly Service ID & Key from Fastly.   \n1. Once Fastly Service ID & Key is obtained, these variables can be set at Main environment.\n    ```\n    platform variable:create -e main --level environment env:HTTPCACHE_PURGE_TYPE --value 'fastly'\n    platform variable:create -e main --level environment env:FASTLY_SERVICE_ID --value 'YOUR_ID_HERE'\n    platform variable:create -e main --level environment env:FASTLY_KEY --value 'YOUR_ID_HERE'\n    ```\n1. Verify or Update your `routes.yaml` to enable caching for your site by setting `enabled: true`\n    ```\n        cache:\n            enabled: true\n            cookies: []\n    ```\n1. Verify or Update your `.platform.app.yaml` expiration time for your files.\n    ```\n    web:\n        locations:\n            '/':\n                expires: 6h  \n    ```\n\nOnce completed, the main env deployed on Platform.sh should be on Fastly CDN.  You may have to fine tune the expires setting for your static resources and set certain ones (ones identify not to change often such as font files) to longer to leverage browser caching.\n\nPlatform.sh References:\n* [Set Fastly Credentials on Platform.sh](https://docs.platform.sh/frameworks/ibexa/fastly.html#set-credentials-on-platformsh)\n* [HTTP Cache](https://docs.platform.sh/configuration/routes/cache.html)\n* [Router Cache](https://docs.platform.sh/languages/php/tuning.html#ensure-that-the-router-cache-is-properly-configured)\n* [Expires](https://docs.platform.sh/configuration/app/web.html#locations)\n* [How to Guide: How to configure caching for static assets](https://community.platform.sh/t/how-to-configure-caching-for-static-assets/187)\n\n\nIf there are issues or you need to troubleshoot, here are some good resources:\n* [Checking Fastly Cache](https://docs.fastly.com/en/guides/checking-cache)\n\n    ``` curl -svo /dev/null -H \"Fastly-Debug:1\" www.example.com/index.html ```\n* [Purging Fastly Cache](https://docs.fastly.com/api/purge)\n\n    ``` curl -X PURGE www.example.com/index.html ```\n\n## How to load environment specific html snippets\n\nWhen you want to inject different html snippets depending on your environment type, you can use Server Side Includes (SSI) mechanism.\n### Activate SSI\n\n* Activate SSI for your route(s) in your routes.yaml file. See: https://docs.platform.sh/configuration/routes/ssi.html\n* Use SSI_ENV enviroment variable to specify type of your environment. Default value is 'dev'.\n* Ensure ssi configs are loaded to psh container and set SSI_CONF_PATH environment variable to path to json file containing SSI configs.\n* Ensure your .platform.app.yaml contains invocation of generate-ssi-files.js node scripts. The script should be invoked during build and deploy phases. PSH phase (build or deploy) should be passed as an argument to the script.\n* Ensure the files of you app, that will be served by psh, contain SSI directives.\n* Ensure a writable volume is mounted to your app.\n\n### SSI config format\n\nSSI configuration file should be in json format.\n\n```\n{\n  key1: {\n    pragma: \"<!--# ssi data should go here -->\",\n    env1: {\n      file: \"key1.env1.html\"\n    }\n    ...\n    envN: {\n      file: \"key1.envN.html\"\n    }\n  }\n  ...\n  keyN: {\n    pragma: \"<!--# ssi data should go here -->\",\n    ...\n    env1: {\n      file: \"keyN.envN.html\"\n    }\n    ...\n    envN: {\n      file: \"keyN.envN.html\"\n    }\n  }\n}\n```\n### How it works\n\n* during build phase, generate-ssi-files reads SSI configs and for each key it creates symlink from PLATFORM_DOCUMENT_ROOT/filename.html into APP_VOLUME/filename.html. Filename is generated based on key. There is an opportunity to improve this logic. We can read and parse pragma field, exract filename from it. But it makes the things more complicated and in addition, pragma may not have files at all.\n* during deploy phase, generate-ssi-files reads SSI configs and SSI_ENV and for each key it copies the file defined in conf.{key}.{env}.{file} to APP_VOLUME/filename.html that was created during build phase.\n\n## How to replace your site prod url with psh environment url in a public file\n\nIf you want to make urls in a particular public file match psh environment url, you can leverage psh-url-replacer node script. For instance, your site sitemap.xml, which is generated during build time, contains production urls and you want to replace the production url with psh environment url, to which your website is deployed to.\n\n### Why\n\nPlatform.sh does not allow to expose environment level environment variables to the application build stage.\n\n### How it works\n\non psh build stage:\n\n- it moves your source file from public dir to a tmp directory\n- then it creates a symlink from a writable volume file to the source public file\n\non psh deploy stage:\n\n- it copies the file from the tmp directory to the writable volume file\n- then it replaces production url with psh environment url in the file\n\n### How to activate this feature\n\nBy default, the feature is activated for sitemap.xml and robots.txt. If you want to activate the feature for some other files or if you have custom installation of sitemap.xml or robots.txt, please follow the following steps:\n\n1. ensure writable volume mounting is configured for your app\n\n1. export environment variables and invoke psh-url-replacer in build section of your psh app .platform.app.yaml\n\n```bash\n\nhooks:\n    build: |\n        export PSH_URL_REPLACER_SRC_FILE=/path/to/your/src/public/file\n        export PSH_URL_REPLACER_TMP_FILE=/path/to/a/tmp/file\n        export PSH_URL_REPLACER_TARGET_FILE=/path/to/writable/volume/file\n        node /path/to/psh-url-replacer.js build\n\n```\n\n1. export environment variables and invoke psh-url-replacer in deploy section of your psh app .platform.app.yaml\n\n```bash\n\nhooks:\n    deploy: |\n        export PSH_URL_REPLACER_TMP_FILE=/path/to/the/tmp/file/you/saved/during/build/phase\n        export PSH_URL_REPLACER_TARGET_FILE=/path/to/writable/volume/file\n        export PSH_URL_REPLACER_SRC_URL=https://your-site-production-url.com\n        export PSH_URL_REPLACER_TARGET_URL=https://your-psh-env.url.site\n        export PSH_URL_REPLACER_PROD_ENV='0' # set to '1' if you want to disable the replacement\n        node /path/to/psh-url-replacer.js deploy\n```\n\n## Known limitations\n\n### General\n- PR Branches and Feature branches created in bitbucket will always inherit from\n  main. This means that you must manually configure basic authentication for\n  these branches if you want them protected from the public internet.\n- There is a 64-character limit on hostnames for TLS, and platform.sh uses 43 of\n  them. Since hostnames are created based on branch names, and since the edit\n  environment uses an additional 5 (\"edit.\"), your branch names should be\n  limited to a maximum of 16 characters to avoid certificate warnings.\n- When you create a bitbucket integration, a webhook is added to your bitbucket\n  repository. However, deleting the integration does not remove the webhook, you\n  must do this manually.\n### Environment memory\nOn development environments, the `edit` site environment can use a large amount\nof memory when running, which might cause out-of-memory issues when building \npages. This is caused by webpack's caching system, and there are two ways\nto circumvent the issue:\n\n#### Increasing container memory\nUse [Large development containers](https://docs.platform.sh/overview/pricing.html#development)\nto increase the total memory available to containers. This is the preferred way \nto solve this problem, as it's easier and faster. Note that this will increase costs.\n\n#### Disable build cache\nDisabling webpack's cache will drastically reduce memory consumption, but\nwill also increase build times. This might be specially noticeable when doing\nsimple operations like creating, cloning or moving pages.\n\nTo disable a site's cache, add `cache: false` to its webpack configuration. This\nis done in the `gatsby-node.js` file on the site root. Read [Gatsby's documentation](https://www.gatsbyjs.com/docs/how-to/custom-configuration/add-custom-webpack-config/#examples)\nfor an example, and refer to [Webpacks's documentation](https://webpack.js.org/configuration/cache/)\nif you want to understand how its caching system works.\n## Troubleshooting\n\n### Viewing Logs\n\nBuild, deploy and application logs for an environment are available using the\nplatform cli. If you want logs for an environment other than the currently\nchecked-out branch (e.g. for a pull request), you must use the `-e` flag. You\ncan first get a list of all available environments by running\n```\nplatform env:list\n```\nYou can then use the identifier from the first column in the commands below.\nIf you want logs from the environment associated with your current local\nbranch, you can omit the `-e` flag.\n\n- Tail/print most recent build log (this now includes deploy log):\n  ```\n  platform activity:log -e <env-id>\n  ```\n  Note that you may have to wait a few moments after performing\n  a git push in order for the new p.sh deployment to begin.\n- Print deploy logs for all builds to the edit environment:\n  ```\n  platform log -e <env-id> -A edit deploy <--lines n>\n  ```\n  (where n is the number of lines.)\n- View or tail application logs for the edit environment\n  ```\n  platform log -e <env-id> -A edit app <--lines n> <--tail>\n  ```\n\nAlternatively, you can visit [the platform.sh console](https://console.platform.sh/webalerts/abcdefghi) and locate\nyour build to view the build log (deployment and application logs\nare only available from the command line).\n\n### Hints\n\n- If the `platform` command is not found, you probably have to run\n  `source .bashrc` to ensure it is in your path.\n- For all deployments in which the app is restarted, the environment may not be\n  fully available for up to a minute after the deployment is complete.\n- You may see errors in the application log relating to insufficient file\n  watchers. This is a known issue. Currently the only workaround is to reduce\n  the number of active environments.\n- Public URLs for an environment are available by running\n  ```\n  platform url -e <env-id>\n  ```\n- There are many other useful platform cli subcommands.  Run `platform list`\n  to see them all.\n\n## Deploying bodiless packages from a private registry\n\nBy default the public regisry will be used to download bodiless packages: //registry.npmjs.org/\n\nIn order to switch to a private registry follow Step 3 (Create platform.sh environment variables.) of this doc.\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/johnsonandjohnson/bodiless-js/issues"},"_id":"@asemirsk/psh@1.0.1-beta.6","_nodeVersion":"16.13.2","_npmVersion":"lerna/4.0.0/node@v16.13.2+x64 (linux)","dist":{"integrity":"sha512-T7fCmGHvzSs8jXrcjcUK2Owc61RDvT202DQ3C4f4BqHc/ta8JGS0rKTXNFQEAdk70yXKcqfeHOdUw4vy9CXwLA==","shasum":"e2c68c0b39ab7759ee37e42bdb3b0824ba0b4a1f","tarball":"https://registry.npmjs.org/@asemirsk/psh/-/psh-1.0.1-beta.6.tgz","fileCount":14,"unpackedSize":65394,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICU7/O+1bDCEDFB+dzXPoaxe1rUQ8qIM6q5fx9PR5mlOAiEAha69+J+XBCxghq55GT/0ZfI0Z46qQa3O8yf5syJWJjo="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiUJVsACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoZJxAAja7hCjZsLTiYuoq5t/aZhh9rH4iI/nu/DzZI3cWvf2jAI3NY\r\nXGUuVrYaxYZbTqbLZTQU0RCgWVHKzHVrd12k1tyMd2C8UQTRfOygICuLb5pO\r\nvBD3q4EMTgDHjZ3fmU8bQxNhIKjSDGvb6yBjzcIT6Q+oOWe/rSSminGqezLM\r\npbDheAXdyGxvUdjcZTcehzNV7M+jLLttUKHW2BUAg10fM+VSPqcG3c+j9ImP\r\n8jx50m224VrL+EaHc/bk+gKlV3fjA9CIiGAFQrA9JeeawDVDmUT8Q1bWytw6\r\n6xzNlXH5DlQRID7i3BWVlkaxfuiiu5vHABd66RdD0s1ivpUwWidHq6QG0bzX\r\npUwajvCza+c8xjats//b+39xviSTEw+FoiUv82PZXIakI0oSgPR2lZOI68qG\r\nu1nHCmr6UDSiB4ioYuAc+2//M+O6rFCNwIqrX+t1bg5hf3HisSQKpmjlhHRN\r\nV2W/Qvm9dn1IwBz7AiogmtVk+/kuyNXz1yyRv3gEiUfUPARz3RqQhp2YbLqa\r\n6MC+osjcR5rwYPYyt/8TawBZR/hDW180bF82eRmVN1YuiOd2B9xc16V3yAi1\r\ndyvFoM2EKx7EBu3KjaGkNmNWpdQC7wym0pFEvs4mgDcc8f2maRVzKDDQmcJW\r\nKBhE2IClTzOWXwXSVn9B0IKwgX+6XGql6zw=\r\n=G8GP\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"asemirsk","email":"al.semirski@gmail.com"},"maintainers":[{"name":"asemirsk","email":"al.semirski@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/psh_1.0.1-beta.6_1649448300698_0.19482098815203308"},"_hasShrinkwrap":false},"1.0.1":{"name":"@asemirsk/psh","version":"1.0.1","description":"Provides cli tool for initializing a bodiless project on platform.sh","author":{"name":"Chris Oden","email":"coden@its.jnj.com"},"homepage":"https://github.com/johnsonandjohnson/bodiless-js#readme","license":"Apache-2.0","bin":{"bodiless-psh-init":"lib/bodiless-psh-init.js"},"scripts":{"build":"tsc --version && tsc -p ./tsconfig.json ","build:watch":"npm run build -- --watch","clean":"rimraf \"lib/*\" && rimraf tsconfig.tsbuildinfo"},"directories":{"lib":"lib"},"repository":{"type":"git","url":"git+https://github.com/johnsonandjohnson/bodiless-js.git"},"publishConfig":{"access":"public"},"dependencies":{"@asemirsk/cli":"^1.0.1","copyfiles":"^2.1.1","js-yaml":"^3.13.1","lodash":"^4.17.19","rimraf":"^2.6.3"},"devDependencies":{"@types/copyfiles":"^2.1.1"},"gitHead":"b943f745d8dc223a872b770f79f3e0db78f43486","bugs":{"url":"https://github.com/johnsonandjohnson/bodiless-js/issues"},"_id":"@asemirsk/psh@1.0.1","_nodeVersion":"16.13.2","_npmVersion":"lerna/4.0.0/node@v16.13.2+x64 (linux)","dist":{"integrity":"sha512-J+6Csacq6PeeF7i+9e/1NU28r72+6apL3C4ko3K2hZ2GeBRkCudlQc6MYOB490S+Q91kx+pzRRcWGIehNH7Adg==","shasum":"29ee7ac3bfbffc6e8cf530b42d90da29dc6c383d","tarball":"https://registry.npmjs.org/@asemirsk/psh/-/psh-1.0.1.tgz","fileCount":14,"unpackedSize":65380,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAZrt2FaFkaVnP7g7q0moqPll7JnN+FSJDRUxvhHu3gfAiEA/x68d5gcanmO22qqIpqPMHdxH0vnU4KcOyriAP84OkU="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiUJaGACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo+8g/+L9Ocen3a4ri0VvwM7kGPLn62CgOyNYLxwz1/YNt4vfrxJ2/0\r\nwCGz6Wlvg9ujGFRbprChIF1eSr6cx5/vCSAIesPCI37R6g8Ny74lcOSU1nUz\r\nzr6a+vgPPgSkk1k7A75PCom89rSslHRhwBr/E3dgvQ2l3lk3ikUwogOgHU07\r\n/OZ6nE2H9tLbvchfWbnSvCJwbVvhLHNWVzaC5CqHaa0hffVWNDyOlVtUASS4\r\npeFvJMrfCo9RUNuEjK7osvyYj0N0aQQI+KmfPsfQSJsPxaiHe1TovU6OKT3c\r\nSrb/AKjrNt4ztzyif4ehHVtSnaoz3g1T41+v3wqOYncGi7d3XYS8eQ40K/SM\r\nKxnKQUDWhs1YvWN+s/N+PApSEZQlsBkxfH9U5VrNJs6S4RYUFxqztu41SNKr\r\n/HuF7ObCHERSA+X83Y/ggaRLif+JNUkwj9GuPhYylggO9tf4pQ7fC5tvLfDa\r\nYG45AHe2P8Me22VvD2nacLaAyR85bs3zGfMlGoroj3D3WKaaeOMLCdfrAw/Q\r\nKfLC/tEJJ89a7Tc6CCfucwf2FGjVfTScyP5kjhCG1VrNbJxj7mtSi0O6UksN\r\nY0n8LuFl2L6Fro4AFoJV/f/zYDwjhRf1HES/mEYlGvBP6Ayt6IyzYqMm+bVX\r\nLhNJLtNOdag8fkwIAdOTiHq9Y7+aCsDqXWw=\r\n=I0Wr\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"asemirsk","email":"al.semirski@gmail.com"},"maintainers":[{"name":"asemirsk","email":"al.semirski@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/psh_1.0.1_1649448581897_0.9755491679841546"},"_hasShrinkwrap":false},"1.0.2-beta.0":{"name":"@asemirsk/psh","version":"1.0.2-beta.0","description":"Provides cli tool for initializing a bodiless project on platform.sh","author":{"name":"Chris Oden","email":"coden@its.jnj.com"},"homepage":"https://github.com/johnsonandjohnson/bodiless-js#readme","license":"Apache-2.0","bin":{"bodiless-psh-init":"lib/bodiless-psh-init.js"},"scripts":{"build":"tsc --version && tsc -p ./tsconfig.json ","build:watch":"npm run build -- --watch","clean":"rimraf \"lib/*\" && rimraf tsconfig.tsbuildinfo"},"directories":{"lib":"lib"},"repository":{"type":"git","url":"git+https://github.com/johnsonandjohnson/bodiless-js.git"},"publishConfig":{"access":"public"},"dependencies":{"@asemirsk/cli":"^1.0.2-beta.0","copyfiles":"^2.1.1","js-yaml":"^3.13.1","lodash":"^4.17.19","rimraf":"^2.6.3"},"devDependencies":{"@types/copyfiles":"^2.1.1"},"gitHead":"da62659a8fb42aa89cdc8cae2f148c8dd8db5dcb","readme":"# Bodiless integration with platform.sh\n\nThis package provides standard configuration files and helper scripts which\nmake it easy for a bodiless site to be deployed to platform.sh.\n\n## Setting up your project\n\n### Pre-requisites\n\n- Admin access to a [platform.sh](https://platform.sh/) project.\n- A service user with *admin access* to a repository in a Bitbucket Server instance.\n- The [platform.sh cli](https://docs.platform.sh/gettingstarted/cli.html)\n\n### Step 1. Gather required information\n\nTo continue, you will need the following:\n\n#### The platform.sh project key\n- Log in via the platform.sh cli.  From your local machine execute:\n  ```\n  platform login\n  ```\n  You will be directed to log in via a web browser\n- Execute\n  ```\n  platform project:list\n  ```\n  You should see a list of all projects you have access to, something like:\n  ```\n    Your projects are:\n  +---------------+-------------------------+-----------------------------------------------------+\n  | ID            | Title                   | URL                                                 |\n  +---------------+-------------------------+-----------------------------------------------------+\n  | abcdefghijklm | project_a               | https://console.platform.sh/webalerts/abcdefghijklm |\n  | lmnopqrstuvwx | project_b               | https://console.platform.sh/webalerts/lmnopqrstuvwx |\n  +---------------+-------------------------+-----------------------------------------------------+`\n  ```\n- Take note of the project ID for your project. This is the value you will use below.\n\n### Step 2. Initialize your project configuration files\n\nPlatform.sh requires several configuration files to be in place\nin your repository. This package contains default versions of these\nfiles for a BodilessJS.  To install or update them:\n\n1. Add this package as a dependency of your project:\n  ```\n  npm i --save-dev @bodiless/psh\n  ```\n2. Add the following to your `package.json` scripts:\n  ```\n  \"init-psh\": \"bodiless-psh-init\"\n  ```\n3. Install or update the configuration files:\n  ```\n  npm run init-psh\n  ```\n> When `@bodiless/psh` is installing its' files it will try to merge `static` and `edit` `*.platform.app.yaml` files based on the whitelisted keys from `packages/bodiless-psh/resources/.platform/platform.whitelist.yaml`. Only the keys that are specified in `platform.whitelist.yaml` will be merged. Merging will be performed by using the recursive algorithm to preserve any keys that are not in default `.platform.app.yaml`. Non-whitelisted keys will be ignored, and a warning message will be printed to the console.\n\n4. Commit the added configuration files to your repository.  These include\n   ```\n   static.platform.sh\n   .platform.app.yaml\n   .platform/*\n   edit/*\n   ```\n\n### Step 3. Create platform.sh environment variables.\n\nFirst, configure your local install to connect to your platform.sh project. From\nwithin your project root, execute\n```\nplatform project:set-remote {project id}\n```\nwhere {project id} is the platform.sh project id you acquired above.\n\nAll variables below should be set at the project level using the platform.sh command\nline, as described in [the platform.sh documentation](https://docs.platform.sh/development/variables.html#project-variables), and all should be visible at both build time and run time.\n\nAdd the following variables:\n\n- env:APP_GIT_REMOTE_URL -- The URL of your upstream Git repository\n- env:APP_GIT_USER -- The user to access your upstream Git repository.\n- env:APP_GIT_USER_EMAIL -- THe user email for your upstream Git repository.\n- env:APP_GIT_PW -- The user password for your upstream Git repository.\n\n\n> Be sure to specify `--sensitive true` for all credentials.\n\nExample:\n```\n$ platform variable:create\n* Level (--level)\nThe level at which to set the variable\n  [project    ] Project-wide\n  [environment] Environment-specific\n> project\n\n* Name (--name)\nThe variable name\n> APP_GIT_USER_EMAIL\n\n* Value (--value)\nThe variable's value\n> email@your.service.account\n\nJSON (--json)\nIs the value JSON-formatted? [y|N] N\n\nSensitive (--sensitive)\nIs the value sensitive? [y|N] N\n\nPrefix (--prefix)\nThe variable name's prefix\nDefault: none\n  [none] No prefix: The variable will be part of $PLATFORM_VARIABLES.\n  [env:] env: The variable will be exposed directly, e.g. as $APP_GIT_USER_EMAIL.\n> env:\n\nVisible at build time (--visible-build)\nShould the variable be available at build time? [Y|n] Y\n\nVisible at runtime (--visible-runtime)\nShould the variable be available at runtime? [Y|n] Y\n\nCreating variable env:APP_GIT_USER_EMAIL on the project...\n```\n\nYou can verify that the variable was created properly by executing, eg:\n  ```\n  platform variable:get env:APP_GIT_USER_EMAIL\n  ```\n  You should see something like:\n  ```\n  $ platform variable:get env:APP_NPM_AUTH\n  +-----------------+---------------------------+\n  | Property        | Value                     |\n  +-----------------+---------------------------+\n  | id              | env:APP_GIT_USER_EMAL     |\n  | created_at      | 2019-08-09T06:48:52-04:00 |\n  | updated_at      | 2019-08-09T06:48:52-04:00 |\n  | name            | env:APP_GIT_USER_EMAIL    |\n  | attributes      | {  }                      |\n  | is_json         | false                     |\n  | is_sensitive    | false                     |\n  | visible_build   | true                      |\n  | visible_runtime | true                      |\n  | level           | project                   |\n  +-----------------+---------------------------+\n  ```\n\n#### Optional: Configure an NPM Private Registry\n\nIf you wish to install packages from a private registry, you may do so. The\npackages to be installed must be namespaced. Set the following 3 environment\nvariables on p.sh. All variables should be visible at both build and run time:\n- `env:APP_NPM_REGISTRY`: the full path to your registry, eg\n  `//my-artifactory.com/api/npm/my-registry/`.\n- `env:APP_NPM_AUTH`: Ypur NPM authentication token. This should be marked as sensitive.\n  To obtain your token:\n  1. Login to your registry:\n     ```\n     npm login --registry=https://url/of/your/private/registry\n     ```\n     Follow the prompts with the username/password/email of the account you wish\n     to use for p.sh automation.\n  2. Examine your `.npmrc` file (usually located in your home directory). You\n     should see something like\n     ```\n     //url/of/your/privateregistry/:_authToken={token}\n     ```\n  3. Copy the token value to the `env:APP_NPM_AUTH` variable in your p.sh project.\n\n- `env:APP_NPM_NAMESPACE`: The namespace of the packages in your private\n  regsitry, eg `@mynamespace`.\n\n### Step 4. Configure the platform.sh Git Service integration.\n\nPlatform.sh provides out-of-the-box integrations with many popular Git service providers.\nWe have tested with Bitbucket Server and GitHub.\n\nNote that you must have admin access to the repository in order to configure the integration.\n\n#### GitHub\n\nFrom your project root, execute `platform integration:add` and follow\nthe prompts, as:\n\n```\n$ platform integration:add\n* Integration type (--type)\nEnter a number to choose:\n  [0] bitbucket\n  [1] bitbucket_server\n  [2] github\n  [3] gitlab\n  [4] hipchat\n  [5] webhook\n  [6] health.email\n  [7] health.pagerduty\n  [8] health.slack\n  [9] health.webhook\n> 2\n\n* Token (--token)\nAn access token for the integration\n> {your GitHub personal access token}\n\n* Repository (--repository)\nThe repository (e.g. 'foo/bar')\n> johnsonandjohnson/Bodiless-JS\n\nBuild pull requests (--build-pull-requests)\nBuild every pull request as an environment? [Y|n] Y\n\nBuild pull requests post-merge (--build-pull-requests-post-merge)\nBuild pull requests based on their post-merge state? [y|N] y\n\nClone data for pull requests (--pull-requests-clone-parent-data)\nClone the parent environment's data for pull requests? [Y|n] n\n\nFetch branches (--fetch-branches)\nFetch all branches from the remote (as inactive environments)? [Y|n] y\n\nPrune branches (--prune-branches)\nDelete branches that do not exist on the remote? [Y|n] y\n\nWarning: adding a 'github' integration will automatically synchronize code from the external Git repository.\nThis means it can overwrite all the code in your project.\n\nAre you sure you want to continue? [y/N] y\nChecking webhook configuration on the repository: johnsonandjohnson/Bodiless-JS\n  Creating new webhook\n  Webhook created successfully\nCreated integration xxxxxxxx (type: github)\n+---------------------------+--------------------------------------------------------------------+\n| Property                  | Value                                                              |\n+---------------------------+--------------------------------------------------------------------+\n| id                        | xxxxxxx                                                            |\n| type                      | github                                                             |\n| token                     | ******                                                             |\n| base_url                  |                                                                    |\n| repository                | foo/bar                                                            |\n| fetch_branches            | true                                                               |\n| prune_branches            | true                                                               |\n| build_pull_requests       | true                                                               |\n| build_pull_requests_post_ | true                                                               |\n| merge                     |                                                                    |\n| pull_requests_clone_paren | false                                                              |\n| t_data                    |                                                                    |\n| hook_url                  | https://us-2.platform.sh/api/projects/jvaff4bu65vgm/integrations/4 |\n|                           | 4zqv2kqqfcgq/hook                                                  |\n+---------------------------+--------------------------------------------------------------------+\n```\n\n#### Bitbucket Server\n\nFrom your project root, execute `platform integration:add` and follow\nthe prompts, as:\n\n```bash\n$ platform integration:add\n* Integration type (--type)\nEnter a number to choose:\n  [0] bitbucket\n  [1] bitbucket_server\n  [2] github\n  [3] gitlab\n  [4] hipchat\n  [5] webhook\n  [6] health.email\n  [7] health.pagerduty\n  [8] health.slack\n> 1\n\n* Username (--username)\nThe Bitbucket Server username\n> {bitbukcet service username}\n\n* Token (--token)\nAn access token for the integration\n> {bitbucket service user password}\n\n* Repository (--repository)\nThe repository (e.g. 'foo/bar')\n> {project/repository, eg: foo/bar}\n\nBuild pull requests (--build-pull-requests)\nBuild every pull request as an environment? [Y|n] N\n\nClone data for pull requests (--pull-requests-clone-parent-data)\nClone the parent environments data for pull requests? [Y|n] Y\n\nFetch branches (--fetch-branches)\nFetch all branches from the remote (as inactive environments)? [Y|n] Y\n\nPrune branches (--prune-branches)\nDelete branches that do not exist on the remote? [Y|n] Y\n\nWarning: adding a 'bitbucket_server' integration will automatically synchronize code from the external Git repository.\nThis means it can overwrite all the code in your project.\n\nAre you sure you want to continue? [y/N] y\n```\n\n##### Verify the integration\n\n##### GitHub\n- Visit the \"webhooks\" section of your bitbucket repository settings, eg\n  ```\n  https://github.com/project/repo/settings/hooks\n  ```\n  and verify that a webhook to platform.sh has been added. Note you will need admin access\n  to the project in order to view the webhooks.\n- Activate a branch in your project (as described below) and validate that an environment\n  is created and deployed to platform.sh. *Note you must first push the branch to bitbucket*.\n- Issue a PR to your repository and verify that the PR branch is deployed.\n\n##### Bitbucket Server\n- Visit the \"webhooks\" section of your bitbucket repository settings, eg\n  ```\n  https://domain/plugins/servlet/webhooks/projects/{project-key}/repos/{repo-name}\n  ```\n  and verify that a webhook to platform.sh has been added. Note you will need admin access\n  to the project in order to view the webhooks.\n- Activate a branch in your project (as described below) and validate that an environment\n  is created and deployed to platform.sh. *Note you must first push the branch to bitbucket*.\n- Issue a PR to your repository and verify that the PR branch is deployed (note that only\n  the static environment will be build for PR's on Bitbucket).\n\n### Customizing Hook Implementations\n\nThis package includes default implementations of platform.sh\n[build and deploy hooks](https://docs.platform.sh/configuration/app/build.html#hooks) which\nshould work for most Bodiless sites.  However, should your site have special needs, you can\ncustomize by creating a `platform.custom.sh` or `static.platform.custom.sh` script and placing\nit alongside the appropriate `.platform.app.yaml` file (at the root of your repository for the\nstatic site, or in the `/edit` directory for the edit app).  In this script, you can define for\neach platform.sh hook one of the following functions:\n\n- `prepare_{hook} ()` - Run before the default implementation of the hook.\n- `hook ()` - Replaces the default implementation of the hook.\n- `finalize_{hook} ()` - Run after the default implementation of the hook.\n\nIf you wish to extend the default implementation, you can do so by calling it from your function.\nTo do this safely (ie to avoid errors if the default implementation doesn't exist) always use the\n`invoke` helper:\n\n```bash\nprepare_deploy () {\n  invoke default_prepare_deploy\n  # Your custom logic here...\n}\n```\n\n## Building and Deploying\n\n### Continuous Integration\n\nIf you configured platform.sh to build pull requests, then every PR to your repository will be\ndeployed to its own environment. Be aware of the following:\n- It is easy to reach your quota of development environments with this enabled, so use cautiously.\n- Edit environments for pull requests are currently only supported on GitHub -- and pushing changes\n  from the edit environment is not supported even there.\n- On Bitbucket Server, pull requests from *forks* will not automatically rebuild when new commits\n  are added.  This limitation does not apply to GitHub.\n- On both GitHub and Bitbucket, changes pushed to code outside the `/edit` directory will\n  not automatically be deployed to the edit environment.  You must manually update the\n  edit environment as described under [Pushing Changes](#pushing-changes) below.\n- Pull request environments will be automatically deleted when the PR is merged or declined.\n- If you manually delete a PR environment, it will not be recreated when the PR is\n  updated.\n- PR environments are named simply `pr-{pr#}` (eg `pr-123`).  You can easily run platform cli\n  commands against them using the `-e pr-xxx` option.\n- A link to the p.sh environment will be posted to the PR:\n  - **GitHub**: Expand the \"Show All Checks\" link next to the section on the \"Conversations\"\n    tab, and click the \"details\" link next to the platform.sh build.\n  - **Bitbucket Server**: Click the build status icon next to the PR title, and then click the\n    \"platform.sh\" link.\n\n### Manual Deployments\n\n#### Pre-requisites\n\n- Access to a [platform.sh](https://platform.sh/) project.\n- The [platform.sh cli](https://docs.platform.sh/gettingstarted/cli.html)\n\n#### Local setup\n\n- Obtain the project key of the project you wish to deploy: see\n  [The platform.sh project key](#the-platform.sh-project-key), above.\n- Connect your local repository to the correct platform.sh remote. From within the repository root:\n  ```\n  platform project:set-remote {project id}\n  ```\n\n#### Initial deployment of a new branch\n\n- Ensure you are on the correct branch locally.\n- Push the branch to bitbucket.\n  ```\n  git push origin <branch>\n  ```\n- Execute\n    ```\n    platform env:activate\n    ```\n  Note - you may have to wait a few moments after pushing the branch to\n  bitbucket before activating the environment, in order to allow the branch to\n  sync to p.sh. If, when you try to activate, you are asked for an \"Environment\n  ID\", wait a bit and try again.\n- The public URL of the new environment will be printed to the console.\n- You can display (and open) the public URLs for your site by checking out the\n  corresponding branch and executing `platform url`.\n\n##### Basic Authentication\n\nNote that basic authentication may be configured for your environment by\ndefault, and this may prevent access via your browser. To verify, use the\nplatform cli:\n```\nplatform env:http-access\n```\n\nYou can also use this command to enable or disable authentication, and to\nadd/remove credentials.\n```\nplatform help env:http-access\n```\nto learn more.\n\n#### Pushing changes\n\nOnce a new branch is created, changes pushed to Bitbucket will be automatically\ndeployed to the static site on platform.sh. You can run `platform activity:log`\nto see the current build status, or visit [console.platform.sh](https://console.platform.sh),\nlocate your build, and click \"View Logs\".\n\nChanges are *not* automatically deployed to an edit environment; you must manually\ntrigger an update of the edit environment by executing:\n  ```\n  platform ssh -e <env-id> 'bash platform.sh deploy'\n  ```\n\n  You may omit the \"-e <env-id>\" if you have the active branch checked out locally.\n\n#### Deleting an environment\n\nThe platform.sh environment will be deleted when you remove the corresponding\nbranch from bitbucket. *Please delete obsolete branches*.\n\nYou can also remove an environment without deleting your branch by checking\nout the branch locally and executing `platform env:delete -y`.\n\n#### Merging to main\n\nWhen you merge a feature branch to main, the updated main branch will be automatically deployed\nto the static environment on platform.sh.  To deploy changes to the edit environment, you must follow the same process as in [Pushing Changes](#pushing-changes) above.\n\n\n## Handling Redirect with Routes\n\n### Overview\nIn HTTP, URL redirecting is a technique to forward one URL to a different URL. It is commonly used for handling cases like URL shortening, preventing broken links when pages removed, pointing multiple domain addresses to a single URL address, etc. It is also critical to preserve page SEO value when there are URL changes.\n\nRedirection can be implemented on a client page with [Refresh Meta Tag](https://en.wikipedia.org/wiki/Meta_refresh) or JavaScript, but the preferred way is to manage redirect rules with server configuration.\n\nYou can configure redirects on Platform.sh with route yaml in project environments. A route describes how an incoming HTTP request is processed by Platform.sh, which includes URL redirect. The routes are defined inside .platform/routes.yaml file.\n\nAn example of redirect using routes.yaml:\n```\n\"https://www.{default}/\":\n  type: redirect\n  to: \"https://my-host.{default}/\"\n```\n\nHere, the URL https://www.example.com/ will be redirected to https://my-host.example.com/\n\n### Whole-route vs Partial redirects\nPlatform.sh offers two different ways to implement redirect rules, **Whole-route redirects** and **Partial redirects**\n\n* Whole-route redirects on host level. A typical use case for this kind of route is adding or removing a www. prefix to domain,\n\n  .platform/routes.yaml\n  ```\n  https://{default}/:\n    type: redirect\n    to: https://www.{default}/\n  ```\n\n  Here, https://example.com/ will be redirected to https://www.example.com/. This approach can be used to redirect vanity domains to their destination URLs.\n\n* Partial redirects allows redirect rules to be added to existing routes,\n\n  .platform/routes.yaml\n  ```\n      https://{default}/:\n        # [...]\n        redirects:\n          expires: 1d\n          paths:\n            '/from':\n              to: 'https://example.com/'\n              code: 301\n  ```\n\n  Here, \"https://[domain name]/from\" will be redirected to https://www.example.com/.\n\n  Note:\n  * the default response code is 302, in order to use a different response code, mostly commonly 301, add \"code: 301\" as configurable option.\n  * \"expires\" param is optional, it specifies duration the redirect will be cached. Examples of valid values include 3600s, 1d, 2w, 3m.\n\n\n  **Examples**\n\n  file .platform/routes.yaml\n\n  1. Redirect path \"/foo/bar\" to a different site \"https://example.com/\".\n\n      ```\n      https://{default}/:\n        type: upstream\n        redirects:\n          paths:\n            '/foo/bar':\n              to: 'https://example.com/'\n      ```\n\n  1.  Using Regular Expression to redirect path that matches \"/foo/(.*)/bar\" pattern.\n\n      ```\n      https://{default}/:\n        type: upstream\n        redirects:\n          paths:\n            '/foo/(.*)/bar':\n              to: '/$1'\n              regexp: true\n      ```\n\n      In this case, path \"/foo/cards/bar\" will be redirected to \"/cards\".\n\n  1. Redirect with prefix.\n\n      ```\n      https://{default}/:\n        type: upstream\n        redirects:\n          paths:\n            '/foo/bar':\n              to: '/new'\n              prefix: true\n\n      ```\n\n      Path \"/foo/bar\" will be redirected to \"/new\". And path \"/foo/bar/to/my/path\" will be redirected to \"/new/to/my/path\" where both the path and all its children included. If \"prefix\" set to false, only \"/foo/bar\" will be redirected to \"/new\".\n\n\n  1. Carry over suffix path with append_suffix option.\n\n      ```\n        https://{default}/:\n          type: upstream\n          redirects:\n            paths:\n              '/foo/bar':\n                to: 'https://{default}/new'\n                append_suffix: false\n\n      ```\n\n      If append_suffix is set to false, \"/foo/bar/to/my/path\" will be redirected to \"/new\". Otherwise, \"/foo/bar/to/my/path\" will be redirects to \"/new/to/my/path\". append_suffix is ignored if 'prefix' is false or 'regexp' is true.\n\n\n### HTTP vs HTTPS\n\nPlatform.sh recommends using HTTPS requests for all sites exclusively. Specifying HTTPS in route.yaml will automatically redirect any requests for an HTTP URL to HTTPS. While specifying only HTTP routes will result in duplicate HTTPS routes being created automatically, allowing the site to be served from both HTTP and HTTPS without redirects.\n\nAlthough it is not recommended, HTTPS requests can be redirected to HTTP explicitly to serve the site over HTTP only using route.yaml:\n\n```\n\"https://{default}/\":\n  type: redirect\n  to: \"http://{default}/\"\n```\n\n### Avoid redirect chains\n\nA redirect chain is a series of redirects between the initial URL and the destination URL. The redirect chain could be built over time of development or due to a combination of redirect between different protocol, host name or trailing slash processing etc. Redirect chain causes page loss authority value in search result. It also increases page load time and decreases the overall quality of site.\n\nIn order to avoid redirect chains, pay attention on destination path protocol and host name. For example, if the site is running under https and host www, specify destination \"to\" in route.yaml as:\n```\n  to: \"https://www.{default}/path/to/destination/\"\n```\n\nThe trailing slash should be appended to the configure item if platform environment adds trailing slash to url by default.\nsee [Platform.sh Documentation Redirects](https://docs.platform.sh/configuration/routes/redirects.html)\n\n### Generate redirect rules for migration sites\n\nBodilessJS [Site Migration Tool](https://github.com/johnsonandjohnson/Bodiless-JS/tree/main/packages/bodiless-migration-tool) package comes with a feature that allows user to export site redirection into file. See [Tools/Migration](/#/Tools/Migration?id=configuration) for configuration.\n\nUser can apply these exported redirect rules to routers.yaml before deploying to platform.sh.\n\n```yaml\n\"https://{default}/\":\n    type: upstream\n    upstream: \"static:http\"\n    redirects:\n      paths:\n        /image/redirect.png:\n          to: /image/placeholder.png\n          code: 301\n        /page2:\n          to: /page3\n          code: 301\n```\n\n## Using Fastly CDN\n\nPlatform.sh integrates with Fastly via EZ platform for Fastly.  \n\n1. Obtain your Fastly Service ID & Key from Fastly.   \n1. Once Fastly Service ID & Key is obtained, these variables can be set at Main environment.\n    ```\n    platform variable:create -e main --level environment env:HTTPCACHE_PURGE_TYPE --value 'fastly'\n    platform variable:create -e main --level environment env:FASTLY_SERVICE_ID --value 'YOUR_ID_HERE'\n    platform variable:create -e main --level environment env:FASTLY_KEY --value 'YOUR_ID_HERE'\n    ```\n1. Verify or Update your `routes.yaml` to enable caching for your site by setting `enabled: true`\n    ```\n        cache:\n            enabled: true\n            cookies: []\n    ```\n1. Verify or Update your `.platform.app.yaml` expiration time for your files.\n    ```\n    web:\n        locations:\n            '/':\n                expires: 6h  \n    ```\n\nOnce completed, the main env deployed on Platform.sh should be on Fastly CDN.  You may have to fine tune the expires setting for your static resources and set certain ones (ones identify not to change often such as font files) to longer to leverage browser caching.\n\nPlatform.sh References:\n* [Set Fastly Credentials on Platform.sh](https://docs.platform.sh/frameworks/ibexa/fastly.html#set-credentials-on-platformsh)\n* [HTTP Cache](https://docs.platform.sh/configuration/routes/cache.html)\n* [Router Cache](https://docs.platform.sh/languages/php/tuning.html#ensure-that-the-router-cache-is-properly-configured)\n* [Expires](https://docs.platform.sh/configuration/app/web.html#locations)\n* [How to Guide: How to configure caching for static assets](https://community.platform.sh/t/how-to-configure-caching-for-static-assets/187)\n\n\nIf there are issues or you need to troubleshoot, here are some good resources:\n* [Checking Fastly Cache](https://docs.fastly.com/en/guides/checking-cache)\n\n    ``` curl -svo /dev/null -H \"Fastly-Debug:1\" www.example.com/index.html ```\n* [Purging Fastly Cache](https://docs.fastly.com/api/purge)\n\n    ``` curl -X PURGE www.example.com/index.html ```\n\n## How to load environment specific html snippets\n\nWhen you want to inject different html snippets depending on your environment type, you can use Server Side Includes (SSI) mechanism.\n### Activate SSI\n\n* Activate SSI for your route(s) in your routes.yaml file. See: https://docs.platform.sh/configuration/routes/ssi.html\n* Use SSI_ENV enviroment variable to specify type of your environment. Default value is 'dev'.\n* Ensure ssi configs are loaded to psh container and set SSI_CONF_PATH environment variable to path to json file containing SSI configs.\n* Ensure your .platform.app.yaml contains invocation of generate-ssi-files.js node scripts. The script should be invoked during build and deploy phases. PSH phase (build or deploy) should be passed as an argument to the script.\n* Ensure the files of you app, that will be served by psh, contain SSI directives.\n* Ensure a writable volume is mounted to your app.\n\n### SSI config format\n\nSSI configuration file should be in json format.\n\n```\n{\n  key1: {\n    pragma: \"<!--# ssi data should go here -->\",\n    env1: {\n      file: \"key1.env1.html\"\n    }\n    ...\n    envN: {\n      file: \"key1.envN.html\"\n    }\n  }\n  ...\n  keyN: {\n    pragma: \"<!--# ssi data should go here -->\",\n    ...\n    env1: {\n      file: \"keyN.envN.html\"\n    }\n    ...\n    envN: {\n      file: \"keyN.envN.html\"\n    }\n  }\n}\n```\n### How it works\n\n* during build phase, generate-ssi-files reads SSI configs and for each key it creates symlink from PLATFORM_DOCUMENT_ROOT/filename.html into APP_VOLUME/filename.html. Filename is generated based on key. There is an opportunity to improve this logic. We can read and parse pragma field, exract filename from it. But it makes the things more complicated and in addition, pragma may not have files at all.\n* during deploy phase, generate-ssi-files reads SSI configs and SSI_ENV and for each key it copies the file defined in conf.{key}.{env}.{file} to APP_VOLUME/filename.html that was created during build phase.\n\n## How to replace your site prod url with psh environment url in a public file\n\nIf you want to make urls in a particular public file match psh environment url, you can leverage psh-url-replacer node script. For instance, your site sitemap.xml, which is generated during build time, contains production urls and you want to replace the production url with psh environment url, to which your website is deployed to.\n\n### Why\n\nPlatform.sh does not allow to expose environment level environment variables to the application build stage.\n\n### How it works\n\non psh build stage:\n\n- it moves your source file from public dir to a tmp directory\n- then it creates a symlink from a writable volume file to the source public file\n\non psh deploy stage:\n\n- it copies the file from the tmp directory to the writable volume file\n- then it replaces production url with psh environment url in the file\n\n### How to activate this feature\n\nBy default, the feature is activated for sitemap.xml and robots.txt. If you want to activate the feature for some other files or if you have custom installation of sitemap.xml or robots.txt, please follow the following steps:\n\n1. ensure writable volume mounting is configured for your app\n\n1. export environment variables and invoke psh-url-replacer in build section of your psh app .platform.app.yaml\n\n```bash\n\nhooks:\n    build: |\n        export PSH_URL_REPLACER_SRC_FILE=/path/to/your/src/public/file\n        export PSH_URL_REPLACER_TMP_FILE=/path/to/a/tmp/file\n        export PSH_URL_REPLACER_TARGET_FILE=/path/to/writable/volume/file\n        node /path/to/psh-url-replacer.js build\n\n```\n\n1. export environment variables and invoke psh-url-replacer in deploy section of your psh app .platform.app.yaml\n\n```bash\n\nhooks:\n    deploy: |\n        export PSH_URL_REPLACER_TMP_FILE=/path/to/the/tmp/file/you/saved/during/build/phase\n        export PSH_URL_REPLACER_TARGET_FILE=/path/to/writable/volume/file\n        export PSH_URL_REPLACER_SRC_URL=https://your-site-production-url.com\n        export PSH_URL_REPLACER_TARGET_URL=https://your-psh-env.url.site\n        export PSH_URL_REPLACER_PROD_ENV='0' # set to '1' if you want to disable the replacement\n        node /path/to/psh-url-replacer.js deploy\n```\n\n## Known limitations\n\n### General\n- PR Branches and Feature branches created in bitbucket will always inherit from\n  main. This means that you must manually configure basic authentication for\n  these branches if you want them protected from the public internet.\n- There is a 64-character limit on hostnames for TLS, and platform.sh uses 43 of\n  them. Since hostnames are created based on branch names, and since the edit\n  environment uses an additional 5 (\"edit.\"), your branch names should be\n  limited to a maximum of 16 characters to avoid certificate warnings.\n- When you create a bitbucket integration, a webhook is added to your bitbucket\n  repository. However, deleting the integration does not remove the webhook, you\n  must do this manually.\n### Environment memory\nOn development environments, the `edit` site environment can use a large amount\nof memory when running, which might cause out-of-memory issues when building \npages. This is caused by webpack's caching system, and there are two ways\nto circumvent the issue:\n\n#### Increasing container memory\nUse [Large development containers](https://docs.platform.sh/overview/pricing.html#development)\nto increase the total memory available to containers. This is the preferred way \nto solve this problem, as it's easier and faster. Note that this will increase costs.\n\n#### Disable build cache\nDisabling webpack's cache will drastically reduce memory consumption, but\nwill also increase build times. This might be specially noticeable when doing\nsimple operations like creating, cloning or moving pages.\n\nTo disable a site's cache, add `cache: false` to its webpack configuration. This\nis done in the `gatsby-node.js` file on the site root. Read [Gatsby's documentation](https://www.gatsbyjs.com/docs/how-to/custom-configuration/add-custom-webpack-config/#examples)\nfor an example, and refer to [Webpacks's documentation](https://webpack.js.org/configuration/cache/)\nif you want to understand how its caching system works.\n## Troubleshooting\n\n### Viewing Logs\n\nBuild, deploy and application logs for an environment are available using the\nplatform cli. If you want logs for an environment other than the currently\nchecked-out branch (e.g. for a pull request), you must use the `-e` flag. You\ncan first get a list of all available environments by running\n```\nplatform env:list\n```\nYou can then use the identifier from the first column in the commands below.\nIf you want logs from the environment associated with your current local\nbranch, you can omit the `-e` flag.\n\n- Tail/print most recent build log (this now includes deploy log):\n  ```\n  platform activity:log -e <env-id>\n  ```\n  Note that you may have to wait a few moments after performing\n  a git push in order for the new p.sh deployment to begin.\n- Print deploy logs for all builds to the edit environment:\n  ```\n  platform log -e <env-id> -A edit deploy <--lines n>\n  ```\n  (where n is the number of lines.)\n- View or tail application logs for the edit environment\n  ```\n  platform log -e <env-id> -A edit app <--lines n> <--tail>\n  ```\n\nAlternatively, you can visit [the platform.sh console](https://console.platform.sh/webalerts/abcdefghi) and locate\nyour build to view the build log (deployment and application logs\nare only available from the command line).\n\n### Hints\n\n- If the `platform` command is not found, you probably have to run\n  `source .bashrc` to ensure it is in your path.\n- For all deployments in which the app is restarted, the environment may not be\n  fully available for up to a minute after the deployment is complete.\n- You may see errors in the application log relating to insufficient file\n  watchers. This is a known issue. Currently the only workaround is to reduce\n  the number of active environments.\n- Public URLs for an environment are available by running\n  ```\n  platform url -e <env-id>\n  ```\n- There are many other useful platform cli subcommands.  Run `platform list`\n  to see them all.\n\n## Deploying bodiless packages from a private registry\n\nBy default the public regisry will be used to download bodiless packages: //registry.npmjs.org/\n\nIn order to switch to a private registry follow Step 3 (Create platform.sh environment variables.) of this doc.\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/johnsonandjohnson/bodiless-js/issues"},"_id":"@asemirsk/psh@1.0.2-beta.0","_nodeVersion":"16.13.2","_npmVersion":"lerna/4.0.0/node@v16.13.2+x64 (linux)","dist":{"integrity":"sha512-RaHyooP8CMEyeK0tKydNlND4dtGhAvlhPtgYUtLEZbqs7GqLTs8rDraIbRDiUOXjnXVYYkzatVvReDrq/8TYbw==","shasum":"baf1b9701cb189c1c0c31321e6e6312d9817a300","tarball":"https://registry.npmjs.org/@asemirsk/psh/-/psh-1.0.2-beta.0.tgz","fileCount":14,"unpackedSize":65394,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCX6g1Ca2obTxt+9QeRhovW9CXKr3n8YOJ5lJ0h1hOd1wIgBr41ZcruKOFlLm6yJXD/GJSpZP993QwRbcfRN9EMuso="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiUJi8ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrQDg/+OWeQ2Pv1J2nnNTemdDAlezZvv0l/QHvcx6hNHbBQT0hULEXH\r\nJiSms/P9Yh7XtsUKVYBoeWJOvUkef/dF2z873EwahbtbOAUaZv9hQBhhK/OU\r\nLkbGiXBfe12ab0W9yYweltfpodjcefF69da6MMPgQwLWsFegCACc4jqSSiU4\r\nEOWLCF8mXUrW4gNJkqaig+BYlhGkxQrrsVd/mnXALv4qoHMWxC3gle8caXAf\r\nkU+csxEQRj4ty96PeEfxcp9U45kvlZdRyjbtzO3tLOgdh+kcPhNOMoTJWMyd\r\nLEZWhuvIkO1eK28BHG1fD/8Lhn7APngntecFbgyhOePfmTUlnww9biMuJyYs\r\n6+WcmZkyeFG9+otZNmAAEBGcAFAbEJAFhaixLp5+3r9Kvy6qaUpOGyPAfWYR\r\niEbUaZN9072oLoLy91z1MvlGP43Z09iOZROaonnC7g+WW0u7ZhigvuctVOAz\r\nfnMUYyLx+nlLCqUqq6m+nUfBpDXJFNVbaGedMt/EDm88j2LDkDghhRQga2/p\r\nHPGpUwnhcz8t1wyG6tf0Ona+eshMByhsQmn6JXmItbm0Nevl5rTx47mlBTeW\r\nWBd0jFLAZh5zTUwFsxYV56VqwmlfeDTXnJEGNK5+L6S2oNT0ciYzeEq/H/Vw\r\nBzt4kL2a6fbV5oafUk+1paVOi0JSYSjDtKA=\r\n=BrY0\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"asemirsk","email":"al.semirski@gmail.com"},"maintainers":[{"name":"asemirsk","email":"al.semirski@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/psh_1.0.2-beta.0_1649449148647_0.3978332237937914"},"_hasShrinkwrap":false},"1.0.2":{"name":"@asemirsk/psh","version":"1.0.2","description":"Provides cli tool for initializing a bodiless project on platform.sh","author":{"name":"Chris Oden","email":"coden@its.jnj.com"},"homepage":"https://github.com/johnsonandjohnson/bodiless-js#readme","license":"Apache-2.0","bin":{"bodiless-psh-init":"lib/bodiless-psh-init.js"},"scripts":{"build":"tsc --version && tsc -p ./tsconfig.json ","build:watch":"npm run build -- --watch","clean":"rimraf \"lib/*\" && rimraf tsconfig.tsbuildinfo"},"directories":{"lib":"lib"},"repository":{"type":"git","url":"git+https://github.com/johnsonandjohnson/bodiless-js.git"},"publishConfig":{"access":"public"},"dependencies":{"@asemirsk/cli":"^1.0.2","copyfiles":"^2.1.1","js-yaml":"^3.13.1","lodash":"^4.17.19","rimraf":"^2.6.3"},"devDependencies":{"@types/copyfiles":"^2.1.1"},"gitHead":"19cad7cb078a3029c7b40248078ddfa4d413bdcc","bugs":{"url":"https://github.com/johnsonandjohnson/bodiless-js/issues"},"_id":"@asemirsk/psh@1.0.2","_nodeVersion":"16.13.2","_npmVersion":"lerna/4.0.0/node@v16.13.2+x64 (linux)","dist":{"integrity":"sha512-N9N5jCoT61nkYMYXUDL9tRNEbX6NuKacny2XBmyHs05aAEW6xMkG+a77ndjkLtpcKRI8w5HilpcMGrZCbgL+yA==","shasum":"fb308c80b8a7ee61ae1d1adb57ad81dcad6a2ae1","tarball":"https://registry.npmjs.org/@asemirsk/psh/-/psh-1.0.2.tgz","fileCount":14,"unpackedSize":65380,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDfdZs55DaXCatfrxigkh/HY/V3m+04ALd6IHWAJjqbRgIgHSB1OVlQg1LX4kSpnYYEQXd0tWDtG+ijZ1EnM/tzmPM="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiUJl8ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoHkxAAiSGoVlRcDAoW/HSidWzX5MH8YMOm9PzibNg5M5Is2wMTysID\r\ncvQd8Ol8f2OVl8b7sorMPe5cPXgDqIddNgqvKRp1DEhd+ycVEktyG/KQEDL/\r\nANoB40mFmvIYab6kYADS4hdrPaUX+WMoSwKYJZlAeMsu3nS+ihOpqhoe7PSv\r\nZYHJK3x7XAg6+hMbDgZOqmVnExmPO5yEtCSP8GHSPvZsyOZREy1GT0HUcoEF\r\nH67nNyBZnD1BDyPijlNHLRdfMmiA7yT9RS9Ro55A/Czzkh+PxcdpQuVKkset\r\nozx17QQTIA1xbIy3uN0a92LOLvyhaeo+yoq0h7THzgVKM/YJyjNyvYnTHrOJ\r\nH2SE5YAWzPy9K5Z66YKsXkhdCFeAiJzkm1FtAsrD1vUEQHY0MElrIFClFWnl\r\n0UoOjM6wTIt5eHT1D9Vab+dm3cN4a/BamhYSSbmRF08nPCIzmUBsjRP4l9vK\r\n4pKC8SE7fiWmG+zgjGicWnA1ptF3zpaEQWw8ZbwU5F88y0Qbzl0iuEX0k21w\r\nVpv/zuPl+kkW8Z4rLpO9JfzlqhINeYgUv9eG4l0uS2RlNRGCiQH8XS77ccI2\r\nmdfimVHElj1b86b0/PRVzq6V8bKpSKFraW7TiNnz5lMExPha/ou5F945rKtc\r\nlq1hCPOK9qim5vaYqvwLzmFqufehoXjTWHM=\r\n=q1AC\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"asemirsk","email":"al.semirski@gmail.com"},"maintainers":[{"name":"asemirsk","email":"al.semirski@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/psh_1.0.2_1649449340075_0.31214151151960134"},"_hasShrinkwrap":false},"1.1.0":{"name":"@asemirsk/psh","version":"1.1.0","description":"Provides cli tool for initializing a bodiless project on platform.sh","author":{"name":"Chris Oden","email":"coden@its.jnj.com"},"homepage":"https://github.com/johnsonandjohnson/bodiless-js#readme","license":"Apache-2.0","bin":{"bodiless-psh-init":"lib/bodiless-psh-init.js"},"scripts":{"build":"tsc --version && tsc -p ./tsconfig.json ","build:watch":"npm run build -- --watch","clean":"rimraf \"lib/*\" && rimraf tsconfig.tsbuildinfo"},"directories":{"lib":"lib"},"repository":{"type":"git","url":"git+https://github.com/johnsonandjohnson/bodiless-js.git"},"publishConfig":{"access":"public"},"dependencies":{"@asemirsk/cli":"^1.1.0","copyfiles":"^2.1.1","js-yaml":"^3.13.1","lodash":"^4.17.19","rimraf":"^2.6.3"},"devDependencies":{"@types/copyfiles":"^2.1.1"},"gitHead":"e767bae774cc17eba5d92b638b7628cdc9236086","bugs":{"url":"https://github.com/johnsonandjohnson/bodiless-js/issues"},"_id":"@asemirsk/psh@1.1.0","_nodeVersion":"16.13.2","_npmVersion":"lerna/4.0.0/node@v16.13.2+x64 (linux)","dist":{"integrity":"sha512-47VrXhFIDl5jLsVxzR95tVudkljJ2po22qTkAc0t4D11cpYJCIj0ZZYzOIrJK47aPBfQLYzVrdjqZw7BWT2YWA==","shasum":"053b932831d0042c3387153d543a055f698875db","tarball":"https://registry.npmjs.org/@asemirsk/psh/-/psh-1.1.0.tgz","fileCount":15,"unpackedSize":66331,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDICSZAUOoVQlbuhISCGvppbqtqFDgg9ICVju2kvzwDHwIhAPSAS1ytGJUrzv1lMz8Z4f9oA/T3pLaQjuo7QC1eleb+"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiXtAcACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqhXg//RjpDHWTD6/pwYwPplOzxuYi9qLA2U12tfRnZxFKQQkAySPN4\r\nGPaI6Yl3IMMZ/QNyVUQHCoxOt44iTg2XjNXA0mC5lku0m1b14dpO31wF1qbE\r\nYujiSL8ERqgDUM4aYmxzl+RI6yMEbH+87R8mIoNdgI0Yunaj2SEZzteMHEsd\r\nSiyZANK9OeO2CKvNAEA5VDLjtvSLqF12//MzUyecc7TqWIgXyq378gj2w1rn\r\nClzaWd2qt1+U7hEiXX3mWBkDktPXSsPtmw9vMoQsrDwBbQIZaZ+jX7W9K/Ac\r\n8EjHhI/PeHZ7YoiB8XET2JzCv9J5Mwjwa0XVd9doQqAvcr7js6my7LM45TLY\r\nha87wGqHn1GNyBqpU+/hRgSi2j0xkX0cAB0Bz/9f7CP5nvwcp9ckIMNHyTn6\r\nLuqCTSMVdfwRsYOD/TIT7R5KjlQ0ollFu2nJ92u89rbT7WqcZEm41vf4QJCK\r\nT8ifUjdx5GfPssXDn/zD+KBxUKnyo0WJp8B6Ru2trCYqRiNrn9FFyzmN5Kng\r\nhDVQtsUhQ0+3YNq4dnsVMBbSRzu2oaANScVJrQbQU7pt6X4AwMd/6/k79FAt\r\nnbZ9o1ltXJHMTP3BwK6sQNSvPGsAxNp2PC9gFKN8Mlcv2ezOsuOux9Bk/d9T\r\n2aRpy/ATnXYGSlsyN1WfE1fgJ+OITO9fx9k=\r\n=3Bl+\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"asemirsk","email":"al.semirski@gmail.com"},"maintainers":[{"name":"asemirsk","email":"al.semirski@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/psh_1.1.0_1650380828518_0.9549323064706228"},"_hasShrinkwrap":false},"1.0.0-canary-24-22.0":{"name":"@asemirsk/psh","version":"1.0.0-canary-24-22.0","description":"Provides cli tool for initializing a bodiless project on platform.sh","author":{"name":"Chris Oden","email":"coden@its.jnj.com"},"homepage":"https://github.com/johnsonandjohnson/bodiless-js#readme","license":"Apache-2.0","bin":{"bodiless-psh-init":"lib/bodiless-psh-init.js"},"scripts":{"build":"run-p build:lib","build:lib":"tsc -p ./tsconfig.json","build:watch":"npm run build:lib -- --watch","clean":"rimraf \"lib/*\" && rimraf tsconfig.tsbuildinfo"},"directories":{"lib":"lib"},"repository":{"type":"git","url":"git+https://github.com/johnsonandjohnson/bodiless-js.git"},"publishConfig":{"access":"public"},"dependencies":{"copyfiles":"^2.1.1","js-yaml":"^3.13.1","lodash":"^4.17.19","rimraf":"^2.6.3"},"devDependencies":{"@types/copyfiles":"^2.1.1"},"gitHead":"a48e91c77704024ccd08e24d4f85d1cd6971ccb1","readme":"# Bodiless integration with platform.sh\n\nThis package provides standard configuration files and helper scripts which\nmake it easy for a bodiless site to be deployed to platform.sh.\n\n## Setting up your project\n\n### Pre-requisites\n\n- Admin access to a [platform.sh](https://platform.sh/) project.\n- A service user with *admin access* to a repository in a Bitbucket Server instance.\n- The [platform.sh cli](https://docs.platform.sh/gettingstarted/cli.html)\n\n### Step 1. Gather required information\n\nTo continue, you will need the following:\n\n#### The platform.sh project key\n- Log in via the platform.sh cli.  From your local machine execute:\n  ```\n  platform login\n  ```\n  You will be directed to log in via a web browser\n- Execute\n  ```\n  platform project:list\n  ```\n  You should see a list of all projects you have access to, something like:\n  ```\n    Your projects are:\n  +---------------+-------------------------+-----------------------------------------------------+\n  | ID            | Title                   | URL                                                 |\n  +---------------+-------------------------+-----------------------------------------------------+\n  | abcdefghijklm | project_a               | https://console.platform.sh/webalerts/abcdefghijklm |\n  | lmnopqrstuvwx | project_b               | https://console.platform.sh/webalerts/lmnopqrstuvwx |\n  +---------------+-------------------------+-----------------------------------------------------+`\n  ```\n- Take note of the project ID for your project. This is the value you will use below.\n\n### Step 2. Initialize your project configuration files\n\nPlatform.sh requires several configuration files to be in place\nin your repository. This package contains default versions of these\nfiles for a BodilessJS.  To install or update them:\n\n1. Add this package as a dependency of your project:\n  ```\n  npm i --save-dev @bodiless/psh\n  ```\n2. Add the following to your `package.json` scripts:\n  ```\n  \"init-psh\": \"bodiless-psh-init\"\n  ```\n3. Install or update the configuration files:\n  ```\n  npm run init-psh\n  ```\n> When `@bodiless/psh` is installing its' files it will try to merge `static` and `edit` `*.platform.app.yaml` files based on the whitelisted keys from `packages/bodiless-psh/resources/.platform/platform.whitelist.yaml`. Only the keys that are specified in `platform.whitelist.yaml` will be merged. Merging will be performed by using the recursive algorithm to preserve any keys that are not in default `.platform.app.yaml`. Non-whitelisted keys will be ignored, and a warning message will be printed to the console.\n\n4. Commit the added configuration files to your repository.  These include\n   ```\n   static.platform.sh\n   .platform.app.yaml\n   .platform/*\n   edit/*\n   ```\n\n### Step 3. Create platform.sh environment variables.\n\nFirst, configure your local install to connect to your platform.sh project. From\nwithin your project root, execute\n```\nplatform project:set-remote {project id}\n```\nwhere {project id} is the platform.sh project id you acquired above.\n\nAll variables below should be set at the project level using the platform.sh command\nline, as described in [the platform.sh documentation](https://docs.platform.sh/development/variables.html#project-variables), and all should be visible at both build time and run time.\n\nAdd the following variables:\n\n- env:APP_GIT_REMOTE_URL -- The URL of your upstream Git repository\n- env:APP_GIT_USER -- The user to access your upstream Git repository.\n- env:APP_GIT_USER_EMAIL -- THe user email for your upstream Git repository.\n- env:APP_GIT_PW -- The user password for your upstream Git repository.\n\n\n> Be sure to specify `--sensitive true` for all credentials.\n\nExample:\n```\n$ platform variable:create\n* Level (--level)\nThe level at which to set the variable\n  [project    ] Project-wide\n  [environment] Environment-specific\n> project\n\n* Name (--name)\nThe variable name\n> APP_GIT_USER_EMAIL\n\n* Value (--value)\nThe variable's value\n> email@your.service.account\n\nJSON (--json)\nIs the value JSON-formatted? [y|N] N\n\nSensitive (--sensitive)\nIs the value sensitive? [y|N] N\n\nPrefix (--prefix)\nThe variable name's prefix\nDefault: none\n  [none] No prefix: The variable will be part of $PLATFORM_VARIABLES.\n  [env:] env: The variable will be exposed directly, e.g. as $APP_GIT_USER_EMAIL.\n> env:\n\nVisible at build time (--visible-build)\nShould the variable be available at build time? [Y|n] Y\n\nVisible at runtime (--visible-runtime)\nShould the variable be available at runtime? [Y|n] Y\n\nCreating variable env:APP_GIT_USER_EMAIL on the project...\n```\n\nYou can verify that the variable was created properly by executing, eg:\n  ```\n  platform variable:get env:APP_GIT_USER_EMAIL\n  ```\n  You should see something like:\n  ```\n  $ platform variable:get env:APP_NPM_AUTH\n  +-----------------+---------------------------+\n  | Property        | Value                     |\n  +-----------------+---------------------------+\n  | id              | env:APP_GIT_USER_EMAL     |\n  | created_at      | 2019-08-09T06:48:52-04:00 |\n  | updated_at      | 2019-08-09T06:48:52-04:00 |\n  | name            | env:APP_GIT_USER_EMAIL    |\n  | attributes      | {  }                      |\n  | is_json         | false                     |\n  | is_sensitive    | false                     |\n  | visible_build   | true                      |\n  | visible_runtime | true                      |\n  | level           | project                   |\n  +-----------------+---------------------------+\n  ```\n\n#### Optional: Configure an NPM Private Registry\n\nIf you wish to install packages from a private registry, you may do so. The\npackages to be installed must be namespaced. Set the following 3 environment\nvariables on p.sh. All variables should be visible at both build and run time:\n- `env:APP_NPM_REGISTRY`: the full path to your registry, eg\n  `//my-artifactory.com/api/npm/my-registry/`.\n- `env:APP_NPM_AUTH`: Ypur NPM authentication token. This should be marked as sensitive.\n  To obtain your token:\n  1. Login to your registry:\n     ```\n     npm login --registry=https://url/of/your/private/registry\n     ```\n     Follow the prompts with the username/password/email of the account you wish\n     to use for p.sh automation.\n  2. Examine your `.npmrc` file (usually located in your home directory). You\n     should see something like\n     ```\n     //url/of/your/privateregistry/:_authToken={token}\n     ```\n  3. Copy the token value to the `env:APP_NPM_AUTH` variable in your p.sh project.\n\n- `env:APP_NPM_NAMESPACE`: The namespace of the packages in your private\n  regsitry, eg `@mynamespace`.\n\n### Step 4. Configure the platform.sh Git Service integration.\n\nPlatform.sh provides out-of-the-box integrations with many popular Git service providers.\nWe have tested with Bitbucket Server and GitHub.\n\nNote that you must have admin access to the repository in order to configure the integration.\n\n#### GitHub\n\nFrom your project root, execute `platform integration:add` and follow\nthe prompts, as:\n\n```\n$ platform integration:add\n* Integration type (--type)\nEnter a number to choose:\n  [0] bitbucket\n  [1] bitbucket_server\n  [2] github\n  [3] gitlab\n  [4] hipchat\n  [5] webhook\n  [6] health.email\n  [7] health.pagerduty\n  [8] health.slack\n  [9] health.webhook\n> 2\n\n* Token (--token)\nAn access token for the integration\n> {your GitHub personal access token}\n\n* Repository (--repository)\nThe repository (e.g. 'foo/bar')\n> johnsonandjohnson/Bodiless-JS\n\nBuild pull requests (--build-pull-requests)\nBuild every pull request as an environment? [Y|n] Y\n\nBuild pull requests post-merge (--build-pull-requests-post-merge)\nBuild pull requests based on their post-merge state? [y|N] y\n\nClone data for pull requests (--pull-requests-clone-parent-data)\nClone the parent environment's data for pull requests? [Y|n] n\n\nFetch branches (--fetch-branches)\nFetch all branches from the remote (as inactive environments)? [Y|n] y\n\nPrune branches (--prune-branches)\nDelete branches that do not exist on the remote? [Y|n] y\n\nWarning: adding a 'github' integration will automatically synchronize code from the external Git repository.\nThis means it can overwrite all the code in your project.\n\nAre you sure you want to continue? [y/N] y\nChecking webhook configuration on the repository: johnsonandjohnson/Bodiless-JS\n  Creating new webhook\n  Webhook created successfully\nCreated integration xxxxxxxx (type: github)\n+---------------------------+--------------------------------------------------------------------+\n| Property                  | Value                                                              |\n+---------------------------+--------------------------------------------------------------------+\n| id                        | xxxxxxx                                                            |\n| type                      | github                                                             |\n| token                     | ******                                                             |\n| base_url                  |                                                                    |\n| repository                | foo/bar                                                            |\n| fetch_branches            | true                                                               |\n| prune_branches            | true                                                               |\n| build_pull_requests       | true                                                               |\n| build_pull_requests_post_ | true                                                               |\n| merge                     |                                                                    |\n| pull_requests_clone_paren | false                                                              |\n| t_data                    |                                                                    |\n| hook_url                  | https://us-2.platform.sh/api/projects/jvaff4bu65vgm/integrations/4 |\n|                           | 4zqv2kqqfcgq/hook                                                  |\n+---------------------------+--------------------------------------------------------------------+\n```\n\n#### Bitbucket Server\n\nFrom your project root, execute `platform integration:add` and follow\nthe prompts, as:\n\n```bash\n$ platform integration:add\n* Integration type (--type)\nEnter a number to choose:\n  [0] bitbucket\n  [1] bitbucket_server\n  [2] github\n  [3] gitlab\n  [4] hipchat\n  [5] webhook\n  [6] health.email\n  [7] health.pagerduty\n  [8] health.slack\n> 1\n\n* Username (--username)\nThe Bitbucket Server username\n> {bitbukcet service username}\n\n* Token (--token)\nAn access token for the integration\n> {bitbucket service user password}\n\n* Repository (--repository)\nThe repository (e.g. 'foo/bar')\n> {project/repository, eg: foo/bar}\n\nBuild pull requests (--build-pull-requests)\nBuild every pull request as an environment? [Y|n] N\n\nClone data for pull requests (--pull-requests-clone-parent-data)\nClone the parent environments data for pull requests? [Y|n] Y\n\nFetch branches (--fetch-branches)\nFetch all branches from the remote (as inactive environments)? [Y|n] Y\n\nPrune branches (--prune-branches)\nDelete branches that do not exist on the remote? [Y|n] Y\n\nWarning: adding a 'bitbucket_server' integration will automatically synchronize code from the external Git repository.\nThis means it can overwrite all the code in your project.\n\nAre you sure you want to continue? [y/N] y\n```\n\n##### Verify the integration\n\n##### GitHub\n- Visit the \"webhooks\" section of your bitbucket repository settings, eg\n  ```\n  https://github.com/project/repo/settings/hooks\n  ```\n  and verify that a webhook to platform.sh has been added. Note you will need admin access\n  to the project in order to view the webhooks.\n- Activate a branch in your project (as described below) and validate that an environment\n  is created and deployed to platform.sh. *Note you must first push the branch to bitbucket*.\n- Issue a PR to your repository and verify that the PR branch is deployed.\n\n##### Bitbucket Server\n- Visit the \"webhooks\" section of your bitbucket repository settings, eg\n  ```\n  https://domain/plugins/servlet/webhooks/projects/{project-key}/repos/{repo-name}\n  ```\n  and verify that a webhook to platform.sh has been added. Note you will need admin access\n  to the project in order to view the webhooks.\n- Activate a branch in your project (as described below) and validate that an environment\n  is created and deployed to platform.sh. *Note you must first push the branch to bitbucket*.\n- Issue a PR to your repository and verify that the PR branch is deployed (note that only\n  the static environment will be build for PR's on Bitbucket).\n\n### Customizing Hook Implementations\n\nThis package includes default implementations of platform.sh\n[build and deploy hooks](https://docs.platform.sh/configuration/app/build.html#hooks) which\nshould work for most Bodiless sites.  However, should your site have special needs, you can\ncustomize by creating a `platform.custom.sh` or `static.platform.custom.sh` script and placing\nit alongside the appropriate `.platform.app.yaml` file (at the root of your repository for the\nstatic site, or in the `/edit` directory for the edit app).  In this script, you can define for\neach platform.sh hook one of the following functions:\n\n- `prepare_{hook} ()` - Run before the default implementation of the hook.\n- `hook ()` - Replaces the default implementation of the hook.\n- `finalize_{hook} ()` - Run after the default implementation of the hook.\n\nIf you wish to extend the default implementation, you can do so by calling it from your function.\nTo do this safely (ie to avoid errors if the default implementation doesn't exist) always use the\n`invoke` helper:\n\n```bash\nprepare_deploy () {\n  invoke default_prepare_deploy\n  # Your custom logic here...\n}\n```\n\n## Building and Deploying\n\n### Continuous Integration\n\nIf you configured platform.sh to build pull requests, then every PR to your repository will be\ndeployed to its own environment. Be aware of the following:\n- It is easy to reach your quota of development environments with this enabled, so use cautiously.\n- Edit environments for pull requests are currently only supported on GitHub -- and pushing changes\n  from the edit environment is not supported even there.\n- On Bitbucket Server, pull requests from *forks* will not automatically rebuild when new commits\n  are added.  This limitation does not apply to GitHub.\n- On both GitHub and Bitbucket, changes pushed to code outside the `/edit` directory will\n  not automatically be deployed to the edit environment.  You must manually update the\n  edit environment as described under [Pushing Changes](#pushing-changes) below.\n- Pull request environments will be automatically deleted when the PR is merged or declined.\n- If you manually delete a PR environment, it will not be recreated when the PR is\n  updated.\n- PR environments are named simply `pr-{pr#}` (eg `pr-123`).  You can easily run platform cli\n  commands against them using the `-e pr-xxx` option.\n- A link to the p.sh environment will be posted to the PR:\n  - **GitHub**: Expand the \"Show All Checks\" link next to the section on the \"Conversations\"\n    tab, and click the \"details\" link next to the platform.sh build.\n  - **Bitbucket Server**: Click the build status icon next to the PR title, and then click the\n    \"platform.sh\" link.\n\n### Manual Deployments\n\n#### Pre-requisites\n\n- Access to a [platform.sh](https://platform.sh/) project.\n- The [platform.sh cli](https://docs.platform.sh/gettingstarted/cli.html)\n\n#### Local setup\n\n- Obtain the project key of the project you wish to deploy: see\n  [The platform.sh project key](#the-platform.sh-project-key), above.\n- Connect your local repository to the correct platform.sh remote. From within the repository root:\n  ```\n  platform project:set-remote {project id}\n  ```\n\n#### Initial deployment of a new branch\n\n- Ensure you are on the correct branch locally.\n- Push the branch to bitbucket.\n  ```\n  git push origin <branch>\n  ```\n- Execute\n    ```\n    platform env:activate\n    ```\n  Note - you may have to wait a few moments after pushing the branch to\n  bitbucket before activating the environment, in order to allow the branch to\n  sync to p.sh. If, when you try to activate, you are asked for an \"Environment\n  ID\", wait a bit and try again.\n- The public URL of the new environment will be printed to the console.\n- You can display (and open) the public URLs for your site by checking out the\n  corresponding branch and executing `platform url`.\n\n##### Basic Authentication\n\nNote that basic authentication may be configured for your environment by\ndefault, and this may prevent access via your browser. To verify, use the\nplatform cli:\n```\nplatform env:http-access\n```\n\nYou can also use this command to enable or disable authentication, and to\nadd/remove credentials.\n```\nplatform help env:http-access\n```\nto learn more.\n\n#### Pushing changes\n\nOnce a new branch is created, changes pushed to Bitbucket will be automatically\ndeployed to the static site on platform.sh. You can run `platform activity:log`\nto see the current build status, or visit [console.platform.sh](https://console.platform.sh),\nlocate your build, and click \"View Logs\".\n\nChanges are *not* automatically deployed to an edit environment; you must manually\ntrigger an update of the edit environment by executing:\n  ```\n  platform ssh -e <env-id> 'bash platform.sh deploy'\n  ```\n\n  You may omit the \"-e <env-id>\" if you have the active branch checked out locally.\n\n#### Deleting an environment\n\nThe platform.sh environment will be deleted when you remove the corresponding\nbranch from bitbucket. *Please delete obsolete branches*.\n\nYou can also remove an environment without deleting your branch by checking\nout the branch locally and executing `platform env:delete -y`.\n\n#### Merging to main\n\nWhen you merge a feature branch to main, the updated main branch will be automatically deployed\nto the static environment on platform.sh.  To deploy changes to the edit environment, you must follow the same process as in [Pushing Changes](#pushing-changes) above.\n\n\n## Handling Redirect with Routes\n\n### Overview\nIn HTTP, URL redirecting is a technique to forward one URL to a different URL. It is commonly used for handling cases like URL shortening, preventing broken links when pages removed, pointing multiple domain addresses to a single URL address, etc. It is also critical to preserve page SEO value when there are URL changes.\n\nRedirection can be implemented on a client page with [Refresh Meta Tag](https://en.wikipedia.org/wiki/Meta_refresh) or JavaScript, but the preferred way is to manage redirect rules with server configuration.\n\nYou can configure redirects on Platform.sh with route yaml in project environments. A route describes how an incoming HTTP request is processed by Platform.sh, which includes URL redirect. The routes are defined inside .platform/routes.yaml file.\n\nAn example of redirect using routes.yaml:\n```\n\"https://www.{default}/\":\n  type: redirect\n  to: \"https://my-host.{default}/\"\n```\n\nHere, the URL https://www.example.com/ will be redirected to https://my-host.example.com/\n\n### Whole-route vs Partial redirects\nPlatform.sh offers two different ways to implement redirect rules, **Whole-route redirects** and **Partial redirects**\n\n* Whole-route redirects on host level. A typical use case for this kind of route is adding or removing a www. prefix to domain,\n\n  .platform/routes.yaml\n  ```\n  https://{default}/:\n    type: redirect\n    to: https://www.{default}/\n  ```\n\n  Here, https://example.com/ will be redirected to https://www.example.com/. This approach can be used to redirect vanity domains to their destination URLs.\n\n* Partial redirects allows redirect rules to be added to existing routes,\n\n  .platform/routes.yaml\n  ```\n      https://{default}/:\n        # [...]\n        redirects:\n          expires: 1d\n          paths:\n            '/from':\n              to: 'https://example.com/'\n              code: 301\n  ```\n\n  Here, \"https://[domain name]/from\" will be redirected to https://www.example.com/.\n\n  Note:\n  * the default response code is 302, in order to use a different response code, mostly commonly 301, add \"code: 301\" as configurable option.\n  * \"expires\" param is optional, it specifies duration the redirect will be cached. Examples of valid values include 3600s, 1d, 2w, 3m.\n\n\n  **Examples**\n\n  file .platform/routes.yaml\n\n  1. Redirect path \"/foo/bar\" to a different site \"https://example.com/\".\n\n      ```\n      https://{default}/:\n        type: upstream\n        redirects:\n          paths:\n            '/foo/bar':\n              to: 'https://example.com/'\n      ```\n\n  1.  Using Regular Expression to redirect path that matches \"/foo/(.*)/bar\" pattern.\n\n      ```\n      https://{default}/:\n        type: upstream\n        redirects:\n          paths:\n            '/foo/(.*)/bar':\n              to: '/$1'\n              regexp: true\n      ```\n\n      In this case, path \"/foo/cards/bar\" will be redirected to \"/cards\".\n\n  1. Redirect with prefix.\n\n      ```\n      https://{default}/:\n        type: upstream\n        redirects:\n          paths:\n            '/foo/bar':\n              to: '/new'\n              prefix: true\n\n      ```\n\n      Path \"/foo/bar\" will be redirected to \"/new\". And path \"/foo/bar/to/my/path\" will be redirected to \"/new/to/my/path\" where both the path and all its children included. If \"prefix\" set to false, only \"/foo/bar\" will be redirected to \"/new\".\n\n\n  1. Carry over suffix path with append_suffix option.\n\n      ```\n        https://{default}/:\n          type: upstream\n          redirects:\n            paths:\n              '/foo/bar':\n                to: 'https://{default}/new'\n                append_suffix: false\n\n      ```\n\n      If append_suffix is set to false, \"/foo/bar/to/my/path\" will be redirected to \"/new\". Otherwise, \"/foo/bar/to/my/path\" will be redirects to \"/new/to/my/path\". append_suffix is ignored if 'prefix' is false or 'regexp' is true.\n\n\n### HTTP vs HTTPS\n\nPlatform.sh recommends using HTTPS requests for all sites exclusively. Specifying HTTPS in route.yaml will automatically redirect any requests for an HTTP URL to HTTPS. While specifying only HTTP routes will result in duplicate HTTPS routes being created automatically, allowing the site to be served from both HTTP and HTTPS without redirects.\n\nAlthough it is not recommended, HTTPS requests can be redirected to HTTP explicitly to serve the site over HTTP only using route.yaml:\n\n```\n\"https://{default}/\":\n  type: redirect\n  to: \"http://{default}/\"\n```\n\n### Avoid redirect chains\n\nA redirect chain is a series of redirects between the initial URL and the destination URL. The redirect chain could be built over time of development or due to a combination of redirect between different protocol, host name or trailing slash processing etc. Redirect chain causes page loss authority value in search result. It also increases page load time and decreases the overall quality of site.\n\nIn order to avoid redirect chains, pay attention on destination path protocol and host name. For example, if the site is running under https and host www, specify destination \"to\" in route.yaml as:\n```\n  to: \"https://www.{default}/path/to/destination/\"\n```\n\nThe trailing slash should be appended to the configure item if platform environment adds trailing slash to url by default.\nsee [Platform.sh Documentation Redirects](https://docs.platform.sh/configuration/routes/redirects.html)\n\n### Generate redirect rules for migration sites\n\nBodilessJS [Site Migration Tool](https://github.com/johnsonandjohnson/Bodiless-JS/tree/main/packages/bodiless-migration-tool) package comes with a feature that allows user to export site redirection into file. See [Tools/Migration](/#/Tools/Migration?id=configuration) for configuration.\n\nUser can apply these exported redirect rules to routers.yaml before deploying to platform.sh.\n\n```yaml\n\"https://{default}/\":\n    type: upstream\n    upstream: \"static:http\"\n    redirects:\n      paths:\n        /image/redirect.png:\n          to: /image/placeholder.png\n          code: 301\n        /page2:\n          to: /page3\n          code: 301\n```\n\n## Using Fastly CDN\n\nPlatform.sh integrates with Fastly via EZ platform for Fastly.  \n\n1. Obtain your Fastly Service ID & Key from Fastly.   \n1. Once Fastly Service ID & Key is obtained, these variables can be set at Main environment.\n    ```\n    platform variable:create -e main --level environment env:HTTPCACHE_PURGE_TYPE --value 'fastly'\n    platform variable:create -e main --level environment env:FASTLY_SERVICE_ID --value 'YOUR_ID_HERE'\n    platform variable:create -e main --level environment env:FASTLY_KEY --value 'YOUR_ID_HERE'\n    ```\n1. Verify or Update your `routes.yaml` to enable caching for your site by setting `enabled: true`\n    ```\n        cache:\n            enabled: true\n            cookies: []\n    ```\n1. Verify or Update your `.platform.app.yaml` expiration time for your files.\n    ```\n    web:\n        locations:\n            '/':\n                expires: 6h  \n    ```\n\nOnce completed, the main env deployed on Platform.sh should be on Fastly CDN.  You may have to fine tune the expires setting for your static resources and set certain ones (ones identify not to change often such as font files) to longer to leverage browser caching.\n\nPlatform.sh References:\n* [Set Fastly Credentials on Platform.sh](https://docs.platform.sh/frameworks/ibexa/fastly.html#set-credentials-on-platformsh)\n* [HTTP Cache](https://docs.platform.sh/configuration/routes/cache.html)\n* [Router Cache](https://docs.platform.sh/languages/php/tuning.html#ensure-that-the-router-cache-is-properly-configured)\n* [Expires](https://docs.platform.sh/configuration/app/web.html#locations)\n* [How to Guide: How to configure caching for static assets](https://community.platform.sh/t/how-to-configure-caching-for-static-assets/187)\n\n\nIf there are issues or you need to troubleshoot, here are some good resources:\n* [Checking Fastly Cache](https://docs.fastly.com/en/guides/checking-cache)\n\n    ``` curl -svo /dev/null -H \"Fastly-Debug:1\" www.example.com/index.html ```\n* [Purging Fastly Cache](https://docs.fastly.com/api/purge)\n\n    ``` curl -X PURGE www.example.com/index.html ```\n\n## How to load environment specific html snippets\n\nWhen you want to inject different html snippets depending on your environment type, you can use Server Side Includes (SSI) mechanism.\n### Activate SSI\n\n* Activate SSI for your route(s) in your routes.yaml file. See: https://docs.platform.sh/configuration/routes/ssi.html\n* Use SSI_ENV enviroment variable to specify type of your environment. Default value is 'dev'.\n* Ensure ssi configs are loaded to psh container and set SSI_CONF_PATH environment variable to path to json file containing SSI configs.\n* Ensure your .platform.app.yaml contains invocation of generate-ssi-files.js node scripts. The script should be invoked during build and deploy phases. PSH phase (build or deploy) should be passed as an argument to the script.\n* Ensure the files of you app, that will be served by psh, contain SSI directives.\n* Ensure a writable volume is mounted to your app.\n\n### SSI config format\n\nSSI configuration file should be in json format.\n\n```\n{\n  key1: {\n    pragma: \"<!--# ssi data should go here -->\",\n    env1: {\n      file: \"key1.env1.html\"\n    }\n    ...\n    envN: {\n      file: \"key1.envN.html\"\n    }\n  }\n  ...\n  keyN: {\n    pragma: \"<!--# ssi data should go here -->\",\n    ...\n    env1: {\n      file: \"keyN.envN.html\"\n    }\n    ...\n    envN: {\n      file: \"keyN.envN.html\"\n    }\n  }\n}\n```\n### How it works\n\n* during build phase, generate-ssi-files reads SSI configs and for each key it creates symlink from PLATFORM_DOCUMENT_ROOT/filename.html into APP_VOLUME/filename.html. Filename is generated based on key. There is an opportunity to improve this logic. We can read and parse pragma field, exract filename from it. But it makes the things more complicated and in addition, pragma may not have files at all.\n* during deploy phase, generate-ssi-files reads SSI configs and SSI_ENV and for each key it copies the file defined in conf.{key}.{env}.{file} to APP_VOLUME/filename.html that was created during build phase.\n\n## How to replace your site prod url with psh environment url in a public file\n\nIf you want to make urls in a particular public file match psh environment url, you can leverage psh-url-replacer node script. For instance, your site sitemap.xml, which is generated during build time, contains production urls and you want to replace the production url with psh environment url, to which your website is deployed to.\n\n### Why\n\nPlatform.sh does not allow to expose environment level environment variables to the application build stage.\n\n### How it works\n\non psh build stage:\n\n- it moves your source file from public dir to a tmp directory\n- then it creates a symlink from a writable volume file to the source public file\n\non psh deploy stage:\n\n- it copies the file from the tmp directory to the writable volume file\n- then it replaces production url with psh environment url in the file\n\n### How to activate this feature\n\nBy default, the feature is activated for sitemap.xml and robots.txt. If you want to activate the feature for some other files or if you have custom installation of sitemap.xml or robots.txt, please follow the following steps:\n\n1. ensure writable volume mounting is configured for your app\n\n1. export environment variables and invoke psh-url-replacer in build section of your psh app .platform.app.yaml\n\n```bash\n\nhooks:\n    build: |\n        export PSH_URL_REPLACER_SRC_FILE=/path/to/your/src/public/file\n        export PSH_URL_REPLACER_TMP_FILE=/path/to/a/tmp/file\n        export PSH_URL_REPLACER_TARGET_FILE=/path/to/writable/volume/file\n        node /path/to/psh-url-replacer.js build\n\n```\n\n1. export environment variables and invoke psh-url-replacer in deploy section of your psh app .platform.app.yaml\n\n```bash\n\nhooks:\n    deploy: |\n        export PSH_URL_REPLACER_TMP_FILE=/path/to/the/tmp/file/you/saved/during/build/phase\n        export PSH_URL_REPLACER_TARGET_FILE=/path/to/writable/volume/file\n        export PSH_URL_REPLACER_SRC_URL=https://your-site-production-url.com\n        export PSH_URL_REPLACER_TARGET_URL=https://your-psh-env.url.site\n        export PSH_URL_REPLACER_PROD_ENV='0' # set to '1' if you want to disable the replacement\n        node /path/to/psh-url-replacer.js deploy\n```\n\n## Known limitations\n\n### General\n- PR Branches and Feature branches created in bitbucket will always inherit from\n  main. This means that you must manually configure basic authentication for\n  these branches if you want them protected from the public internet.\n- There is a 64-character limit on hostnames for TLS, and platform.sh uses 43 of\n  them. Since hostnames are created based on branch names, and since the edit\n  environment uses an additional 5 (\"edit.\"), your branch names should be\n  limited to a maximum of 16 characters to avoid certificate warnings.\n- When you create a bitbucket integration, a webhook is added to your bitbucket\n  repository. However, deleting the integration does not remove the webhook, you\n  must do this manually.\n### Environment memory\nOn development environments, the `edit` site environment can use a large amount\nof memory when running, which might cause out-of-memory issues when building \npages. This is caused by webpack's caching system, and there are two ways\nto circumvent the issue:\n\n#### Increasing container memory\nUse [Large development containers](https://docs.platform.sh/overview/pricing.html#development)\nto increase the total memory available to containers. This is the preferred way \nto solve this problem, as it's easier and faster. Note that this will increase costs.\n\n#### Disable build cache\nDisabling webpack's cache will drastically reduce memory consumption, but\nwill also increase build times. This might be specially noticeable when doing\nsimple operations like creating, cloning or moving pages.\n\nTo disable a site's cache, add `cache: false` to its webpack configuration. This\nis done in the `gatsby-node.js` file on the site root. Read [Gatsby's documentation](https://www.gatsbyjs.com/docs/how-to/custom-configuration/add-custom-webpack-config/#examples)\nfor an example, and refer to [Webpacks's documentation](https://webpack.js.org/configuration/cache/)\nif you want to understand how its caching system works.\n## Troubleshooting\n\n### Viewing Logs\n\nBuild, deploy and application logs for an environment are available using the\nplatform cli. If you want logs for an environment other than the currently\nchecked-out branch (e.g. for a pull request), you must use the `-e` flag. You\ncan first get a list of all available environments by running\n```\nplatform env:list\n```\nYou can then use the identifier from the first column in the commands below.\nIf you want logs from the environment associated with your current local\nbranch, you can omit the `-e` flag.\n\n- Tail/print most recent build log (this now includes deploy log):\n  ```\n  platform activity:log -e <env-id>\n  ```\n  Note that you may have to wait a few moments after performing\n  a git push in order for the new p.sh deployment to begin.\n- Print deploy logs for all builds to the edit environment:\n  ```\n  platform log -e <env-id> -A edit deploy <--lines n>\n  ```\n  (where n is the number of lines.)\n- View or tail application logs for the edit environment\n  ```\n  platform log -e <env-id> -A edit app <--lines n> <--tail>\n  ```\n\nAlternatively, you can visit [the platform.sh console](https://console.platform.sh/webalerts/abcdefghi) and locate\nyour build to view the build log (deployment and application logs\nare only available from the command line).\n\n### Hints\n\n- If the `platform` command is not found, you probably have to run\n  `source .bashrc` to ensure it is in your path.\n- For all deployments in which the app is restarted, the environment may not be\n  fully available for up to a minute after the deployment is complete.\n- You may see errors in the application log relating to insufficient file\n  watchers. This is a known issue. Currently the only workaround is to reduce\n  the number of active environments.\n- Public URLs for an environment are available by running\n  ```\n  platform url -e <env-id>\n  ```\n- There are many other useful platform cli subcommands.  Run `platform list`\n  to see them all.\n\n## Deploying bodiless packages from a private registry\n\nBy default the public regisry will be used to download bodiless packages: //registry.npmjs.org/\n\nIn order to switch to a private registry follow Step 3 (Create platform.sh environment variables.) of this doc.\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/johnsonandjohnson/bodiless-js/issues"},"_id":"@asemirsk/psh@1.0.0-canary-24-22.0","_nodeVersion":"16.13.2","_npmVersion":"lerna/4.0.0/node@v16.13.2+x64 (linux)","dist":{"integrity":"sha512-foZ9xWjKW0sizcdWGL2ybGGr5AH/ZIjKhsLnSFAGHOWWeHmUJL8Q9Cj3iTDM1IyJa+CVFfYHpHM5iY8Fgyy99g==","shasum":"45c631945f2a8afaa32af79d156369d98392c906","tarball":"https://registry.npmjs.org/@asemirsk/psh/-/psh-1.0.0-canary-24-22.0.tgz","fileCount":15,"unpackedSize":66976,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFpBbE0WLviz4feupUjIXCW8nghX09B2fcEkLNwmA671AiBJQOBYzmBQekk+22J6k5NNNfsGr2viUyFlm1CbALCt+A=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJijezbACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmok3BAAgVGMIXB6/yJLn7rhfh7PNS6SwlycIzOgVuCY4tN3GEUK+kdG\r\na/GPhxK3sQilQ0jmvW+D8FKvyTJMgkaw8qTzlDMyxQ37Zbm/cQSXcN5GG3c4\r\nLkDNnM1QNgGBiS4g9ItO6xT34aVpCpbFDhirUO/iq3YpLJSf8MspzUK8z4F3\r\nu/dbOwp+c5t2ohESQBfPjtqr+f9VqIJI3uivG9Uu4UvIuFrqAwbb5O3e2aIs\r\nTxgF1YyBavqP7xE84LEXBEbaE4k8+MdH5iuR8qAzsevtPRGPR3a83UiDNBjc\r\n6R7z8e6dELLPZxVFkzMQcGKiF1GU+iIeJ1slfQpLc6ahqEqdS3xwyn5h38zx\r\nq9fQ1vcjOKGSeSZY3G/ywTSZTFj6vMlU5RSvDqp1E1SxBC/uUPQEOXwzMus9\r\n7iJsVAUEvZdB/te6OMmEShgfFQzQrfWbcf3+k7U9CHSDk9Ethf3yYbUSUq8N\r\ne9o6o/T7iGFvZ7jNGMfx1Dm+QyMdFGjcGFC5/kt5h7yCYYLZEKSIJj8EuZyU\r\nOy7142ElU9IBXW0wpkiAzqZXaRG2AVACdhJVogLtXGLvz8q666/n88YZvlp6\r\nnEYJNXNgKSLyPPCON+TKHEsBo8rCTxyuNOb/tDqAyLmjtOX3fu//bAlMGhp4\r\n0SIugiOBpSlVnPyEG55QSuJSb00DjZrey+U=\r\n=2lvP\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"asemirsk","email":"al.semirski@gmail.com"},"maintainers":[{"name":"asemirsk","email":"al.semirski@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/psh_1.0.0-canary-24-22.0_1653468379767_0.7925609050431783"},"_hasShrinkwrap":false},"1.0.0-canary-24-23.0":{"name":"@asemirsk/psh","version":"1.0.0-canary-24-23.0","description":"Provides cli tool for initializing a bodiless project on platform.sh","author":{"name":"Chris Oden","email":"coden@its.jnj.com"},"homepage":"https://github.com/johnsonandjohnson/bodiless-js#readme","license":"Apache-2.0","bin":{"bodiless-psh-init":"lib/bodiless-psh-init.js"},"scripts":{"build":"run-p build:lib","build:lib":"tsc -p ./tsconfig.json","build:watch":"npm run build:lib -- --watch","clean":"rimraf \"lib/*\" && rimraf tsconfig.tsbuildinfo"},"directories":{"lib":"lib"},"repository":{"type":"git","url":"git+https://github.com/johnsonandjohnson/bodiless-js.git"},"publishConfig":{"access":"public"},"dependencies":{"copyfiles":"^2.1.1","js-yaml":"^3.13.1","lodash":"^4.17.19","rimraf":"^2.6.3"},"devDependencies":{"@types/copyfiles":"^2.1.1"},"gitHead":"2cab1eaf4ac4d1a8ef3ef53ba3228ff16f7504eb","readme":"# Bodiless integration with platform.sh\n\nThis package provides standard configuration files and helper scripts which\nmake it easy for a bodiless site to be deployed to platform.sh.\n\n## Setting up your project\n\n### Pre-requisites\n\n- Admin access to a [platform.sh](https://platform.sh/) project.\n- A service user with *admin access* to a repository in a Bitbucket Server instance.\n- The [platform.sh cli](https://docs.platform.sh/gettingstarted/cli.html)\n\n### Step 1. Gather required information\n\nTo continue, you will need the following:\n\n#### The platform.sh project key\n- Log in via the platform.sh cli.  From your local machine execute:\n  ```\n  platform login\n  ```\n  You will be directed to log in via a web browser\n- Execute\n  ```\n  platform project:list\n  ```\n  You should see a list of all projects you have access to, something like:\n  ```\n    Your projects are:\n  +---------------+-------------------------+-----------------------------------------------------+\n  | ID            | Title                   | URL                                                 |\n  +---------------+-------------------------+-----------------------------------------------------+\n  | abcdefghijklm | project_a               | https://console.platform.sh/webalerts/abcdefghijklm |\n  | lmnopqrstuvwx | project_b               | https://console.platform.sh/webalerts/lmnopqrstuvwx |\n  +---------------+-------------------------+-----------------------------------------------------+`\n  ```\n- Take note of the project ID for your project. This is the value you will use below.\n\n### Step 2. Initialize your project configuration files\n\nPlatform.sh requires several configuration files to be in place\nin your repository. This package contains default versions of these\nfiles for a BodilessJS.  To install or update them:\n\n1. Add this package as a dependency of your project:\n  ```\n  npm i --save-dev @asemirsk/psh\n  ```\n2. Add the following to your `package.json` scripts:\n  ```\n  \"init-psh\": \"bodiless-psh-init\"\n  ```\n3. Install or update the configuration files:\n  ```\n  npm run init-psh\n  ```\n> When `@asemirsk/psh` is installing its' files it will try to merge `static` and `edit` `*.platform.app.yaml` files based on the whitelisted keys from `packages/bodiless-psh/resources/.platform/platform.whitelist.yaml`. Only the keys that are specified in `platform.whitelist.yaml` will be merged. Merging will be performed by using the recursive algorithm to preserve any keys that are not in default `.platform.app.yaml`. Non-whitelisted keys will be ignored, and a warning message will be printed to the console.\n\n4. Commit the added configuration files to your repository.  These include\n   ```\n   static.platform.sh\n   .platform.app.yaml\n   .platform/*\n   edit/*\n   ```\n\n### Step 3. Create platform.sh environment variables.\n\nFirst, configure your local install to connect to your platform.sh project. From\nwithin your project root, execute\n```\nplatform project:set-remote {project id}\n```\nwhere {project id} is the platform.sh project id you acquired above.\n\nAll variables below should be set at the project level using the platform.sh command\nline, as described in [the platform.sh documentation](https://docs.platform.sh/development/variables.html#project-variables), and all should be visible at both build time and run time.\n\nAdd the following variables:\n\n- env:APP_GIT_REMOTE_URL -- The URL of your upstream Git repository\n- env:APP_GIT_USER -- The user to access your upstream Git repository.\n- env:APP_GIT_USER_EMAIL -- THe user email for your upstream Git repository.\n- env:APP_GIT_PW -- The user password for your upstream Git repository.\n\n\n> Be sure to specify `--sensitive true` for all credentials.\n\nExample:\n```\n$ platform variable:create\n* Level (--level)\nThe level at which to set the variable\n  [project    ] Project-wide\n  [environment] Environment-specific\n> project\n\n* Name (--name)\nThe variable name\n> APP_GIT_USER_EMAIL\n\n* Value (--value)\nThe variable's value\n> email@your.service.account\n\nJSON (--json)\nIs the value JSON-formatted? [y|N] N\n\nSensitive (--sensitive)\nIs the value sensitive? [y|N] N\n\nPrefix (--prefix)\nThe variable name's prefix\nDefault: none\n  [none] No prefix: The variable will be part of $PLATFORM_VARIABLES.\n  [env:] env: The variable will be exposed directly, e.g. as $APP_GIT_USER_EMAIL.\n> env:\n\nVisible at build time (--visible-build)\nShould the variable be available at build time? [Y|n] Y\n\nVisible at runtime (--visible-runtime)\nShould the variable be available at runtime? [Y|n] Y\n\nCreating variable env:APP_GIT_USER_EMAIL on the project...\n```\n\nYou can verify that the variable was created properly by executing, eg:\n  ```\n  platform variable:get env:APP_GIT_USER_EMAIL\n  ```\n  You should see something like:\n  ```\n  $ platform variable:get env:APP_NPM_AUTH\n  +-----------------+---------------------------+\n  | Property        | Value                     |\n  +-----------------+---------------------------+\n  | id              | env:APP_GIT_USER_EMAL     |\n  | created_at      | 2019-08-09T06:48:52-04:00 |\n  | updated_at      | 2019-08-09T06:48:52-04:00 |\n  | name            | env:APP_GIT_USER_EMAIL    |\n  | attributes      | {  }                      |\n  | is_json         | false                     |\n  | is_sensitive    | false                     |\n  | visible_build   | true                      |\n  | visible_runtime | true                      |\n  | level           | project                   |\n  +-----------------+---------------------------+\n  ```\n\n#### Optional: Configure an NPM Private Registry\n\nIf you wish to install packages from a private registry, you may do so. The\npackages to be installed must be namespaced. Set the following 3 environment\nvariables on p.sh. All variables should be visible at both build and run time:\n- `env:APP_NPM_REGISTRY`: the full path to your registry, eg\n  `//my-artifactory.com/api/npm/my-registry/`.\n- `env:APP_NPM_AUTH`: Ypur NPM authentication token. This should be marked as sensitive.\n  To obtain your token:\n  1. Login to your registry:\n     ```\n     npm login --registry=https://url/of/your/private/registry\n     ```\n     Follow the prompts with the username/password/email of the account you wish\n     to use for p.sh automation.\n  2. Examine your `.npmrc` file (usually located in your home directory). You\n     should see something like\n     ```\n     //url/of/your/privateregistry/:_authToken={token}\n     ```\n  3. Copy the token value to the `env:APP_NPM_AUTH` variable in your p.sh project.\n\n- `env:APP_NPM_NAMESPACE`: The namespace of the packages in your private\n  regsitry, eg `@mynamespace`.\n\n### Step 4. Configure the platform.sh Git Service integration.\n\nPlatform.sh provides out-of-the-box integrations with many popular Git service providers.\nWe have tested with Bitbucket Server and GitHub.\n\nNote that you must have admin access to the repository in order to configure the integration.\n\n#### GitHub\n\nFrom your project root, execute `platform integration:add` and follow\nthe prompts, as:\n\n```\n$ platform integration:add\n* Integration type (--type)\nEnter a number to choose:\n  [0] bitbucket\n  [1] bitbucket_server\n  [2] github\n  [3] gitlab\n  [4] hipchat\n  [5] webhook\n  [6] health.email\n  [7] health.pagerduty\n  [8] health.slack\n  [9] health.webhook\n> 2\n\n* Token (--token)\nAn access token for the integration\n> {your GitHub personal access token}\n\n* Repository (--repository)\nThe repository (e.g. 'foo/bar')\n> johnsonandjohnson/Bodiless-JS\n\nBuild pull requests (--build-pull-requests)\nBuild every pull request as an environment? [Y|n] Y\n\nBuild pull requests post-merge (--build-pull-requests-post-merge)\nBuild pull requests based on their post-merge state? [y|N] y\n\nClone data for pull requests (--pull-requests-clone-parent-data)\nClone the parent environment's data for pull requests? [Y|n] n\n\nFetch branches (--fetch-branches)\nFetch all branches from the remote (as inactive environments)? [Y|n] y\n\nPrune branches (--prune-branches)\nDelete branches that do not exist on the remote? [Y|n] y\n\nWarning: adding a 'github' integration will automatically synchronize code from the external Git repository.\nThis means it can overwrite all the code in your project.\n\nAre you sure you want to continue? [y/N] y\nChecking webhook configuration on the repository: johnsonandjohnson/Bodiless-JS\n  Creating new webhook\n  Webhook created successfully\nCreated integration xxxxxxxx (type: github)\n+---------------------------+--------------------------------------------------------------------+\n| Property                  | Value                                                              |\n+---------------------------+--------------------------------------------------------------------+\n| id                        | xxxxxxx                                                            |\n| type                      | github                                                             |\n| token                     | ******                                                             |\n| base_url                  |                                                                    |\n| repository                | foo/bar                                                            |\n| fetch_branches            | true                                                               |\n| prune_branches            | true                                                               |\n| build_pull_requests       | true                                                               |\n| build_pull_requests_post_ | true                                                               |\n| merge                     |                                                                    |\n| pull_requests_clone_paren | false                                                              |\n| t_data                    |                                                                    |\n| hook_url                  | https://us-2.platform.sh/api/projects/jvaff4bu65vgm/integrations/4 |\n|                           | 4zqv2kqqfcgq/hook                                                  |\n+---------------------------+--------------------------------------------------------------------+\n```\n\n#### Bitbucket Server\n\nFrom your project root, execute `platform integration:add` and follow\nthe prompts, as:\n\n```bash\n$ platform integration:add\n* Integration type (--type)\nEnter a number to choose:\n  [0] bitbucket\n  [1] bitbucket_server\n  [2] github\n  [3] gitlab\n  [4] hipchat\n  [5] webhook\n  [6] health.email\n  [7] health.pagerduty\n  [8] health.slack\n> 1\n\n* Username (--username)\nThe Bitbucket Server username\n> {bitbukcet service username}\n\n* Token (--token)\nAn access token for the integration\n> {bitbucket service user password}\n\n* Repository (--repository)\nThe repository (e.g. 'foo/bar')\n> {project/repository, eg: foo/bar}\n\nBuild pull requests (--build-pull-requests)\nBuild every pull request as an environment? [Y|n] N\n\nClone data for pull requests (--pull-requests-clone-parent-data)\nClone the parent environments data for pull requests? [Y|n] Y\n\nFetch branches (--fetch-branches)\nFetch all branches from the remote (as inactive environments)? [Y|n] Y\n\nPrune branches (--prune-branches)\nDelete branches that do not exist on the remote? [Y|n] Y\n\nWarning: adding a 'bitbucket_server' integration will automatically synchronize code from the external Git repository.\nThis means it can overwrite all the code in your project.\n\nAre you sure you want to continue? [y/N] y\n```\n\n##### Verify the integration\n\n##### GitHub\n- Visit the \"webhooks\" section of your bitbucket repository settings, eg\n  ```\n  https://github.com/project/repo/settings/hooks\n  ```\n  and verify that a webhook to platform.sh has been added. Note you will need admin access\n  to the project in order to view the webhooks.\n- Activate a branch in your project (as described below) and validate that an environment\n  is created and deployed to platform.sh. *Note you must first push the branch to bitbucket*.\n- Issue a PR to your repository and verify that the PR branch is deployed.\n\n##### Bitbucket Server\n- Visit the \"webhooks\" section of your bitbucket repository settings, eg\n  ```\n  https://domain/plugins/servlet/webhooks/projects/{project-key}/repos/{repo-name}\n  ```\n  and verify that a webhook to platform.sh has been added. Note you will need admin access\n  to the project in order to view the webhooks.\n- Activate a branch in your project (as described below) and validate that an environment\n  is created and deployed to platform.sh. *Note you must first push the branch to bitbucket*.\n- Issue a PR to your repository and verify that the PR branch is deployed (note that only\n  the static environment will be build for PR's on Bitbucket).\n\n### Customizing Hook Implementations\n\nThis package includes default implementations of platform.sh\n[build and deploy hooks](https://docs.platform.sh/configuration/app/build.html#hooks) which\nshould work for most Bodiless sites.  However, should your site have special needs, you can\ncustomize by creating a `platform.custom.sh` or `static.platform.custom.sh` script and placing\nit alongside the appropriate `.platform.app.yaml` file (at the root of your repository for the\nstatic site, or in the `/edit` directory for the edit app).  In this script, you can define for\neach platform.sh hook one of the following functions:\n\n- `prepare_{hook} ()` - Run before the default implementation of the hook.\n- `hook ()` - Replaces the default implementation of the hook.\n- `finalize_{hook} ()` - Run after the default implementation of the hook.\n\nIf you wish to extend the default implementation, you can do so by calling it from your function.\nTo do this safely (ie to avoid errors if the default implementation doesn't exist) always use the\n`invoke` helper:\n\n```bash\nprepare_deploy () {\n  invoke default_prepare_deploy\n  # Your custom logic here...\n}\n```\n\n## Building and Deploying\n\n### Continuous Integration\n\nIf you configured platform.sh to build pull requests, then every PR to your repository will be\ndeployed to its own environment. Be aware of the following:\n- It is easy to reach your quota of development environments with this enabled, so use cautiously.\n- Edit environments for pull requests are currently only supported on GitHub -- and pushing changes\n  from the edit environment is not supported even there.\n- On Bitbucket Server, pull requests from *forks* will not automatically rebuild when new commits\n  are added.  This limitation does not apply to GitHub.\n- On both GitHub and Bitbucket, changes pushed to code outside the `/edit` directory will\n  not automatically be deployed to the edit environment.  You must manually update the\n  edit environment as described under [Pushing Changes](#pushing-changes) below.\n- Pull request environments will be automatically deleted when the PR is merged or declined.\n- If you manually delete a PR environment, it will not be recreated when the PR is\n  updated.\n- PR environments are named simply `pr-{pr#}` (eg `pr-123`).  You can easily run platform cli\n  commands against them using the `-e pr-xxx` option.\n- A link to the p.sh environment will be posted to the PR:\n  - **GitHub**: Expand the \"Show All Checks\" link next to the section on the \"Conversations\"\n    tab, and click the \"details\" link next to the platform.sh build.\n  - **Bitbucket Server**: Click the build status icon next to the PR title, and then click the\n    \"platform.sh\" link.\n\n### Manual Deployments\n\n#### Pre-requisites\n\n- Access to a [platform.sh](https://platform.sh/) project.\n- The [platform.sh cli](https://docs.platform.sh/gettingstarted/cli.html)\n\n#### Local setup\n\n- Obtain the project key of the project you wish to deploy: see\n  [The platform.sh project key](#the-platform.sh-project-key), above.\n- Connect your local repository to the correct platform.sh remote. From within the repository root:\n  ```\n  platform project:set-remote {project id}\n  ```\n\n#### Initial deployment of a new branch\n\n- Ensure you are on the correct branch locally.\n- Push the branch to bitbucket.\n  ```\n  git push origin <branch>\n  ```\n- Execute\n    ```\n    platform env:activate\n    ```\n  Note - you may have to wait a few moments after pushing the branch to\n  bitbucket before activating the environment, in order to allow the branch to\n  sync to p.sh. If, when you try to activate, you are asked for an \"Environment\n  ID\", wait a bit and try again.\n- The public URL of the new environment will be printed to the console.\n- You can display (and open) the public URLs for your site by checking out the\n  corresponding branch and executing `platform url`.\n\n##### Basic Authentication\n\nNote that basic authentication may be configured for your environment by\ndefault, and this may prevent access via your browser. To verify, use the\nplatform cli:\n```\nplatform env:http-access\n```\n\nYou can also use this command to enable or disable authentication, and to\nadd/remove credentials.\n```\nplatform help env:http-access\n```\nto learn more.\n\n#### Pushing changes\n\nOnce a new branch is created, changes pushed to Bitbucket will be automatically\ndeployed to the static site on platform.sh. You can run `platform activity:log`\nto see the current build status, or visit [console.platform.sh](https://console.platform.sh),\nlocate your build, and click \"View Logs\".\n\nChanges are *not* automatically deployed to an edit environment; you must manually\ntrigger an update of the edit environment by executing:\n  ```\n  platform ssh -e <env-id> 'bash platform.sh deploy'\n  ```\n\n  You may omit the \"-e <env-id>\" if you have the active branch checked out locally.\n\n#### Deleting an environment\n\nThe platform.sh environment will be deleted when you remove the corresponding\nbranch from bitbucket. *Please delete obsolete branches*.\n\nYou can also remove an environment without deleting your branch by checking\nout the branch locally and executing `platform env:delete -y`.\n\n#### Merging to main\n\nWhen you merge a feature branch to main, the updated main branch will be automatically deployed\nto the static environment on platform.sh.  To deploy changes to the edit environment, you must follow the same process as in [Pushing Changes](#pushing-changes) above.\n\n\n## Handling Redirect with Routes\n\n### Overview\nIn HTTP, URL redirecting is a technique to forward one URL to a different URL. It is commonly used for handling cases like URL shortening, preventing broken links when pages removed, pointing multiple domain addresses to a single URL address, etc. It is also critical to preserve page SEO value when there are URL changes.\n\nRedirection can be implemented on a client page with [Refresh Meta Tag](https://en.wikipedia.org/wiki/Meta_refresh) or JavaScript, but the preferred way is to manage redirect rules with server configuration.\n\nYou can configure redirects on Platform.sh with route yaml in project environments. A route describes how an incoming HTTP request is processed by Platform.sh, which includes URL redirect. The routes are defined inside .platform/routes.yaml file.\n\nAn example of redirect using routes.yaml:\n```\n\"https://www.{default}/\":\n  type: redirect\n  to: \"https://my-host.{default}/\"\n```\n\nHere, the URL https://www.example.com/ will be redirected to https://my-host.example.com/\n\n### Whole-route vs Partial redirects\nPlatform.sh offers two different ways to implement redirect rules, **Whole-route redirects** and **Partial redirects**\n\n* Whole-route redirects on host level. A typical use case for this kind of route is adding or removing a www. prefix to domain,\n\n  .platform/routes.yaml\n  ```\n  https://{default}/:\n    type: redirect\n    to: https://www.{default}/\n  ```\n\n  Here, https://example.com/ will be redirected to https://www.example.com/. This approach can be used to redirect vanity domains to their destination URLs.\n\n* Partial redirects allows redirect rules to be added to existing routes,\n\n  .platform/routes.yaml\n  ```\n      https://{default}/:\n        # [...]\n        redirects:\n          expires: 1d\n          paths:\n            '/from':\n              to: 'https://example.com/'\n              code: 301\n  ```\n\n  Here, \"https://[domain name]/from\" will be redirected to https://www.example.com/.\n\n  Note:\n  * the default response code is 302, in order to use a different response code, mostly commonly 301, add \"code: 301\" as configurable option.\n  * \"expires\" param is optional, it specifies duration the redirect will be cached. Examples of valid values include 3600s, 1d, 2w, 3m.\n\n\n  **Examples**\n\n  file .platform/routes.yaml\n\n  1. Redirect path \"/foo/bar\" to a different site \"https://example.com/\".\n\n      ```\n      https://{default}/:\n        type: upstream\n        redirects:\n          paths:\n            '/foo/bar':\n              to: 'https://example.com/'\n      ```\n\n  1.  Using Regular Expression to redirect path that matches \"/foo/(.*)/bar\" pattern.\n\n      ```\n      https://{default}/:\n        type: upstream\n        redirects:\n          paths:\n            '/foo/(.*)/bar':\n              to: '/$1'\n              regexp: true\n      ```\n\n      In this case, path \"/foo/cards/bar\" will be redirected to \"/cards\".\n\n  1. Redirect with prefix.\n\n      ```\n      https://{default}/:\n        type: upstream\n        redirects:\n          paths:\n            '/foo/bar':\n              to: '/new'\n              prefix: true\n\n      ```\n\n      Path \"/foo/bar\" will be redirected to \"/new\". And path \"/foo/bar/to/my/path\" will be redirected to \"/new/to/my/path\" where both the path and all its children included. If \"prefix\" set to false, only \"/foo/bar\" will be redirected to \"/new\".\n\n\n  1. Carry over suffix path with append_suffix option.\n\n      ```\n        https://{default}/:\n          type: upstream\n          redirects:\n            paths:\n              '/foo/bar':\n                to: 'https://{default}/new'\n                append_suffix: false\n\n      ```\n\n      If append_suffix is set to false, \"/foo/bar/to/my/path\" will be redirected to \"/new\". Otherwise, \"/foo/bar/to/my/path\" will be redirects to \"/new/to/my/path\". append_suffix is ignored if 'prefix' is false or 'regexp' is true.\n\n\n### HTTP vs HTTPS\n\nPlatform.sh recommends using HTTPS requests for all sites exclusively. Specifying HTTPS in route.yaml will automatically redirect any requests for an HTTP URL to HTTPS. While specifying only HTTP routes will result in duplicate HTTPS routes being created automatically, allowing the site to be served from both HTTP and HTTPS without redirects.\n\nAlthough it is not recommended, HTTPS requests can be redirected to HTTP explicitly to serve the site over HTTP only using route.yaml:\n\n```\n\"https://{default}/\":\n  type: redirect\n  to: \"http://{default}/\"\n```\n\n### Avoid redirect chains\n\nA redirect chain is a series of redirects between the initial URL and the destination URL. The redirect chain could be built over time of development or due to a combination of redirect between different protocol, host name or trailing slash processing etc. Redirect chain causes page loss authority value in search result. It also increases page load time and decreases the overall quality of site.\n\nIn order to avoid redirect chains, pay attention on destination path protocol and host name. For example, if the site is running under https and host www, specify destination \"to\" in route.yaml as:\n```\n  to: \"https://www.{default}/path/to/destination/\"\n```\n\nThe trailing slash should be appended to the configure item if platform environment adds trailing slash to url by default.\nsee [Platform.sh Documentation Redirects](https://docs.platform.sh/configuration/routes/redirects.html)\n\n### Generate redirect rules for migration sites\n\nBodilessJS [Site Migration Tool](https://github.com/johnsonandjohnson/Bodiless-JS/tree/main/packages/bodiless-migration-tool) package comes with a feature that allows user to export site redirection into file. See [Tools/Migration](/#/Tools/Migration?id=configuration) for configuration.\n\nUser can apply these exported redirect rules to routers.yaml before deploying to platform.sh.\n\n```yaml\n\"https://{default}/\":\n    type: upstream\n    upstream: \"static:http\"\n    redirects:\n      paths:\n        /image/redirect.png:\n          to: /image/placeholder.png\n          code: 301\n        /page2:\n          to: /page3\n          code: 301\n```\n\n## Using Fastly CDN\n\nPlatform.sh integrates with Fastly via EZ platform for Fastly.  \n\n1. Obtain your Fastly Service ID & Key from Fastly.   \n1. Once Fastly Service ID & Key is obtained, these variables can be set at Main environment.\n    ```\n    platform variable:create -e main --level environment env:HTTPCACHE_PURGE_TYPE --value 'fastly'\n    platform variable:create -e main --level environment env:FASTLY_SERVICE_ID --value 'YOUR_ID_HERE'\n    platform variable:create -e main --level environment env:FASTLY_KEY --value 'YOUR_ID_HERE'\n    ```\n1. Verify or Update your `routes.yaml` to enable caching for your site by setting `enabled: true`\n    ```\n        cache:\n            enabled: true\n            cookies: []\n    ```\n1. Verify or Update your `.platform.app.yaml` expiration time for your files.\n    ```\n    web:\n        locations:\n            '/':\n                expires: 6h  \n    ```\n\nOnce completed, the main env deployed on Platform.sh should be on Fastly CDN.  You may have to fine tune the expires setting for your static resources and set certain ones (ones identify not to change often such as font files) to longer to leverage browser caching.\n\nPlatform.sh References:\n* [Set Fastly Credentials on Platform.sh](https://docs.platform.sh/frameworks/ibexa/fastly.html#set-credentials-on-platformsh)\n* [HTTP Cache](https://docs.platform.sh/configuration/routes/cache.html)\n* [Router Cache](https://docs.platform.sh/languages/php/tuning.html#ensure-that-the-router-cache-is-properly-configured)\n* [Expires](https://docs.platform.sh/configuration/app/web.html#locations)\n* [How to Guide: How to configure caching for static assets](https://community.platform.sh/t/how-to-configure-caching-for-static-assets/187)\n\n\nIf there are issues or you need to troubleshoot, here are some good resources:\n* [Checking Fastly Cache](https://docs.fastly.com/en/guides/checking-cache)\n\n    ``` curl -svo /dev/null -H \"Fastly-Debug:1\" www.example.com/index.html ```\n* [Purging Fastly Cache](https://docs.fastly.com/api/purge)\n\n    ``` curl -X PURGE www.example.com/index.html ```\n\n## How to load environment specific html snippets\n\nWhen you want to inject different html snippets depending on your environment type, you can use Server Side Includes (SSI) mechanism.\n### Activate SSI\n\n* Activate SSI for your route(s) in your routes.yaml file. See: https://docs.platform.sh/configuration/routes/ssi.html\n* Use SSI_ENV enviroment variable to specify type of your environment. Default value is 'dev'.\n* Ensure ssi configs are loaded to psh container and set SSI_CONF_PATH environment variable to path to json file containing SSI configs.\n* Ensure your .platform.app.yaml contains invocation of generate-ssi-files.js node scripts. The script should be invoked during build and deploy phases. PSH phase (build or deploy) should be passed as an argument to the script.\n* Ensure the files of you app, that will be served by psh, contain SSI directives.\n* Ensure a writable volume is mounted to your app.\n\n### SSI config format\n\nSSI configuration file should be in json format.\n\n```\n{\n  key1: {\n    pragma: \"<!--# ssi data should go here -->\",\n    env1: {\n      file: \"key1.env1.html\"\n    }\n    ...\n    envN: {\n      file: \"key1.envN.html\"\n    }\n  }\n  ...\n  keyN: {\n    pragma: \"<!--# ssi data should go here -->\",\n    ...\n    env1: {\n      file: \"keyN.envN.html\"\n    }\n    ...\n    envN: {\n      file: \"keyN.envN.html\"\n    }\n  }\n}\n```\n### How it works\n\n* during build phase, generate-ssi-files reads SSI configs and for each key it creates symlink from PLATFORM_DOCUMENT_ROOT/filename.html into APP_VOLUME/filename.html. Filename is generated based on key. There is an opportunity to improve this logic. We can read and parse pragma field, exract filename from it. But it makes the things more complicated and in addition, pragma may not have files at all.\n* during deploy phase, generate-ssi-files reads SSI configs and SSI_ENV and for each key it copies the file defined in conf.{key}.{env}.{file} to APP_VOLUME/filename.html that was created during build phase.\n\n## How to replace your site prod url with psh environment url in a public file\n\nIf you want to make urls in a particular public file match psh environment url, you can leverage psh-url-replacer node script. For instance, your site sitemap.xml, which is generated during build time, contains production urls and you want to replace the production url with psh environment url, to which your website is deployed to.\n\n### Why\n\nPlatform.sh does not allow to expose environment level environment variables to the application build stage.\n\n### How it works\n\non psh build stage:\n\n- it moves your source file from public dir to a tmp directory\n- then it creates a symlink from a writable volume file to the source public file\n\non psh deploy stage:\n\n- it copies the file from the tmp directory to the writable volume file\n- then it replaces production url with psh environment url in the file\n\n### How to activate this feature\n\nBy default, the feature is activated for sitemap.xml and robots.txt. If you want to activate the feature for some other files or if you have custom installation of sitemap.xml or robots.txt, please follow the following steps:\n\n1. ensure writable volume mounting is configured for your app\n\n1. export environment variables and invoke psh-url-replacer in build section of your psh app .platform.app.yaml\n\n```bash\n\nhooks:\n    build: |\n        export PSH_URL_REPLACER_SRC_FILE=/path/to/your/src/public/file\n        export PSH_URL_REPLACER_TMP_FILE=/path/to/a/tmp/file\n        export PSH_URL_REPLACER_TARGET_FILE=/path/to/writable/volume/file\n        node /path/to/psh-url-replacer.js build\n\n```\n\n1. export environment variables and invoke psh-url-replacer in deploy section of your psh app .platform.app.yaml\n\n```bash\n\nhooks:\n    deploy: |\n        export PSH_URL_REPLACER_TMP_FILE=/path/to/the/tmp/file/you/saved/during/build/phase\n        export PSH_URL_REPLACER_TARGET_FILE=/path/to/writable/volume/file\n        export PSH_URL_REPLACER_SRC_URL=https://your-site-production-url.com\n        export PSH_URL_REPLACER_TARGET_URL=https://your-psh-env.url.site\n        export PSH_URL_REPLACER_PROD_ENV='0' # set to '1' if you want to disable the replacement\n        node /path/to/psh-url-replacer.js deploy\n```\n\n## Known limitations\n\n### General\n- PR Branches and Feature branches created in bitbucket will always inherit from\n  main. This means that you must manually configure basic authentication for\n  these branches if you want them protected from the public internet.\n- There is a 64-character limit on hostnames for TLS, and platform.sh uses 43 of\n  them. Since hostnames are created based on branch names, and since the edit\n  environment uses an additional 5 (\"edit.\"), your branch names should be\n  limited to a maximum of 16 characters to avoid certificate warnings.\n- When you create a bitbucket integration, a webhook is added to your bitbucket\n  repository. However, deleting the integration does not remove the webhook, you\n  must do this manually.\n### Environment memory\nOn development environments, the `edit` site environment can use a large amount\nof memory when running, which might cause out-of-memory issues when building \npages. This is caused by webpack's caching system, and there are two ways\nto circumvent the issue:\n\n#### Increasing container memory\nUse [Large development containers](https://docs.platform.sh/overview/pricing.html#development)\nto increase the total memory available to containers. This is the preferred way \nto solve this problem, as it's easier and faster. Note that this will increase costs.\n\n#### Disable build cache\nDisabling webpack's cache will drastically reduce memory consumption, but\nwill also increase build times. This might be specially noticeable when doing\nsimple operations like creating, cloning or moving pages.\n\nTo disable a site's cache, add `cache: false` to its webpack configuration. This\nis done in the `gatsby-node.js` file on the site root. Read [Gatsby's documentation](https://www.gatsbyjs.com/docs/how-to/custom-configuration/add-custom-webpack-config/#examples)\nfor an example, and refer to [Webpacks's documentation](https://webpack.js.org/configuration/cache/)\nif you want to understand how its caching system works.\n## Troubleshooting\n\n### Viewing Logs\n\nBuild, deploy and application logs for an environment are available using the\nplatform cli. If you want logs for an environment other than the currently\nchecked-out branch (e.g. for a pull request), you must use the `-e` flag. You\ncan first get a list of all available environments by running\n```\nplatform env:list\n```\nYou can then use the identifier from the first column in the commands below.\nIf you want logs from the environment associated with your current local\nbranch, you can omit the `-e` flag.\n\n- Tail/print most recent build log (this now includes deploy log):\n  ```\n  platform activity:log -e <env-id>\n  ```\n  Note that you may have to wait a few moments after performing\n  a git push in order for the new p.sh deployment to begin.\n- Print deploy logs for all builds to the edit environment:\n  ```\n  platform log -e <env-id> -A edit deploy <--lines n>\n  ```\n  (where n is the number of lines.)\n- View or tail application logs for the edit environment\n  ```\n  platform log -e <env-id> -A edit app <--lines n> <--tail>\n  ```\n\nAlternatively, you can visit [the platform.sh console](https://console.platform.sh/webalerts/abcdefghi) and locate\nyour build to view the build log (deployment and application logs\nare only available from the command line).\n\n### Hints\n\n- If the `platform` command is not found, you probably have to run\n  `source .bashrc` to ensure it is in your path.\n- For all deployments in which the app is restarted, the environment may not be\n  fully available for up to a minute after the deployment is complete.\n- You may see errors in the application log relating to insufficient file\n  watchers. This is a known issue. Currently the only workaround is to reduce\n  the number of active environments.\n- Public URLs for an environment are available by running\n  ```\n  platform url -e <env-id>\n  ```\n- There are many other useful platform cli subcommands.  Run `platform list`\n  to see them all.\n\n## Deploying bodiless packages from a private registry\n\nBy default the public regisry will be used to download bodiless packages: //registry.npmjs.org/\n\nIn order to switch to a private registry follow Step 3 (Create platform.sh environment variables.) of this doc.\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/johnsonandjohnson/bodiless-js/issues"},"_id":"@asemirsk/psh@1.0.0-canary-24-23.0","_nodeVersion":"16.13.2","_npmVersion":"lerna/4.0.0/node@v16.13.2+x64 (linux)","dist":{"integrity":"sha512-1B+zA2rlEK3r53nDquYnPK5GQhztxUFZMDtr+t9159kG+EMU0hl5w2kh0iRhDlegUxM7G5v284RGWiJqSz+1DQ==","shasum":"bb596512a43a51a651104204a4c97507392d0810","tarball":"https://registry.npmjs.org/@asemirsk/psh/-/psh-1.0.0-canary-24-23.0.tgz","fileCount":15,"unpackedSize":66976,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC+qY93J1l3FboIY3TGpPbuL0H8Rd1u7dX/dYbnWLJ4DgIgcK00ivR4Ve/3evyjiRch/nxVuCEjRDqFZyFmEEd/0Zc="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJijfHpACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmov/g//Ro5hKWqPQhju8boDRcGIHRlxnoH/z1D0vmg8SfHJ4DSul4bc\r\ngiijTo+mScKi6SN+c5elY//wZODx5TQTjAiANp24TxTVQSwQp3rQqjg1UMI9\r\nGWNjfdF1aREEN/fV2IeG7EG1ETuiEWLoyPGXUF8jcYKPI/t1wgOnnfyMrK3E\r\nv47MQrrHOclzMmMt5xj8mij2dlmJxeWckAL17mcA7d5Jd8X0gygtUvyO7zRq\r\nZmxzTHEx/1bRfMw7IVe7n7KP672V8xhaWdOk960X0JSb93/wh30cAi1sRvbk\r\n5PF8r9DJkBPac7JlcYj4Aghv7LSh+anHJJziC+KQlm0zluf8ORa3OIS64OYa\r\noszG0xdfRppJmsQNpYlLS1GZITnRgtpvjo1cZfJLegHLoNLkOFuQLK0166qL\r\n+I6MlA5Jv7qUtvsUTzRc7itLYi/FgJbMJe17CUldZp5wqlifzZLnOC/p/l7O\r\neG+FHCjpuIQ5KgSNb5sxDxm5sOmhZEOmdYTBmO4E/SnnqG1msSmR/s/8Eyu0\r\n2XmZigU9IVJ7P8qoFBgv917O29ITMEsMu+8USuIvmkUg4GtGR4hXU2+XWV5y\r\ng07+LSQuK6UDLms82ADFgN5X/WIQSoXPlr9t8huSQRMCb1/c/kT8hlmqViV+\r\n1kRPgabfV+2YIVqbIKa1l+LS5q4QIsO1h9g=\r\n=62EE\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"asemirsk","email":"al.semirski@gmail.com"},"maintainers":[{"name":"asemirsk","email":"al.semirski@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/psh_1.0.0-canary-24-23.0_1653469672925_0.5267692463353115"},"_hasShrinkwrap":false},"1.0.0-canary-24-24.0":{"name":"@asemirsk/psh","version":"1.0.0-canary-24-24.0","description":"Provides cli tool for initializing a bodiless project on platform.sh","author":{"name":"Chris Oden","email":"coden@its.jnj.com"},"homepage":"https://github.com/johnsonandjohnson/bodiless-js#readme","license":"Apache-2.0","bin":{"bodiless-psh-init":"lib/bodiless-psh-init.js"},"scripts":{"build":"run-p build:lib","build:lib":"tsc -p ./tsconfig.json","build:watch":"npm run build:lib -- --watch","clean":"rimraf \"lib/*\" && rimraf tsconfig.tsbuildinfo"},"directories":{"lib":"lib"},"repository":{"type":"git","url":"git+https://github.com/johnsonandjohnson/bodiless-js.git"},"publishConfig":{"access":"public"},"dependencies":{"copyfiles":"^2.1.1","js-yaml":"^3.13.1","lodash":"^4.17.19","rimraf":"^2.6.3"},"devDependencies":{"@types/copyfiles":"^2.1.1"},"gitHead":"af2c8ace172b3dc3a1f237c51eb55be1e21978bb","readme":"# Bodiless integration with platform.sh\n\nThis package provides standard configuration files and helper scripts which\nmake it easy for a bodiless site to be deployed to platform.sh.\n\n## Setting up your project\n\n### Pre-requisites\n\n- Admin access to a [platform.sh](https://platform.sh/) project.\n- A service user with *admin access* to a repository in a Bitbucket Server instance.\n- The [platform.sh cli](https://docs.platform.sh/gettingstarted/cli.html)\n\n### Step 1. Gather required information\n\nTo continue, you will need the following:\n\n#### The platform.sh project key\n- Log in via the platform.sh cli.  From your local machine execute:\n  ```\n  platform login\n  ```\n  You will be directed to log in via a web browser\n- Execute\n  ```\n  platform project:list\n  ```\n  You should see a list of all projects you have access to, something like:\n  ```\n    Your projects are:\n  +---------------+-------------------------+-----------------------------------------------------+\n  | ID            | Title                   | URL                                                 |\n  +---------------+-------------------------+-----------------------------------------------------+\n  | abcdefghijklm | project_a               | https://console.platform.sh/webalerts/abcdefghijklm |\n  | lmnopqrstuvwx | project_b               | https://console.platform.sh/webalerts/lmnopqrstuvwx |\n  +---------------+-------------------------+-----------------------------------------------------+`\n  ```\n- Take note of the project ID for your project. This is the value you will use below.\n\n### Step 2. Initialize your project configuration files\n\nPlatform.sh requires several configuration files to be in place\nin your repository. This package contains default versions of these\nfiles for a BodilessJS.  To install or update them:\n\n1. Add this package as a dependency of your project:\n  ```\n  npm i --save-dev @asemirsk/psh\n  ```\n2. Add the following to your `package.json` scripts:\n  ```\n  \"init-psh\": \"bodiless-psh-init\"\n  ```\n3. Install or update the configuration files:\n  ```\n  npm run init-psh\n  ```\n> When `@asemirsk/psh` is installing its' files it will try to merge `static` and `edit` `*.platform.app.yaml` files based on the whitelisted keys from `packages/bodiless-psh/resources/.platform/platform.whitelist.yaml`. Only the keys that are specified in `platform.whitelist.yaml` will be merged. Merging will be performed by using the recursive algorithm to preserve any keys that are not in default `.platform.app.yaml`. Non-whitelisted keys will be ignored, and a warning message will be printed to the console.\n\n4. Commit the added configuration files to your repository.  These include\n   ```\n   static.platform.sh\n   .platform.app.yaml\n   .platform/*\n   edit/*\n   ```\n\n### Step 3. Create platform.sh environment variables.\n\nFirst, configure your local install to connect to your platform.sh project. From\nwithin your project root, execute\n```\nplatform project:set-remote {project id}\n```\nwhere {project id} is the platform.sh project id you acquired above.\n\nAll variables below should be set at the project level using the platform.sh command\nline, as described in [the platform.sh documentation](https://docs.platform.sh/development/variables.html#project-variables), and all should be visible at both build time and run time.\n\nAdd the following variables:\n\n- env:APP_GIT_REMOTE_URL -- The URL of your upstream Git repository\n- env:APP_GIT_USER -- The user to access your upstream Git repository.\n- env:APP_GIT_USER_EMAIL -- THe user email for your upstream Git repository.\n- env:APP_GIT_PW -- The user password for your upstream Git repository.\n\n\n> Be sure to specify `--sensitive true` for all credentials.\n\nExample:\n```\n$ platform variable:create\n* Level (--level)\nThe level at which to set the variable\n  [project    ] Project-wide\n  [environment] Environment-specific\n> project\n\n* Name (--name)\nThe variable name\n> APP_GIT_USER_EMAIL\n\n* Value (--value)\nThe variable's value\n> email@your.service.account\n\nJSON (--json)\nIs the value JSON-formatted? [y|N] N\n\nSensitive (--sensitive)\nIs the value sensitive? [y|N] N\n\nPrefix (--prefix)\nThe variable name's prefix\nDefault: none\n  [none] No prefix: The variable will be part of $PLATFORM_VARIABLES.\n  [env:] env: The variable will be exposed directly, e.g. as $APP_GIT_USER_EMAIL.\n> env:\n\nVisible at build time (--visible-build)\nShould the variable be available at build time? [Y|n] Y\n\nVisible at runtime (--visible-runtime)\nShould the variable be available at runtime? [Y|n] Y\n\nCreating variable env:APP_GIT_USER_EMAIL on the project...\n```\n\nYou can verify that the variable was created properly by executing, eg:\n  ```\n  platform variable:get env:APP_GIT_USER_EMAIL\n  ```\n  You should see something like:\n  ```\n  $ platform variable:get env:APP_NPM_AUTH\n  +-----------------+---------------------------+\n  | Property        | Value                     |\n  +-----------------+---------------------------+\n  | id              | env:APP_GIT_USER_EMAL     |\n  | created_at      | 2019-08-09T06:48:52-04:00 |\n  | updated_at      | 2019-08-09T06:48:52-04:00 |\n  | name            | env:APP_GIT_USER_EMAIL    |\n  | attributes      | {  }                      |\n  | is_json         | false                     |\n  | is_sensitive    | false                     |\n  | visible_build   | true                      |\n  | visible_runtime | true                      |\n  | level           | project                   |\n  +-----------------+---------------------------+\n  ```\n\n#### Optional: Configure an NPM Private Registry\n\nIf you wish to install packages from a private registry, you may do so. The\npackages to be installed must be namespaced. Set the following 3 environment\nvariables on p.sh. All variables should be visible at both build and run time:\n- `env:APP_NPM_REGISTRY`: the full path to your registry, eg\n  `//my-artifactory.com/api/npm/my-registry/`.\n- `env:APP_NPM_AUTH`: Ypur NPM authentication token. This should be marked as sensitive.\n  To obtain your token:\n  1. Login to your registry:\n     ```\n     npm login --registry=https://url/of/your/private/registry\n     ```\n     Follow the prompts with the username/password/email of the account you wish\n     to use for p.sh automation.\n  2. Examine your `.npmrc` file (usually located in your home directory). You\n     should see something like\n     ```\n     //url/of/your/privateregistry/:_authToken={token}\n     ```\n  3. Copy the token value to the `env:APP_NPM_AUTH` variable in your p.sh project.\n\n- `env:APP_NPM_NAMESPACE`: The namespace of the packages in your private\n  regsitry, eg `@mynamespace`.\n\n### Step 4. Configure the platform.sh Git Service integration.\n\nPlatform.sh provides out-of-the-box integrations with many popular Git service providers.\nWe have tested with Bitbucket Server and GitHub.\n\nNote that you must have admin access to the repository in order to configure the integration.\n\n#### GitHub\n\nFrom your project root, execute `platform integration:add` and follow\nthe prompts, as:\n\n```\n$ platform integration:add\n* Integration type (--type)\nEnter a number to choose:\n  [0] bitbucket\n  [1] bitbucket_server\n  [2] github\n  [3] gitlab\n  [4] hipchat\n  [5] webhook\n  [6] health.email\n  [7] health.pagerduty\n  [8] health.slack\n  [9] health.webhook\n> 2\n\n* Token (--token)\nAn access token for the integration\n> {your GitHub personal access token}\n\n* Repository (--repository)\nThe repository (e.g. 'foo/bar')\n> johnsonandjohnson/Bodiless-JS\n\nBuild pull requests (--build-pull-requests)\nBuild every pull request as an environment? [Y|n] Y\n\nBuild pull requests post-merge (--build-pull-requests-post-merge)\nBuild pull requests based on their post-merge state? [y|N] y\n\nClone data for pull requests (--pull-requests-clone-parent-data)\nClone the parent environment's data for pull requests? [Y|n] n\n\nFetch branches (--fetch-branches)\nFetch all branches from the remote (as inactive environments)? [Y|n] y\n\nPrune branches (--prune-branches)\nDelete branches that do not exist on the remote? [Y|n] y\n\nWarning: adding a 'github' integration will automatically synchronize code from the external Git repository.\nThis means it can overwrite all the code in your project.\n\nAre you sure you want to continue? [y/N] y\nChecking webhook configuration on the repository: johnsonandjohnson/Bodiless-JS\n  Creating new webhook\n  Webhook created successfully\nCreated integration xxxxxxxx (type: github)\n+---------------------------+--------------------------------------------------------------------+\n| Property                  | Value                                                              |\n+---------------------------+--------------------------------------------------------------------+\n| id                        | xxxxxxx                                                            |\n| type                      | github                                                             |\n| token                     | ******                                                             |\n| base_url                  |                                                                    |\n| repository                | foo/bar                                                            |\n| fetch_branches            | true                                                               |\n| prune_branches            | true                                                               |\n| build_pull_requests       | true                                                               |\n| build_pull_requests_post_ | true                                                               |\n| merge                     |                                                                    |\n| pull_requests_clone_paren | false                                                              |\n| t_data                    |                                                                    |\n| hook_url                  | https://us-2.platform.sh/api/projects/jvaff4bu65vgm/integrations/4 |\n|                           | 4zqv2kqqfcgq/hook                                                  |\n+---------------------------+--------------------------------------------------------------------+\n```\n\n#### Bitbucket Server\n\nFrom your project root, execute `platform integration:add` and follow\nthe prompts, as:\n\n```bash\n$ platform integration:add\n* Integration type (--type)\nEnter a number to choose:\n  [0] bitbucket\n  [1] bitbucket_server\n  [2] github\n  [3] gitlab\n  [4] hipchat\n  [5] webhook\n  [6] health.email\n  [7] health.pagerduty\n  [8] health.slack\n> 1\n\n* Username (--username)\nThe Bitbucket Server username\n> {bitbukcet service username}\n\n* Token (--token)\nAn access token for the integration\n> {bitbucket service user password}\n\n* Repository (--repository)\nThe repository (e.g. 'foo/bar')\n> {project/repository, eg: foo/bar}\n\nBuild pull requests (--build-pull-requests)\nBuild every pull request as an environment? [Y|n] N\n\nClone data for pull requests (--pull-requests-clone-parent-data)\nClone the parent environments data for pull requests? [Y|n] Y\n\nFetch branches (--fetch-branches)\nFetch all branches from the remote (as inactive environments)? [Y|n] Y\n\nPrune branches (--prune-branches)\nDelete branches that do not exist on the remote? [Y|n] Y\n\nWarning: adding a 'bitbucket_server' integration will automatically synchronize code from the external Git repository.\nThis means it can overwrite all the code in your project.\n\nAre you sure you want to continue? [y/N] y\n```\n\n##### Verify the integration\n\n##### GitHub\n- Visit the \"webhooks\" section of your bitbucket repository settings, eg\n  ```\n  https://github.com/project/repo/settings/hooks\n  ```\n  and verify that a webhook to platform.sh has been added. Note you will need admin access\n  to the project in order to view the webhooks.\n- Activate a branch in your project (as described below) and validate that an environment\n  is created and deployed to platform.sh. *Note you must first push the branch to bitbucket*.\n- Issue a PR to your repository and verify that the PR branch is deployed.\n\n##### Bitbucket Server\n- Visit the \"webhooks\" section of your bitbucket repository settings, eg\n  ```\n  https://domain/plugins/servlet/webhooks/projects/{project-key}/repos/{repo-name}\n  ```\n  and verify that a webhook to platform.sh has been added. Note you will need admin access\n  to the project in order to view the webhooks.\n- Activate a branch in your project (as described below) and validate that an environment\n  is created and deployed to platform.sh. *Note you must first push the branch to bitbucket*.\n- Issue a PR to your repository and verify that the PR branch is deployed (note that only\n  the static environment will be build for PR's on Bitbucket).\n\n### Customizing Hook Implementations\n\nThis package includes default implementations of platform.sh\n[build and deploy hooks](https://docs.platform.sh/configuration/app/build.html#hooks) which\nshould work for most Bodiless sites.  However, should your site have special needs, you can\ncustomize by creating a `platform.custom.sh` or `static.platform.custom.sh` script and placing\nit alongside the appropriate `.platform.app.yaml` file (at the root of your repository for the\nstatic site, or in the `/edit` directory for the edit app).  In this script, you can define for\neach platform.sh hook one of the following functions:\n\n- `prepare_{hook} ()` - Run before the default implementation of the hook.\n- `hook ()` - Replaces the default implementation of the hook.\n- `finalize_{hook} ()` - Run after the default implementation of the hook.\n\nIf you wish to extend the default implementation, you can do so by calling it from your function.\nTo do this safely (ie to avoid errors if the default implementation doesn't exist) always use the\n`invoke` helper:\n\n```bash\nprepare_deploy () {\n  invoke default_prepare_deploy\n  # Your custom logic here...\n}\n```\n\n## Building and Deploying\n\n### Continuous Integration\n\nIf you configured platform.sh to build pull requests, then every PR to your repository will be\ndeployed to its own environment. Be aware of the following:\n- It is easy to reach your quota of development environments with this enabled, so use cautiously.\n- Edit environments for pull requests are currently only supported on GitHub -- and pushing changes\n  from the edit environment is not supported even there.\n- On Bitbucket Server, pull requests from *forks* will not automatically rebuild when new commits\n  are added.  This limitation does not apply to GitHub.\n- On both GitHub and Bitbucket, changes pushed to code outside the `/edit` directory will\n  not automatically be deployed to the edit environment.  You must manually update the\n  edit environment as described under [Pushing Changes](#pushing-changes) below.\n- Pull request environments will be automatically deleted when the PR is merged or declined.\n- If you manually delete a PR environment, it will not be recreated when the PR is\n  updated.\n- PR environments are named simply `pr-{pr#}` (eg `pr-123`).  You can easily run platform cli\n  commands against them using the `-e pr-xxx` option.\n- A link to the p.sh environment will be posted to the PR:\n  - **GitHub**: Expand the \"Show All Checks\" link next to the section on the \"Conversations\"\n    tab, and click the \"details\" link next to the platform.sh build.\n  - **Bitbucket Server**: Click the build status icon next to the PR title, and then click the\n    \"platform.sh\" link.\n\n### Manual Deployments\n\n#### Pre-requisites\n\n- Access to a [platform.sh](https://platform.sh/) project.\n- The [platform.sh cli](https://docs.platform.sh/gettingstarted/cli.html)\n\n#### Local setup\n\n- Obtain the project key of the project you wish to deploy: see\n  [The platform.sh project key](#the-platform.sh-project-key), above.\n- Connect your local repository to the correct platform.sh remote. From within the repository root:\n  ```\n  platform project:set-remote {project id}\n  ```\n\n#### Initial deployment of a new branch\n\n- Ensure you are on the correct branch locally.\n- Push the branch to bitbucket.\n  ```\n  git push origin <branch>\n  ```\n- Execute\n    ```\n    platform env:activate\n    ```\n  Note - you may have to wait a few moments after pushing the branch to\n  bitbucket before activating the environment, in order to allow the branch to\n  sync to p.sh. If, when you try to activate, you are asked for an \"Environment\n  ID\", wait a bit and try again.\n- The public URL of the new environment will be printed to the console.\n- You can display (and open) the public URLs for your site by checking out the\n  corresponding branch and executing `platform url`.\n\n##### Basic Authentication\n\nNote that basic authentication may be configured for your environment by\ndefault, and this may prevent access via your browser. To verify, use the\nplatform cli:\n```\nplatform env:http-access\n```\n\nYou can also use this command to enable or disable authentication, and to\nadd/remove credentials.\n```\nplatform help env:http-access\n```\nto learn more.\n\n#### Pushing changes\n\nOnce a new branch is created, changes pushed to Bitbucket will be automatically\ndeployed to the static site on platform.sh. You can run `platform activity:log`\nto see the current build status, or visit [console.platform.sh](https://console.platform.sh),\nlocate your build, and click \"View Logs\".\n\nChanges are *not* automatically deployed to an edit environment; you must manually\ntrigger an update of the edit environment by executing:\n  ```\n  platform ssh -e <env-id> 'bash platform.sh deploy'\n  ```\n\n  You may omit the \"-e <env-id>\" if you have the active branch checked out locally.\n\n#### Deleting an environment\n\nThe platform.sh environment will be deleted when you remove the corresponding\nbranch from bitbucket. *Please delete obsolete branches*.\n\nYou can also remove an environment without deleting your branch by checking\nout the branch locally and executing `platform env:delete -y`.\n\n#### Merging to main\n\nWhen you merge a feature branch to main, the updated main branch will be automatically deployed\nto the static environment on platform.sh.  To deploy changes to the edit environment, you must follow the same process as in [Pushing Changes](#pushing-changes) above.\n\n\n## Handling Redirect with Routes\n\n### Overview\nIn HTTP, URL redirecting is a technique to forward one URL to a different URL. It is commonly used for handling cases like URL shortening, preventing broken links when pages removed, pointing multiple domain addresses to a single URL address, etc. It is also critical to preserve page SEO value when there are URL changes.\n\nRedirection can be implemented on a client page with [Refresh Meta Tag](https://en.wikipedia.org/wiki/Meta_refresh) or JavaScript, but the preferred way is to manage redirect rules with server configuration.\n\nYou can configure redirects on Platform.sh with route yaml in project environments. A route describes how an incoming HTTP request is processed by Platform.sh, which includes URL redirect. The routes are defined inside .platform/routes.yaml file.\n\nAn example of redirect using routes.yaml:\n```\n\"https://www.{default}/\":\n  type: redirect\n  to: \"https://my-host.{default}/\"\n```\n\nHere, the URL https://www.example.com/ will be redirected to https://my-host.example.com/\n\n### Whole-route vs Partial redirects\nPlatform.sh offers two different ways to implement redirect rules, **Whole-route redirects** and **Partial redirects**\n\n* Whole-route redirects on host level. A typical use case for this kind of route is adding or removing a www. prefix to domain,\n\n  .platform/routes.yaml\n  ```\n  https://{default}/:\n    type: redirect\n    to: https://www.{default}/\n  ```\n\n  Here, https://example.com/ will be redirected to https://www.example.com/. This approach can be used to redirect vanity domains to their destination URLs.\n\n* Partial redirects allows redirect rules to be added to existing routes,\n\n  .platform/routes.yaml\n  ```\n      https://{default}/:\n        # [...]\n        redirects:\n          expires: 1d\n          paths:\n            '/from':\n              to: 'https://example.com/'\n              code: 301\n  ```\n\n  Here, \"https://[domain name]/from\" will be redirected to https://www.example.com/.\n\n  Note:\n  * the default response code is 302, in order to use a different response code, mostly commonly 301, add \"code: 301\" as configurable option.\n  * \"expires\" param is optional, it specifies duration the redirect will be cached. Examples of valid values include 3600s, 1d, 2w, 3m.\n\n\n  **Examples**\n\n  file .platform/routes.yaml\n\n  1. Redirect path \"/foo/bar\" to a different site \"https://example.com/\".\n\n      ```\n      https://{default}/:\n        type: upstream\n        redirects:\n          paths:\n            '/foo/bar':\n              to: 'https://example.com/'\n      ```\n\n  1.  Using Regular Expression to redirect path that matches \"/foo/(.*)/bar\" pattern.\n\n      ```\n      https://{default}/:\n        type: upstream\n        redirects:\n          paths:\n            '/foo/(.*)/bar':\n              to: '/$1'\n              regexp: true\n      ```\n\n      In this case, path \"/foo/cards/bar\" will be redirected to \"/cards\".\n\n  1. Redirect with prefix.\n\n      ```\n      https://{default}/:\n        type: upstream\n        redirects:\n          paths:\n            '/foo/bar':\n              to: '/new'\n              prefix: true\n\n      ```\n\n      Path \"/foo/bar\" will be redirected to \"/new\". And path \"/foo/bar/to/my/path\" will be redirected to \"/new/to/my/path\" where both the path and all its children included. If \"prefix\" set to false, only \"/foo/bar\" will be redirected to \"/new\".\n\n\n  1. Carry over suffix path with append_suffix option.\n\n      ```\n        https://{default}/:\n          type: upstream\n          redirects:\n            paths:\n              '/foo/bar':\n                to: 'https://{default}/new'\n                append_suffix: false\n\n      ```\n\n      If append_suffix is set to false, \"/foo/bar/to/my/path\" will be redirected to \"/new\". Otherwise, \"/foo/bar/to/my/path\" will be redirects to \"/new/to/my/path\". append_suffix is ignored if 'prefix' is false or 'regexp' is true.\n\n\n### HTTP vs HTTPS\n\nPlatform.sh recommends using HTTPS requests for all sites exclusively. Specifying HTTPS in route.yaml will automatically redirect any requests for an HTTP URL to HTTPS. While specifying only HTTP routes will result in duplicate HTTPS routes being created automatically, allowing the site to be served from both HTTP and HTTPS without redirects.\n\nAlthough it is not recommended, HTTPS requests can be redirected to HTTP explicitly to serve the site over HTTP only using route.yaml:\n\n```\n\"https://{default}/\":\n  type: redirect\n  to: \"http://{default}/\"\n```\n\n### Avoid redirect chains\n\nA redirect chain is a series of redirects between the initial URL and the destination URL. The redirect chain could be built over time of development or due to a combination of redirect between different protocol, host name or trailing slash processing etc. Redirect chain causes page loss authority value in search result. It also increases page load time and decreases the overall quality of site.\n\nIn order to avoid redirect chains, pay attention on destination path protocol and host name. For example, if the site is running under https and host www, specify destination \"to\" in route.yaml as:\n```\n  to: \"https://www.{default}/path/to/destination/\"\n```\n\nThe trailing slash should be appended to the configure item if platform environment adds trailing slash to url by default.\nsee [Platform.sh Documentation Redirects](https://docs.platform.sh/configuration/routes/redirects.html)\n\n### Generate redirect rules for migration sites\n\nBodilessJS [Site Migration Tool](https://github.com/johnsonandjohnson/Bodiless-JS/tree/main/packages/bodiless-migration-tool) package comes with a feature that allows user to export site redirection into file. See [Tools/Migration](/#/Tools/Migration?id=configuration) for configuration.\n\nUser can apply these exported redirect rules to routers.yaml before deploying to platform.sh.\n\n```yaml\n\"https://{default}/\":\n    type: upstream\n    upstream: \"static:http\"\n    redirects:\n      paths:\n        /image/redirect.png:\n          to: /image/placeholder.png\n          code: 301\n        /page2:\n          to: /page3\n          code: 301\n```\n\n## Using Fastly CDN\n\nPlatform.sh integrates with Fastly via EZ platform for Fastly.  \n\n1. Obtain your Fastly Service ID & Key from Fastly.   \n1. Once Fastly Service ID & Key is obtained, these variables can be set at Main environment.\n    ```\n    platform variable:create -e main --level environment env:HTTPCACHE_PURGE_TYPE --value 'fastly'\n    platform variable:create -e main --level environment env:FASTLY_SERVICE_ID --value 'YOUR_ID_HERE'\n    platform variable:create -e main --level environment env:FASTLY_KEY --value 'YOUR_ID_HERE'\n    ```\n1. Verify or Update your `routes.yaml` to enable caching for your site by setting `enabled: true`\n    ```\n        cache:\n            enabled: true\n            cookies: []\n    ```\n1. Verify or Update your `.platform.app.yaml` expiration time for your files.\n    ```\n    web:\n        locations:\n            '/':\n                expires: 6h  \n    ```\n\nOnce completed, the main env deployed on Platform.sh should be on Fastly CDN.  You may have to fine tune the expires setting for your static resources and set certain ones (ones identify not to change often such as font files) to longer to leverage browser caching.\n\nPlatform.sh References:\n* [Set Fastly Credentials on Platform.sh](https://docs.platform.sh/frameworks/ibexa/fastly.html#set-credentials-on-platformsh)\n* [HTTP Cache](https://docs.platform.sh/configuration/routes/cache.html)\n* [Router Cache](https://docs.platform.sh/languages/php/tuning.html#ensure-that-the-router-cache-is-properly-configured)\n* [Expires](https://docs.platform.sh/configuration/app/web.html#locations)\n* [How to Guide: How to configure caching for static assets](https://community.platform.sh/t/how-to-configure-caching-for-static-assets/187)\n\n\nIf there are issues or you need to troubleshoot, here are some good resources:\n* [Checking Fastly Cache](https://docs.fastly.com/en/guides/checking-cache)\n\n    ``` curl -svo /dev/null -H \"Fastly-Debug:1\" www.example.com/index.html ```\n* [Purging Fastly Cache](https://docs.fastly.com/api/purge)\n\n    ``` curl -X PURGE www.example.com/index.html ```\n\n## How to load environment specific html snippets\n\nWhen you want to inject different html snippets depending on your environment type, you can use Server Side Includes (SSI) mechanism.\n### Activate SSI\n\n* Activate SSI for your route(s) in your routes.yaml file. See: https://docs.platform.sh/configuration/routes/ssi.html\n* Use SSI_ENV enviroment variable to specify type of your environment. Default value is 'dev'.\n* Ensure ssi configs are loaded to psh container and set SSI_CONF_PATH environment variable to path to json file containing SSI configs.\n* Ensure your .platform.app.yaml contains invocation of generate-ssi-files.js node scripts. The script should be invoked during build and deploy phases. PSH phase (build or deploy) should be passed as an argument to the script.\n* Ensure the files of you app, that will be served by psh, contain SSI directives.\n* Ensure a writable volume is mounted to your app.\n\n### SSI config format\n\nSSI configuration file should be in json format.\n\n```\n{\n  key1: {\n    pragma: \"<!--# ssi data should go here -->\",\n    env1: {\n      file: \"key1.env1.html\"\n    }\n    ...\n    envN: {\n      file: \"key1.envN.html\"\n    }\n  }\n  ...\n  keyN: {\n    pragma: \"<!--# ssi data should go here -->\",\n    ...\n    env1: {\n      file: \"keyN.envN.html\"\n    }\n    ...\n    envN: {\n      file: \"keyN.envN.html\"\n    }\n  }\n}\n```\n### How it works\n\n* during build phase, generate-ssi-files reads SSI configs and for each key it creates symlink from PLATFORM_DOCUMENT_ROOT/filename.html into APP_VOLUME/filename.html. Filename is generated based on key. There is an opportunity to improve this logic. We can read and parse pragma field, exract filename from it. But it makes the things more complicated and in addition, pragma may not have files at all.\n* during deploy phase, generate-ssi-files reads SSI configs and SSI_ENV and for each key it copies the file defined in conf.{key}.{env}.{file} to APP_VOLUME/filename.html that was created during build phase.\n\n## How to replace your site prod url with psh environment url in a public file\n\nIf you want to make urls in a particular public file match psh environment url, you can leverage psh-url-replacer node script. For instance, your site sitemap.xml, which is generated during build time, contains production urls and you want to replace the production url with psh environment url, to which your website is deployed to.\n\n### Why\n\nPlatform.sh does not allow to expose environment level environment variables to the application build stage.\n\n### How it works\n\non psh build stage:\n\n- it moves your source file from public dir to a tmp directory\n- then it creates a symlink from a writable volume file to the source public file\n\non psh deploy stage:\n\n- it copies the file from the tmp directory to the writable volume file\n- then it replaces production url with psh environment url in the file\n\n### How to activate this feature\n\nBy default, the feature is activated for sitemap.xml and robots.txt. If you want to activate the feature for some other files or if you have custom installation of sitemap.xml or robots.txt, please follow the following steps:\n\n1. ensure writable volume mounting is configured for your app\n\n1. export environment variables and invoke psh-url-replacer in build section of your psh app .platform.app.yaml\n\n```bash\n\nhooks:\n    build: |\n        export PSH_URL_REPLACER_SRC_FILE=/path/to/your/src/public/file\n        export PSH_URL_REPLACER_TMP_FILE=/path/to/a/tmp/file\n        export PSH_URL_REPLACER_TARGET_FILE=/path/to/writable/volume/file\n        node /path/to/psh-url-replacer.js build\n\n```\n\n1. export environment variables and invoke psh-url-replacer in deploy section of your psh app .platform.app.yaml\n\n```bash\n\nhooks:\n    deploy: |\n        export PSH_URL_REPLACER_TMP_FILE=/path/to/the/tmp/file/you/saved/during/build/phase\n        export PSH_URL_REPLACER_TARGET_FILE=/path/to/writable/volume/file\n        export PSH_URL_REPLACER_SRC_URL=https://your-site-production-url.com\n        export PSH_URL_REPLACER_TARGET_URL=https://your-psh-env.url.site\n        export PSH_URL_REPLACER_PROD_ENV='0' # set to '1' if you want to disable the replacement\n        node /path/to/psh-url-replacer.js deploy\n```\n\n## Known limitations\n\n### General\n- PR Branches and Feature branches created in bitbucket will always inherit from\n  main. This means that you must manually configure basic authentication for\n  these branches if you want them protected from the public internet.\n- There is a 64-character limit on hostnames for TLS, and platform.sh uses 43 of\n  them. Since hostnames are created based on branch names, and since the edit\n  environment uses an additional 5 (\"edit.\"), your branch names should be\n  limited to a maximum of 16 characters to avoid certificate warnings.\n- When you create a bitbucket integration, a webhook is added to your bitbucket\n  repository. However, deleting the integration does not remove the webhook, you\n  must do this manually.\n### Environment memory\nOn development environments, the `edit` site environment can use a large amount\nof memory when running, which might cause out-of-memory issues when building \npages. This is caused by webpack's caching system, and there are two ways\nto circumvent the issue:\n\n#### Increasing container memory\nUse [Large development containers](https://docs.platform.sh/overview/pricing.html#development)\nto increase the total memory available to containers. This is the preferred way \nto solve this problem, as it's easier and faster. Note that this will increase costs.\n\n#### Disable build cache\nDisabling webpack's cache will drastically reduce memory consumption, but\nwill also increase build times. This might be specially noticeable when doing\nsimple operations like creating, cloning or moving pages.\n\nTo disable a site's cache, add `cache: false` to its webpack configuration. This\nis done in the `gatsby-node.js` file on the site root. Read [Gatsby's documentation](https://www.gatsbyjs.com/docs/how-to/custom-configuration/add-custom-webpack-config/#examples)\nfor an example, and refer to [Webpacks's documentation](https://webpack.js.org/configuration/cache/)\nif you want to understand how its caching system works.\n## Troubleshooting\n\n### Viewing Logs\n\nBuild, deploy and application logs for an environment are available using the\nplatform cli. If you want logs for an environment other than the currently\nchecked-out branch (e.g. for a pull request), you must use the `-e` flag. You\ncan first get a list of all available environments by running\n```\nplatform env:list\n```\nYou can then use the identifier from the first column in the commands below.\nIf you want logs from the environment associated with your current local\nbranch, you can omit the `-e` flag.\n\n- Tail/print most recent build log (this now includes deploy log):\n  ```\n  platform activity:log -e <env-id>\n  ```\n  Note that you may have to wait a few moments after performing\n  a git push in order for the new p.sh deployment to begin.\n- Print deploy logs for all builds to the edit environment:\n  ```\n  platform log -e <env-id> -A edit deploy <--lines n>\n  ```\n  (where n is the number of lines.)\n- View or tail application logs for the edit environment\n  ```\n  platform log -e <env-id> -A edit app <--lines n> <--tail>\n  ```\n\nAlternatively, you can visit [the platform.sh console](https://console.platform.sh/webalerts/abcdefghi) and locate\nyour build to view the build log (deployment and application logs\nare only available from the command line).\n\n### Hints\n\n- If the `platform` command is not found, you probably have to run\n  `source .bashrc` to ensure it is in your path.\n- For all deployments in which the app is restarted, the environment may not be\n  fully available for up to a minute after the deployment is complete.\n- You may see errors in the application log relating to insufficient file\n  watchers. This is a known issue. Currently the only workaround is to reduce\n  the number of active environments.\n- Public URLs for an environment are available by running\n  ```\n  platform url -e <env-id>\n  ```\n- There are many other useful platform cli subcommands.  Run `platform list`\n  to see them all.\n\n## Deploying bodiless packages from a private registry\n\nBy default the public regisry will be used to download bodiless packages: //registry.npmjs.org/\n\nIn order to switch to a private registry follow Step 3 (Create platform.sh environment variables.) of this doc.\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/johnsonandjohnson/bodiless-js/issues"},"_id":"@asemirsk/psh@1.0.0-canary-24-24.0","_nodeVersion":"16.13.2","_npmVersion":"lerna/4.0.0/node@v16.13.2+x64 (linux)","dist":{"integrity":"sha512-G5lOepnC40JUIMZK9aNdIyPcMKQTW0Wj52/gHuW87EhkBwNXBUT1dxOeS+QqjaTuahSX4HNPO8q4+OMbyIHSsw==","shasum":"d31ee7b4b97829ab70f4f5c23572504645b1d7d4","tarball":"https://registry.npmjs.org/@asemirsk/psh/-/psh-1.0.0-canary-24-24.0.tgz","fileCount":15,"unpackedSize":66976,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDhOzyBsxqRt/nrn+LeB/y57h3XhVwf7GEZIoAzY2fkpAiBtpftg8WNHoQ5uJoeIEW/V2Mn7iMqcqhwzAL8Qt8KzBg=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJijfQ+ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpnpBAAgWyd19Pufnfnz3hA20qaa1f1aU+ngHt8SYmxURL+x2vfDU1c\r\nd8OE8P0hvcpg2VdsJp5SC0GP/z95bJ9PGZsyuWlycebb7Om9Dh9n+/Ob0OGr\r\nPdeUKZcYtq08N+HjsXhNtiSqc4axBt25mwP3Gan+sOQSrdON1Mf/P2eGj9Zq\r\nSFQ76XDPL/AdapySlJD2rUE2YZCFN7u4HOMikY7Vj2sZbsS+Oi4PHX8zeLHq\r\nRXBks6Imv06HHK4dWbxX3dzTU8Z3Xa+1UVbKU+T7GZLtVj4lFHBttmXVr3Cz\r\n87z9ctAImdPf9F9dhA1KLn350+nLDzObG0siabXx3IgVXGq1O0EKttZYwJoK\r\nFpy8oBgpSQEF7AcbuhiktoyRtEEgvXftHVS6/cA1BOKYW8YGqpMEV3ZXJcTf\r\nM+snj/ZVDgxmW64hIC5V8kfV9DC60/KC2SebKCg1masaQEsoqgWRdTBRwQqz\r\nRNowwj8w2CmlKP5l2xCLTlEwewv4dsj6A2c7D32jauAvaQdFNmhvNhCBxTzq\r\nM7d4YlNvpd7NnUEbWLper3h4ULmXBpF1Plw7ODwyF0MHclR4NljMJ1Ar2BZu\r\n70yNuITntgHPIJC8IzzFbm3YTzIpjHEdrB7LUtnuKQRwZSuENZDNcjhiCl3a\r\nEl3Ei/XgsLZ1QpMY9NRnwBW6bSvhu2YsMH8=\r\n=ft5+\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"asemirsk","email":"al.semirski@gmail.com"},"maintainers":[{"name":"asemirsk","email":"al.semirski@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/psh_1.0.0-canary-24-24.0_1653470270083_0.6542077433205349"},"_hasShrinkwrap":false}},"maintainers":[{"name":"asemirsk","email":"al.semirski@gmail.com"}],"description":"Provides cli tool for initializing a bodiless project on platform.sh","homepage":"https://github.com/johnsonandjohnson/bodiless-js#readme","repository":{"type":"git","url":"git+https://github.com/johnsonandjohnson/bodiless-js.git"},"author":{"name":"Chris Oden","email":"coden@its.jnj.com"},"bugs":{"url":"https://github.com/johnsonandjohnson/bodiless-js/issues"},"license":"Apache-2.0","readme":"","readmeFilename":""}