Apps are bundled in packages. When a new version of a package is released, users are going to update the package, and with it all apps in the package. It may be necessary to apply changes to all instances of those apps, for example, when an attribute named foo is to be renamed to bar.

The .Update method is for this purpose: to update all affected files. (All files that are instances of apps of the updated package.)


Let’s assume you are the vendor of the package example.com, and you have a gallery app at example.com/gallery-1. Your app uses a string attribute foo that you want to rename to bar.

  • Rename /gallery-1 to /gallery-2 as you can’t reuse the application path.
  • Recreate the (now empty) file /gallery-1 and set its type to app-1.
  • Create the file /gallery-1/.Update.
  • Set the .Update file’s link property to path /gallery-2. (This documents that the /gallery-2 app supersedes the /gallery-1 app. Required to do updates one version at a time.)
  • Set its type to sjs-3 or any interpreter of your choice, and write the code that will do the transformation:
    • f will point to the instance being transformed.
    • Remember that f may have a longer typeChain to your app. It is guaranteed that the files on the typeChain of f will be updated after f itself. Thus, the typeChain of f ends in /gallery-1.
    • Rename the string attribute foo to bar.
    • Do NOT change the type of the file f to point to /gallery-2, it will be done automatically. In fact, it may not need to be updated, if there is a longer typeChain.
  • To update local instances of the app (eg. examples), see the sjs-3 os.updateInstances() method.

Updating an entire package is a single transaction.

Important note

In the above example, never ever remove the file /gallery-1. It makes sure that restoring an old version of a website will continue to just work.

Caveat emptor

  • Changing the .ContentSecurityPolicy rules of a website during an update is not currently supported. Get in touch if you need it implemented. Note that the website owner will have to approve .ContentSecurityPolicy changes every single time.
  • Packages are only updated when they are commited. (Read: they have no uncommited changes, that is, their undo chain is empty.)

Design considerations

  • Updating shall be idempotent. Run as often as you want, and always end up with the same result.
  • Updating shall not require access to previous versions of a package.
  • Updating any historical version of a package to the current state shall yield the same result. This is a common scenario due to having version control.
  • Support longer type chains, hide this complexity from developers.
Subscribe to our newsletter!