Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Convert all our config files to JSON5 #1088

Closed
octogonz opened this issue Feb 10, 2019 · 15 comments
Closed

Proposal: Convert all our config files to JSON5 #1088

octogonz opened this issue Feb 10, 2019 · 15 comments
Labels
design proposal A new direction that is complex enough to have open questions but specific enough to implement general discussion Not a bug or enhancement, just a discussion

Comments

@octogonz
Copy link
Collaborator

Problem

The web-build-tools repo has used .json config files for a long time. We've always put // comments in these files, because the proposition of an undocumented config file is preposterous and unprofessional. :-P

However, GitHub's syntax highlighter has the differing opinion that JSON standard (despite ironically being a REQUEST FOR COMMENTS) does not allow comments. And despite the father of JSON himself saying that comments are fine. It's making us look bad, because all our config files get red highlighting everywhere, like this:

/**
 * This is the main configuration file for Rush.
 * For full documentation, please see https://rushjs.io
 */
{
  "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush.schema.json",

  /**
   * (Required) This specifies the version of the Rush engine to be used in this repo.
   * Rush's "version selector" feature ensures that the globally installed tool will
   * behave like this release, regardless of which version is installed globally.
   *
   * The common/scripts/install-run-rush.js automation script also uses this version.
   *
   * NOTE: If you upgrade to a new major version of Rush, you should replace the "v5"
   * path segment in the "$schema" field for all your Rush config files.  This will ensure
   * correct error-underlining and tab-completion for editors such as VS Code.
   */
  "rushVersion": "5.5.4",

Investigation

Why doesn't JSON allow comments? It was originally intended as a machine-to-machine data format. Back when JSON was proposed, XML was already the accepted standard for large config files intended to be maintained by humans. Humans authoring JSON is a relatively new usage scenario that arose mainly with NodeJS, due to its lack of a decent XML library.

It seems like the JSON standard isn't going to fix this problem. I did some research, and here's the most obvious alternatives:

  • YAML: I don't like YAML because (1) the syntax has many redundant ways to express a given thing, so I've observed people constantly having trouble remembering exactly what the different symbols mean, and (2) parsing all this YAML grammar requires a library that is large and slow, and (3) YAML doesn't have a mature schema facility; they expect you to convert YAML to JSON and then use a JSON schema validator. I will say that I do like YAML as an output format (e.g. shrinkwrap.yaml) because it is concise and easy to diff, and the library allows you to disable the weird notations.

  • Hjson: This seems somewhat popular, however the syntax seems pretty counterintuitive and error-prone to me. For example, x: ab ef is translates to "x": "ab ef", whereas x: [ab ef] does not translate to "x": ["ab ef"] or "x": ["ab", "ef"].

  • jsonc: Not very popular. Its syntax is different from Hjson, and also seemed counterintuitive and error-prone. For example hey: [this needs no commas] translates to "hey": ["this", "needs", "no", "commas"] and {a : b c : d} translates to {"a": "b", "c": "d"}. (Also the name is confusingly similar to https://github.com/json-c/json-c which is a JSON parser written in C.)

  • JSON5: Out of the gate, JSON5 has the advantage that it's not trying to invent anything new. Their idea is to carve out a JSON-like subset of the ECMAScript 5 grammar that is already standardized and familiar to everyone. It's better than ECMAScript because this is a pure data representation (e.g. that can be described by a conventional JSON schema), and it can be read and rewritten with a relatively simple parser. Conveniently, the @microsoft/node-core-library JsonFile API is based on jju which already supports JSON5. (I didn't realize this, but you can already put JSON5 notation in rush.json and Rush doesn't complain. Oops!)

    The one concern I had with JSON5 was that ECMAScript is continually evolving: Their file extension is .json5 -- will we have to come back every year and rename all our file extensions to .json6 or .json7 or .json8 with each new JavaScript standard? Nobody does that with .js files. I opened an issue to ask about this, and they had a reasonable argument that newer ECMAScript versions have relatively little to contribute to the syntaxes relevant to JSON.

Proposal

  1. Let's convert all our config files to use JSON5.
  2. Let's rename the file extension to .json5 so GitHub highlights it correctly
  3. Let's fix the places where we write .json with non-JSON content (e.g. issue Ensure schema JSON documents are valid JSON #996)

What do you think? Comments welcome...

@mike-north @hogmoru @iclanton @daspek @patmill @dzearing @cliffkoh @kenotron

@octogonz octogonz added the general discussion Not a bug or enhancement, just a discussion label Feb 10, 2019
@octogonz
Copy link
Collaborator Author

BTW I noticed that VS Code's JSON language service supports comments using a library called jsonc-parser that accepts "JSON with JavaScript style comments" and no other syntax extensions besides that. (Not to be confused with jsonc which I mentioned above.)

@octogonz
Copy link
Collaborator Author

octogonz commented Feb 10, 2019

If you want JSON5 highlighting in VS Code, apparently it's not built-in. You have to install the JSON5 syntax extension. If you want this highlighter to operation on file with the .json file extension, you can add this to your VS Code settings.json:

"files.associations": { "*.json": "json5" }

@daspek
Copy link

daspek commented Feb 10, 2019

How big of a problem is the syntax highlighting in github? I would think that changing our file extension would be more confusing than leaving things as they are.

This problem can't be unique to us. I just perused the repos of a handful of popular open source projects. Most had comments in their .json files somewhere, complete with syntax highlighting errors. None had a json5 or jsonc or hjson file.

@octogonz
Copy link
Collaborator Author

How big of a problem is the syntax highlighting in github? I would think that changing our file extension would be more confusing than leaving things as they are.

VS Code is now following GitHub's convention and displaying rush.json with tons of red underlines everywhere. It seems like the community is deciding that "JSON is for machines," and we really should be using a different file format for human-editable config files.

JSON5 has all the right characteristics:

  • It preserves the character of JSON, and adds only a minimal set of enhancements
  • The enhancements are all 100% standardized by ECMAScript 5
  • The "5" in the file extension protects against further feature creep (if they make a JSON6, we'll probably choose not to adopt it, because JSON5 is good enough)
  • JSON5 is already fully implemented by our JSON parser and works with our existing schemas
  • There's a growing community of JavaScript developers adopting it

@daspek
Copy link

daspek commented Mar 11, 2019

I haven't personally seen evidence of the growing community of developers adopting json5. I do believe that most folks agree with the spirit, but i have never seen a "json5" file in the wild. and according to google trends there doesn't seem to be any appreciable movement. also reference this comparison of xml, json, and json5 over the last 5 years.

i still believe that the disruption from changing our file extension far outweighs any of the benefits.

@octogonz
Copy link
Collaborator Author

I think my "stake in the ground" is that my config files are going to have comments in them. And the syntax highlighters are not going to make them appear to be full of errors.

So it seems like the options are:

  • change the file extension to a JSON variant that allows comments
  • abandon JSON entirely
  • change VS Code and GitHub to accept comments in JSON files (both a matter of persuading some people at Microsoft)

I think I'd be okay with any of these options. Which one are you advocating?

@octogonz
Copy link
Collaborator Author

@zkochan just posted a Twitter poll announcing that PNPM will support package.json5. :-)

@chaseholdren
Copy link

.gitattributes file contents:

*.json                       linguist-language=JSON-with-Comments

sjBao pushed a commit to sjBao/coffee-kiosk that referenced this issue Jan 27, 2020
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..e2aabb8
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,14 @@
+# Don't allow people to merge changes to these generated files, because the result
+# may be invalid.  You need to run "rush update" again.
+pnpm-lock.yaml               merge=binary
+shrinkwrap.yaml              merge=binary
+npm-shrinkwrap.json          merge=binary
+yarn.lock                    merge=binary
+
+# Rush's JSON config files use JavaScript-style code comments.  The rule below prevents pedantic
+# syntax highlighters such as GitHub's from highlighting these comments as errors.  Your text editor
+# may also require a special configuration to allow comments in JSON.
+#
+# For more information, see this issue: microsoft/rushstack#1088
+#
+*.json                       linguist-language=JSON-with-Comments
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..93856b3
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,63 @@
+# Logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Runtime data
+*.pid
+*.seed
+*.pid.lock
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+
+# nyc test coverage
+.nyc_output
+
+# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# Bower dependency directory (https://bower.io/)
+bower_components
+
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (https://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directories
+node_modules/
+jspm_packages/
+
+# Optional npm cache directory
+.npm
+
+# Optional eslint cache
+.eslintcache
+
+# Optional REPL history
+.node_repl_history
+
+# Output of 'npm pack'
+*.tgz
+
+# Yarn Integrity file
+.yarn-integrity
+
+# dotenv environment variables file
+.env
+
+# next.js build output
+.next
+
+# OS X temporary files
+.DS_Store
+
+# Rush temporary files
+common/temp/
+**/.rush/temp/
diff --git a/common/config/rush/.npmrc b/common/config/rush/.npmrc
new file mode 100644
index 0000000..237d304
--- /dev/null
+++ b/common/config/rush/.npmrc
@@ -0,0 +1,12 @@
+# Rush uses this file to configure the package registry, regardless of whether the
+# package manager is PNPM, NPM, or Yarn.  Prior to invoking the package manager,
+# Rush will always copy this file to the folder where installation is performed.
+# When NPM is the package manager, Rush works around NPM's processing of
+# undefined environment variables by deleting any lines that reference undefined
+# environment variables.
+#
+# DO NOT SPECIFY AUTHENTICATION CREDENTIALS IN THIS FILE.  It should only be used
+# to configure registry sources.
+
+registry=https://registry.npmjs.org/
+always-auth=false
diff --git a/common/config/rush/command-line.json b/common/config/rush/command-line.json
new file mode 100644
index 0000000..3fcd7b0
--- /dev/null
+++ b/common/config/rush/command-line.json
@@ -0,0 +1,221 @@
+/**
+ * This configuration file defines custom commands for the "rush" command-line.
+ * For full documentation, please see https://rushjs.io
+ */
+{
+  "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/command-line.schema.json",
+
+  /**
+   * Custom "commands" introduce new verbs for the command-line.  To see the help for these
+   * example commands, try "rush --help", "rush my-bulk-command --help", or
+   * "rush my-global-command --help".
+   */
+  "commands": [
+    // {
+    //   /**
+    //    * (Required) Determines the type of custom command.
+    //    * Rush's "bulk" commands are invoked separately for each project.  Rush will look in
+    //    * each project's package.json file for a "scripts" entry whose name matches the
+    //    * command name.  By default, the command will run for every project in the repo,
+    //    * according to the dependency graph (similar to how "rush build" works).
+    //    * The set of projects can be restricted e.g. using the "--to" or "--from" parameters.
+    //    */
+    //   "commandKind": "bulk",
+    //
+    //   /**
+    //    * (Required) The name that will be typed as part of the command line.  This is also the name
+    //    * of the "scripts" hook in the project's package.json file.
+    //    * The name should be comprised of lower case words separated by hyphens or colons. The name should include an
+    //    * English verb (e.g. "deploy"). Use a hyphen to separate words (e.g. "upload-docs"). A group of related commands
+    //    * can be prefixed with a colon (e.g. "docs:generate", "docs:deploy", "docs:serve", etc).
+    //    */
+    //   "name": "my-bulk-command",
+    //
+    //   /**
+    //    * (Required) A short summary of the custom command to be shown when printing command line
+    //    * help, e.g. "rush --help".
+    //    */
+    //   "summary": "Example bulk custom command",
+    //
+    //   /**
+    //    * A detailed description of the command to be shown when printing command line
+    //    * help (e.g. "rush --help my-command").
+    //    * If omitted, the "summary" text will be shown instead.
+    //    *
+    //    * Whenever you introduce commands/parameters, taking a little time to write meaningful
+    //    * documentation can make a big difference for the developer experience in your repo.
+    //    */
+    //   "description": "This is an example custom command that runs separately for each project",
+    //
+    //   /**
+    //    * By default, Rush operations acquire a lock file which prevents multiple commands from executing simultaneously
+    //    * in the same repo folder.  (For example, it would be a mistake to run "rush install" and "rush build" at the
+    //    * same time.)  If your command makes sense to run concurrently with other operations,
+    //    * set "safeForSimultaneousRushProcesses" to true to disable this protection.
+    //    *
+    //    * In particular, this is needed for custom scripts that invoke other Rush commands.
+    //    */
+    //   "safeForSimultaneousRushProcesses": false,
+    //
+    //   /**
+    //    * (Required) If true, then this command is safe to be run in parallel, i.e. executed
+    //    * simultaneously for multiple projects.  Similar to "rush build", regardless of parallelism
+    //    * projects will not start processing until their dependencies have completed processing.
+    //    */
+    //   "enableParallelism": false,
+    //
+    //   /**
+    //    * Normally projects will be processed according to their dependency order: a given project will not start
+    //    * processing the command until all of its dependencies have completed.  This restriction doesn't apply for
+    //    * certain operations, for example a "clean" task that deletes output files.  In this case
+    //    * you can set "ignoreDependencyOrder" to true to increase parallelism.
+    //    */
+    //   "ignoreDependencyOrder": false,
+    //
+    //   /**
+    //    * Normally Rush requires that each project's package.json has a "scripts" entry matching
+    //    * the custom command name.  To disable this check, set "ignoreMissingScript" to true;
+    //    * projects with a missing definition will be skipped.
+    //    */
+    //   "ignoreMissingScript": false,
+    //
+    //   /**
+    //    * When invoking shell scripts, Rush uses a heuristic to distinguish errors from warnings:
+    //    * - If the shell script returns a nonzero process exit code, Rush interprets this as "one or more errors".
+    //    * Error output is displayed in red, and it prevents Rush from attempting to process any downstream projects.
+    //    * - If the shell script returns a zero process exit code but writes something to its stderr stream,
+    //    * Rush interprets this as "one or more warnings". Warning output is printed in yellow, but does NOT prevent
+    //    * Rush from processing downstream projects.
+    //    *
+    //    * Thus, warnings do not interfere with local development, but they will cause a CI job to fail, because
+    //    * the Rush process itself returns a nonzero exit code if there are any warnings or errors. This is by design.
+    //    * In an active monorepo, we've found that if you allow any warnings in your master branch, it inadvertently
+    //    * teaches developers to ignore warnings, which quickly leads to a situation where so many "expected" warnings
+    //    * have accumulated that warnings no longer serve any useful purpose.
+    //    *
+    //    * Sometimes a poorly behaved task will write output to stderr even though its operation was successful.
+    //    * In that case, it's strongly recommended to fix the task.  However, as a workaround you can set
+    //    * allowWarningsInSuccessfulBuild=true, which causes Rush to return a nonzero exit code for errors only.
+    //    *
+    //    * Note: The default value is false. In Rush 5.7.x and earlier, the default value was true.
+    //    */
+    //   "allowWarningsInSuccessfulBuild": false
+    // },
+    //
+    // {
+    //   /**
+    //    * (Required) Determines the type of custom command.
+    //    * Rush's "global" commands are invoked once for the entire repo.
+    //    */
+    //   "commandKind": "global",
+    //
+    //   "name": "my-global-command",
+    //   "summary": "Example global custom command",
+    //   "description": "This is an example custom command that runs once for the entire repo",
+    //
+    //   "safeForSimultaneousRushProcesses": false,
+    //
+    //   /**
+    //    * A script that will be invoked using the OS shell. The working directory will be the folder
+    //    * that contains rush.json.  If custom parameters are associated with this command, their
+    //    * values will be appended to the end of this string.
+    //    */
+    //   "shellCommand": "node common/scripts/my-global-command.js"
+    // }
+  ],
+
+  /**
+   * Custom "parameters" introduce new parameters for specified Rush command-line commands.
+   * For example, you might define a "--production" parameter for the "rush build" command.
+   */
+  "parameters": [
+    // {
+    //   /**
+    //    * (Required) Determines the type of custom parameter.
+    //    * A "flag" is a custom command-line parameter whose presence acts as an on/off switch.
+    //    */
+    //   "parameterKind": "flag",
+    //
+    //   /**
+    //    * (Required) The long name of the parameter.  It must be lower-case and use dash delimiters.
+    //    */
+    //   "longName": "--my-flag",
+    //
+    //   /**
+    //    * An optional alternative short name for the parameter.  It must be a dash followed by a single
+    //    * lower-case or upper-case letter, which is case-sensitive.
+    //    *
+    //    * NOTE: The Rush developers recommend that automation scripts should always use the long name
+    //    * to improve readability.  The short name is only intended as a convenience for humans.
+    //    * The alphabet letters run out quickly, and are difficult to memorize, so *only* use
+    //    * a short name if you expect the parameter to be needed very often in everyday operations.
+    //    */
+    //   "shortName": "-m",
+    //
+    //   /**
+    //    * (Required) A long description to be shown in the command-line help.
+    //    *
+    //    * Whenever you introduce commands/parameters, taking a little time to write meaningful
+    //    * documentation can make a big difference for the developer experience in your repo.
+    //    */
+    //   "description": "A custom flag parameter that is passed to the scripts that are invoked when building projects",
+    //
+    //   /**
+    //    * (Required) A list of custom commands and/or built-in Rush commands that this parameter may
+    //    * be used with.  The parameter will be appended to the shell command that Rush invokes.
+    //    */
+    //    "associatedCommands": [ "build", "rebuild" ]
+    // },
+    //
+    // {
+    //   /**
+    //    * (Required) Determines the type of custom parameter.
+    //    * A "flag" is a custom command-line parameter whose presence acts as an on/off switch.
+    //    */
+    //   "parameterKind": "choice",
+    //   "longName": "--my-choice",
+    //   "description": "A custom choice parameter for the \"my-global-command\" custom command",
+    //
+    //   "associatedCommands": [ "my-global-command" ],
+    //
+    //   /**
+    //    * Normally if a parameter is omitted from the command line, it will not be passed
+    //    * to the shell command. this value will be inserted by default.  Whereas if a "defaultValue"
+    //    * is defined, the parameter will always be passed to the shell command, and will use the
+    //    * default value if unspecified.  The value must be one of the defined alternatives.
+    //    */
+    //   "defaultValue": "vanilla",
+    //
+    //   /**
+    //    * (Required) A list of alternative argument values that can be chosen for this parameter.
+    //    */
+    //   "alternatives": [
+    //     {
+    //       /**
+    //        * A token that is one of the alternatives that can be used with the choice parameter,
+    //        * e.g. "vanilla" in "--flavor vanilla".
+    //        */
+    //       "name": "vanilla",
+    //
+    //       /**
+    //        * A detailed description for the alternative that can be shown in the command-line help.
+    //        *
+    //        * Whenever you introduce commands/parameters, taking a little time to write meaningful
+    //        * documentation can make a big difference for the developer experience in your repo.
+    //        */
+    //       "description": "Use the vanilla flavor (the default)"
+    //     },
+    //
+    //     {
+    //       "name": "chocolate",
+    //       "description": "Use the chocolate flavor"
+    //     },
+    //
+    //     {
+    //       "name": "strawberry",
+    //       "description": "Use the strawberry flavor"
+    //     }
+    //   ]
+    // }
+  ]
+}
diff --git a/common/config/rush/common-versions.json b/common/config/rush/common-versions.json
new file mode 100644
index 0000000..345c896
--- /dev/null
+++ b/common/config/rush/common-versions.json
@@ -0,0 +1,64 @@
+/**
+ * This configuration file specifies NPM dependency version selections that affect all projects
+ * in a Rush repo.  For full documentation, please see https://rushjs.io
+ */
+{
+  "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/common-versions.schema.json",
+
+  /**
+   * A table that specifies a "preferred version" for a given NPM package.  This feature is typically used
+   * to hold back an indirect dependency to a specific older version, or to reduce duplication of indirect dependencies.
+   *
+   * The "preferredVersions" value can be any SemVer range specifier (e.g. "~1.2.3").  Rush injects these values into
+   * the "dependencies" field of the top-level common/temp/package.json, which influences how the package manager
+   * will calculate versions.  The specific effect depends on your package manager.  Generally it will have no
+   * effect on an incompatible or already constrained SemVer range.  If you are using PNPM, similar effects can be
+   * achieved using the pnpmfile.js hook.  See the Rush documentation for more details.
+   *
+   * After modifying this field, it's recommended to run "rush update --full" so that the package manager
+   * will recalculate all version selections.
+   */
+  "preferredVersions": {
+
+    /**
+     * When someone asks for "^1.0.0" make sure they get "1.2.3" when working in this repo,
+     * instead of the latest version.
+     */
+    // "some-library": "1.2.3"
+  },
+
+  /**
+   * When set to true, for all projects in the repo, all dependencies will be automatically added as preferredVersions,
+   * except in cases where different projects specify different version ranges for a given dependency.  For older
+   * package managers, this tended to reduce duplication of indirect dependencies.  However, it can sometimes cause
+   * trouble for indirect dependencies with incompatible peerDependencies ranges.
+   *
+   * The default value is true.  If you're encountering installation errors related to peer dependencies,
+   * it's recommended to set this to false.
+   *
+   * After modifying this field, it's recommended to run "rush update --full" so that the package manager
+   * will recalculate all version selections.
+   */
+  // "implicitlyPreferredVersions": false,
+
+  /**
+   * The "rush check" command can be used to enforce that every project in the repo must specify
+   * the same SemVer range for a given dependency.  However, sometimes exceptions are needed.
+   * The allowedAlternativeVersions table allows you to list other SemVer ranges that will be
+   * accepted by "rush check" for a given dependency.
+   *
+   * IMPORTANT: THIS TABLE IS FOR *ADDITIONAL* VERSION RANGES THAT ARE ALTERNATIVES TO THE
+   * USUAL VERSION (WHICH IS INFERRED BY LOOKING AT ALL PROJECTS IN THE REPO).
+   * This design avoids unnecessary churn in this file.
+   */
+   "allowedAlternativeVersions": {
+
+    /**
+     * For example, allow some projects to use an older TypeScript compiler
+     * (in addition to whatever "usual" version is being used by other projects in the repo):
+     */
+    // "typescript": [
+    //   "~2.4.0"
+    // ]
+  }
+}
diff --git a/common/config/rush/experiments.json b/common/config/rush/experiments.json
new file mode 100644
index 0000000..b2e8c65
--- /dev/null
+++ b/common/config/rush/experiments.json
@@ -0,0 +1,16 @@
+/**
+ * This configuration file allows repo maintainers to enable and disable experimental
+ * Rush features. For full documentation, please see https://rushjs.io
+ */
+{
+  "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/experiments.schema.json",
+
+  /**
+    * Rush 5.14.0 improved incremental builds to ignore spurious changes in the pnpm-lock.json file.
+    * This optimization is enabled by default. If you encounter a problem where "rush build" is neglecting
+    * to build some projects, please open a GitHub issue. As a workaround you can uncomment this line
+    * to temporarily restore the old behavior where everything must be rebuilt whenever pnpm-lock.json
+    * is modified.
+    */
+  // "legacyIncrementalBuildDependencyDetection": true
+}
diff --git a/common/config/rush/pnpmfile.js b/common/config/rush/pnpmfile.js
new file mode 100644
index 0000000..2c7e5dc
--- /dev/null
+++ b/common/config/rush/pnpmfile.js
@@ -0,0 +1,38 @@
+"use strict";
+
+/**
+ * When using the PNPM package manager, you can use pnpmfile.js to workaround
+ * dependencies that have mistakes in their package.json file.  (This feature is
+ * functionally similar to Yarn's "resolutions".)
+ *
+ * For details, see the PNPM documentation:
+ * https://pnpm.js.org/docs/en/hooks.html
+ *
+ * IMPORTANT: SINCE THIS FILE CONTAINS EXECUTABLE CODE, MODIFYING IT IS LIKELY TO INVALIDATE
+ * ANY CACHED DEPENDENCY ANALYSIS.  After any modification to pnpmfile.js, it's recommended to run
+ * "rush update --full" so that PNPM will recalculate all version selections.
+ */
+module.exports = {
+  hooks: {
+    readPackage
+  }
+};
+
+/**
+ * This hook is invoked during installation before a package's dependencies
+ * are selected.
+ * The `packageJson` parameter is the deserialized package.json
+ * contents for the package that is about to be installed.
+ * The `context` parameter provides a log() function.
+ * The return value is the updated object.
+ */
+function readPackage(packageJson, context) {
+
+  // // The karma types have a missing dependency on typings from the log4js package.
+  // if (packageJson.name === '@types/karma') {
+  //  context.log('Fixed up dependencies for @types/karma');
+  //  packageJson.dependencies['log4js'] = '0.6.38';
+  // }
+
+  return packageJson;
+}
diff --git a/common/config/rush/version-policies.json b/common/config/rush/version-policies.json
new file mode 100644
index 0000000..dbe704b
--- /dev/null
+++ b/common/config/rush/version-policies.json
@@ -0,0 +1,90 @@
+/**
+ * This is configuration file is used for advanced publishing configurations with Rush.
+ * For full documentation, please see https://rushjs.io
+ */
+
+ /**
+  * A list of version policy definitions.  A "version policy" is a custom package versioning
+  * strategy that affects "rush change", "rush version", and "rush publish".  The strategy applies
+  * to a set of projects that are specified using the "versionPolicyName" field in rush.json.
+  */
+[
+  // {
+  //   /**
+  //    * (Required) Indicates the kind of version policy being defined ("lockStepVersion" or "individualVersion").
+  //    *
+  //    * The "lockStepVersion" mode specifies that the projects will use "lock-step versioning".  This
+  //    * strategy is appropriate for a set of packages that act as selectable components of a
+  //    * unified product.  The entire set of packages are always published together, and always share
+  //    * the same NPM version number.  When the packages depend on other packages in the set, the
+  //    * SemVer range is usually restricted to a single version.
+  //    */
+  //   "definitionName": "lockStepVersion",
+  //
+  //   /**
+  //    * (Required) The name that will be used for the "versionPolicyName" field in rush.json.
+  //    * This name is also used command-line parameters such as "--version-policy"
+  //    * and "--to-version-policy".
+  //    */
+  //   "policyName": "MyBigFramework",
+  //
+  //   /**
+  //    * (Required) The current version.  All packages belonging to the set should have this version
+  //    * in the current branch.  When bumping versions, Rush uses this to determine the next version.
+  //    * (The "version" field in package.json is NOT considered.)
+  //    */
+  //   "version": "1.0.0",
+  //
+  //   /**
+  //    * (Required) The type of bump that will be performed when publishing the next release.
+  //    * When creating a release branch in Git, this field should be updated according to the
+  //    * type of release.
+  //    *
+  //    * Valid values are: "prerelease", "release", "minor", "patch", "major"
+  //    */
+  //   "nextBump": "prerelease",
+  //
+  //   /**
+  //    * (Optional) If specified, all packages in the set share a common CHANGELOG.md file.
+  //    * This file is stored with the specified "main" project, which must be a member of the set.
+  //    *
+  //    * If this field is omitted, then a separate CHANGELOG.md file will be maintained for each
+  //    * package in the set.
+  //    */
+  //   "mainProject": "my-app"
+  // },
+  //
+  // {
+  //   /**
+  //    * (Required) Indicates the kind of version policy being defined ("lockStepVersion" or "individualVersion").
+  //    *
+  //    * The "individualVersion" mode specifies that the projects will use "individual versioning".
+  //    * This is the typical NPM model where each package has an independent version number
+  //    * and CHANGELOG.md file.  Although a single CI definition is responsible for publishing the
+  //    * packages, they otherwise don't have any special relationship.  The version bumping will
+  //    * depend on how developers answer the "rush change" questions for each package that
+  //    * is changed.
+  //    */
+  //   "definitionName": "individualVersion",
+  //
+  //   "policyName": "MyRandomLibraries",
+  //
+  //   /**
+  //    * (Optional) This can be used to enforce that all packages in the set must share a common
+  //    * major version number, e.g. because they are from the same major release branch.
+  //    * It can also be used to discourage people from accidentally making "MAJOR" SemVer changes
+  //    * inappropriately.  The minor/patch version parts will be bumped independently according
+  //    * to the types of changes made to each project, according to the "rush change" command.
+  //    */
+  //   "lockedMajor": 3,
+  //
+  //   /**
+  //    * (Optional) When publishing is managed by Rush, by default the "rush change" command will
+  //    * request changes for any projects that are modified by a pull request. These change entries
+  //    * will produce a CHANGELOG.md file. If you author your CHANGELOG.md manually or announce updates
+  //    * in some other way, set "exemptFromRushChange" to true to tell "rush change" to ignore the projects
+  //    * belonging to this version policy.
+  //    */
+  //   "exemptFromRushChange": false
+  // }
+]
diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..c4c6a86
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,5 @@
+# Coffee Kiosk
+This is a playground application where I am learning how to play with the following
+technologies:
+* RushJS - JavaScript Repository Manager
+* MobX - State Manager
diff --git a/rush.json b/rush.json
new file mode 100644
index 0000000..1f9e714
--- /dev/null
+++ b/rush.json
@@ -0,0 +1,368 @@
+/**
+ * This is the main configuration file for Rush.
+ * For full documentation, please see https://rushjs.io
+ */
+{
+  "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush.schema.json",
+
+  /**
+   * (Required) This specifies the version of the Rush engine to be used in this repo.
+   * Rush's "version selector" feature ensures that the globally installed tool will
+   * behave like this release, regardless of which version is installed globally.
+   *
+   * The common/scripts/install-run-rush.js automation script also uses this version.
+   *
+   * NOTE: If you upgrade to a new major version of Rush, you should replace the "v5"
+   * path segment in the "$schema" field for all your Rush config files.  This will ensure
+   * correct error-underlining and tab-completion for editors such as VS Code.
+   */
+  "rushVersion": "5.19.1",
+
+  /**
+   * The next field selects which package manager should be installed and determines its version.
+   * Rush installs its own local copy of the package manager to ensure that your build process
+   * is fully isolated from whatever tools are present in the local environment.
+   *
+   * Specify one of: "pnpmVersion", "npmVersion", or "yarnVersion".  See the Rush documentation
+   * for details about these alternatives.
+   */
+  "pnpmVersion": "2.15.1",
+
+  // "npmVersion": "4.5.0",
+  // "yarnVersion": "1.9.4",
+
+  /**
+   * Options that are only used when the PNPM package manager is selected
+   */
+  "pnpmOptions": {
+
+    /**
+     * If true, then Rush will add the "--strict-peer-dependencies" option when invoking PNPM.
+     * This causes "rush install" to fail if there are unsatisfied peer dependencies, which is
+     * an invalid state that can cause build failures or incompatible dependency versions.
+     * (For historical reasons, JavaScript package managers generally do not treat this invalid
+     * state as an error.)
+     *
+     * The default value is false to avoid legacy compatibility issues.
+     * It is strongly recommended to set strictPeerDependencies=true.
+     */
+    // "strictPeerDependencies": true,
+
+
+    /**
+     * Configures the strategy used to select versions during installation.
+     *
+     * This feature requires PNPM version 3.1 or newer.  It corresponds to the "--resolution-strategy" command-line
+     * option for PNPM.  Possible values are "fast" and "fewer-dependencies".  PNPM's default is "fast", but this may
+     * be incompatible with certain packages, for example the "@types" packages from DefinitelyTyped.  Rush's default
+     * is "fewer-dependencies", which causes PNPM to avoid installing a newer version if an already installed version
+     * can be reused; this is more similar to NPM's algorithm.
+     *
+     * After modifying this field, it's recommended to run "rush update --full" so that the package manager
+     * will recalculate all version selections.
+     */
+    // "resolutionStrategy": "fast"
+  },
+
+  /**
+   * Older releases of the Node.js engine may be missing features required by your system.
+   * Other releases may have bugs.  In particular, the "latest" version will not be a
+   * Long Term Support (LTS) version and is likely to have regressions.
+   *
+   * Specify a SemVer range to ensure developers use a Node.js version that is appropriate
+   * for your repo.
+   */
+  "nodeSupportedVersionRange": ">=10.13.0 <11.0.0",
+
+  /**
+  * Odd-numbered major versions of Node.js are experimental.  Even-numbered releases
+  * spend six months in a stabilization period before the first Long Term Support (LTS) version.
+  * For example, 8.9.0 was the first LTS version of Node.js 8.  Pre-LTS versions are not recommended
+  * for production usage because they frequently have bugs.  They may cause Rush itself
+  * to malfunction.
+  *
+  * Rush normally prints a warning if it detects a pre-LTS Node.js version.  If you are testing
+  * pre-LTS versions in preparation for supporting the first LTS version, you can use this setting
+  * to disable Rush's warning.
+  */
+  // "suppressNodeLtsWarning": false,
+
+  /**
+   * If you would like the version specifiers for your dependencies to be consistent, then
+   * uncomment this line. This is effectively similar to running "rush check" before any
+   * of the following commands:
+   *
+   *   rush install, rush update, rush link, rush version, rush publish
+   *
+   * In some cases you may want this turned on, but need to allow certain packages to use a different
+   * version. In those cases, you will need to add an entry to the "allowedAlternativeVersions"
+   * section of the common-versions.json.
+   */
+   // "ensureConsistentVersions": true,
+
+  /**
+   * Large monorepos can become intimidating for newcomers if project folder paths don't follow
+   * a consistent and recognizable pattern.  When the system allows nested folder trees,
+   * we've found that teams will often use subfolders to create islands that isolate
+   * their work from others ("shipping the org").  This hinders collaboration and code sharing.
+   *
+   * The Rush developers recommend a "category folder" model, where buildable project folders
+   * must always be exactly two levels below the repo root.  The parent folder acts as the category.
+   * This provides a basic facility for grouping related projects (e.g. "apps", "libaries",
+   * "tools", "prototypes") while still encouraging teams to organize their projects into
+   * a unified taxonomy.  Limiting to 2 levels seems very restrictive at first, but if you have
+   * 20 categories and 20 projects in each category, this scheme can easily accommodate hundreds
+   * of projects.  In practice, you will find that the folder hierarchy needs to be rebalanced
+   * occasionally, but if that's painful, it's a warning sign that your development style may
+   * discourage refactoring.  Reorganizing the categories should be an enlightening discussion
+   * that brings people together, and maybe also identifies poor coding practices (e.g. file
+   * references that reach into other project's folders without using Node.js module resolution).
+   *
+   * The defaults are projectFolderMinDepth=1 and projectFolderMaxDepth=2.
+   *
+   * To remove these restrictions, you could set projectFolderMinDepth=1
+   * and set projectFolderMaxDepth to a large number.
+   */
+  // "projectFolderMinDepth": 2,
+  // "projectFolderMaxDepth": 2,
+
+  /**
+   * This feature helps you to review and approve new packages before they are introduced
+   * to your monorepo.  For example, you may be concerned about licensing, code quality,
+   * performance, or simply accumulating too many libraries with overlapping functionality.
+   * The approvals are tracked in two config files "browser-approved-packages.json"
+   * and "nonbrowser-approved-packages.json".  See the Rush documentation for details.
+   */
+  // "approvedPackagesPolicy": {
+  //   /**
+  //    * The review categories allow you to say for example "This library is approved for usage
+  //    * in prototypes, but not in production code."
+  //    *
+  //    * Each project can be associated with one review category, by assigning the "reviewCategory" field
+  //    * in the "projects" section of rush.json.  The approval is then recorded in the files
+  //    * "common/config/rush/browser-approved-packages.json" and "nonbrowser-approved-packages.json"
+  //    * which are automatically generated during "rush update".
+  //    *
+  //    * Designate categories with whatever granularity is appropriate for your review process,
+  //    * or you could just have a single category called "default".
+  //    */
+  //   "reviewCategories": [
+  //     // Some example categories:
+  //     "production", // projects that ship to production
+  //     "tools",      // non-shipping projects that are part of the developer toolchain
+  //     "prototypes"  // experiments that should mostly be ignored by the review process
+  //   ],
+  //
+  //   /**
+  //    * A list of NPM package scopes that will be excluded from review.
+  //    * We recommend to exclude TypeScript typings (the "@types" scope), because
+  //    * if the underlying package was already approved, this would imply that the typings
+  //    * are also approved.
+  //    */
+  //   // "ignoredNpmScopes": [ "@types" ]
+  // },
+
+  /**
+   * If you use Git as your version control system, this section has some additional
+   * optional features you can use.
+   */
+  "gitPolicy": {
+    /**
+     * Work at a big company?  Tired of finding Git commits at work with unprofessional Git
+     * emails such as "beer-lover@my-college.edu"?  Rush can validate people's Git email address
+     * before they get started.
+     *
+     * Define a list of regular expressions describing allowable e-mail patterns for Git commits.
+     * They are case-insensitive anchored JavaScript RegExps.  Example: ".*@example\.com"
+     *
+     * IMPORTANT: Because these are regular expressions encoded as JSON string literals,
+     * RegExp escapes need two backspashes, and ordinary periods should be "\\.".
+     */
+    // "allowedEmailRegExps": [
+    //   "[^@]+@users\\.noreply\\.github\\.com",
+    //   "travis@example\\.org"
+    // ],
+
+    /**
+     * When Rush reports that the address is malformed, the notice can include an example
+     * of a recommended email.  Make sure it conforms to one of the allowedEmailRegExps
+     * expressions.
+     */
+    // "sampleEmail": "mrexample@users.noreply.github.com",
+
+    /**
+     * The commit message to use when committing changes during 'rush publish'.
+     *
+     * For example, if you want to prevent these commits from triggering a CI build,
+     * you might configure your system's trigger to look for a special string such as "[skip-ci]"
+     * in the commit message, and then customize Rush's message to contain that string.
+     */
+    // "versionBumpCommitMessage": "Applying package updates. [skip-ci]"
+  },
+
+  "repository": {
+    /**
+     * The URL of this Git repository, used by "rush change" to determine the base branch for your PR.
+     *
+     * The "rush change" command needs to determine which files are affected by your PR diff.
+     * If you merged or cherry-picked commits from the master branch into your PR branch, those commits
+     * should be excluded from this diff (since they belong to some other PR).  In order to do that,
+     * Rush needs to know where to find the base branch for your PR.  This information cannot be
+     * determined from Git alone, since the "pull request" feature is not a Git concept.  Ideally
+     * Rush would use a vendor-specific protocol to query the information from GitHub, Azure DevOps, etc.
+     * But to keep things simple, "rush change" simply assumes that your PR is against the "master" branch
+     * of the Git remote indicated by the respository.url setting in rush.json.  If you are working in
+     * a GitHub "fork" of the real repo, this setting will be different from the repository URL of your
+     * your PR branch, and in this situation "rush change" will also automatically invoke "git fetch"
+     * to retrieve the latest activity for the remote master branch.
+     */
+    // "url": "https://github.com/microsoft/rush-example",
+    // "defaultBranch": "master",
+    // "defaultRemote": "origin"
+  },
+
+  /**
+   * Event hooks are customized script actions that Rush executes when specific events occur
+   */
+  "eventHooks": {
+    /**
+     * The list of shell commands to run before the Rush installation starts
+     */
+    "preRushInstall": [
+      // "common/scripts/pre-rush-install.js"
+    ],
+
+    /**
+     * The list of shell commands to run after the Rush installation finishes
+     */
+    "postRushInstall": [],
+
+    /**
+     * The list of shell commands to run before the Rush build command starts
+     */
+    "preRushBuild": [],
+
+    /**
+     * The list of shell commands to run after the Rush build command finishes
+     */
+    "postRushBuild": []
+  },
+
+  /**
+   * Installation variants allow you to maintain a parallel set of configuration files that can be
+   * used to build the entire monorepo with an alternate set of dependencies.  For example, suppose
+   * you upgrade all your projects to use a new release of an important framework, but during a transition period
+   * you intend to maintain compability with the old release.  In this situation, you probably want your
+   * CI validation to build the entire repo twice: once with the old release, and once with the new release.
+   *
+   * Rush "installation variants" correspond to sets of config files located under this folder:
+   *
+   *   common/config/rush/variants/<variant_name>
+   *
+   * The variant folder can contain an alternate common-versions.json file.  Its "preferredVersions" field can be used
+   * to select older versions of dependencies (within a loose SemVer range specified in your package.json files).
+   * To install a variant, run "rush install --variant <variant_name>".
+   *
+   * For more details and instructions, see this article:  https://rushjs.io/pages/advanced/installation_variants/
+   */
+  "variants": [
+    // {
+    //   /**
+    //    * The folder name for this variant.
+    //    */
+    //   "variantName": "old-sdk",
+    //
+    //   /**
+    //    * An informative description
+    //    */
+    //   "description": "Build this repo using the previous release of the SDK"
+    // }
+  ],
+
+  /**
+   * Rush can collect anonymous telemetry about everyday developer activity such as
+   * success/failure of installs, builds, and other operations.  You can use this to identify
+   * problems with your toolchain or Rush itself.  THIS TELEMETRY IS NOT SHARED WITH MICROSOFT.
+   * It is written into JSON files in the common/temp folder.  It's up to you to write scripts
+   * that read these JSON files and do something with them.  These scripts are typically registered
+   * in the "eventHooks" section.
+   */
+  // "telemetryEnabled": false,
+
+  /**
+   * Allows creation of hotfix changes. This feature is experimental so it is disabled by default.
+   * If this is set, 'rush change' only allows a 'hotfix' change type to be specified. This change type
+   * will be used when publishing subsequent changes from the monorepo.
+   */
+  // "hotfixChangeEnabled": false,
+
+  /**
+   * (Required) This is the inventory of projects to be managed by Rush.
+   *
+   * Rush does not automatically scan for projects using wildcards, for a few reasons:
+   * 1. Depth-first scans are expensive, particularly when tools need to repeatedly collect the list.
+   * 2. On a caching CI machine, scans can accidentally pick up files left behind from a previous build.
+   * 3. It's useful to have a centralized inventory of all projects and their important metadata.
+   */
+  "projects": [
+    // {
+    //   /**
+    //    * The NPM package name of the project (must match package.json)
+    //    */
+    //   "packageName": "my-app",
+    //
+    //   /**
+    //    * The path to the project folder, relative to the rush.json config file.
+    //    */
+    //   "projectFolder": "apps/my-app",
+    //
+    //   /**
+    //    * An optional category for usage in the "browser-approved-packages.json"
+    //    * and "nonbrowser-approved-packages.json" files.  The value must be one of the
+    //    * strings from the "reviewCategories" defined above.
+    //    */
+    //   "reviewCategory": "production",
+    //
+    //   /**
+    //    * A list of local projects that appear as devDependencies for this project, but cannot be
+    //    * locally linked because it would create a cyclic dependency; instead, the last published
+    //    * version will be installed in the Common folder.
+    //    */
+    //   "cyclicDependencyProjects": [
+    //     // "my-toolchain"
+    //   ],
+    //
+    //   /**
+    //    * If true, then this project will be ignored by the "rush check" command.
+    //    * The default value is false.
+    //    */
+    //   // "skipRushCheck": false,
+    //
+    //   /**
+    //    * A flag indicating that changes to this project will be published to npm, which affects
+    //    * the Rush change and publish workflows. The default value is false.
+    //    * NOTE: "versionPolicyName" and "shouldPublish" are alternatives; you cannot specify them both.
+    //    */
+    //   // "shouldPublish": false,
+    //
+    //   /**
+    //    * An optional version policy associated with the project.  Version policies are defined
+    //    * in "version-policies.json" file.  See the "rush publish" documentation for more info.
+    //    * NOTE: "versionPolicyName" and "shouldPublish" are alternatives; you cannot specify them both.
+    //    */
+    //   // "versionPolicyName": ""
+    // },
+    //
+    // {
+    //   "packageName": "my-controls",
+    //   "projectFolder": "libraries/my-controls",
+    //   "reviewCategory": "production"
+    // },
+    //
+    // {
+    //   "packageName": "my-toolchain",
+    //   "projectFolder": "tools/my-toolchain",
+    //   "reviewCategory": "tools"
+    // }
+  ]
+}
@xiaoxiangmoe
Copy link

xiaoxiangmoe commented Apr 3, 2020

I'm using api-extractor run --local --verbose --config api-extractor.jsonc now.

jsonc means JSON-with-Comments in VSCode.

@alipi
Copy link

alipi commented May 20, 2021

Why not just use ESM?

rush.config.mjs

/**
 * This is the main configuration file for Rush.
 * For full documentation, please see https://rushjs.io
 */

export default {

   $schema: "https://developer.microsoft.com/json-schemas/rush/v5/rush.schema.json",

   /**
    * (Required) This specifies the version of the Rush engine to be used in this repo.
    * Rush's "version selector" feature ensures that the globally installed tool will
    * behave like this release, regardless of which version is installed globally.
    *
    * The common/scripts/install-run-rush.js automation script also uses this version.
    *
    * NOTE: If you upgrade to a new major version of Rush, you should replace the "v5"
    * path segment in the "$schema" field for all your Rush config files.  This will ensure
    * correct error-underlining and tab-completion for editors such as VS Code.
    */
   rushVersion: "5.47.0",

   // ...
};

rush.js

(async () => {
   try {
      const { default: config } = await import("./rush.config.mjs");
      console.log(config);
   }
   catch(ex) {
      console.error(ex);
   }
})();

output

{
  '$schema': 'https://developer.microsoft.com/json-schemas/rush/v5/rush.schema.json',
  rushVersion: '5.47.0'
}

soanvig pushed a commit to energywebfoundation/origin-247-sdk that referenced this issue Jun 24, 2021
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..e2aabb8
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,14 @@
+# Don't allow people to merge changes to these generated files, because the result
+# may be invalid.  You need to run "rush update" again.
+pnpm-lock.yaml               merge=binary
+shrinkwrap.yaml              merge=binary
+npm-shrinkwrap.json          merge=binary
+yarn.lock                    merge=binary
+
+# Rush's JSON config files use JavaScript-style code comments.  The rule below prevents pedantic
+# syntax highlighters such as GitHub's from highlighting these comments as errors.  Your text editor
+# may also require a special configuration to allow comments in JSON.
+#
+# For more information, see this issue: https://github.com/microsoft/rushstack/issues/1088
+#
+*.json                       linguist-language=JSON-with-Comments
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e5d9ae7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,65 @@
+# Logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Runtime data
+*.pid
+*.seed
+*.pid.lock
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+
+# nyc test coverage
+.nyc_output
+
+# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# Bower dependency directory (https://bower.io/)
+bower_components
+
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (https://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directories
+node_modules/
+jspm_packages/
+
+# Optional npm cache directory
+.npm
+
+# Optional eslint cache
+.eslintcache
+
+# Optional REPL history
+.node_repl_history
+
+# Output of 'npm pack'
+*.tgz
+
+# Yarn Integrity file
+.yarn-integrity
+
+# dotenv environment variables file
+.env
+
+# next.js build output
+.next
+
+# OS X temporary files
+.DS_Store
+
+# Rush temporary files
+common/deploy/
+common/temp/
+common/autoinstallers/*/.npmrc
+**/.rush/temp/
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..8f2bdb2
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,25 @@
+#-------------------------------------------------------------------------------------------------------------------
+# Keep this section in sync with .gitignore
+#-------------------------------------------------------------------------------------------------------------------
+
+👋 (copy + paste your .gitignore file contents here) 👋
+
+#-------------------------------------------------------------------------------------------------------------------
+# Prettier-specific overrides
+#-------------------------------------------------------------------------------------------------------------------
+
+# Rush files
+common/changes/
+common/scripts/
+common/config/
+CHANGELOG.*
+
+# Package manager files
+pnpm-lock.yaml
+yarn.lock
+package-lock.json
+shrinkwrap.json
+
+# Build outputs
+dist
+lib
\ No newline at end of file
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..ee879b2
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,8 @@
+{
+    "printWidth": 100,
+    "singleQuote": true,
+    "useTabs": false,
+    "semi": true,
+    "tabWidth": 4,
+    "trailingComma": "none"
+}
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e682eea
--- /dev/null
+++ b/README.md
@@ -0,0 +1,3 @@
+# Origin 24/7 SDK
+
+SDK for implementing Origin solutions in 24/7 mode - which is continuous certificate trade between sites.
diff --git a/common/autoinstallers/rush-prettier/package.json b/common/autoinstallers/rush-prettier/package.json
new file mode 100644
index 0000000..85ef25f
--- /dev/null
+++ b/common/autoinstallers/rush-prettier/package.json
@@ -0,0 +1,9 @@
+{
+    "name": "rush-prettier",
+    "version": "1.0.0",
+    "private": true,
+    "dependencies": {
+        "prettier": "^2.2.1",
+        "pretty-quick": "^3.1.0"
+    }
+}
diff --git a/common/autoinstallers/rush-prettier/pnpm-lock.yaml b/common/autoinstallers/rush-prettier/pnpm-lock.yaml
new file mode 100644
index 0000000..3cdbafe
--- /dev/null
+++ b/common/autoinstallers/rush-prettier/pnpm-lock.yaml
@@ -0,0 +1,325 @@
+dependencies:
+  prettier: 2.2.1
+  pretty-quick: 3.1.0_prettier@2.2.1
+lockfileVersion: 5.1
+packages:
+  /@types/minimatch/3.0.3:
+    dev: false
+    resolution:
+      integrity: sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
+  /ansi-styles/4.3.0:
+    dependencies:
+      color-convert: 2.0.1
+    dev: false
+    engines:
+      node: '>=8'
+    resolution:
+      integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
+  /array-differ/3.0.0:
+    dev: false
+    engines:
+      node: '>=8'
+    resolution:
+      integrity: sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==
+  /array-union/2.1.0:
+    dev: false
+    engines:
+      node: '>=8'
+    resolution:
+      integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
+  /arrify/2.0.1:
+    dev: false
+    engines:
+      node: '>=8'
+    resolution:
+      integrity: sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==
+  /balanced-match/1.0.0:
+    dev: false
+    resolution:
+      integrity: sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
+  /brace-expansion/1.1.11:
+    dependencies:
+      balanced-match: 1.0.0
+      concat-map: 0.0.1
+    dev: false
+    resolution:
+      integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
+  /chalk/3.0.0:
+    dependencies:
+      ansi-styles: 4.3.0
+      supports-color: 7.2.0
+    dev: false
+    engines:
+      node: '>=8'
+    resolution:
+      integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==
+  /color-convert/2.0.1:
+    dependencies:
+      color-name: 1.1.4
+    dev: false
+    engines:
+      node: '>=7.0.0'
+    resolution:
+      integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
+  /color-name/1.1.4:
+    dev: false
+    resolution:
+      integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
+  /concat-map/0.0.1:
+    dev: false
+    resolution:
+      integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
+  /cross-spawn/7.0.3:
+    dependencies:
+      path-key: 3.1.1
+      shebang-command: 2.0.0
+      which: 2.0.2
+    dev: false
+    engines:
+      node: '>= 8'
+    resolution:
+      integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
+  /end-of-stream/1.4.4:
+    dependencies:
+      once: 1.4.0
+    dev: false
+    resolution:
+      integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
+  /execa/4.1.0:
+    dependencies:
+      cross-spawn: 7.0.3
+      get-stream: 5.2.0
+      human-signals: 1.1.1
+      is-stream: 2.0.0
+      merge-stream: 2.0.0
+      npm-run-path: 4.0.1
+      onetime: 5.1.2
+      signal-exit: 3.0.3
+      strip-final-newline: 2.0.0
+    dev: false
+    engines:
+      node: '>=10'
+    resolution:
+      integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==
+  /find-up/4.1.0:
+    dependencies:
+      locate-path: 5.0.0
+      path-exists: 4.0.0
+    dev: false
+    engines:
+      node: '>=8'
+    resolution:
+      integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
+  /get-stream/5.2.0:
+    dependencies:
+      pump: 3.0.0
+    dev: false
+    engines:
+      node: '>=8'
+    resolution:
+      integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==
+  /has-flag/4.0.0:
+    dev: false
+    engines:
+      node: '>=8'
+    resolution:
+      integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
+  /human-signals/1.1.1:
+    dev: false
+    engines:
+      node: '>=8.12.0'
+    resolution:
+      integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==
+  /ignore/5.1.8:
+    dev: false
+    engines:
+      node: '>= 4'
+    resolution:
+      integrity: sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==
+  /is-stream/2.0.0:
+    dev: false
+    engines:
+      node: '>=8'
+    resolution:
+      integrity: sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==
+  /isexe/2.0.0:
+    dev: false
+    resolution:
+      integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
+  /locate-path/5.0.0:
+    dependencies:
+      p-locate: 4.1.0
+    dev: false
+    engines:
+      node: '>=8'
+    resolution:
+      integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==
+  /merge-stream/2.0.0:
+    dev: false
+    resolution:
+      integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
+  /mimic-fn/2.1.0:
+    dev: false
+    engines:
+      node: '>=6'
+    resolution:
+      integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
+  /minimatch/3.0.4:
+    dependencies:
+      brace-expansion: 1.1.11
+    dev: false
+    resolution:
+      integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
+  /mri/1.1.6:
+    dev: false
+    engines:
+      node: '>=4'
+    resolution:
+      integrity: sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ==
+  /multimatch/4.0.0:
+    dependencies:
+      '@types/minimatch': 3.0.3
+      array-differ: 3.0.0
+      array-union: 2.1.0
+      arrify: 2.0.1
+      minimatch: 3.0.4
+    dev: false
+    engines:
+      node: '>=8'
+    resolution:
+      integrity: sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==
+  /npm-run-path/4.0.1:
+    dependencies:
+      path-key: 3.1.1
+    dev: false
+    engines:
+      node: '>=8'
+    resolution:
+      integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==
+  /once/1.4.0:
+    dependencies:
+      wrappy: 1.0.2
+    dev: false
+    resolution:
+      integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
+  /onetime/5.1.2:
+    dependencies:
+      mimic-fn: 2.1.0
+    dev: false
+    engines:
+      node: '>=6'
+    resolution:
+      integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
+  /p-limit/2.3.0:
+    dependencies:
+      p-try: 2.2.0
+    dev: false
+    engines:
+      node: '>=6'
+    resolution:
+      integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
+  /p-locate/4.1.0:
+    dependencies:
+      p-limit: 2.3.0
+    dev: false
+    engines:
+      node: '>=8'
+    resolution:
+      integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==
+  /p-try/2.2.0:
+    dev: false
+    engines:
+      node: '>=6'
+    resolution:
+      integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
+  /path-exists/4.0.0:
+    dev: false
+    engines:
+      node: '>=8'
+    resolution:
+      integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
+  /path-key/3.1.1:
+    dev: false
+    engines:
+      node: '>=8'
+    resolution:
+      integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
+  /prettier/2.2.1:
+    dev: false
+    engines:
+      node: '>=10.13.0'
+    hasBin: true
+    resolution:
+      integrity: sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==
+  /pretty-quick/3.1.0_prettier@2.2.1:
+    dependencies:
+      chalk: 3.0.0
+      execa: 4.1.0
+      find-up: 4.1.0
+      ignore: 5.1.8
+      mri: 1.1.6
+      multimatch: 4.0.0
+      prettier: 2.2.1
+    dev: false
+    engines:
+      node: '>=10.13'
+    hasBin: true
+    peerDependencies:
+      prettier: '>=2.0.0'
+    resolution:
+      integrity: sha512-DtxIxksaUWCgPFN7E1ZZk4+Aav3CCuRdhrDSFZENb404sYMtuo9Zka823F+Mgeyt8Zt3bUiCjFzzWYE9LYqkmQ==
+  /pump/3.0.0:
+    dependencies:
+      end-of-stream: 1.4.4
+      once: 1.4.0
+    dev: false
+    resolution:
+      integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
+  /shebang-command/2.0.0:
+    dependencies:
+      shebang-regex: 3.0.0
+    dev: false
+    engines:
+      node: '>=8'
+    resolution:
+      integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
+  /shebang-regex/3.0.0:
+    dev: false
+    engines:
+      node: '>=8'
+    resolution:
+      integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
+  /signal-exit/3.0.3:
+    dev: false
+    resolution:
+      integrity: sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
+  /strip-final-newline/2.0.0:
+    dev: false
+    engines:
+      node: '>=6'
+    resolution:
+      integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
+  /supports-color/7.2.0:
+    dependencies:
+      has-flag: 4.0.0
+    dev: false
+    engines:
+      node: '>=8'
+    resolution:
+      integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
+  /which/2.0.2:
+    dependencies:
+      isexe: 2.0.0
+    dev: false
+    engines:
+      node: '>= 8'
+    hasBin: true
+    resolution:
+      integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
+  /wrappy/1.0.2:
+    dev: false
+    resolution:
+      integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
+specifiers:
+  prettier: ^2.2.1
+  pretty-quick: ^3.1.0
diff --git a/common/autoinstallers/rush-tools/package.json b/common/autoinstallers/rush-tools/package.json
new file mode 100644
index 0000000..169abf0
--- /dev/null
+++ b/common/autoinstallers/rush-tools/package.json
@@ -0,0 +1,8 @@
+{
+    "name": "rush-tools",
+    "version": "1.0.0",
+    "private": true,
+    "dependencies": {
+        "concurrently": "5.3.0"
+    }
+}
diff --git a/common/autoinstallers/rush-tools/pnpm-lock.yaml b/common/autoinstallers/rush-tools/pnpm-lock.yaml
new file mode 100644
index 0000000..11e3ed2
--- /dev/null
+++ b/common/autoinstallers/rush-tools/pnpm-lock.yaml
@@ -0,0 +1,384 @@
+dependencies:
+    concurrently: 5.3.0
+lockfileVersion: 5.1
+packages:
+    /ansi-regex/4.1.0:
+        dev: false
+        engines:
+            node: '>=6'
+        resolution:
+            integrity: sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
+    /ansi-styles/3.2.1:
+        dependencies:
+            color-convert: 1.9.3
+        dev: false
+        engines:
+            node: '>=4'
+        resolution:
+            integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
+    /camelcase/5.3.1:
+        dev: false
+        engines:
+            node: '>=6'
+        resolution:
+            integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
+    /chalk/2.4.2:
+        dependencies:
+            ansi-styles: 3.2.1
+            escape-string-regexp: 1.0.5
+            supports-color: 5.5.0
+        dev: false
+        engines:
+            node: '>=4'
+        resolution:
+            integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
+    /cliui/5.0.0:
+        dependencies:
+            string-width: 3.1.0
+            strip-ansi: 5.2.0
+            wrap-ansi: 5.1.0
+        dev: false
+        resolution:
+            integrity: sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==
+    /color-convert/1.9.3:
+        dependencies:
+            color-name: 1.1.3
+        dev: false
+        resolution:
+            integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
+    /color-name/1.1.3:
+        dev: false
+        resolution:
+            integrity: sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
+    /concurrently/5.3.0:
+        dependencies:
+            chalk: 2.4.2
+            date-fns: 2.16.1
+            lodash: 4.17.20
+            read-pkg: 4.0.1
+            rxjs: 6.6.3
+            spawn-command: 0.0.2-1
+            supports-color: 6.1.0
+            tree-kill: 1.2.2
+            yargs: 13.3.2
+        dev: false
+        engines:
+            node: '>=6.0.0'
+        hasBin: true
+        resolution:
+            integrity: sha512-8MhqOB6PWlBfA2vJ8a0bSFKATOdWlHiQlk11IfmQBPaHVP8oP2gsh2MObE6UR3hqDHqvaIvLTyceNW6obVuFHQ==
+    /date-fns/2.16.1:
+        dev: false
+        engines:
+            node: '>=0.11'
+        resolution:
+            integrity: sha512-sAJVKx/FqrLYHAQeN7VpJrPhagZc9R4ImZIWYRFZaaohR3KzmuK88touwsSwSVT8Qcbd4zoDsnGfX4GFB4imyQ==
+    /decamelize/1.2.0:
+        dev: false
+        engines:
+            node: '>=0.10.0'
+        resolution:
+            integrity: sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
+    /emoji-regex/7.0.3:
+        dev: false
+        resolution:
+            integrity: sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
+    /error-ex/1.3.2:
+        dependencies:
+            is-arrayish: 0.2.1
+        dev: false
+        resolution:
+            integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
+    /escape-string-regexp/1.0.5:
+        dev: false
+        engines:
+            node: '>=0.8.0'
+        resolution:
+            integrity: sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
+    /find-up/3.0.0:
+        dependencies:
+            locate-path: 3.0.0
+        dev: false
+        engines:
+            node: '>=6'
+        resolution:
+            integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==
+    /function-bind/1.1.1:
+        dev: false
+        resolution:
+            integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
+    /get-caller-file/2.0.5:
+        dev: false
+        engines:
+            node: 6.* || 8.* || >= 10.*
+        resolution:
+            integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
+    /has-flag/3.0.0:
+        dev: false
+        engines:
+            node: '>=4'
+        resolution:
+            integrity: sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
+    /has/1.0.3:
+        dependencies:
+            function-bind: 1.1.1
+        dev: false
+        engines:
+            node: '>= 0.4.0'
+        resolution:
+            integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
+    /hosted-git-info/2.8.8:
+        dev: false
+        resolution:
+            integrity: sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==
+    /is-arrayish/0.2.1:
+        dev: false
+        resolution:
+            integrity: sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
+    /is-core-module/2.2.0:
+        dependencies:
+            has: 1.0.3
+        dev: false
+        resolution:
+            integrity: sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==
+    /is-fullwidth-code-point/2.0.0:
+        dev: false
+        engines:
+            node: '>=4'
+        resolution:
+            integrity: sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
+    /json-parse-better-errors/1.0.2:
+        dev: false
+        resolution:
+            integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==
+    /locate-path/3.0.0:
+        dependencies:
+            p-locate: 3.0.0
+            path-exists: 3.0.0
+        dev: false
+        engines:
+            node: '>=6'
+        resolution:
+            integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==
+    /lodash/4.17.20:
+        dev: false
+        resolution:
+            integrity: sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
+    /normalize-package-data/2.5.0:
+        dependencies:
+            hosted-git-info: 2.8.8
+            resolve: 1.19.0
+            semver: 5.7.1
+            validate-npm-package-license: 3.0.4
+        dev: false
+        resolution:
+            integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==
+    /p-limit/2.3.0:
+        dependencies:
+            p-try: 2.2.0
+        dev: false
+        engines:
+            node: '>=6'
+        resolution:
+            integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
+    /p-locate/3.0.0:
+        dependencies:
+            p-limit: 2.3.0
+        dev: false
+        engines:
+            node: '>=6'
+        resolution:
+            integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==
+    /p-try/2.2.0:
+        dev: false
+        engines:
+            node: '>=6'
+        resolution:
+            integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
+    /parse-json/4.0.0:
+        dependencies:
+            error-ex: 1.3.2
+            json-parse-better-errors: 1.0.2
+        dev: false
+        engines:
+            node: '>=4'
+        resolution:
+            integrity: sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=
+    /path-exists/3.0.0:
+        dev: false
+        engines:
+            node: '>=4'
+        resolution:
+            integrity: sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=
+    /path-parse/1.0.6:
+        dev: false
+        resolution:
+            integrity: sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
+    /pify/3.0.0:
+        dev: false
+        engines:
+            node: '>=4'
+        resolution:
+            integrity: sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=
+    /read-pkg/4.0.1:
+        dependencies:
+            normalize-package-data: 2.5.0
+            parse-json: 4.0.0
+            pify: 3.0.0
+        dev: false
+        engines:
+            node: '>=6'
+        resolution:
+            integrity: sha1-ljYlN48+HE1IyFhytabsfV0JMjc=
+    /require-directory/2.1.1:
+        dev: false
+        engines:
+            node: '>=0.10.0'
+        resolution:
+            integrity: sha1-jGStX9MNqxyXbiNE/+f3kqam30I=
+    /require-main-filename/2.0.0:
+        dev: false
+        resolution:
+            integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
+    /resolve/1.19.0:
+        dependencies:
+            is-core-module: 2.2.0
+            path-parse: 1.0.6
+        dev: false
+        resolution:
+            integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==
+    /rxjs/6.6.3:
+        dependencies:
+            tslib: 1.14.1
+        dev: false
+        engines:
+            npm: '>=2.0.0'
+        resolution:
+            integrity: sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==
+    /semver/5.7.1:
+        dev: false
+        hasBin: true
+        resolution:
+            integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
+    /set-blocking/2.0.0:
+        dev: false
+        resolution:
+            integrity: sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
+    /spawn-command/0.0.2-1:
+        dev: false
+        resolution:
+            integrity: sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=
+    /spdx-correct/3.1.1:
+        dependencies:
+            spdx-expression-parse: 3.0.1
+            spdx-license-ids: 3.0.7
+        dev: false
+        resolution:
+            integrity: sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==
+    /spdx-exceptions/2.3.0:
+        dev: false
+        resolution:
+            integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==
+    /spdx-expression-parse/3.0.1:
+        dependencies:
+            spdx-exceptions: 2.3.0
+            spdx-license-ids: 3.0.7
+        dev: false
+        resolution:
+            integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==
+    /spdx-license-ids/3.0.7:
+        dev: false
+        resolution:
+            integrity: sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==
+    /string-width/3.1.0:
+        dependencies:
+            emoji-regex: 7.0.3
+            is-fullwidth-code-point: 2.0.0
+            strip-ansi: 5.2.0
+        dev: false
+        engines:
+            node: '>=6'
+        resolution:
+            integrity: sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==
+    /strip-ansi/5.2.0:
+        dependencies:
+            ansi-regex: 4.1.0
+        dev: false
+        engines:
+            node: '>=6'
+        resolution:
+            integrity: sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==
+    /supports-color/5.5.0:
+        dependencies:
+            has-flag: 3.0.0
+        dev: false
+        engines:
+            node: '>=4'
+        resolution:
+            integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
+    /supports-color/6.1.0:
+        dependencies:
+            has-flag: 3.0.0
+        dev: false
+        engines:
+            node: '>=6'
+        resolution:
+            integrity: sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==
+    /tree-kill/1.2.2:
+        dev: false
+        hasBin: true
+        resolution:
+            integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==
+    /tslib/1.14.1:
+        dev: false
+        resolution:
+            integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
+    /validate-npm-package-license/3.0.4:
+        dependencies:
+            spdx-correct: 3.1.1
+            spdx-expression-parse: 3.0.1
+        dev: false
+        resolution:
+            integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==
+    /which-module/2.0.0:
+        dev: false
+        resolution:
+            integrity: sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
+    /wrap-ansi/5.1.0:
+        dependencies:
+            ansi-styles: 3.2.1
+            string-width: 3.1.0
+            strip-ansi: 5.2.0
+        dev: false
+        engines:
+            node: '>=6'
+        resolution:
+            integrity: sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==
+    /y18n/4.0.1:
+        dev: false
+        resolution:
+            integrity: sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==
+    /yargs-parser/13.1.2:
+        dependencies:
+            camelcase: 5.3.1
+            decamelize: 1.2.0
+        dev: false
+        resolution:
+            integrity: sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==
+    /yargs/13.3.2:
+        dependencies:
+            cliui: 5.0.0
+            find-up: 3.0.0
+            get-caller-file: 2.0.5
+            require-directory: 2.1.1
+            require-main-filename: 2.0.0
+            set-blocking: 2.0.0
+            string-width: 3.1.0
+            which-module: 2.0.0
+            y18n: 4.0.1
+            yargs-parser: 13.1.2
+        dev: false
+        resolution:
+            integrity: sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==
+specifiers:
+    concurrently: 5.3.0
diff --git a/common/config/.eslintrc.js b/common/config/.eslintrc.js
new file mode 100644
index 0000000..f0f1496
--- /dev/null
+++ b/common/config/.eslintrc.js
@@ -0,0 +1,65 @@
+module.exports = {
+    env: {
+        browser: true,
+        es6: true,
+        node: true,
+        mocha: true
+    },
+    extends: [
+        'airbnb-base',
+        'plugin:@typescript-eslint/recommended',
+        'prettier/@typescript-eslint',
+        'plugin:prettier/recommended'
+    ],
+    globals: {
+        Atomics: 'readonly',
+        SharedArrayBuffer: 'readonly'
+    },
+    parser: '@typescript-eslint/parser',
+    parserOptions: {
+        ecmaVersion: 2018,
+        sourceType: 'module'
+    },
+    plugins: ['@typescript-eslint'],
+    rules: {
+        '@typescript-eslint/explicit-function-return-type': 'off',
+        '@typescript-eslint/naming-convention': [
+            'error',
+            {
+                selector: 'interface',
+                format: ['PascalCase'],
+                prefix: ['I']
+            }
+        ],
+        '@typescript-eslint/no-unused-vars': 'error',
+        'no-await-in-loop': 'off',
+        'no-plusplus': 'off',
+        'no-console': 'off',
+        'no-continue': 'off',
+        'import/prefer-default-export': 'off',
+        'no-restricted-syntax': 'off',
+        'no-constant-condition': 'off',
+        'class-methods-use-this': 'off',
+        'no-underscore-dangle': 'off',
+        'no-bitwise': 'off',
+        'no-restricted-properties': 'off',
+        'import/extensions': [
+            'error',
+            'ignorePackages',
+            {
+                js: 'never',
+                jsx: 'never',
+                ts: 'never',
+                tsx: 'never'
+            }
+        ],
+        'no-useless-constructor': 'off'
+    },
+    settings: {
+        'import/resolver': {
+            node: {
+                extensions: ['.js', '.jsx', '.ts', '.tsx', '.d.ts']
+            }
+        }
+    }
+};
diff --git a/common/config/rush/.npmrc b/common/config/rush/.npmrc
new file mode 100644
index 0000000..c5980e6
--- /dev/null
+++ b/common/config/rush/.npmrc
@@ -0,0 +1,22 @@
+# Rush uses this file to configure the NPM package registry during installation.  It is applicable
+# to PNPM, NPM, and Yarn package managers.  It is used by operations such as "rush install",
+# "rush update", and the "install-run.js" scripts.
+#
+# NOTE: The "rush publish" command uses .npmrc-publish instead.
+#
+# Before invoking the package manager, Rush will copy this file to the folder where installation
+# is performed.  The copied file will omit any config lines that reference environment variables
+# that are undefined in that session; this avoids problems that would otherwise result due to
+# a missing variable being replaced by an empty string.
+#
+# * * * SECURITY WARNING * * *
+#
+# It is NOT recommended to store authentication tokens in a text file on a lab machine, because
+# other unrelated processes may be able to read the file.  Also, the file may persist indefinitely,
+# for example if the machine loses power.  A safer practice is to pass the token via an
+# environment variable, which can be referenced from .npmrc using ${} expansion.  For example:
+#
+#   //registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN}
+#
+registry=https://registry.npmjs.org/
+always-auth=false
diff --git a/common/config/rush/.npmrc-publish b/common/config/rush/.npmrc-publish
new file mode 100644
index 0000000..26b3b48
--- /dev/null
+++ b/common/config/rush/.npmrc-publish
@@ -0,0 +1,20 @@
+# This config file is very similar to common/config/rush/.npmrc, except that .npmrc-publish
+# is used by the "rush publish" command, as publishing often involves different credentials
+# and registries than other operations.
+#
+# Before invoking the package manager, Rush will copy this file to "common/temp/publish-home/.npmrc"
+# and then temporarily map that folder as the "home directory" for the current user account.
+# This enables the same settings to apply for each project folder that gets published.  The copied file
+# will omit any config lines that reference environment variables that are undefined in that session;
+# this avoids problems that would otherwise result due to a missing variable being replaced by
+# an empty string.
+#
+# * * * SECURITY WARNING * * *
+#
+# It is NOT recommended to store authentication tokens in a text file on a lab machine, because
+# other unrelated processes may be able to read the file.  Also, the file may persist indefinitely,
+# for example if the machine loses power.  A safer practice is to pass the token via an
+# environment variable, which can be referenced from .npmrc using ${} expansion.  For example:
+#
+#   //registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN}
+#
diff --git a/common/config/rush/.pnpmfile.cjs b/common/config/rush/.pnpmfile.cjs
new file mode 100644
index 0000000..9456174
--- /dev/null
+++ b/common/config/rush/.pnpmfile.cjs
@@ -0,0 +1,38 @@
+'use strict';
+
+/**
+ * When using the PNPM package manager, you can use pnpmfile.js to workaround
+ * dependencies that have mistakes in their package.json file.  (This feature is
+ * functionally similar to Yarn's "resolutions".)
+ *
+ * For details, see the PNPM documentation:
+ * https://pnpm.js.org/docs/en/hooks.html
+ *
+ * IMPORTANT: SINCE THIS FILE CONTAINS EXECUTABLE CODE, MODIFYING IT IS LIKELY TO INVALIDATE
+ * ANY CACHED DEPENDENCY ANALYSIS.  After any modification to pnpmfile.js, it's recommended to run
+ * "rush update --full" so that PNPM will recalculate all version selections.
+ */
+module.exports = {
+  hooks: {
+    readPackage
+  }
+};
+
+/**
+ * This hook is invoked during installation before a package's dependencies
+ * are selected.
+ * The `packageJson` parameter is the deserialized package.json
+ * contents for the package that is about to be installed.
+ * The `context` parameter provides a log() function.
+ * The return value is the updated object.
+ */
+function readPackage(packageJson, context) {
+
+  // // The karma types have a missing dependency on typings from the log4js package.
+  // if (packageJson.name === '@types/karma') {
+  //  context.log('Fixed up dependencies for @types/karma');
+  //  packageJson.dependencies['log4js'] = '0.6.38';
+  // }
+
+  return packageJson;
+}
diff --git a/common/config/rush/artifactory.json b/common/config/rush/artifactory.json
new file mode 100644
index 0000000..fd5a071
--- /dev/null
+++ b/common/config/rush/artifactory.json
@@ -0,0 +1,85 @@
+/**
+ * This configuration file manages Rush integration with JFrog Artifactory services.
+ * More documentation is available on the Rush website: https://rushjs.io
+ */
+{
+  "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/artifactory.schema.json",
+
+  "packageRegistry": {
+    /**
+     * (Required) Set this to "true" to enable Rush to manage tokens for an Artifactory NPM registry.
+     * When enabled, "rush install" will automatically detect when the user's ~/.npmrc
+     * authentication token is missing or expired.  And "rush setup" will prompt the user to
+     * renew their token.
+     *
+     * The default value is false.
+     */
+    "enabled": false,
+
+    /**
+     * (Required) Specify the URL of your NPM registry.  This is the same URL that appears in
+     * your .npmrc file.  It should look something like this example:
+     *
+     *   https://your-company.jfrog.io/your-project/api/npm/npm-private/
+     */
+    "registryUrl": "",
+
+    /**
+     * A list of custom strings that "rush setup" should add to the user's ~/.npmrc file at the time
+     * when the token is updated.  This could be used for example to configure the company registry
+     * to be used whenever NPM is invoked as a standalone command (but it's not needed for Rush
+     * operations like "rush add" and "rush install", which get their mappings from the monorepo's
+     * common/config/rush/.npmrc file).
+     *
+     * NOTE: The ~/.npmrc settings are global for the user account on a given machine, so be careful
+     * about adding settings that may interfere with other work outside the monorepo.
+     */
+    "userNpmrcLinesToAdd": [
+      // "@example:registry=https://your-company.jfrog.io/your-project/api/npm/npm-private/"
+    ],
+
+    /**
+     * (Required) Specifies the URL of the Artifactory control panel where the user can generate
+     * an API key.  This URL is printed after the "visitWebsite" message.
+     * It should look something like this example:  https://your-company.jfrog.io/
+     * Specify an empty string to suppress this line entirely.
+     */
+    "artifactoryWebsiteUrl": "",
+
+    /**
+     * These settings allow the "rush setup" interactive prompts to be customized, for
+     * example with messages specific to your team or configuration.  Specify an empty string
+     * to suppress that message entirely.
+     */
+    "messageOverrides": {
+      /**
+       * Overrides the message that normally says:
+       * "This monorepo consumes packages from an Artifactory private NPM registry."
+       */
+      // "introduction": "",
+      /**
+       * Overrides the message that normally says:
+       * "Please contact the repository maintainers for help with setting up an Artifactory user account."
+       */
+      // "obtainAnAccount": "",
+      /**
+       * Overrides the message that normally says:
+       * "Please open this URL in your web browser:"
+       *
+       * The "artifactoryWebsiteUrl" string is printed after this message.
+       */
+      // "visitWebsite": "",
+      /**
+       * Overrides the message that normally says:
+       * "Your user name appears in the upper-right corner of the JFrog website."
+       */
+      // "locateUserName": "",
+      /**
+       * Overrides the message that normally says:
+       * "Click 'Edit Profile' on the JFrog website.  Click the 'Generate API Key'
+       * button if you haven't already done so previously."
+       */
+      // "locateApiKey": ""
+    }
+  }
+}
diff --git a/common/config/rush/build-cache.json b/common/config/rush/build-cache.json
new file mode 100644
index 0000000..c1d7f8a
--- /dev/null
+++ b/common/config/rush/build-cache.json
@@ -0,0 +1,84 @@
+/**
+ * This configuration file manages Rush's build cache feature.
+ * More documentation is available on the Rush website: https://rushjs.io
+ */
+ {
+  "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/build-cache.schema.json",
+
+  /**
+   * (Required) EXPERIMENTAL - Set this to true to enable the build cache feature.
+   *
+   * See https://rushjs.io/pages/maintainer/build_cache/ for details about this experimental feature.
+   */
+  "buildCacheEnabled": false,
+
+  /**
+   * (Required) Choose where project build outputs will be cached.
+   *
+   * Possible values: "local-only", "azure-blob-storage", "amazon-s3"
+   */
+  "cacheProvider": "local-only",
+
+  /**
+   * Setting this property overrides the cache entry ID.  If this property is set, it must contain
+   * a [hash] token. It may also contain a [projectName] or a [projectName:normalized] token.
+   */
+  // "cacheEntryNamePattern": "[projectName:normalized]-[hash]"
+
+  /**
+   * Use this configuration with "cacheProvider"="azure-blob-storage"
+   */
+  "azureBlobStorageConfiguration": {
+    /**
+     * (Required) The name of the the Azure storage account to use for build cache.
+     */
+    // "storageAccountName": "example",
+
+    /**
+     * (Required) The name of the container in the Azure storage account to use for build cache.
+     */
+    // "storageContainerName": "my-container",
+
+    /**
+     * The Azure environment the storage account exists in. Defaults to AzurePublicCloud.
+     *
+     * Possible values: "AzurePublicCloud", "AzureChina", "AzureGermany", "AzureGovernment"
+     */
+    // "azureEnvironment": "AzurePublicCloud",
+
+    /**
+     * An optional prefix for cache item blob names.
+     */
+    // "blobPrefix": "my-prefix",
+
+    /**
+     * If set to true, allow writing to the cache. Defaults to false.
+     */
+    // "isCacheWriteAllowed": true
+  },
+
+  /**
+   * Use this configuration with "cacheProvider"="amazon-s3"
+   */
+  "amazonS3Configuration": {
+    /**
+     * (Required) The Amazon S3 region of the bucket to use for build cache (e.g. "us-east-1").
+     */
+    // "s3Region": "us-east-1",
+
+    /**
+     * The name of the bucket in Amazon S3 to use for build cache.
+     */
+    // (Required) "s3Bucket": "my-bucket",
+
+    /**
+     * An optional prefix ("folder") for cache items.
+     */
+    // "s3Prefix": "my-prefix",
+
+    /**
+     * If set to true, allow writing to the cache. Defaults to false.
+     */
+    // "isCacheWriteAllowed": true
+  }
+}
diff --git a/common/config/rush/command-line.json b/common/config/rush/command-line.json
new file mode 100644
index 0000000..86e9c3d
--- /dev/null
+++ b/common/config/rush/command-line.json
@@ -0,0 +1,297 @@
+/**
+ * This configuration file defines custom commands for the "rush" command-line.
+ * More documentation is available on the Rush website: https://rushjs.io
+ */
+{
+  "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/command-line.schema.json",
+
+  /**
+   * Custom "commands" introduce new verbs for the command-line.  To see the help for these
+   * example commands, try "rush --help", "rush my-bulk-command --help", or
+   * "rush my-global-command --help".
+   */
+  "commands": [
+    // {
+    //   /**
+    //    * (Required) Determines the type of custom command.
+    //    * Rush's "bulk" commands are invoked separately for each project.  Rush will look in
+    //    * each project's package.json file for a "scripts" entry whose name matches the
+    //    * command name.  By default, the command will run for every project in the repo,
+    //    * according to the dependency graph (similar to how "rush build" works).
+    //    * The set of projects can be restricted e.g. using the "--to" or "--from" parameters.
+    //    */
+    //   "commandKind": "bulk",
+    //
+    //   /**
+    //    * (Required) The name that will be typed as part of the command line.  This is also the name
+    //    * of the "scripts" hook in the project's package.json file.
+    //    * The name should be comprised of lower case words separated by hyphens or colons. The name should include an
+    //    * English verb (e.g. "deploy"). Use a hyphen to separate words (e.g. "upload-docs"). A group of related commands
+    //    * can be prefixed with a colon (e.g. "docs:generate", "docs:deploy", "docs:serve", etc).
+    //    *
+    //    * Note that if the "rebuild" command is overridden here, it becomes separated from the "build" command
+    //    * and will call the "rebuild" script instead of the "build" script.
+    //    */
+    //   "name": "my-bulk-command",
+    //
+    //   /**
+    //    * (Required) A short summary of the custom command to be shown when printing command line
+    //    * help, e.g. "rush --help".
+    //    */
+    //   "summary": "Example bulk custom command",
+    //
+    //   /**
+    //    * A detailed description of the command to be shown when printing command line
+    //    * help (e.g. "rush --help my-command").
+    //    * If omitted, the "summary" text will be shown instead.
+    //    *
+    //    * Whenever you introduce commands/parameters, taking a little time to write meaningful
+    //    * documentation can make a big difference for the developer experience in your repo.
+    //    */
+    //   "description": "This is an example custom command that runs separately for each project",
+    //
+    //   /**
+    //    * By default, Rush operations acquire a lock file which prevents multiple commands from executing simultaneously
+    //    * in the same repo folder.  (For example, it would be a mistake to run "rush install" and "rush build" at the
+    //    * same time.)  If your command makes sense to run concurrently with other operations,
+    //    * set "safeForSimultaneousRushProcesses" to true to disable this protection.
+    //    *
+    //    * In particular, this is needed for custom scripts that invoke other Rush commands.
+    //    */
+    //   "safeForSimultaneousRushProcesses": false,
+    //
+    //   /**
+    //    * (Required) If true, then this command is safe to be run in parallel, i.e. executed
+    //    * simultaneously for multiple projects.  Similar to "rush build", regardless of parallelism
+    //    * projects will not start processing until their dependencies have completed processing.
+    //    */
+    //   "enableParallelism": false,
+    //
+    //   /**
+    //    * Normally projects will be processed according to their dependency order: a given project will not start
+    //    * processing the command until all of its dependencies have completed.  This restriction doesn't apply for
+    //    * certain operations, for example a "clean" task that deletes output files.  In this case
+    //    * you can set "ignoreDependencyOrder" to true to increase parallelism.
+    //    */
+    //   "ignoreDependencyOrder": false,
+    //
+    //   /**
+    //    * Normally Rush requires that each project's package.json has a "scripts" entry matching
+    //    * the custom command name.  To disable this check, set "ignoreMissingScript" to true;
+    //    * projects with a missing definition will be skipped.
+    //    */
+    //   "ignoreMissingScript": false,
+    //
+    //   /**
+    //    * When invoking shell scripts, Rush uses a heuristic to distinguish errors from warnings:
+    //    * - If the shell script returns a nonzero process exit code, Rush interprets this as "one or more errors".
+    //    * Error output is displayed in red, and it prevents Rush from attempting to process any downstream projects.
+    //    * - If the shell script returns a zero process exit code but writes something to its stderr stream,
+    //    * Rush interprets this as "one or more warnings". Warning output is printed in yellow, but does NOT prevent
+    //    * Rush from processing downstream projects.
+    //    *
+    //    * Thus, warnings do not interfere with local development, but they will cause a CI job to fail, because
+    //    * the Rush process itself returns a nonzero exit code if there are any warnings or errors. This is by design.
+    //    * In an active monorepo, we've found that if you allow any warnings in your master branch, it inadvertently
+    //    * teaches developers to ignore warnings, which quickly leads to a situation where so many "expected" warnings
+    //    * have accumulated that warnings no longer serve any useful purpose.
+    //    *
+    //    * Sometimes a poorly behaved task will write output to stderr even though its operation was successful.
+    //    * In that case, it's strongly recommended to fix the task.  However, as a workaround you can set
+    //    * allowWarningsInSuccessfulBuild=true, which causes Rush to return a nonzero exit code for errors only.
+    //    *
+    //    * Note: The default value is false. In Rush 5.7.x and earlier, the default value was true.
+    //    */
+    //   "allowWarningsInSuccessfulBuild": false,
+    //
+    //   /**
+    //    * If true then this command will be incremental like the built-in "build" command
+    //    */
+    //   "incremental": false,
+    //
+    //   /**
+    //    * (EXPERIMENTAL) Normally Rush terminates after the command finishes. If this option is set to "true" Rush
+    //    * will instead enter a loop where it watches the file system for changes to the selected projects. Whenever a
+    //    * change is detected, the command will be invoked again for the changed project and any selected projects that
+    //    * directly or indirectly depend on it.
+    //    *
+    //    * For details, refer to the website article "Using watch mode".
+    //    */
+    //   "watchForChanges": false,
+    //
+    //   /**
+    //    * (EXPERIMENTAL) Disable cache for this action. This may be useful if this command affects state outside of
+    //    * projects' own folders.
+    //    */
+    //   "disableBuildCache ": false
+    // },
+    //
+    // {
+    //   /**
+    //    * (Required) Determines the type of custom command.
+    //    * Rush's "global" commands are invoked once for the entire repo.
+    //    */
+    //   "commandKind": "global",
+    //
+    //   "name": "my-global-command",
+    //   "summary": "Example global custom command",
+    //   "description": "This is an example custom command that runs once for the entire repo",
+    //
+    //   "safeForSimultaneousRushProcesses": false,
+    //
+    //   /**
+    //    * (Required) A script that will be invoked using the OS shell. The working directory will be
+    //    * the folder that contains rush.json.  If custom parameters are associated with this command, their
+    //    * values will be appended to the end of this string.
+    //    */
+    //   "shellCommand": "node common/scripts/my-global-command.js",
+    //
+    //   /**
+    //    * If your "shellCommand" script depends on NPM packages, the recommended best practice is
+    //    * to make it into a regular Rush project that builds using your normal toolchain.  In cases where
+    //    * the command needs to work without first having to run "rush build", the recommended practice
+    //    * is to publish the project to an NPM registry and use common/scripts/install-run.js to launch it.
+    //    *
+    //    * Autoinstallers offer another possibility: They are folders under "common/autoinstallers" with
+    //    * a package.json file and shrinkwrap file. Rush will automatically invoke the package manager to
+    //    * install these dependencies before an associated command is invoked.  Autoinstallers have the
+    //    * advantage that they work even in a branch where "rush install" is broken, which makes them a
+    //    * good solution for Git hook scripts.  But they have the disadvantages of not being buildable
+    //    * projects, and of increasing the overall installation footprint for your monorepo.
+    //    *
+    //    * The "autoinstallerName" setting must not contain a path and must be a valid NPM package name.
+    //    * For example, the name "my-task" would map to "common/autoinstallers/my-task/package.json", and
+    //    * the "common/autoinstallers/my-task/node_modules/.bin" folder would be added to the shell PATH when
+    //    * invoking the "shellCommand".
+    //    */
+    //   // "autoinstallerName": "my-task"
+    // }
+  ],
+
+  /**
+   * Custom "parameters" introduce new parameters for specified Rush command-line commands.
+   * For example, you might define a "--production" parameter for the "rush build" command.
+   */
+  "parameters": [
+    // {
+    //   /**
+    //    * (Required) Determines the type of custom parameter.
+    //    * A "flag" is a custom command-line parameter whose presence acts as an on/off switch.
+    //    */
+    //   "parameterKind": "flag",
+    //
+    //   /**
+    //    * (Required) The long name of the parameter.  It must be lower-case and use dash delimiters.
+    //    */
+    //   "longName": "--my-flag",
+    //
+    //   /**
+    //    * An optional alternative short name for the parameter.  It must be a dash followed by a single
+    //    * lower-case or upper-case letter, which is case-sensitive.
+    //    *
+    //    * NOTE: The Rush developers recommend that automation scripts should always use the long name
+    //    * to improve readability.  The short name is only intended as a convenience for humans.
+    //    * The alphabet letters run out quickly, and are difficult to memorize, so *only* use
+    //    * a short name if you expect the parameter to be needed very often in everyday operations.
+    //    */
+    //   "shortName": "-m",
+    //
+    //   /**
+    //    * (Required) A long description to be shown in the command-line help.
+    //    *
+    //    * Whenever you introduce commands/parameters, taking a little time to write meaningful
+    //    * documentation can make a big difference for the developer experience in your repo.
+    //    */
+    //   "description": "A custom flag parameter that is passed to the scripts that are invoked when building projects",
+    //
+    //   /**
+    //    * (Required) A list of custom commands and/or built-in Rush commands that this parameter may
+    //    * be used with.  The parameter will be appended to the shell command that Rush invokes.
+    //    */
+    //   "associatedCommands": ["build", "rebuild"]
+    // },
+    //
+    // {
+    //   /**
+    //    * (Required) Determines the type of custom parameter.
+    //    * A "string" is a custom command-line parameter whose value is a simple text string.
+    //    */
+    //   "parameterKind": "string",
+    //   "longName": "--my-string",
+    //   "description": "A custom string parameter for the \"my-global-command\" custom command",
+    //
+    //   "associatedCommands": ["my-global-command"],
+    //
+    //   /**
+    //    * The name of the argument, which will be shown in the command-line help.
+    //    *
+    //    * For example, if the parameter name is '--count" and the argument name is "NUMBER",
+    //    * then the command-line help would display "--count NUMBER".  The argument name must
+    //    * be comprised of upper-case letters, numbers, and underscores.  It should be kept short.
+    //    */
+    //   "argumentName": "SOME_TEXT",
+    //
+    //   /**
+    //    * If true, this parameter must be included with the command.  The default is false.
+    //    */
+    //   "required": false
+    // },
+    //
+    // {
+    //   /**
+    //    * (Required) Determines the type of custom parameter.
+    //    * A "choice" is a custom command-line parameter whose argument must be chosen from a list of
+    //    * allowable alternatives.
+    //    */
+    //   "parameterKind": "choice",
+    //   "longName": "--my-choice",
+    //   "description": "A custom choice parameter for the \"my-global-command\" custom command",
+    //
+    //   "associatedCommands": ["my-global-command"],
+    //
+    //   /**
+    //    * If true, this parameter must be included with the command.  The default is false.
+    //    */
+    //   "required": false,
+    //
+    //   /**
+    //    * Normally if a parameter is omitted from the command line, it will not be passed
+    //    * to the shell command. this value will be inserted by default.  Whereas if a "defaultValue"
+    //    * is defined, the parameter will always be passed to the shell command, and will use the
+    //    * default value if unspecified.  The value must be one of the defined alternatives.
+    //    */
+    //   "defaultValue": "vanilla",
+    //
+    //   /**
+    //    * (Required) A list of alternative argument values that can be chosen for this parameter.
+    //    */
+    //   "alternatives": [
+    //     {
+    //       /**
+    //        * A token that is one of the alternatives that can be used with the choice parameter,
+    //        * e.g. "vanilla" in "--flavor vanilla".
+    //        */
+    //       "name": "vanilla",
+    //
+    //       /**
+    //        * A detailed description for the alternative that can be shown in the command-line help.
+    //        *
+    //        * Whenever you introduce commands/parameters, taking a little time to write meaningful
+    //        * documentation can make a big difference for the developer experience in your repo.
+    //        */
+    //       "description": "Use the vanilla flavor (the default)"
+    //     },
+    //
+    //     {
+    //       "name": "chocolate",
+    //       "description": "Use the chocolate flavor"
+    //     },
+    //
+    //     {
+    //       "name": "strawberry",
+    //       "description": "Use the strawberry flavor"
+    //     }
+    //   ]
+    // }
+  ]
+}
diff --git a/common/config/rush/common-versions.json b/common/config/rush/common-versions.json
new file mode 100644
index 0000000..8357e88
--- /dev/null
+++ b/common/config/rush/common-versions.json
@@ -0,0 +1,62 @@
+/**
+ * This configuration file specifies NPM dependency version selections that affect all projects
+ * in a Rush repo.  More documentation is available on the Rush website: https://rushjs.io
+ */
+{
+  "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/common-versions.schema.json",
+
+  /**
+   * A table that specifies a "preferred version" for a given NPM package.  This feature is typically used
+   * to hold back an indirect dependency to a specific older version, or to reduce duplication of indirect dependencies.
+   *
+   * The "preferredVersions" value can be any SemVer range specifier (e.g. "~1.2.3").  Rush injects these values into
+   * the "dependencies" field of the top-level common/temp/package.json, which influences how the package manager
+   * will calculate versions.  The specific effect depends on your package manager.  Generally it will have no
+   * effect on an incompatible or already constrained SemVer range.  If you are using PNPM, similar effects can be
+   * achieved using the pnpmfile.js hook.  See the Rush documentation for more details.
+   *
+   * After modifying this field, it's recommended to run "rush update --full" so that the package manager
+   * will recalculate all version selections.
+   */
+  "preferredVersions": {
+    /**
+     * When someone asks for "^1.0.0" make sure they get "1.2.3" when working in this repo,
+     * instead of the latest version.
+     */
+    // "some-library": "1.2.3"
+  },
+
+  /**
+   * When set to true, for all projects in the repo, all dependencies will be automatically added as preferredVersions,
+   * except in cases where different projects specify different version ranges for a given dependency.  For older
+   * package managers, this tended to reduce duplication of indirect dependencies.  However, it can sometimes cause
+   * trouble for indirect dependencies with incompatible peerDependencies ranges.
+   *
+   * The default value is true.  If you're encountering installation errors related to peer dependencies,
+   * it's recommended to set this to false.
+   *
+   * After modifying this field, it's recommended to run "rush update --full" so that the package manager
+   * will recalculate all version selections.
+   */
+  // "implicitlyPreferredVersions": false,
+
+  /**
+   * The "rush check" command can be used to enforce that every project in the repo must specify
+   * the same SemVer range for a given dependency.  However, sometimes exceptions are needed.
+   * The allowedAlternativeVersions table allows you to list other SemVer ranges that will be
+   * accepted by "rush check" for a given dependency.
+   *
+   * IMPORTANT: THIS TABLE IS FOR *ADDITIONAL* VERSION RANGES THAT ARE ALTERNATIVES TO THE
+   * USUAL VERSION (WHICH IS INFERRED BY LOOKING AT ALL PROJECTS IN THE REPO).
+   * This design avoids unnecessary churn in this file.
+   */
+  "allowedAlternativeVersions": {
+    /**
+     * For example, allow some projects to use an older TypeScript compiler
+     * (in addition to whatever "usual" version is being used by other projects in the repo):
+     */
+    // "typescript": [
+    //   "~2.4.0"
+    // ]
+  }
+}
diff --git a/common/config/rush/experiments.json b/common/config/rush/experiments.json
new file mode 100644
index 0000000..0e276ca
--- /dev/null
+++ b/common/config/rush/experiments.json
@@ -0,0 +1,32 @@
+/**
+ * This configuration file allows repo maintainers to enable and disable experimental
+ * Rush features.  More documentation is available on the Rush website: https://rushjs.io
+ */
+{
+  "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/experiments.schema.json",
+
+  /**
+   * By default, 'rush install' passes --no-prefer-frozen-lockfile to 'pnpm install'.
+   * Set this option to true to pass '--frozen-lockfile' instead for faster installs.
+   */
+  // "usePnpmFrozenLockfileForRushInstall": true,
+
+  /**
+   * By default, 'rush update' passes --no-prefer-frozen-lockfile to 'pnpm install'.
+   * Set this option to true to pass '--prefer-frozen-lockfile' instead to minimize shrinkwrap changes.
+   */
+  // "usePnpmPreferFrozenLockfileForRushUpdate": true,
+
+  /**
+   * If using the 'preventManualShrinkwrapChanges' option, restricts the hash to only include the layout of external dependencies.
+   * Used to allow links between workspace projects or the addition/removal of references to existing dependency versions to not
+   * cause hash changes.
+   */
+  // "omitImportersFromPreventManualShrinkwrapChanges": true,
+
+  /**
+   * If true, the chmod field in temporary project tar headers will not be normalized.
+   * This normalization can help ensure consistent tarball integrity across platforms.
+   */
+  // "noChmodFieldInTarHeaderNormalization": true
+}
diff --git a/common/config/rush/version-policies.json b/common/config/rush/version-policies.json
new file mode 100644
index 0000000..b0f1733
--- /dev/null
+++ b/common/config/rush/version-policies.json
@@ -0,0 +1,90 @@
+/**
+ * This is configuration file is used for advanced publishing configurations with Rush.
+ * More documentation is available on the Rush website: https://rushjs.io
+ */
+
+/**
+ * A list of version policy definitions.  A "version policy" is a custom package versioning
+ * strategy that affects "rush change", "rush version", and "rush publish".  The strategy applies
+ * to a set of projects that are specified using the "versionPolicyName" field in rush.json.
+ */
+[
+  // {
+  //   /**
+  //    * (Required) Indicates the kind of version policy being defined ("lockStepVersion" or "individualVersion").
+  //    *
+  //    * The "lockStepVersion" mode specifies that the projects will use "lock-step versioning".  This
+  //    * strategy is appropriate for a set of packages that act as selectable components of a
+  //    * unified product.  The entire set of packages are always published together, and always share
+  //    * the same NPM version number.  When the packages depend on other packages in the set, the
+  //    * SemVer range is usually restricted to a single version.
+  //    */
+  //   "definitionName": "lockStepVersion",
+  //
+  //   /**
+  //    * (Required) The name that will be used for the "versionPolicyName" field in rush.json.
+  //    * This name is also used command-line parameters such as "--version-policy"
+  //    * and "--to-version-policy".
+  //    */
+  //   "policyName": "MyBigFramework",
+  //
+  //   /**
+  //    * (Required) The current version.  All packages belonging to the set should have this version
+  //    * in the current branch.  When bumping versions, Rush uses this to determine the next version.
+  //    * (The "version" field in package.json is NOT considered.)
+  //    */
+  //   "version": "1.0.0",
+  //
+  //   /**
+  //    * (Required) The type of bump that will be performed when publishing the next release.
+  //    * When creating a release branch in Git, this field should be updated according to the
+  //    * type of release.
+  //    *
+  //    * Valid values are: "prerelease", "release", "minor", "patch", "major"
+  //    */
+  //   "nextBump": "prerelease",
+  //
+  //   /**
+  //    * (Optional) If specified, all packages in the set share a common CHANGELOG.md file.
+  //    * This file is stored with the specified "main" project, which must be a member of the set.
+  //    *
+  //    * If this field is omitted, then a separate CHANGELOG.md file will be maintained for each
+  //    * package in the set.
+  //    */
+  //   "mainProject": "my-app"
+  // },
+  //
+  // {
+  //   /**
+  //    * (Required) Indicates the kind of version policy being defined ("lockStepVersion" or "individualVersion").
+  //    *
+  //    * The "individualVersion" mode specifies that the projects will use "individual versioning".
+  //    * This is the typical NPM model where each package has an independent version number
+  //    * and CHANGELOG.md file.  Although a single CI definition is responsible for publishing the
+  //    * packages, they otherwise don't have any special relationship.  The version bumping will
+  //    * depend on how developers answer the "rush change" questions for each package that
+  //    * is changed.
+  //    */
+  //   "definitionName": "individualVersion",
+  //
+  //   "policyName": "MyRandomLibraries",
+  //
+  //   /**
+  //    * (Optiona…
@elliot-nelson
Copy link
Collaborator

Closing for now, as the issue is resolved.

  • Our JSON files look good in GitHub (and so do any new rush monorepos if they use the provided .gitattributes default).
  • When pasting snippets of JSON files in GitHub comments or pull requests, you can use the jsonc header to get JSON-with-comments styling.
  • Our parser supports JSON5, but 3 years later I still haven't seen much of a push to switch to JSON5 so I think we can stick with JSONC for now.

@frog-o
Copy link

frog-o commented Aug 28, 2022

@elliot-nelson I real don't feel this has been resolved.
I been try to get start with api-extractor ( all automatic documentation just seem horrible to me)
i been following api-extractor doc here.
There documentation dose not mention you can use ".jsonc" and when you run

api-extractor --init

It produces an .json file. I would like push the use of json5 a little more but if jsonc works i can see why it not worth the hassle
but at the very least IMHO api-extractor --init and all other rush tools should create a jsonc file by default. The rest seem like a hack.
Do you feel different or is this just my inexperience?

@elliot-nelson
Copy link
Collaborator

@frog-o To be honest, I cannot defend the current status quo, because it is confusing to have a landscape where the file extension .json can mean "strict JSON" (ECMA standard) or "JSONC" (JSON with comments).

But, that is the status quo today:

  • VSCode's own configuration files end in .json, but contain JSONC.
  • TypeScript's tsconfig.json is actually JSONC.
  • Jest's jest.config.json is actually JSONC.
  • ESlint's eslintrc.json is actually JSONC.

In every case, the .json configuration file supports comments, in defiance of the spec; in every case, the file extension .jsonc is unrecognized. (In fact, I have never seen a file with the file extension .jsonc anywhere in any codebase.)

So it is a little unsatisfactory, but Rush is simply following the standard here.

@frog-o
Copy link

frog-o commented Aug 28, 2022 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
design proposal A new direction that is complex enough to have open questions but specific enough to implement general discussion Not a bug or enhancement, just a discussion
Projects
Archived in project
Development

No branches or pull requests

8 participants
@elliot-nelson @alipi @octogonz @xiaoxiangmoe @daspek @chaseholdren @frog-o and others